# How the MCP Server Handles SIGTERM and SIGINT Signals for Graceful Shutdown

> Learn how the MCP server gracefully handles SIGTERM and SIGINT signals. Discover the process of closing transport and exiting with code 0 by registering signal listeners.

- Repository: [Kevin Kern/deepwiki-mcp](https://github.com/regenrek/deepwiki-mcp)
- Tags: internals
- Published: 2026-02-16

---

**The MCP server registers signal listeners in [`src/index.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/index.ts) that trigger the `stopServer` helper in [`src/server.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/server.ts), which closes the underlying MCP transport and exits the process with code 0.**

The `regenrek/deepwiki-mcp` repository implements a robust signal handling mechanism to ensure the Model Context Protocol (MCP) server shuts down gracefully when receiving termination signals. This prevents data loss and ensures open transports close properly before the Node.js process exits.

## Signal Registration in the Entry Point

The CLI entry point at [`src/index.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/index.ts) registers handlers for both `SIGTERM` and `SIGINT` before starting any network transport. This guarantees the handlers remain active for the entire process lifetime.

```typescript
process.on('SIGTERM', () => stopServer(mcp))
process.on('SIGINT',  () => stopServer(mcp))

```

These listeners are attached **before** the stdio, HTTP, or SSE transport initializes, ensuring that even early termination attempts trigger the graceful shutdown sequence. The handlers capture the `mcp` server instance and pass it to the `stopServer` utility defined in [`src/server.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/server.ts).

## Graceful Shutdown Logic Implementation

The actual shutdown logic resides in [`src/server.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/server.ts) within the exported `stopServer` function. This implementation ensures the MCP SDK closes all active connections before forcing process termination.

### Closing the MCP Transport

The function first attempts to close the underlying MCP server using the SDK's native `close` method. This method shuts down any open transports, including HTTP listeners, SSE sessions, or stdio pipes.

```typescript
export async function stopServer(server: McpServer) {
  try {
    await server.close()
  } catch (error) {
    console.error('Error occurred during server stop:', error)
  } finally {
    process.exit(0)
  }
}

```

Errors during the close operation are caught and logged to `stderr`, but they do not prevent the shutdown sequence from completing.

### Process Termination Guarantees

The `finally` block ensures `process.exit(0)` executes regardless of whether the server closed successfully or threw an error. This guarantees the Node.js process terminates with exit code 0, signaling to the operating system that the shutdown was intentional and successful.

## Practical Implementation Example

When building a custom MCP server using this pattern, mirror the built-in CLI structure to ensure robust signal handling:

```typescript
import { createServer, startServer, stopServer } from './src/server'

// Create the MCP instance
const mcp = createServer({ name: 'my-mcp', version: '1.0.0' })

// Register graceful-shutdown handlers before starting transport
process.on('SIGTERM', () => stopServer(mcp))
process.on('SIGINT',  () => stopServer(mcp))

// Start with the desired transport (e.g., HTTP on port 4000)
await startServer(mcp, { type: 'http', port: 4000, endpoint: '/mcp' })

```

## Testing Signal Handling

Verify the graceful shutdown behavior using shell commands:

```bash

# Run the server in the background

node ./dist/cli.mjs &
SERVER_PID=$!

# Give it a moment to start

sleep 1

# Send SIGTERM

kill -TERM $SERVER_PID

# Wait and verify the process exited cleanly

wait $SERVER_PID && echo "Graceful shutdown completed"

```

## Summary

- **Early Registration**: Signal handlers attach in [`src/index.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/index.ts) (lines 27-28) before transport initialization, ensuring coverage for the entire process lifetime.
- **SDK Integration**: The `stopServer` function in [`src/server.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/server.ts) (lines 83-92) delegates to the MCP SDK's `close` method to terminate transports cleanly.
- **Guaranteed Exit**: A `finally` block ensures `process.exit(0)` executes even if shutdown errors occur, preventing zombie processes.
- **OS Compliance**: Exit code 0 signals successful termination to process managers like systemd, Docker, and Kubernetes.

## Frequently Asked Questions

### What happens if the MCP server is in the middle of a request when SIGTERM is received?

The `server.close()` method from the MCP SDK initiates a graceful shutdown, allowing existing connections to complete while preventing new ones. However, the current implementation in `regenrek/deepwiki-mcp` does not implement a custom timeout; it relies on the SDK's internal behavior and immediately proceeds to `process.exit(0)` after the close promise resolves or rejects.

### Can I customize the shutdown behavior to run additional cleanup tasks?

Yes. You can modify the `stopServer` function in [`src/server.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/server.ts) to include additional cleanup logic before or after the `server.close()` call. For example, you could flush logs to disk, close database connections, or notify external services. Ensure you wrap cleanup operations in try-catch blocks to prevent errors from blocking the final `process.exit(0)` call in the `finally` block.

### Why does the server exit with code 0 instead of a different exit code?

Exit code 0 indicates successful termination to the operating system and process managers like systemd, Docker, or Kubernetes. Since the shutdown is intentional and successful (even if minor errors occurred during transport closure), code 0 is appropriate. If you need to distinguish between different shutdown scenarios for monitoring purposes, you could modify the `process.exit()` call to use different codes based on error conditions, though this would require changes to [`src/server.ts`](https://github.com/regenrek/deepwiki-mcp/blob/main/src/server.ts).