NestJS MCP Server Module
一个 NestJS 模块,允许将服务暴露为 MCP (Meta-Control Protocol) 服务器,并使用服务器发送事件 (Server-Sent Events, SSE) 传输,从而方便客户端进行工具发现和执行。
README
NestJS MCP 服务器模块
一个 NestJS 模块,用于将您的服务公开为具有服务器发送事件 (SSE) 传输的 MCP(模型上下文协议)服务器。 此包简化了公开客户端可以通过 SSE 发现和执行的工具。
特性
- SSE 传输:内置
/sse端点用于流式传输,/messages用于处理工具执行 - 工具发现:使用装饰器自动发现和注册工具
- 工具请求验证:定义 Zod 模式来验证工具请求。
- 进度通知:从工具向客户端发送持续的进度更新。
- 身份验证:与 NestJS Guards 集成以保护端点。
安装
npm install @rekog/mcp-nest reflect-metadata @modelcontextprotocol/sdk zod @nestjs/common @nestjs/core
快速开始
1. 导入模块
// app.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@rekog/mcp-nest';
import { GreetingTool } from './greeting.tool';
@Module({
imports: [
McpModule.forRoot({
name: 'my-mcp-server',
version: '1.0.0',
})
],
providers: [GreetingTool]
})
export class AppModule {}
2. 定义工具
// greeting.tool.ts
import { Injectable } from '@nestjs/common';
import { Tool, Context } from '@rekog/mcp-nest';
import { z } from 'zod';
import { Progress } from '@modelcontextprotocol/sdk/types';
@Injectable()
export class GreetingTool {
constructor() {}
@Tool({
name: 'hello-world',
description:
'返回问候语并模拟具有进度更新的长时间操作',
parameters: z.object({
name: z.string().default('World'),
}),
})
async sayHello({ name }, context: Context) {
const greeting = `Hello, ${name}!`;
const totalSteps = 5;
for (let i = 0; i < totalSteps; i++) {
await new Promise((resolve) => setTimeout(resolve, 500));
// 发送进度更新。
await context.reportProgress({
progress: (i + 1) * 20,
total: 100,
} as Progress);
}
return {
content: [{ type: 'text', text: greeting }],
};
}
}
你完成了!
身份验证
您可以使用标准的 NestJS Guards 来保护您的 MCP 端点。
1. 创建一个 Guard
实现 CanActivate 接口。 该 guard 应该处理请求验证(例如,检查 JWT、API 密钥)并可选择将用户信息附加到请求对象。
<details>
<summary>Guard 实现示例</summary>
// auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
const authorization = request.headers.authorization;
// 示例:检查特定的 Bearer 令牌
if (authorization && authorization.startsWith('Bearer ')) {
const token = authorization.substring(7);
if (token === 'your-secret-token') {
// 如果需要,附加用户信息(可选)
request.user = { id: 'user-123', roles: ['admin'] };
return true; // 允许访问
}
}
return false; // 拒绝访问
}
}
</details>
2. 应用 Guard
将您的 guard 传递给 McpModule.forRoot 配置。 该 guard 将应用于 /sse 和 /messages 端点。
// app.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@rekog/mcp-nest';
import { GreetingTool } from './greeting.tool';
import { AuthGuard } from './auth.guard';
@Module({
imports: [
McpModule.forRoot({
name: 'my-mcp-server',
version: '1.0.0',
guards: [AuthGuard] // 在此处应用 guard
})
],
providers: [GreetingTool, AuthGuard] // 确保也提供了 Guard
})
export class AppModule {}
3. 在工具中访问用户上下文(可选)
如果您的 guard 将用户信息附加到 request 对象(例如,request.user = ...),您可以在您的工具中将其作为第三个参数访问。
// authenticated-greeting.tool.ts
import { Injectable } from '@nestjs/common';
import { Tool, Context } from '@rekog/mcp-nest';
import { z } from 'zod';
import { Request } from 'express'; // 从 express 导入 Request
@Injectable()
export class AuthenticatedGreetingTool {
@Tool({
name: 'auth-hello-world',
description: '问候已验证的用户',
parameters: z.object({}), // 此示例不需要参数
})
// 添加 'request' 作为第三个参数
async sayAuthHello(args: {}, context: Context, request: Request & { user?: { id: string } }) {
const userId = request.user?.id || 'Anonymous';
const greeting = `Hello, user ${userId}!`;
return {
content: [{ type: 'text', text: greeting }],
};
}
}
注意:确保您的工具(在此示例中为 AuthenticatedGreetingTool)已添加到 AppModule 中的 providers 数组中。
客户端连接
如果启用了身份验证,客户端需要在连接时提供必要的凭据(例如,Authorization 标头)。
未验证的客户端
// client.ts (无身份验证)
import { Client } from '@modelcontextprotocol/sdk/client';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse';
const client = new Client(
{ name: 'client-name', version: '1.0.0' },
{ capabilities: {} }
);
await client.connect(
new SSEClientTransport(new URL('http://localhost:3000/sse'))
);
// ... 列出工具,调用工具等。
已验证的客户端
将请求选项(如标头)传递给 SSEClientTransport。
// client.ts (带身份验证)
import { Client } from '@modelcontextprotocol/sdk/client';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse';
const client = new Client(
{ name: 'client-name', version: '1.0.0' },
{ capabilities: {} }
);
const transport = new SSEClientTransport(
new URL('http://localhost:3000/sse'),
{
// 在此处提供必要的凭据
requestInit: {
headers: {
Authorization: 'Bearer your-secret-token' // 匹配 guard 期望
}
}
}
);
await client.connect(transport);
// 执行 'auth-hello-world' 工具
const greetResult = await client.callTool(
{
name: 'auth-hello-world',
arguments: {},
},
undefined, // responseSchema 是可选的
{
onprogress: (progress) => { // 示例进度处理程序
console.log(
`Progress: ${progress.progress}/${progress.total}`
);
},
},
);
console.log(greetResult.content[0].text); // 输出:Hello, user user-123!
API 端点
GET /sse:SSE 连接端点(如果已配置,则受 guard 保护)POST /messages:工具执行端点(如果已配置,则受 guard 保护)
配置参考
McpOptions
| 属性 | 类型 | 描述 | 默认值 |
|---|---|---|---|
name |
string | 服务器名称 | - |
version |
string | 服务器版本 | - |
capabilities |
Record<string, any> | 服务器功能,定义服务器可以做什么。 | {} |
guards |
any[] (NestJS Guards) |
要应用于 MCP 端点的 NestJS Guards 数组。 | [] |
sseEndpoint |
string (可选) | SSE 连接的端点。 | 'sse' |
messagesEndpoint |
string (可选) | 用于处理工具执行的端点。 | 'messages' |
globalApiPrefix |
string (可选) | 所有端点的全局 API 前缀。 | '' |
工具装饰器
@Tool 装饰器用于将方法定义为 MCP 工具。
@Tool({ name: string, description: string, parameters?: z.ZodObject<any> })
name:工具的名称。 这将用于在listTools请求中列出它。description:工具的描述。parameters:(可选)一个 Zod 模式,定义工具输入参数的预期结构。
上下文参数
传递给 @Tool 装饰方法的第二个参数是 Context 对象。
context.reportProgress(progress: Progress):向客户端发送进度更新消息。Progress通常具有{ progress: number, total: number }。
请求参数
传递给 @Tool 装饰方法的第三个参数是 Request 对象。
request:来自底层 HTTP 框架(例如,Express)的请求对象。 这可用于访问标头、查询参数等。
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。