Skip to content

Unable to cleanly shutdown/close MCP Server #113

@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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions