Skip to content

Unable to cleanly shutdown/close MCP Server #113

Closed
@davidfiala

Description

@davidfiala

It appears that the most basic version of starting/stopping an MCP server leaves a handle or reference open which prevents node from exiting.

I've observed that if I process.stdin.destroy() then I can unblock MCP and get the whatever handles it is using to close.

Versions:
node: v23.2.0
@modelcontextprotocol/sdk: 1.0.4

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = new Server(
  {
    name: 'foo/bar',
    version: '0.0.1',
  },
  {
    capabilities: {
      resources: {},
      tools: {},
    },
  },
);

async function main() {
  const transport = new StdioServerTransport();
  server.connect(transport);
  await server.close();
  await transport.close();

  console.warn('Will I hang forever here? Unfortunately, yes.');

  // Destroying stdin prevents the hang, but it's ugly:
  // process.stdin.destroy();
}

main();

The uncleaned handles appear to be added in server.connect(transport); since it will exit cleanly if I comment that line.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions