[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-mcp-shengchan-huanjing-transport-auth-kuozhan-tiaozhan":3},{"article":4,"author":55},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":35,"related_articles":36},"d0000000-0000-0000-0000-000000000505","a0000000-0000-0000-0000-000000000036","MCP 在生产环境中：解决 Transport、Auth 和扩展挑战","mcp-shengchan-huanjing-transport-auth-kuozhan-tiaozhan","深入探讨在生产环境中运行 Model Context Protocol 服务器——传输选择、身份验证模式、扩展策略、审计日志和企业部署的网关架构。","## 从原型到生产：有什么变化\n\n构建一个在笔记本电脑上运行的 MCP server 很简单。运行一个能处理数千个并发 AI agent 会话的分布式基础设施则是完全不同的工程挑战。生产 MCP 部署必须解决五个原型可以忽略的问题：**transport 可扩展性**、**身份验证和授权**、**大规模会话管理**、**审计跟踪**和**多服务器编排**。\n\n本文是一份技术指南，面向将 MCP server 从开发环境迁移到生产环境的工程团队。我们假设您已构建过至少一个 MCP server 并了解协议基础。如果没有，请先阅读我们关于构建第一个 MCP server 的配套文章。\n\n## Transport 可扩展性：stdio vs SSE vs Streamable HTTP\n\nMCP 定义了三种传输机制。为生产环境选择正确的传输是您的第一个架构决策。\n\n### stdio Transport\n\nstdio transport 通过标准输入\u002F输出流进行通信。Host 应用程序将 MCP server 作为子进程启动，并通过 stdin\u002Fstdout 交换 JSON-RPC 消息。\n\n**优势：**\n- 零网络配置\n- 进程级隔离\n- 无端口冲突\n- 最低延迟（无网络堆栈）\n\n**局限性：**\n- Server 必须与 host 在同一台机器上运行\n- 每个 client 会话一个 server 进程\n- 无法进行负载均衡\n- 无水平扩展\n\n**最适合：** 本地开发工具、IDE 扩展、单用户桌面应用程序。\n\n### SSE (Server-Sent Events) Transport\n\nSSE transport 使用 HTTP 进行 client 到 server 的消息传递，使用 Server-Sent Events 进行 server 到 client 的消息传递。Server 作为 HTTP 服务运行。\n\n**优势：**\n- 可通过网络访问（远程服务器）\n- 与现有 HTTP 基础设施兼容\n- 支持多个并发 client\n- 可穿越防火墙和代理\n\n**局限性：**\n- 单向流（仅 server 到 client 通过 SSE）\n- 需要会话亲和性（有状态连接）\n- 某些负载均衡器在处理长连接 SSE 时有困难\n- 协议中没有内置的重连语义\n\n**最适合：** 中小型部署、内部工具、拥有现有 HTTP 基础设施的团队。\n\n### Streamable HTTP Transport\n\nStreamable HTTP 是最新的 transport，专为生产部署设计。它对所有消息使用标准 HTTP POST，对长时间运行的操作使用可选的 SSE 流。\n\n**优势：**\n- 完全无状态的请求\u002F响应模型\n- 与任何 HTTP 负载均衡器兼容\n- 通过 `Mcp-Session-Id` 头内置会话管理\n- 支持流式和非流式响应\n- CDN 和代理兼容\n\n**局限性：**\n- 需要服务器端会话存储（Redis、数据库）\n- 每消息开销略高于 stdio\n- 较新的 transport——生态系统工具较少\n\n**最适合：** 生产云部署、多租户平台、企业环境。\n\n### Transport 比较矩阵\n\n| 特性 | stdio | SSE | Streamable HTTP |\n|------|-------|-----|-----------------|\n| 网络访问 | 仅本地 | 远程 | 远程 |\n| 负载均衡 | 不可能 | Session-sticky | 标准 HTTP LB |\n| 水平扩展 | 否 | 有限 | 是 |\n| 防火墙友好 | N\u002FA | 是 | 是 |\n| 重连 | N\u002FA | 手动 | 内置 |\n| 并发 client | 1 | 多个 | 多个 |\n| 延迟 | 最低 | 低 | 低 |\n| 无状态性 | 有状态 | 有状态 | 可无状态 |\n| 生产就绪度 | 仅开发 | 中等 | 高 |\n\n## 身份验证：SSO 集成、API Key 和 OAuth\n\n生产中的 MCP server 必须同时验证 AI host 应用程序和代表其行事的最终用户的身份。\n\n### 远程服务器的 OAuth 2.0\n\nMCP 规范包含用于远程（基于 HTTP）服务器的内置 OAuth 2.0 流程：\n\n1. MCP client 发送不带凭据的 `initialize` 请求。\n2. Server 响应 HTTP 401 和指向 OAuth 授权端点的 `WWW-Authenticate` 头。\n3. Host 应用程序打开浏览器进行用户身份验证。\n4. 身份验证成功后，host 收到 access token。\n5. 后续 MCP 请求在 `Authorization: Bearer` 头中包含 token。\n\n```typescript\nimport { McpServer } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fmcp.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002FstreamableHttp.js\";\nimport express from \"express\";\n\nconst app = express();\n\napp.use(\"\u002Fmcp\", async (req, res, next) => {\n  const token = req.headers.authorization?.replace(\"Bearer \", \"\");\n  if (!token) {\n    res.status(401).json({\n      error: \"unauthorized\",\n      oauth_url: \"https:\u002F\u002Fauth.example.com\u002Foauth\u002Fauthorize\",\n    });\n    return;\n  }\n  const user = await validateToken(token);\n  if (!user) {\n    res.status(403).json({ error: \"invalid_token\" });\n    return;\n  }\n  req.mcpUser = user;\n  next();\n});\n```\n\n### API Key 身份验证\n\n对于服务间 MCP 通信（无人类用户参与），API key 更为简单：\n\n```typescript\nconst API_KEYS = new Map([\n  [\"sk-prod-abc123\", { name: \"analytics-service\", scopes: [\"read\"] }],\n  [\"sk-prod-def456\", { name: \"admin-service\", scopes: [\"read\", \"write\"] }],\n]);\n\nfunction authenticateApiKey(key: string) {\n  return API_KEYS.get(key) || null;\n}\n```\n\n### SSO 集成模式\n\n对于企业部署，与现有 SSO（SAML、OIDC）集成：\n\n```\nUser -> AI Host -> MCP Client -> MCP Server -> SSO Provider\n                                      |\n                                      v\n                              验证 OIDC token\n                              提取用户角色\n                              应用工具级 RBAC\n```\n\n每个 MCP tool 可以在执行前检查已验证用户的角色：\n\n```typescript\nserver.tool(\n  \"delete_record\",\n  \"按 ID 删除数据库记录\",\n  { table: z.string(), id: z.string() },\n  async ({ table, id }, { authContext }) => {\n    if (!authContext.roles.includes(\"admin\")) {\n      return {\n        content: [{ type: \"text\", text: \"禁止：需要管理员角色\" }],\n        isError: true,\n      };\n    }\n    \u002F\u002F 继续删除操作\n  }\n);\n```\n\n## 扩展：有状态会话 vs 负载均衡器\n\nMCP 会话本质上是有状态的：`initialize` 握手协商能力，服务器可能在会话内的工具调用之间维护上下文。这与水平扩展之间存在矛盾。\n\n### 会话存储架构\n\n将会话状态从服务器进程提取到外部存储：\n\n```typescript\ninterface McpSession {\n  id: string;\n  userId: string;\n  capabilities: ServerCapabilities;\n  createdAt: Date;\n  lastActivityAt: Date;\n  metadata: Record\u003Cstring, unknown>;\n}\n\nclass RedisSessionStore {\n  constructor(private redis: Redis) {}\n\n  async create(session: McpSession): Promise\u003Cvoid> {\n    await this.redis.set(\n      `mcp:session:${session.id}`,\n      JSON.stringify(session),\n      \"EX\", 3600\n    );\n  }\n\n  async get(sessionId: string): Promise\u003CMcpSession | null> {\n    const data = await this.redis.get(`mcp:session:${sessionId}`);\n    return data ? JSON.parse(data) : null;\n  }\n}\n```\n\n### 使用 Streamable HTTP 进行水平扩展\n\n通过外部化会话和 Streamable HTTP transport，您可以在标准负载均衡器后运行多个 MCP server 实例。无需 session-sticky 路由。任何服务器实例都可以通过从 Redis 加载会话来处理任何请求。\n\n### Auto-Scaling 配置\n\nMCP server 的 Kubernetes HPA 示例：\n\n```yaml\napiVersion: autoscaling\u002Fv2\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: mcp-server\nspec:\n  scaleTargetRef:\n    apiVersion: apps\u002Fv1\n    kind: Deployment\n    name: mcp-server\n  minReplicas: 2\n  maxReplicas: 20\n  metrics:\n    - type: Resource\n      resource:\n        name: cpu\n        target:\n          type: Utilization\n          averageUtilization: 70\n    - type: Pods\n      pods:\n        metric:\n          name: mcp_active_sessions\n        target:\n          type: AverageValue\n          averageValue: \"100\"\n```\n\n## 审计跟踪和日志记录\n\n生产中的每个 MCP tool 调用都必须记录，以用于安全、合规和调试。\n\n### 结构化日志 Schema\n\n```typescript\ninterface McpAuditLog {\n  timestamp: string;\n  sessionId: string;\n  userId: string;\n  toolName: string;\n  toolInput: Record\u003Cstring, unknown>;\n  toolOutput: string;\n  durationMs: number;\n  success: boolean;\n  errorMessage?: string;\n  ipAddress: string;\n  userAgent: string;\n}\n```\n\n### 合规性考虑\n\n| 要求 | 实现 |\n|------|------|\n| GDPR 数据访问 | 记录 AI 通过 MCP tools 访问了哪些用户数据 |\n| SOC 2 审计跟踪 | 带时间戳的所有工具调用不可变日志 |\n| PII 保护 | 在日志记录前编辑工具输入中的敏感字段 |\n| 数据保留 | 设置符合合规要求的日志 TTL |\n| 访问审查 | 记录身份验证事件和权限检查 |\n\n## 多服务器部署的 Gateway 模式\n\n企业环境通常需要数十个 MCP server——每个内部系统一个。**MCP Gateway** 集中管理：\n\nGateway 提供：\n\n1. **统一身份验证**：所有后端服务器一个认证流程。\n2. **工具命名空间路由**：工具以服务器名称为前缀（`jira.create_issue`、`slack.send_message`）。\n3. **集中式速率限制**：按用户、按工具和按服务器的限制。\n4. **请求路由**：将工具调用路由到相应的后端服务器。\n5. **熔断器**：如果后端服务器不健康，gateway 返回优雅的错误而非挂起。\n\n## 常见问题\n\n**问：在生产中应该使用 stdio 还是 HTTP transport？**\n答：对于需要扩展到单台机器以外的任何部署，使用 Streamable HTTP。仅在 AI host 和 MCP server 在同一台机器上运行的本地桌面集成中使用 stdio。\n\n**问：一个 MCP server 可以处理多少并发会话？**\n答：使用 Streamable HTTP 和外部化会话，单个 Node.js 服务器实例通常处理 500-1,000 个并发会话。使用 Rust 或 Go 服务器，可实现 5,000-10,000 个。超出此范围时进行水平扩展。\n\n**问：如何处理 MCP server 停机？**\n答：实现健康检查（`\u002Fhealth` 端点），使用 Kubernetes 存活\u002F就绪探针，并为 gateway 配置熔断器。MCP client 将收到连接错误，AI host 可将其呈现为\"工具暂时不可用\"。\n\n**问：MCP server 可以调用其他 MCP server 吗？**\n答：可以。MCP server 也可以是 MCP client，形成链式调用。这是 agent 间通信的基础。谨慎使用此模式——深层链增加延迟和故障概率。\n\n**问：如何管理 MCP server API 版本？**\n答：使用 `initialize` 响应中的服务器版本字段。对于破坏性更改（删除工具、更改 schema），升级主版本号并在迁移期间同时支持新旧版本。\n\n**问：MCP 消息的最大大小是多少？**\n答：协议本身没有定义最大值，但实际限制取决于 transport 和基础设施。对于 Streamable HTTP，将响应保持在 10 MB 以下。对于 stdio，系统管道缓冲区（通常 64 KB）可能需要对大型响应进行分块。","\u003Ch2 id=\"\">从原型到生产：有什么变化\u003C\u002Fh2>\n\u003Cp>构建一个在笔记本电脑上运行的 MCP server 很简单。运行一个能处理数千个并发 AI agent 会话的分布式基础设施则是完全不同的工程挑战。生产 MCP 部署必须解决五个原型可以忽略的问题：\u003Cstrong>transport 可扩展性\u003C\u002Fstrong>、\u003Cstrong>身份验证和授权\u003C\u002Fstrong>、\u003Cstrong>大规模会话管理\u003C\u002Fstrong>、\u003Cstrong>审计跟踪\u003C\u002Fstrong>和\u003Cstrong>多服务器编排\u003C\u002Fstrong>。\u003C\u002Fp>\n\u003Cp>本文是一份技术指南，面向将 MCP server 从开发环境迁移到生产环境的工程团队。我们假设您已构建过至少一个 MCP server 并了解协议基础。如果没有，请先阅读我们关于构建第一个 MCP server 的配套文章。\u003C\u002Fp>\n\u003Ch2 id=\"transport-stdio-vs-sse-vs-streamable-http\">Transport 可扩展性：stdio vs SSE vs Streamable HTTP\u003C\u002Fh2>\n\u003Cp>MCP 定义了三种传输机制。为生产环境选择正确的传输是您的第一个架构决策。\u003C\u002Fp>\n\u003Ch3>stdio Transport\u003C\u002Fh3>\n\u003Cp>stdio transport 通过标准输入\u002F输出流进行通信。Host 应用程序将 MCP server 作为子进程启动，并通过 stdin\u002Fstdout 交换 JSON-RPC 消息。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>优势：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>零网络配置\u003C\u002Fli>\n\u003Cli>进程级隔离\u003C\u002Fli>\n\u003Cli>无端口冲突\u003C\u002Fli>\n\u003Cli>最低延迟（无网络堆栈）\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>局限性：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Server 必须与 host 在同一台机器上运行\u003C\u002Fli>\n\u003Cli>每个 client 会话一个 server 进程\u003C\u002Fli>\n\u003Cli>无法进行负载均衡\u003C\u002Fli>\n\u003Cli>无水平扩展\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>最适合：\u003C\u002Fstrong> 本地开发工具、IDE 扩展、单用户桌面应用程序。\u003C\u002Fp>\n\u003Ch3>SSE (Server-Sent Events) Transport\u003C\u002Fh3>\n\u003Cp>SSE transport 使用 HTTP 进行 client 到 server 的消息传递，使用 Server-Sent Events 进行 server 到 client 的消息传递。Server 作为 HTTP 服务运行。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>优势：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>可通过网络访问（远程服务器）\u003C\u002Fli>\n\u003Cli>与现有 HTTP 基础设施兼容\u003C\u002Fli>\n\u003Cli>支持多个并发 client\u003C\u002Fli>\n\u003Cli>可穿越防火墙和代理\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>局限性：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>单向流（仅 server 到 client 通过 SSE）\u003C\u002Fli>\n\u003Cli>需要会话亲和性（有状态连接）\u003C\u002Fli>\n\u003Cli>某些负载均衡器在处理长连接 SSE 时有困难\u003C\u002Fli>\n\u003Cli>协议中没有内置的重连语义\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>最适合：\u003C\u002Fstrong> 中小型部署、内部工具、拥有现有 HTTP 基础设施的团队。\u003C\u002Fp>\n\u003Ch3>Streamable HTTP Transport\u003C\u002Fh3>\n\u003Cp>Streamable HTTP 是最新的 transport，专为生产部署设计。它对所有消息使用标准 HTTP POST，对长时间运行的操作使用可选的 SSE 流。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>优势：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>完全无状态的请求\u002F响应模型\u003C\u002Fli>\n\u003Cli>与任何 HTTP 负载均衡器兼容\u003C\u002Fli>\n\u003Cli>通过 \u003Ccode>Mcp-Session-Id\u003C\u002Fcode> 头内置会话管理\u003C\u002Fli>\n\u003Cli>支持流式和非流式响应\u003C\u002Fli>\n\u003Cli>CDN 和代理兼容\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>局限性：\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>需要服务器端会话存储（Redis、数据库）\u003C\u002Fli>\n\u003Cli>每消息开销略高于 stdio\u003C\u002Fli>\n\u003Cli>较新的 transport——生态系统工具较少\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>最适合：\u003C\u002Fstrong> 生产云部署、多租户平台、企业环境。\u003C\u002Fp>\n\u003Ch3>Transport 比较矩阵\u003C\u002Fh3>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>特性\u003C\u002Fth>\u003Cth>stdio\u003C\u002Fth>\u003Cth>SSE\u003C\u002Fth>\u003Cth>Streamable HTTP\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>网络访问\u003C\u002Ftd>\u003Ctd>仅本地\u003C\u002Ftd>\u003Ctd>远程\u003C\u002Ftd>\u003Ctd>远程\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>负载均衡\u003C\u002Ftd>\u003Ctd>不可能\u003C\u002Ftd>\u003Ctd>Session-sticky\u003C\u002Ftd>\u003Ctd>标准 HTTP LB\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>水平扩展\u003C\u002Ftd>\u003Ctd>否\u003C\u002Ftd>\u003Ctd>有限\u003C\u002Ftd>\u003Ctd>是\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>防火墙友好\u003C\u002Ftd>\u003Ctd>N\u002FA\u003C\u002Ftd>\u003Ctd>是\u003C\u002Ftd>\u003Ctd>是\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>重连\u003C\u002Ftd>\u003Ctd>N\u002FA\u003C\u002Ftd>\u003Ctd>手动\u003C\u002Ftd>\u003Ctd>内置\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>并发 client\u003C\u002Ftd>\u003Ctd>1\u003C\u002Ftd>\u003Ctd>多个\u003C\u002Ftd>\u003Ctd>多个\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>延迟\u003C\u002Ftd>\u003Ctd>最低\u003C\u002Ftd>\u003Ctd>低\u003C\u002Ftd>\u003Ctd>低\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>无状态性\u003C\u002Ftd>\u003Ctd>有状态\u003C\u002Ftd>\u003Ctd>有状态\u003C\u002Ftd>\u003Ctd>可无状态\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>生产就绪度\u003C\u002Ftd>\u003Ctd>仅开发\u003C\u002Ftd>\u003Ctd>中等\u003C\u002Ftd>\u003Ctd>高\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch2 id=\"sso-api-key-oauth\">身份验证：SSO 集成、API Key 和 OAuth\u003C\u002Fh2>\n\u003Cp>生产中的 MCP server 必须同时验证 AI host 应用程序和代表其行事的最终用户的身份。\u003C\u002Fp>\n\u003Ch3>远程服务器的 OAuth 2.0\u003C\u002Fh3>\n\u003Cp>MCP 规范包含用于远程（基于 HTTP）服务器的内置 OAuth 2.0 流程：\u003C\u002Fp>\n\u003Col>\n\u003Cli>MCP client 发送不带凭据的 \u003Ccode>initialize\u003C\u002Fcode> 请求。\u003C\u002Fli>\n\u003Cli>Server 响应 HTTP 401 和指向 OAuth 授权端点的 \u003Ccode>WWW-Authenticate\u003C\u002Fcode> 头。\u003C\u002Fli>\n\u003Cli>Host 应用程序打开浏览器进行用户身份验证。\u003C\u002Fli>\n\u003Cli>身份验证成功后，host 收到 access token。\u003C\u002Fli>\n\u003Cli>后续 MCP 请求在 \u003Ccode>Authorization: Bearer\u003C\u002Fcode> 头中包含 token。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cpre>\u003Ccode class=\"language-typescript\">import { McpServer } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fmcp.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002FstreamableHttp.js\";\nimport express from \"express\";\n\nconst app = express();\n\napp.use(\"\u002Fmcp\", async (req, res, next) =&gt; {\n  const token = req.headers.authorization?.replace(\"Bearer \", \"\");\n  if (!token) {\n    res.status(401).json({\n      error: \"unauthorized\",\n      oauth_url: \"https:\u002F\u002Fauth.example.com\u002Foauth\u002Fauthorize\",\n    });\n    return;\n  }\n  const user = await validateToken(token);\n  if (!user) {\n    res.status(403).json({ error: \"invalid_token\" });\n    return;\n  }\n  req.mcpUser = user;\n  next();\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>API Key 身份验证\u003C\u002Fh3>\n\u003Cp>对于服务间 MCP 通信（无人类用户参与），API key 更为简单：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">const API_KEYS = new Map([\n  [\"sk-prod-abc123\", { name: \"analytics-service\", scopes: [\"read\"] }],\n  [\"sk-prod-def456\", { name: \"admin-service\", scopes: [\"read\", \"write\"] }],\n]);\n\nfunction authenticateApiKey(key: string) {\n  return API_KEYS.get(key) || null;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>SSO 集成模式\u003C\u002Fh3>\n\u003Cp>对于企业部署，与现有 SSO（SAML、OIDC）集成：\u003C\u002Fp>\n\u003Cpre>\u003Ccode>User -&gt; AI Host -&gt; MCP Client -&gt; MCP Server -&gt; SSO Provider\n                                      |\n                                      v\n                              验证 OIDC token\n                              提取用户角色\n                              应用工具级 RBAC\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>每个 MCP tool 可以在执行前检查已验证用户的角色：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">server.tool(\n  \"delete_record\",\n  \"按 ID 删除数据库记录\",\n  { table: z.string(), id: z.string() },\n  async ({ table, id }, { authContext }) =&gt; {\n    if (!authContext.roles.includes(\"admin\")) {\n      return {\n        content: [{ type: \"text\", text: \"禁止：需要管理员角色\" }],\n        isError: true,\n      };\n    }\n    \u002F\u002F 继续删除操作\n  }\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"vs\">扩展：有状态会话 vs 负载均衡器\u003C\u002Fh2>\n\u003Cp>MCP 会话本质上是有状态的：\u003Ccode>initialize\u003C\u002Fcode> 握手协商能力，服务器可能在会话内的工具调用之间维护上下文。这与水平扩展之间存在矛盾。\u003C\u002Fp>\n\u003Ch3>会话存储架构\u003C\u002Fh3>\n\u003Cp>将会话状态从服务器进程提取到外部存储：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">interface McpSession {\n  id: string;\n  userId: string;\n  capabilities: ServerCapabilities;\n  createdAt: Date;\n  lastActivityAt: Date;\n  metadata: Record&lt;string, unknown&gt;;\n}\n\nclass RedisSessionStore {\n  constructor(private redis: Redis) {}\n\n  async create(session: McpSession): Promise&lt;void&gt; {\n    await this.redis.set(\n      `mcp:session:${session.id}`,\n      JSON.stringify(session),\n      \"EX\", 3600\n    );\n  }\n\n  async get(sessionId: string): Promise&lt;McpSession | null&gt; {\n    const data = await this.redis.get(`mcp:session:${sessionId}`);\n    return data ? JSON.parse(data) : null;\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>使用 Streamable HTTP 进行水平扩展\u003C\u002Fh3>\n\u003Cp>通过外部化会话和 Streamable HTTP transport，您可以在标准负载均衡器后运行多个 MCP server 实例。无需 session-sticky 路由。任何服务器实例都可以通过从 Redis 加载会话来处理任何请求。\u003C\u002Fp>\n\u003Ch3>Auto-Scaling 配置\u003C\u002Fh3>\n\u003Cp>MCP server 的 Kubernetes HPA 示例：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yaml\">apiVersion: autoscaling\u002Fv2\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: mcp-server\nspec:\n  scaleTargetRef:\n    apiVersion: apps\u002Fv1\n    kind: Deployment\n    name: mcp-server\n  minReplicas: 2\n  maxReplicas: 20\n  metrics:\n    - type: Resource\n      resource:\n        name: cpu\n        target:\n          type: Utilization\n          averageUtilization: 70\n    - type: Pods\n      pods:\n        metric:\n          name: mcp_active_sessions\n        target:\n          type: AverageValue\n          averageValue: \"100\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">审计跟踪和日志记录\u003C\u002Fh2>\n\u003Cp>生产中的每个 MCP tool 调用都必须记录，以用于安全、合规和调试。\u003C\u002Fp>\n\u003Ch3>结构化日志 Schema\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-typescript\">interface McpAuditLog {\n  timestamp: string;\n  sessionId: string;\n  userId: string;\n  toolName: string;\n  toolInput: Record&lt;string, unknown&gt;;\n  toolOutput: string;\n  durationMs: number;\n  success: boolean;\n  errorMessage?: string;\n  ipAddress: string;\n  userAgent: string;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>合规性考虑\u003C\u002Fh3>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>要求\u003C\u002Fth>\u003Cth>实现\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>GDPR 数据访问\u003C\u002Ftd>\u003Ctd>记录 AI 通过 MCP tools 访问了哪些用户数据\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>SOC 2 审计跟踪\u003C\u002Ftd>\u003Ctd>带时间戳的所有工具调用不可变日志\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>PII 保护\u003C\u002Ftd>\u003Ctd>在日志记录前编辑工具输入中的敏感字段\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>数据保留\u003C\u002Ftd>\u003Ctd>设置符合合规要求的日志 TTL\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>访问审查\u003C\u002Ftd>\u003Ctd>记录身份验证事件和权限检查\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch2 id=\"gateway\">多服务器部署的 Gateway 模式\u003C\u002Fh2>\n\u003Cp>企业环境通常需要数十个 MCP server——每个内部系统一个。\u003Cstrong>MCP Gateway\u003C\u002Fstrong> 集中管理：\u003C\u002Fp>\n\u003Cp>Gateway 提供：\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>统一身份验证\u003C\u002Fstrong>：所有后端服务器一个认证流程。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>工具命名空间路由\u003C\u002Fstrong>：工具以服务器名称为前缀（\u003Ccode>jira.create_issue\u003C\u002Fcode>、\u003Ccode>slack.send_message\u003C\u002Fcode>）。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>集中式速率限制\u003C\u002Fstrong>：按用户、按工具和按服务器的限制。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>请求路由\u003C\u002Fstrong>：将工具调用路由到相应的后端服务器。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>熔断器\u003C\u002Fstrong>：如果后端服务器不健康，gateway 返回优雅的错误而非挂起。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"\">常见问题\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>问：在生产中应该使用 stdio 还是 HTTP transport？\u003C\u002Fstrong>\n答：对于需要扩展到单台机器以外的任何部署，使用 Streamable HTTP。仅在 AI host 和 MCP server 在同一台机器上运行的本地桌面集成中使用 stdio。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：一个 MCP server 可以处理多少并发会话？\u003C\u002Fstrong>\n答：使用 Streamable HTTP 和外部化会话，单个 Node.js 服务器实例通常处理 500-1,000 个并发会话。使用 Rust 或 Go 服务器，可实现 5,000-10,000 个。超出此范围时进行水平扩展。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：如何处理 MCP server 停机？\u003C\u002Fstrong>\n答：实现健康检查（\u003Ccode>\u002Fhealth\u003C\u002Fcode> 端点），使用 Kubernetes 存活\u002F就绪探针，并为 gateway 配置熔断器。MCP client 将收到连接错误，AI host 可将其呈现为“工具暂时不可用“。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：MCP server 可以调用其他 MCP server 吗？\u003C\u002Fstrong>\n答：可以。MCP server 也可以是 MCP client，形成链式调用。这是 agent 间通信的基础。谨慎使用此模式——深层链增加延迟和故障概率。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：如何管理 MCP server API 版本？\u003C\u002Fstrong>\n答：使用 \u003Ccode>initialize\u003C\u002Fcode> 响应中的服务器版本字段。对于破坏性更改（删除工具、更改 schema），升级主版本号并在迁移期间同时支持新旧版本。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：MCP 消息的最大大小是多少？\u003C\u002Fstrong>\n答：协议本身没有定义最大值，但实际限制取决于 transport 和基础设施。对于 Streamable HTTP，将响应保持在 10 MB 以下。对于 stdio，系统管道缓冲区（通常 64 KB）可能需要对大型响应进行分块。\u003C\u002Fp>\n","zh","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:38.543532Z","MCP 在生产环境中：Transport、Auth 和扩展挑战","在生产环境中运行 MCP server 的技术指南。涵盖传输选择、OAuth 身份验证、使用 Redis 会话进行水平扩展、审计日志和网关模式。","mcp 生产环境 扩展",null,"index, follow",[22,27,31],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000008","AI","ai","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000012","DevOps","devops",{"id":32,"name":33,"slug":34,"created_at":26},"c0000000-0000-0000-0000-000000000013","Security","security","工程",[37,43,49],{"id":38,"title":39,"slug":40,"excerpt":41,"locale":12,"category_name":35,"published_at":42},"d0000000-0000-0000-0000-000000000668","为什么Bali在2026年正在成为东南亚的影响力科技中心","weishenme-bali-2026-zhengzai-chengwei-dongnanya-yingxiangli-keji-zhongxin","Bali在东南亚创业生态系统中排名第16位。随着Web3构建者、AI可持续发展初创公司和生态旅游科技公司的集中，该岛正在打造区域影响力科技之都的独特定位。","2026-03-28T10:44:48.898750Z",{"id":44,"title":45,"slug":46,"excerpt":47,"locale":12,"category_name":35,"published_at":48},"d0000000-0000-0000-0000-000000000667","ASEAN数据保护拼图：开发者合规清单","asean-shuju-baohu-pintu-kaifazhe-heguiqingdan","七个ASEAN国家现已拥有全面的数据保护法律，各自具有不同的同意模型、本地化要求和处罚结构。这是一份为构建多国应用程序的开发者准备的实用合规清单。","2026-03-28T10:44:48.893467Z",{"id":50,"title":51,"slug":52,"excerpt":53,"locale":12,"category_name":35,"published_at":54},"d0000000-0000-0000-0000-000000000666","Indonesia 290亿美元数字化转型：软件公司的机遇","indonesia-290yi-meiyuan-shuzihua-zhuanxing-ruanjian-gongsi-jiyu","Indonesia IT服务市场预计在2026年达到290.3亿美元，高于2025年的243.7亿美元。云基础设施、AI、电子商务和数据中心正在推动东南亚最快的增长。","2026-03-28T10:44:48.875457Z",{"id":13,"name":56,"slug":57,"bio":58,"photo_url":19,"linkedin":19,"role":59,"created_at":60,"updated_at":60},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]