Skip to content

Unable to cleanly shutdown/close MCP Server #113

Closed

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.

Activity

  1. linked a pull request that will close this issueAdded clean shutdown + tests #115on Jan 3, 2025
  2. added a commit that references this issue on May 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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