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

链接

相关推荐
薛定谔的猫25 小时前
Cursor 系列(3):关于MCP
前端·cursor·mcp
王国强200910 小时前
Unla MCP 网关代理配置教程
mcp
kagg88612 小时前
mcp-gateway —— 隐藏mcp上下文以避免不必要的tokens开销
llm·mcp
AAA阿giao13 小时前
qoder-cli:下一代命令行 AI 编程代理——全面解析与深度实践指南
开发语言·前端·人工智能·ai编程·mcp·context7·qoder-cli
饭勺oO1 天前
AI 编程配置太头疼?ACP 帮你一键搞定,再也不用反复折腾!
ai·prompt·agent·acp·mcp·skills·agent skill
AlienZHOU1 天前
MCP 是最大骗局?Skills 才是救星?
agent·mcp·vibecoding
Linux内核拾遗1 天前
人人都在聊 MCP,它到底解决了什么?
aigc·ai编程·mcp
谷哥的小弟1 天前
SQLite MCP服务器安装以及客户端连接配置
服务器·数据库·人工智能·sqlite·大模型·源码·mcp
tyw152 天前
解决 Trae MySQL MCP 连接失败(Fail to start)
mcp·trae·fail to start·mysql mcp·mcp兼容
谷哥的小弟2 天前
File System MCP服务器安装以及客户端连接配置
服务器·人工智能·大模型·file system·mcp·ai项目