Express MCP Handler
raw JSON →Express-mcp-handler is a middleware library designed to integrate the Model Context Protocol (MCP) into Express.js applications. It facilitates seamless communication between large language models (LLMs) and external tools or data sources by providing standardized handling for MCP requests. The package is currently in version 0.3.0, indicating it is in early development and its API may evolve rapidly, though it appears actively maintained. Key differentiators include its ability to manage stateful, stateless, and Server-Sent Events (SSE) based MCP interactions, offering a flexible solution for various integration patterns. Built with TypeScript, it provides a type-safe API, enhancing reliability and developer experience. It also offers customizable options for error handling, session management, and lifecycle hooks, making it adaptable to complex application requirements, and directly plugs into existing Express routes.
Common errors
error Error: Cannot find package 'express' (or @modelcontextprotocol/sdk, zod) imported from ... ↓
npm install express @modelcontextprotocol/sdk zod. error TypeError: (0 , express_mcp_handler_1.statelessHandler) is not a function ↓
"type": "module" in package.json) and use import statements. If using TypeScript, ensure your tsconfig.json targets a modern module resolution (e.g., "ES2022" or "Node16"). error ERR_REQUIRE_ESM: Must use import to load ES Module: ...express-mcp-handler/dist/index.js ↓
import statements. If this is not feasible, consider a build step like Babel or Webpack to handle module transformations, or ensure your package.json specifies "type": "module" for relevant files. Warnings
breaking As the package is currently in version 0.x.x, the API is subject to change without a major version bump. Users should expect potential breaking changes in minor or patch releases. ↓
gotcha This package requires `express`, `@modelcontextprotocol/sdk`, and `zod` as peer dependencies. They must be installed separately alongside `express-mcp-handler`. ↓
gotcha The package targets Node.js version 18.0.0 or higher. Running on older Node.js versions may lead to compatibility issues or unexpected behavior due to modern JavaScript features and ESM support. ↓
gotcha The `statelessHandler` typically expects a 'server factory' function that returns a new `McpServer` instance per request, while `statefulHandler` can often use a single, pre-configured `McpServer` instance. Incorrectly providing a factory where an instance is expected, or vice-versa, can lead to unexpected session management or state issues. ↓
Install
npm install express-mcp-handler yarn add express-mcp-handler pnpm add express-mcp-handler Imports
- statelessHandler wrong
const statelessHandler = require('express-mcp-handler').statelessHandler;correctimport { statelessHandler } from 'express-mcp-handler'; - statefulHandler wrong
import statefulHandler from 'express-mcp-handler';correctimport { statefulHandler } from 'express-mcp-handler'; - sseHandler wrong
const { sseHandler } = require('express-mcp-handler');correctimport { sseHandler } from 'express-mcp-handler';
Quickstart
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { statelessHandler } from 'express-mcp-handler';
const app = express();
app.use(express.json());
// Create a factory function that returns a new McpServer instance for each request
const serverFactory = () => new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
// Add tool definitions here, e.g.:
// tools: [
// {
// id: 'getCurrentTime',
// description: 'Gets the current time.',
// inputSchema: z.object({}),
// outputSchema: z.object({ time: z.string() }),
// handler: async () => ({ time: new Date().toISOString() }),
// },
// ],
});
// Mount the stateless handler on a POST endpoint
app.post('/mcp', statelessHandler(serverFactory));
app.listen(3000, () => {
console.log('Express MCP server running on port 3000');
});