NestJS MCP Server 是一个用于使用 NestJS 构建 Model Context Protocol (MCP) 服务器的模块化库。它提供了装饰器、模块和集成模式,以可扩展且易于维护的方式暴露 MCP 资源、工具和提示。此项目是官方 @modelcontextprotocol/sdk 的封装,并始终与它的类型和规范保持兼容。
npm install @nestjs-mcp/server @modelcontextprotocol/sdk zod
# 或
yarn add @nestjs-mcp/server @modelcontextprotocol/sdk zod
# 或
pnpm add @nestjs-mcp/server @modelcontextprotocol/sdk zod
在您的 NestJS 应用程序中注册 MCP 模块并暴露一个简单的工具:
import { Module } from '@nestjs/common';
import { CallToolResult } from '@modelcontextprotocol/sdk/types';
import { Resolver, Tool, McpModule } from '@nestjs-mcp/server';
@Resolver()
export class HealthResolver {
/**
* 简单的健康检查工具
*/
@Tool({ name: 'server_health_check' })
healthCheck(): CallToolResult {
return {
content: [
{
type: 'text',
text: '服务器运行正常。所有系统运行正常。',
},
],
};
}
}
@Module({
imports: [
McpModule.forRoot({
name: '我的 MCP 服务器',
version: '1.0.0',
}),
],
providers: [HealthResolver],
})
export class AppModule {}
Model Context Protocol (MCP) 是一种开放协议,用于连接 LLM 到外部数据、工具和提示。MCP 服务器以标准化方式暴露资源(数据)、工具(操作)和提示(对话流程),使与 LLM 驱动客户端的无缝集成成为可能。
MCP 服务器是向 LLM 暴露功能的主要入口点。它管理资源、工具和提示的注册和发现。
资源表示可以被 LLM 查询或检索的结构化数据或文档。资源通常是只读的,并通过唯一的 URI 来标识。
工具是一个可以由 LLM 调用的操作或函数。工具可能会有副作用,并可以接受参数来执行计算或触发操作。
提示定义了 LLM 的对话流程、模板或交互模式。提示有助于指导模型在特定场景中的行为。
参见 能力 部分了解实现细节和代码示例。
McpModule.forRoot在您的 NestJS 应用程序中全局注册 MCP 服务器。
参数:
options: McpModuleOptions — 主服务器配置对象:
name: string: 您的 MCP 服务器名称。version: string: 您的 MCP 服务器版本。instructions?: string: 可选的客户端 MCP 服务器描述。capabilities?: Record<string, unknown>: 可选的附加功能元数据。providers?: Provider[]: 可选的要包含在模块中的 NestJS 提供者数组。imports?: any[]: 可选的要导入的 NestJS 模块数组。logging?: McpLoggingOptions: 可选的日志配置:
enabled?: boolean(默认值:true):启用/禁用日志记录。level?: 'error' | 'warn' | 'log' | 'debug' | 'verbose'(默认值:'verbose'):设置日志级别。transports?: McpModuleTransportOptions: 可选的传输配置(参见 传输选项)。protocolOptions?: Record<string, unknown>: 直接传递给底层 @modelcontextprotocol/sdk 服务器实例的其他参数。返回:
示例:
import { Module } from '@nestjs/common';
import { McpModule } from '@nestjs-mcp/server';
@Module({
imports: [
McpModule.forRoot({
name: '我的服务器',
version: '1.0.0',
instructions: '提供实用工具和数据的服务器。',
logging: { level: 'log' },
transports: { sse: { enabled: false } }, // 禁用 SSE 传输
// ...其他 MCP 选项
}),
],
})
export class AppModule {}
McpModule.forRootAsync使用异步选项全局注册 MCP 服务器,适用于与配置模块(如 @nestjs/config)集成。
注意:
imports数组应包括提供useFactory所需依赖项的任何模块(例如,如果您注入ConfigService,则为ConfigModule)。- 只在根模块(
AppModule)中使用一次forRootAsync。- 查看
McpModuleAsyncOptions以获取所有可用选项。
参数:
options: McpModuleAsyncOptions — 异步配置对象:
imports?: any[]: 在工厂运行之前导入的可选模块。useFactory: (...args: any[]) => Promise<McpModuleOptions> | McpModuleOptions: 返回 McpModuleOptions 的工厂函数。inject?: any[]: 注入到 useFactory 的可选提供者。返回:
示例(与 ConfigModule 结合使用):
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { McpModule } from '@nestjs-mcp/server';
@Module({
imports: [
ConfigModule.forRoot(), // 确保导入 ConfigModule
McpModule.forRootAsync({
imports: [ConfigModule], // 在这里也导入 ConfigModule
useFactory: (configService: ConfigService) => ({
name: configService.get<string>('MCP_SERVER_NAME', '默认服务器'),
version: configService.get<string>('MCP_SERVER_VERSION', '1.0.0'),
instructions: configService.get<string>('MCP_SERVER_DESC'),
logging: {
level: configService.get('MCP_LOG_LEVEL', 'verbose'),
},
// ...来自 configService 的其他选项
}),
inject: [ConfigService], // 将 ConfigService 注入到工厂
}),
],
})
export class AppModule {}
McpModule.forFeature在特性模块中注册额外的 MCP 资源、工具或提示。使用此功能将大型服务器组织成多个模块。包含 MCP 功能的解析器必须包含在特性模块的 providers 数组中。
参数:
options?: McpFeatureOptions(目前未使用,保留用于未来增强)。返回:
示例:
// src/status/status.resolver.ts
import { Resolver, Tool } from '@nestjs-mcp/server';
import { CallToolResult } from '@modelcontextprotocol/sdk/types';
@Resolver('status')
export class StatusResolver {
@Tool({ name: 'health_check' })
healthCheck(): CallToolResult {
return { content: [{ type: 'text', text: 'OK' }] };
}
}
// src/status/status.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@nestjs-mcp/server';
import { StatusResolver } from './status.resolver';
@Module({
imports: [McpModule.forFeature()], // 在这里导入 forFeature
providers: [StatusResolver], // 注册您的解析器
})
export class StatusModule {}
此库提供了两种主要方式在您的 NestJS 应用程序中注册 MCP 功能:
McpModule.forRoot 进行全局注册在您的根应用程序模块中使用 McpModule.forRoot 来配置和注册 MCP 服务器。这是每个 MCP 服务器应用程序所必需的。
import { Module } from '@nestjs/common';
import { McpModule } from '@nestjs-mcp/server';
import { PromptsResolver } from './prompts.resolver';
@Module({
imports: [
McpModule.forRoot({
name: '我的 MCP 服务器',
version: '1.0.0',
// ...其他 MCP 选项
}),
],
providers: [PromptsResolver],
})
export class AppModule {}
McpModule.forFeature 注册特性模块在特性模块中使用 McpModule.forFeature 注册额外的解析器、工具或资源。这对于将大型服务器组织成多个模块非常有用。
import { Module } from '@nestjs/common';
import { McpModule } from '@nestjs-mcp/server';
import { ToolsResolver } from './tools.resolver';
@Module({
imports: [McpModule.forFeature()],
providers: [ToolsResolver],
})
export class ToolsModule {}
AppModule)中使用一次 forRoot 或 forRootAsync。@Resolver 类)的任何特性模块中使用 forFeature。providers 数组中。此库提供了一组装饰器来定义 MCP 功能并应用横切关注点,如守卫。装饰器可以在解析器(类)级别和方法级别使用。
解析器是一个将相关 MCP 功能分组的类。所有 MCP 功能方法(@Prompt、@Resource、@Tool)必须属于一个用 @Resolver 装饰的类。
@Injectable(): 解析器类由 MCP 模块自动视为提供者,并且不需要 @Injectable() 装饰器。@Resolver('my_namespace') 以在该解析器内命名空间这些功能。@UseGuards() 在类级别应用守卫。示例:
import { Resolver, Prompt, Resource, Tool } from '@nestjs-mcp/server';
// 导入您需要注入的服务
import { SomeService } from '../some.service';
@Resolver('workspace') // 不需要 @Injectable()
export class MyResolver {
// 如常注入依赖
constructor(private readonly someService: SomeService) {}
@Prompt({ name: 'greet_user' }) // 功能必须在解析器内
greetPrompt(/*...args...*/) {
const greeting = this.someService.getGreeting();
/* ... */
}
@Resource({ name: 'user_profile', uri: 'user://{id}' })
getUserResource(/*...args...*/) {
/* ... */
}
@Tool({ name: 'calculate_sum' })
sumTool(/*...args...*/) {
/* ... */
}
}
您还可以在解析器级别应用守卫:
import { UseGuards, Resolver } from '@nestjs-mcp/server';
import { MyGuard } from './guards/my.guard';
@UseGuards(MyGuard) // 应用于此解析器内的所有功能
@Resolver('secure') // 不需要 @Injectable()
export class SecureResolver {
// 此解析器内的所有功能都将使用 MyGuard
}
在解析器类的方法上使用装饰器以将其暴露为 MCP 提示。接受与 @modelcontextprotocol/sdk 中的 server.prompt() 兼容的选项。name 应使用 snake_case。
import { Prompt, Resolver } from '@nestjs-mcp/server';
import { RequestHandlerExtra } from '@nestjs-mcp/server'; // 导入额外信息类型
import { z } from 'zod'; // 示例如果使用 Zod 模式
// 可选:如果需要定义模式
// const SummaryArgs = z.object({ topic: z.string() });
@Resolver('prompts') // 必须在解析器类内
export class MyPrompts {
@Prompt({
name: 'generate_summary',
description: '为给定的文本生成摘要。',
// argsSchema: SummaryArgs
})
generateSummaryPrompt(
// params: z.infer<typeof SummaryArgs>, // 基于 argsSchema(如果有定义)的参数
extra: RequestHandlerExtra, // 包含 sessionId 和其他元数据
) {
console.log(`为会话生成摘要:${extra.sessionId}`);
/* ... 返回 CallPromptResult ... */
return { content: [{ type: 'text', text: '摘要已生成。' }] };
}
}
在解析器类的方法上使用装饰器以将其暴露为 MCP 资源。接受与 @modelcontextprotocol/sdk 中的 server.resource() 兼容的选项。name 应使用 snake_case。
import { Resource, Resolver } from '@nestjs-mcp/server';
import { RequestHandlerExtra } from '@nestjs-mcp/server'; // 导入额外信息类型
import { URL } from 'url'; // 资源 URI 类型
import { z } from 'zod'; // 示例如果使用 Zod 模板
// 可选:如果需要定义模板模式
// const DocQueryTemplate = z.object({ query: z.string() });
@Resolver('data') // 必须在解析器类内
export class MyResources {
@Resource({
name: 'user_profile',
uri: 'user://profiles/{userId}',
// metadata: