MCP.so
登录
返回博客

如何部署 MCP 服务器:远程托管完整指南(2026)

2026年10月15日MCP.so TeamMCP.so Team

如何部署 MCP 服务器并作为远程端点提供服务:Streamable HTTP 传输、符合规范的 OAuth 认证、Cloudflare Workers、容器与 Serverless 托管、扩容以及上线前的安全清单。

部署 MCP 服务器,就是让它通过 Streamable HTTP 传输在单个 HTTPS 端点上提供服务(通常是 /mcp),再托管到任意能运行 Web 处理函数的平台上,比如 Cloudflare Workers、任意云上的容器,或者 Serverless 函数。然后按 MCP 授权规范的要求,在它前面加上 OAuth Bearer Token 校验。在当前的 2026-07-28 规范下,协议是无状态的,所以部署好的服务器放在普通负载均衡器后面就能水平扩展。

本文假设你已经有一个能跑起来的服务器。如果还没有,可以先看构建 MCP 服务器(TypeScript)或 Python MCP 服务器指南。文中示例使用官方 SDK v2:@modelcontextprotocol/server 2.3.1 和 mcp 2.3.0。

服务器变成远程之后,有哪些变化

本地服务器是由某一个客户端通过 stdio 启动的子进程;远程服务器则是许多客户端共享的一个 URL。下面四件事就成了你的责任:

  1. 传输:Streamable HTTP。每条消息都是发往同一个端点的 HTTP POST,服务器用 JSON 或 SSE 流来响应。旧的双端点 HTTP+SSE 传输已经弃用,参见 MCP SSE 是否已被弃用。
  2. 认证:互联网上任何人都能访问这个 URL,所以必须有真正的访问控制。
  3. 托管与扩容:进程生命周期、超时、多实例。
  4. 加固:Host/Origin 校验、限流、日志以及密钥管理。

选择托管方式

方式适合注意
Cloudflare Workers(或 Deno/Bun)小型无状态服务器、全球边缘节点、有免费额度每个请求有 CPU/时长限制;除非开启,否则没有 Node API
容器(Cloud Run、ECS/Fargate、Fly.io、Kubernetes、虚拟机)任意语言、长时间运行的工具、私有网络镜像、TLS 和扩容配置都要自己管
Serverless 函数(AWS Lambda、Vercel、Netlify)流量波动大、按调用付费函数超时会切断长时间的流
托管式 MCP 平台需要认证、审计、注册表等网关功能的团队厂商锁定;可对比 MCP 网关与代理

新版规范没有会话,所以这四种方式的工作方式完全一样:请求进来,响应出去。选哪种取决于你的数据和依赖在哪里,而不是 MCP 本身。

一个具体示例:Cloudflare Workers

TypeScript SDK 的 createMcpHandler 返回一个 Web 标准的 fetch 处理函数,这正是 Worker 导出的形状。我们使用构建指南中的 createServer 工厂函数,用 wrangler dev(Wrangler 4.151)在本地测试了这套配置,不需要 nodejs_compat 标志。

src/worker.ts:

import {
  createMcpHandler,
  hostHeaderValidationResponse,
} from '@modelcontextprotocol/server';

import { createServer } from './server.js';

const handler = createMcpHandler(createServer);
const ALLOWED_HOSTS = [
  'npm-info-mcp.your-subdomain.workers.dev',
  'localhost',
  '127.0.0.1',
];

export default {
  async fetch(request: Request): Promise<Response> {
    if (new URL(request.url).pathname !== '/mcp')
      return new Response('Not found', { status: 404 });
    const rejected = hostHeaderValidationResponse(request, ALLOWED_HOSTS);
    return rejected ?? handler.fetch(request);
  },
};

wrangler.jsonc:

{
  "name": "npm-info-mcp",
  "main": "src/worker.ts",
  "compatibility_date": "2026-10-01"
}

运行并部署:

npm install -D wrangler
npx wrangler dev        # http://localhost:8787/mcp
npx wrangler deploy     # prints https://npm-info-mcp.<your-subdomain>.workers.dev

用 MCP Inspector 检查线上端点:

npx @modelcontextprotocol/inspector --cli https://npm-info-mcp.your-subdomain.workers.dev/mcp \
  --transport http --method tools/list

API 密钥用 npx wrangler secret put NAME 存储,绝不要写进代码。Cloudflare 在 Agents SDK 中也提供了自己的 MCP 工具,如果你需要基于 Durable Objects 的状态,它会很有用。

容器和其他运行时

在 Node 上,把同一个处理函数挂到 Express 上即可。使用 createMcpExpressApp 并显式设置 Host 白名单,因为绑定到 0.0.0.0 会关闭默认的仅限 localhost 保护:

import { createMcpExpressApp } from '@modelcontextprotocol/express';
import { toNodeHandler } from '@modelcontextprotocol/node';
import { createMcpHandler } from '@modelcontextprotocol/server';

import { createServer } from './server.js';

const app = createMcpExpressApp({
  host: '0.0.0.0',
  allowedHosts: ['mcp.example.com'],
});
const node = toNodeHandler(createMcpHandler(createServer));
app.all('/mcp', (req, res) => void node(req, res, req.body));
app.listen(Number(process.env.PORT ?? 3000), '0.0.0.0');

在 Python 中,构建带白名单的 ASGI 应用,再用任意 ASGI 服务器运行。如果没有白名单,真实域名后面的每个请求都会收到 421 Misdirected Request:

from mcp.server.transport_security import TransportSecuritySettings

app = mcp.streamable_http_app(
    transport_security=TransportSecuritySettings(allowed_hosts=["mcp.example.com", "mcp.example.com:*"])
)
# uvicorn server:app --host 0.0.0.0 --workers 4 --proxy-headers --forwarded-allow-ips='<proxy ip>'

