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

链接

相关推荐
小奏技术5 小时前
基于 Spring AI 和 MCP:用自然语言查询 RocketMQ 消息
后端·aigc·mcp
柒崽9 小时前
如何搭建一个MCP服务,然后在Cursor中调用,半小时,彻底掌握MCP
mcp
波点兔13 小时前
【亲测有效 | Cursor Pro每月500次快速请求扩5倍】(Windows版)Cursor中集成interactive-feedback-mcp
windows·mcp·cursor pro
CodeAgent15 小时前
【MCP 第二篇】实现一个简易的MCP
ai编程·mcp
lowcode15 小时前
MCP协议在LLM系统中的架构与实现原理研究
人工智能·llm·mcp
银空飞羽1 天前
再学学MCP间接提示词注入
安全·mcp·trae
黎燃1 天前
从底层逻辑看 MCP:智能计算的新引擎
mcp
一只爱撸猫的程序猿1 天前
构建一个简单智能客户服务系统的案例
spring boot·程序员·mcp
高冷的程序员大大1 天前
如何使用MCP开发一个客户端和服务端
程序员·mcp