跳到主要内容

MCP-Server设计模式

核对日期:2026-05-09。

1. 定义与边界

MCP Server 是通过 Model Context Protocol 暴露工具、资源、提示词等能力的服务端组件。它可以是本地 stdio 进程,也可以是远程 Streamable HTTP 服务。

MCP Server 不应被设计成“把整个系统无差别暴露给模型”。好的 Server 是一个受限、可审计、语义清晰的能力边界。

2. 为什么重要

MCP Server 的设计质量决定了 Host 和 Agent 能否安全、稳定地使用外部能力。糟糕设计会导致:

  • 工具粒度过粗,无法审批。
  • 资源范围过宽,越权读取。
  • schema 不稳定,模型选择错误。
  • 远程授权混乱,token 被误用。
  • 日志和错误污染协议通道。

3. 核心机制

3.1 Server 能力

能力设计重点
Tools语义清晰、输入输出 schema、错误码、幂等
ResourcesURI 设计、分页、访问控制、内容类型
Prompts参数化模板、版本、适用场景
Logging结构化日志,不污染 stdio 协议流
Roots本地文件边界,不能当 UI 提示

3.2 传输选择

传输适用场景注意点
stdio本地开发工具、IDE 插件、本机文件访问stdout 只输出协议消息,日志走 stderr
Streamable HTTP远程 SaaS、企业共享服务、多用户访问HTTPS、OAuth、会话、限流、审计

MCP 2025-11-25 规范中,Streamable HTTP 是远程服务的核心传输方式;授权规范针对 HTTP-based transport。

4. 设计模式

4.1 Thin Wrapper

一个 MCP 工具包装一个已有 API。

适用:API 已经稳定,权限清晰。

风险:直接暴露内部 API 细节。应通过 adapter 隔离字段。

4.2 Workflow Facade

一个工具触发受控工作流,而不是直接执行多步副作用。

适用:审批、异步任务、长耗时流程。

示例:

deploy.preview -> deploy.request_approval -> deploy.execute

4.3 Read/Write Split

读工具和写工具分离。不要让 customer.manage 同时查询、修改、删除。

适用:几乎所有生产 Server。

4.4 Resource + Tool Pair

Resource 用于读取上下文,Tool 用于执行动作。

示例:

resource: repo://owner/name/pull/123
tool: repo.create_review_comment

4.5 Registry Gateway

企业内部用一个网关管理多个 MCP Server:

  • Server allowlist。
  • OAuth 和 SSO。
  • 工具元数据审查。
  • 审计与限流。
  • 租户隔离。

5. 工程实现

5.1 Server 目录结构

mcp-server-crm/
src/
server.ts
tools/
search-customer.ts
update-customer-status.ts
resources/
customer.ts
auth/
policy.ts
audit/
logger.ts
schemas/
crm.search_customer.json
crm.update_customer_status.json
tests/
contract.test.ts
security.test.ts

5.2 工具实现边界

server.registerTool("crm.search_customer", {
description: "按名称或客户 ID 查询客户摘要。",
inputSchema: SearchCustomerInput,
outputSchema: SearchCustomerOutput
}, async (args, ctx) => {
await assertScope(ctx.auth, "crm:read", args.tenant_id);
const data = await crm.search(args);
return redactCustomer(data);
});

6. 生产实践

  • 每个工具都有 owner、版本、风险等级和错误码表。
  • 远程 Server 默认 HTTPS,使用 OAuth scope 限制能力。
  • Server 不信任 Host 传来的用户声明,需验证 token 和 audience。
  • 对 tools/list 做缓存但要支持变更通知或版本检测。
  • Server 返回结果要限制大小,并提供分页。
  • 对高风险写操作支持 dry-run、preview、idempotency key。
  • 本地 stdio Server 的日志写 stderr,避免破坏协议消息。

7. 常见反模式

反模式后果
暴露 run_sql 给通用 Agent数据泄露和破坏风险
暴露整个 home 目录为 resourceroots 失去权限意义
用一个工具代理所有内部 APIHost 无法审批和审计
忽视多租户隔离用户数据串租户
Server 自行决定调用外部模型且不可见Host 失去成本和数据控制

8. 评测方法

  • 协议契约测试:tools/list、tools/call、错误格式、schema。
  • 权限测试:不同用户、租户、scope 的访问矩阵。
  • 安全测试:prompt injection、路径穿越、越权参数、恶意返回。
  • 稳定性测试:超时、并发、限流、Server 重启。
  • 兼容性测试:目标 Host、SDK、Inspector。

9. 安全与治理

  • 工具描述和返回内容都可能成为攻击面。
  • 远程 Server 必须校验 OAuth token audience,不能接受发给其他资源服务器的 token。
  • 不把第三方 API token 原样返回 Host 或模型。
  • 对 Server 依赖做供应链扫描。
  • 重大工具新增和权限扩大需要安全评审。

10. Server 安全设计清单

要求失败后果
工具粒度读写分离、语义明确Host 无法审批
输入 schema禁止宽泛参数和任意命令参数注入、越权
输出 schemastructuredContent 优先下游解析不稳定
授权校验 token、audience、scopeconfused deputy
租户隔离token、缓存、日志隔离数据串租户
日志结构化日志写 stderr 或日志系统stdio 协议污染
版本tools/list 变化可检测Host 使用过期 schema
供应链依赖扫描、发布签名或来源验证恶意 Server 风险

11. 工程示例:工具返回结构

{
"content": [
{
"type": "text",
"text": "找到 2 条客户记录,详细字段见 structuredContent。"
}
],
"structuredContent": {
"items": [
{"customer_id": "cus_001", "name": "Acme", "tier": "enterprise"},
{"customer_id": "cus_002", "name": "Acme China", "tier": "standard"}
],
"has_more": false
},
"isError": false
}

返回给模型的自然语言内容应只做摘要;稳定消费依赖 structuredContent

12. Server 评测门禁

  • tools/list 契约测试通过。
  • 所有 tool input/output schema 有 JSON Schema 校验。
  • 未授权用户、错误租户、过期 token 全部拒绝。
  • 写工具具备 dry-run 或 idempotency key。
  • prompt injection 工具返回不会被包装成 Host 指令。
  • stdio 模式 stdout 没有非 JSON-RPC 日志。
  • 远程 HTTP 模式启用 HTTPS、OAuth、限流和审计。

13. 权威资料