AIHero
    05 / 06Model Context Protocol 教程 · 阅读约 2 分钟

    MCP 的问题:有状态服务器

    了解如何借助 Redis 以无状态方式部署 MCP 服务器,使其兼容 Vercel、AWS Lambda 等无服务器平台。

    Matt Pocock
    Matt Pocock
    源代码下一课
    本页目录

    上一篇示例中,我们创建了一个可以通过 HTTP 提供服务的简单 MCP Server。

    但它存在一些缺点.

    一次只能连接一个 Client

    最明显的问题是 它一次只能服务一个 Client。它把当前 Transport 保存在单个变量中:

    import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
    import express from "express";
    // The transport variable
    let transport: SSEServerTransport | undefined =
    undefined;
    const app = express();
    app.get("/sse", async (req, res) => {
    transport = new SSEServerTransport("/messages", res);
    await server.connect(transport);
    });

    这意味着,如果 第二个 Client 建立连接,第一个 Client 就会断开.

    有状态 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 保存?

    我会在后续文章中继续探讨。

    登录以保存进度。