express-mcp-处理程序
用于将模型上下文协议 (MCP)与 Express 应用程序集成的中间件,实现 LLM 和工具之间的无缝通信。
什么是模型上下文协议(MCP)?
模型上下文协议 (MCP)是一个用于集成大型语言模型 (LLM) 与外部数据源和工具的开放协议。它使 AI 助手能够通过标准化接口访问实时数据、执行操作并与各种服务交互。
特征
- 有状态处理程序:可以处理一次性请求或使用会话 ID 和服务器发送事件 (SSE) 维护长期会话。
- 无状态处理程序:完全隔离地处理每个请求,以实现简单的一次性交互。
- SSE 处理程序:使用专用的 GET 和 POST 端点处理服务器发送事件 (SSE) 上的模型上下文协议 (MCP)。
- 类型安全 API :使用 TypeScript 构建,可实现可靠集成。
- 灵活的配置:可定制的错误处理、会话管理和生命周期挂钩。
- Express 集成:使用中间件模式直接插入 Express 路由。
安装
通过 npm 安装:
npm install express-mcp-handler
或纱线:
yarn add express-mcp-handler
或者 pnpm:
pnpm add express-mcp-handler
对等依赖关系
此软件包需要以下对等依赖项:
express
>= 4.0.0@modelcontextprotocol/sdk
>= 1.10.2zod
>= 3.0.0
如果尚未安装,请安装它们:
npm install express @modelcontextprotocol/sdk zod
快速入门
这是一个帮助您入门的基本示例:
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',
});
// Mount the stateless handler
app.post('/mcp', statelessHandler(serverFactory));
app.listen(3000, () => {
console.log('Express MCP server running on port 3000');
});
用法
Express-mcp-handler 提供三种处理程序类型以适应不同的用例:
状态模式
使用statefulHandler
在客户端和服务器之间建立可重用的会话,非常适合在多个交互之间维护上下文:
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { statefulHandler } from 'express-mcp-handler';
import { randomUUID } from 'node:crypto';
const app = express();
app.use(express.json());
// Create an MCP server instance
const server = new McpServer({
name: 'my-server',
version: '1.0.0',
});
// Configure handler options
const handlerOptions = {
sessionIdGenerator: randomUUID, // Function to generate unique session IDs
onSessionInitialized: (sessionId: string) => {
console.log(`Session initialized: ${sessionId}`);
// You could store session metadata or initialize resources here
},
onSessionClosed: (sessionId: string) => {
console.log(`Session closed: ${sessionId}`);
// Perform cleanup logic here
},
onError: (error: Error, sessionId?: string) => {
console.error(`Error in session ${sessionId}:`, error);
// Handle errors for monitoring or logging
}
};
// Mount the handlers for different HTTP methods
app.post('/mcp', statefulHandler(server, handlerOptions));
app.get('/mcp', statefulHandler(server, handlerOptions));
app.delete('/mcp', statefulHandler(server, handlerOptions));
app.listen(3000, () => {
console.log('Express MCP server running on port 3000');
});
有状态处理程序:
- 在第一个请求上初始化一个新会话(没有
mcp-session-id
标头) - 返回客户端必须在后续请求中包含的
mcp-session-id
标头 - 管理服务器发送事件 (SSE),将消息从服务器推送到客户端
- 关闭时自动清理会话
无状态模式
使用statelessHandler
进行一次性请求处理,无需会话管理,非常适合无服务器环境或简单请求:
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());
// Function that creates a fresh McpServer for each request
const serverFactory = () => new McpServer({
name: 'stateless-mcp-server',
version: '1.0.0',
});
// Configure with custom error handling
const options = {
onError: (error: Error) => {
console.error('MCP error:', error);
// Add custom error reporting logic here
}
};
app.post('/mcp', statelessHandler(serverFactory, options));
app.listen(3000, () => {
console.log('Express Stateless MCP server running on port 3000');
});
每个无状态请求:
- 创建一个新的传输和服务器实例
- 确保完全隔离,无需会话跟踪
- 适用于简单或无服务器环境
SSE模式
使用sseHandlers
���过服务器发送事件 (SSE) 处理模型上下文协议 (MCP),非常适合实时流响应:
import express from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { sseHandlers } from 'express-mcp-handler';
const app = express();
app.use(express.json());
// Provide a factory function that returns a fresh McpServer for each SSE connection
const serverFactory = () => new McpServer({
name: 'sse-mcp-server',
version: '1.0.0',
});
// Configure SSE handlers
const handlers = sseHandlers(serverFactory, {
onError: (error: Error, sessionId?: string) => {
console.error(`[SSE][${sessionId || 'unknown'}]`, error);
},
onClose: (sessionId: string) => {
console.log(`[SSE] transport closed: ${sessionId}`);
// Clean up any session resources
},
});
// Mount the SSE endpoints
app.get('/sse', handlers.getHandler);
app.post('/messages', handlers.postHandler);
app.listen(3002, () => {
console.log('Express MCP SSE server running on port 3002');
});
SSE 处理程序提供:
- GET /sse :建立 SSE 流并返回
mcp-session-id
标头 - POST /messages :使用
mcp-session-id
查询参数通过 SSE 传输发送 MCP 消息
API 参考
statefulHandler
function statefulHandler(
server: McpServer,
options: {
sessionIdGenerator: () => string;
onSessionInitialized?: (sessionId: string) => void;
onSessionClosed?: (sessionId: string) => void;
onError?: (error: Error, sessionId?: string) => void;
onInvalidSession?: (req: express.Request) => void;
}
): express.RequestHandler;
范围 | 类型 | 描述 |
---|
server | McpServer | McpServer 实例来处理协议逻辑 |
options.sessionIdGenerator | () => string | 返回唯一会话 ID 的函数 |
options.onSessionInitialized | (sessionId: string) => void | *(可选)*使用新会话 ID 调用的回调 |
options.onSessionClosed | (sessionId: string) => void | *(可选)*会话关闭时调用的回调 |
options.onError | (error: Error, sessionId?: string) => void | *(可选)*发生错误时调用的回调 |
options.onInvalidSession | (req: express.Request) => void | *(可选)*访问无效会话时调用的回调 |
无状态处理程序
function statelessHandler(
serverFactory: () => McpServer,
options?: {
sessionIdGenerator?: () => string;
onClose?: (req: express.Request, res: express.Response) => void;
onError?: (error: Error) => void;
}
): express.RequestHandler;
范围 | 类型 | 描述 |
---|
serverFactory | () => McpServer | 为每个请求返回一个新的服务器实例的函数 |
options.sessionIdGenerator | () => string | *(可选)*覆盖传输会话 ID 生成 |
options.onClose | (req: express.Request, res: express.Response) => void | *(可选)*请求/响应周期结束时触发的回调 |
options.onError | (error: Error) => void | *(可选)*处理过程中发生错误时触发的回调 |
sse处理程序
function sseHandlers(
serverFactory: ServerFactory,
options: SSEHandlerOptions
): {
getHandler: express.RequestHandler;
postHandler: express.RequestHandler;
};
范围 | 类型 | 描述 |
---|
serverFactory | ServerFactory | 为每个 SSE 连接返回一个新的McpServer 的工厂函数 |
options.onError | (error: Error, sessionId?: string) => void | *(可选)*发生错误时调用的回调,接收error 和可选的sessionId |
options.onClose | (sessionId: string) => void | (可选) SSE 会话关闭时调用的回调,接收sessionId |
错误处理
所有处理程序类型都通过其选项支持自定义错误处理:
// Example of custom error handling for stateful handler
const handlerOptions = {
// ... other options
onError: (error: Error, sessionId?: string) => {
console.error(`Error in session ${sessionId}:`, error);
// Send error to monitoring service
Sentry.captureException(error, {
extra: { sessionId }
});
}
};
TypeScript 支持
此包使用 TypeScript 编写,并为所有导出提供类型定义。使用 TypeScript 时,您将获得完整的 IntelliSense 和类型检查。
import { statefulHandler, StatefulHandlerOptions } from 'express-mcp-handler';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
// Type-safe options
const options: StatefulHandlerOptions = {
sessionIdGenerator: () => Date.now().toString(),
onError: (error, sessionId) => {
// TypeScript knows the types of these parameters
console.error(`Error in session ${sessionId}:`, error);
}
};
const server = new McpServer({
name: 'typed-server',
version: '1.0.0',
});
// Type-safe handler
app.post('/mcp', statefulHandler(server, options));
发展
为该项目做出贡献:
git clone https://github.com/jhgaylor/express-mcp-handler.git
cd express-mcp-handler
npm install
npm run build
npm test
测试覆盖率
该项目具有可靠的测试覆盖率并承诺对其进行维护。
所有更改均通过我们的 CI/CD 管道进行验证,使用 Jest 进行测试并使用 Codecov 进行覆盖率报告。
持续集成
本项目使用 GitHub Actions 进行持续集成。每次推送到主分支和拉取请求都会:
- 运行 Lint 检查
- 构建项目
- 运行覆盖测试
- 将覆盖率报告上传到Codecov
您可以在此 README 顶部的徽章中或 GitHub 存储库的“操作”选项卡中查看当前 CI 状态。
执照
MIT 许可证
发布到 npm
如果尚未登录,请登录 npm:
将包发布到 npm(将运行您的 prepublishOnly 构建):
要提升、标记和推送新版本:
npm version patch # or minor, major
git push origin main --tags
处理程序类型一览
处理程序 | 设想 | 会议 | 流媒体 |
---|
无状态处理程序 | 一次性或无服务器工作负载 | 不 | 不 |
statefulHandler | 多轮互动 | 是的 | 是的 |
sse处理程序 | 实时 SSE 流 | 是的 | 是的 |
故障排除
缺少mcp-session-id
标头
确保客户端包含初始请求上返回的mcp-session-id
标头。
交通连接提前关闭
验证网络连接并确保客户端正确处理 SSE 事件。
变更日志
该项目所有值得注意的变化都记录在CHANGELOG.md中。