使用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 小时前
Nest 项目小实践之图书展示和搜索
前端·node.js·nestjs
over6971 天前
从 LLM 到全栈 Agent:MCP 协议 × RAG 技术如何重构 AI 的“做事能力”
面试·llm·mcp
用户12039112947261 天前
从MCP到RAG:Agent的开发之路
agent·mcp
用户8307196840821 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
前端付豪1 天前
Nest 项目小实践之前端注册登陆
前端·node.js·nestjs
栀秋6661 天前
重塑 AI 交互边界:基于 LangChain 与 MCP 协议的全栈实践
langchain·llm·mcp
神秘的猪头2 天前
🔌 给 AI 装上“三头六臂”!实战大模型接入第三方 MCP 全攻略
langchain·llm·mcp
神秘的猪头3 天前
🔌 把 MCP 装进大脑!手把手带你构建能“热插拔”工具的 AI Agent
langchain·llm·mcp
小兵张健3 天前
AI 页面与交互迁移流程参考
前端·ai编程·mcp
小兵张健3 天前
掘金发布 SOP(Codex + Playwright MCP + Edge)
前端·mcp