使用nest-mcp-sse快速开发MCP Server

基于 MCP 官方提供的typescript-sdk,可以开发自己的 McpServer。

但是尽管使用 sdk,依然存在一些模板代码,以 SSE 类型的 Server 举例:

typescript 复制代码
const server = new McpServer({
  name: "some-server",
  version: "1.0.0",
});

const app = express();
const port = process.env.PORT || 3000;
const transports: { [sessionId: string]: SSEServerTransport } = {};

app.get("/sse", (req, res) => {
  res.setHeader("Content-Type", "text/event-stream");
  const transport = new SSEServerTransport("/messages", res);
  const sessionId = transport.sessionId;
  transports[sessionId] = transport;
  res.on("close", () => {
    delete transports[sessionId];
  });
  server.connect(transport);
});

app.post("/messages", async (req, res) => {
  const sessionId = req.query.sessionId as string;
  if (!sessionId) {
    return res.status(400).send("Missing sessionId query parameter");
  }
  const transport = transports[sessionId];
  if (!transport) {
    return res
      .status(404)
      .send(`No active transport found for sessionId: ${sessionId}`);
  }
  try {
    await transport.handlePostMessage(req, res);
  } catch (error) {
    if (!res.headersSent) {
      res.status(500).send("Error processing message");
    }
  }
});
app.listen(port);

每开发一个 MCP Server,就需要写上面的这些模板代码,比如

  • MCP Server 实例化
  • 连接 Transport
  • 生命周期管理
  • sse 和 message 接口处理函数

这些都属于杂事,我们开发 MCP Server 通常希望只聚焦于具体 tool 的开发。

所以我开发了 nest-mcp-sse,它是一个用于在 NestJS 工程下快速开发 SSE 传输类型 MCP Server 的动态模块,使用此模块,你可以只聚焦于 MCP tool 的开发。

没有过度封装🥳,只封装了上文所说的那些模板代码,没有对官方sdk的原生 MCP Server 实例的方法做任何封装,尽可能不增加额外学习成本。

功能特点

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

安装

bash 复制代码
pnpm install nest-mcp-sse @modelcontextprotocol/sdk

用法

1. 导入模块

在你的模块中导入 McpModule

typescript 复制代码
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的原生 McpServer 实例,这个实例没有任何封装,完全是原生的

比如,你可以注册工具

ts 复制代码
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"]).describe("时间格式: iso, locale") },
        async ({ format }: { format: "iso" | "locale" }) => {
          const now = new Date();
          let timeValue: string | number;
          switch (format) {
            case "iso":
              timeValue = now.toISOString();
              break;
            case "locale":
              timeValue = now.toLocaleString();
              break;
          }
          return {
            content: [{ type: "text", text: String(timeValue) }],
          };
        }
      );
  }
}

3. 手动注册服务器实例

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

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

typescript 复制代码
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 - 用于消息处理

链接

相关推荐
mCell17 小时前
MCP有了,Agents.md 又是什么?
ai编程·claude·mcp
大模型真好玩1 天前
大模型Agent开发框架哪家强?12项Agent开发框架入门与选型
人工智能·agent·mcp
魁首1 天前
MCP与ACP本质区别深度分析
claude·gemini·mcp
董厂长2 天前
SubAgent的“指令漂移 (Instruction Drift)“困境
人工智能·agent·mcp·subagent
魁首2 天前
初识 MCP (Model Context Protocol)
claude·gemini·mcp
minhuan2 天前
构建AI智能体:四十六、Codebuddy MCP 实践:用高德地图搭建旅游攻略系统
人工智能·mcp·codebuddy·高德api
wifi歪f2 天前
🎨 探究Function Calling 和 MCP 的奥秘
前端·ai编程·mcp
-D调定义之崽崽4 天前
【初学】调试 MCP Server
前端·mcp
AI产品自由4 天前
AI编程学习:Chrome DevTools MCP 到底有多强?
mcp
Blacol5 天前
【MCP】Caldav个人日程助手
人工智能·mcp