如果 TLS 在负载均衡器处终止,--proxy-headers 可以避免重定向指向 http://。两种应用都可以用普通的 Dockerfile 打包,像其他 Web 服务一样部署。记得加一个健康检查路由(Python 中用 @mcp.custom_route("/health", methods=["GET"])),因为 SDK 本身不提供。

按规范添加认证

MCP 授权规范把你的服务器视为 OAuth 2.1 资源服务器:它负责校验 Token,而由独立的授权服务器(Auth0、Okta、Entra ID、Keycloak、WorkOS 等)签发 Token。流程如下:

  1. 没有有效 Token 的请求会收到 401,并带有 WWW-Authenticate: Bearer 响应头,指向你的 Protected Resource Metadata(受保护资源元数据) 文档(RFC 9728)。
  2. 该文档写明了你的授权服务器。客户端找到它、完成注册(2026-07-28 规范推荐 Client ID Metadata Documents,并弃用了动态客户端注册),用 PKCE 引导用户登录,然后带着 Token 重试。
  3. 你的服务器校验 Token,包括它的 audience(受众)。为其他资源签发的 Token 必须拒绝。

在 fetch 运行时上使用 TypeScript SDK,认证网关如下(verifyAccessToken 是你自己的 JWT 或内省校验):

import {
  createMcpHandler,
  requireBearerAuth,
} from '@modelcontextprotocol/server';

const mcpServerUrl = new URL('https://mcp.example.com/mcp');
const gate = requireBearerAuth({
  verifier: { verifyAccessToken },
  requiredScopes: ['mcp'],
  expectedResource: mcpServerUrl,
});
const handler = createMcpHandler(createServer);

export default {
  async fetch(request: Request): Promise<Response> {
    const auth = await gate(request);
    if (auth instanceof Response) return auth; // 401/403 with the WWW-Authenticate challenge
    return handler.fetch(request, { authInfo: auth });
  },
};

oauthMetadataResponse 负责提供 well-known 元数据文档,工具处理函数通过 ctx.http.authInfo 读取调用方信息。对于仅供机器访问的内部服务器,在请求头里放静态 API 密钥也可以接受,但要把它当作密钥对待并定期轮换。完整流程及图示见 MCP 认证与 OAuth。

扩容与状态

  • 新版客户端(2026-07-28) 发送的是自包含的请求:没有 initialize 握手,也没有 Mcp-Session-Id。任何实例都能处理任何请求,所以不需要粘性会话。
  • 旧版客户端(2025 年的修订版) 可能需要会话。TypeScript 处理函数默认以无状态方式服务它们(legacy: 'stateless')。在 Python 中,旧版会话保存在单个 worker 的内存里,所以要么开启粘性会话,要么使用 stateless_http=True 运行。
  • 需要跨调用保留的状态放进你自己的存储(数据库、KV、Redis),通过服务器下发、作为工具参数传递的 ID 来引用,而不是放在进程内存里。
  • 多轮往返工具(调用过程中向用户提问)会给客户端一个加密封装的 requestState。在 Python 中,要给每个实例相同的 RequestStateSecurity(keys=[...]) 和相同的服务器名称,否则落到其他 worker 上的重试会失败。
  • 变更通知(subscriptions/listen)是绑定在单个实例上的长连接流。用共享的 pub/sub 总线把事件分发到各个实例,并确认你的平台超时设置允许长时间的流。

上线前的安全清单

  • 只用 HTTPS,并校验 Host 和 Origin(使用上面的 SDK 辅助函数)。
  • 除健康检查和 OAuth 元数据文档外,所有路由都要求认证。校验 Token 的受众和过期时间。
  • 绝不要把客户端的 Token 透传给上游 API。使用你自己的凭据或 Token 交换。
  • 上游凭据遵循最小权限原则,并保存在密钥管理服务中。
  • 按用户和 IP 限流,并限制请求大小(Python SDK 默认把请求体上限设为 4 MiB)。
  • 清楚标记破坏性工具,对确实只读的工具使用只读注解。
  • 记录工具调用及调用方身份,但不要记录密钥或完整载荷。
  • 对照 MCP 安全最佳实践清单逐项检查,并用 Inspector 针对生产 URL 进行测试。

下一步

服务器上线后,在官方 MCP Registry 中把它的 URL 发布为 remotes 条目(类型为 streamable-http),并提交到 MCP.so,让用户能在 MCP 服务器目录中找到它。想参考运行良好的远程服务器,可以看看 Sentry 和 Notion 的官方服务器,或者阅读远程 MCP 服务器指南。

常见问题

如何部署 MCP 服务器?

让服务器通过 Streamable HTTP 传输在一个 HTTPS 端点(例如 /mcp)上提供服务,托管到 Cloudflare Workers、容器或 Serverless 函数上,并在前面加上 OAuth Bearer Token 校验。然后用 MCP Inspector 测试线上 URL。

可以免费部署 MCP 服务器吗?

可以。小型无状态服务器完全能放进 Cloudflare Workers 的免费额度,许多容器和 Serverless 平台也有免费额度。只有流量或 CPU 时间增长后才需要付费。

远程 MCP 服务器需要粘性会话吗?

对于使用 2026-07-28 规范的客户端不需要,因为每个请求都是自包含的,任何实例都能处理。2025 年的旧版客户端可能使用会话,可以用无状态方式服务它们,或者开启会话亲和。

如何保护已部署的 MCP 服务器?

使用 HTTPS,校验 Host 和 Origin 请求头,要求 OAuth Token 并检查其受众和过期时间。同时加上限流,把上游凭据存放在密钥管理服务中,绝不要把客户端的 Token 透传给其他 API。