使用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 - 用于消息处理

链接

相关推荐
Allshadow20 小时前
Nest.js - 目录结构
javascript·nestjs
MicrosoftReactor1 天前
技术速递|智能体构建智能体:基于 Microsoft Agent Framework 与 Foundry 的 Skill 优先架构蓝图
ai·架构·agent·智能体·mcp
南一Nanyi2 天前
依赖注入和控制反转
前端·设计模式·nestjs
牧艺2 天前
从 Tool Calling 到 MCP Server:把业务能力做成 Agent 可复用接口
agent·全栈·mcp
凡泰AI2 天前
如何借助MCP打通企业APP内部服务:从统一调用到小程序承接
小程序·uni-app·app·mpaas·mcp·小程序容器
小四的小六3 天前
MCP Client实战翻车记:两个Server同时跑,AI调错了Tool
openai·ai编程·mcp
在水一缸3 天前
当 AI 拥有了“核按钮”:深入解析 MCP 服务器与命令执行护栏
运维·服务器·人工智能·命令执行·智能体·ai安全·mcp
晓得迷路了3 天前
栗子前端技术周刊第 138 期 - NestJS 12、Astro 7.1、npm 12...
前端·javascript·nestjs
wMoqi4 天前
trae cn 中ai开发配置skill mcp 规则参考(yudao-cloud项目-个人用)
ai·skill·yudao·mcp·trae