nest

内容来源:README.md(说明文档) · 原始地址 · 查看安装指南

原始内容

nest-mcp-sse

这是一个用于在 NestJS 工程下快速开发 SSE 传输类型 McpServer 的动态模块,使用此模块,你将无需理会连接 Transport、生命周期管理、McpServer 实例化等杂事,聚焦于 MCP tool 的开发。

此模块没有过度封装🥳

只做了 MCP Server 实例管理和 SSE Transport 管理,没有对官方 sdk 的原生 MCP Server 的方法做任何封装,尽可能不增加学习成本。

功能特点

  • 快速在 NestJS 应用中创建 MCP 服务器
  • 支持多个 MCP Server 实例管理
  • 自动处理 SSE 连接生命周期

安装

# npm
npm install nest-mcp-sse @modelcontextprotocol/sdk zod

# yarn
yarn add nest-mcp-sse @modelcontextprotocol/sdk zod

# pnpm
pnpm add nest-mcp-sse @modelcontextprotocol/sdk zod

用法

1. 导入模块

在你的模块中导入 McpModule

import { Module } from "@nestjs/common";
import { McpModule } from "nest-mcp-sse";

@Module({
  imports: [
    McpModule.register({
      controllerBaseUrl: "api/mcp",
      mcpServerConfigs: [
        {
          serverId: "my-mcp-server",
          serverInfo: {
            name: "my-mcp-server",
            version: "1.0.0",
          },
        },
      ],
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

另外,你也可以通过forRootforFeature导入模块,区别如下:

  • forRoot:通常在根模块注册
  • forFeature:和 forRoot 注册的模块共享 Service 实例
  • register:用一次注册一次,不和任何模块共享

2. 操作 McpServer

创建 MCP Server 之后,你可以通过getServer方法获取到官方 sdk 的原生 MCP Server 实例,这个实例没有任何封装,完全是原生的。

比如,你可以注册工具

import { Controller } from "@nestjs/common";
import { McpServerService } from "nest-mcp-sse";
import { z } from "zod";

@Controller()
export class AppController {
  constructor(private readonly mcpServerService: McpServerService) {
    this.mcpServerService.getServer("server-id")?.tool(
      "get-current-time",
      {
        format: z
          .enum(["iso", "locale", "unix"])
          .optional()
          .default("iso")
          .describe("时间格式: iso, locale, 或 unix"),
      },
      async ({ format }: { format: "iso" | "locale" | "unix" }) => {
        const now = new Date();
        let timeValue: string | number;

        switch (format) {
          case "iso":
            timeValue = now.toISOString();
            break;
          case "locale":
            timeValue = now.toLocaleString();
            break;
          case "unix":
            timeValue = now.getTime();
            break;
          default:
            timeValue = now.toISOString();
        }

        return {
          content: [{ type: "text", text: String(timeValue) }],
        };
      }
    );
  }
}

3. 手动注册服务器实例

上面的例子直接在McpModule.register中传入了mcpServerConfigs,这会在模块初始化时就创建 MCP Server。

当然这不是必需的,你可以不传入mcpServerConfigs,在 Controller 或 Service 中手动注册 MCP Server:

import { Controller } from "@nestjs/common";
import { McpServerService } from "nest-mcp-sse";
import { z } from "zod";

@Controller()
export class AppController {
  constructor(private readonly mcpServerService: McpServerService) {
    // 手动注册一个MCP Server实例
    this.mcpServerService.registerServer({
      serverId: "another-server",
      serverInfo: {
        name: "another-mcp-server",
        version: "1.0.0",
      },
    });
  }
}

服务器访问端点

注册模块后,将自动创建以下端点:

  • SSE 连接端点: /{controllerBaseUrl}/{serverId}/sse
  • 消息处理端点: /{controllerBaseUrl}/{serverId}/messages

例如,如果你使用 controllerBaseUrl: 'api/mcp'serverId: 'my-mcp-server',则访问 URL 为:

  • http://localhost:3000/api/mcp/my-mcp-server/sse - 用于 SSE 连接
  • http://localhost:3000/api/mcp/my-mcp-server/messages - 用于消息处理

API

McpModule.register

  • controllerBaseUrl:MCP Controller 的基本 URL 路径
  • sseEndpoint:SSE 连接端点名称,默认为 sse
  • messagesEndpoint:消息处理端点名称,默认为 messages
  • mcpServerConfigs

forRoot 同 register,forFeature 只接收 mcpServerConfigs

McpServerService

McpModule 导出的 Service,用于管理多个 McpServer 实例。

你可以注入到你的 Controller 或 Service 中,使用以下方法:

registerServer

  • 作用:注册一个 McpServer 实例
  • 参数:同McpModule.forRootmcpServerConfigs
  • 返回值:注册的 McpServer 实例

getServer

  • 作用:获取指定 McpServer 实例
  • 参数:serverId
  • 返回值:McpServer 实例

getServerIds

  • 作用:获取所有已注册的 McpServer 实例 id
  • 返回值:string[] 所有已注册的 McpServer 实例 id 数组

hasServer

  • 作用:判断是否已注册指定 McpServer 实例
  • 参数:serverId
  • 返回值:boolean

connect

  • 作用:连接 McpServer 到传输层,一般不需要使用,除非你希望手动管理连接。
  • 参数:
    • serverId
    • transport,Transport 实例
  • 返回值:void

McpTransportService

McpModule 导出的 Service,用于管理多个 SSEServerTransport 实例。

通常不需要使用,除非你希望手动管理连接。

以下仅列出可能使用到的方法,更多方法请参阅源码

getTransport

  • 作用:获取特定传输连接
  • 参数:serverId,sessionId
  • 返回值:SSEServerTransport 实例

getActiveSessionIds

  • 作用:获取 McpServer 的所有活跃会话 ID
  • 参数:serverId
  • 返回值:string[] 所有活跃会话 ID 数组

高级配置

自定义端点名称

你可以在模块注册时自定义 SSE 和消息端点名称:

McpModule.register({
  controllerBaseUrl: "api/mcp",
  sseEndpoint: "connect", // 默认为 'sse'
  messagesEndpoint: "rpc", // 默认为 'messages'
  mcpServerConfigs: [
    /* ... */
  ],
});

示例代码

你可以 clone 该仓库,按以下步骤运行示例代码

pnpm install

cd example

pnpm install

pnpm start