本页目录
在 上一篇示例中,我们创建了一个可以通过 HTTP 提供服务的简单 MCP Server。
但它存在一些缺点.
一次只能连接一个 Client
最明显的问题是 它一次只能服务一个 Client。它把当前 Transport 保存在单个变量中:
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";import express from "express";// The transport variablelet transport: SSEServerTransport | undefined =undefined;const app = express();app.get("/sse", async (req, res) => {transport = new SSEServerTransport("/messages", res);await server.connect(transport);});
这意味着,如果 第二个 Client 建立连接,第一个 Client 就会断开.
想继续深入: 加入“面向真正工程师的 AI 编码”候补名单
有状态 Server
假设我们修复了这个问题:不再把 Transport 存进单个变量,而是按 id 保存,以便稍后取回。
即使这样做,仍然存在一个问题。
这种方式需要有状态 Server。 我们必须在内存中跟踪各个 Transport。一旦 Server 进程退出,这些 Transport 就会丢失。
这会限制 Server 的部署方式。 Vercel 或 AWS Lambda 之类的 serverless 环境无法使用 ——它们会在两次请求之间清除内存中的状态。
必须把它部署到 长期运行的服务器,例如 VPS。
把状态存入 Redis
更好的方式是 把状态存入数据库,例如使用 Redis 这样的键值存储。
现在 Transport 信息存储在 Redis 中, Server 就可以变为无状态,从而能够部署到 serverless 环境。
Vercel 示例
这正是 mcp-on-vercel 采用的方案。我建议 查看 他们的仓库 以了解更多信息。
虽然该仓库针对 Vercel 设计,但它 可以调整后适配任何 serverless 平台.
总结
MCP Server 本质上是 有状态 有状态的。不过,把状态存入数据库后,就能将其部署到 serverless 环境。
这是我推荐的 MCP Server 生产部署方案。
不过,这也引出了一个问题:是否可以从协议设计上让服务变成 无状态?
必须接入键值存储似乎带来了不必要的额外开销。状态是否可以改由 Client 保存?
我会在后续文章中继续探讨。