Model Context Protocol(MCP)终极指南

2026年4月3日Ollie @puppyone

Model Context Protocol(MCP)终极指南

Key takeaways

  • MCP 不是你的数据模型,也不是你的治理层。它标准化的是 agent host 如何发现并调用工具、资源和 prompts。
  • 真正的生产级决策通常不是“用 MCP 还是 API”,而是针对不同工作流,分别让哪一层负责发现能力、确定性契约、策略控制和审计。
  • 一个靠谱的 MCP 落地方案会让工具职责收窄、返回结构稳定,并把读路径和写路径分开,避免智能体靠“临场发挥”做出高风险动作。
  • Docker 加固、请求追踪和结构化日志的重要性并不低于 prompt 质量,因为它们决定了事故是否可控、是否可回放。
  • 当真正困难的问题变成“如何把同一份受治理的上下文通过 MCP、API 和 Skills 分发出去,而不是到处复制知识”时,puppyone 才会发挥价值。

MCP 真正解决的是什么

很多团队第一次接触 Model Context Protocol,都会把它理解成“把工具接给 AI 智能体的标准协议”。这个说法没错,但还是太宽泛,不足以指导架构设计。

更有用的理解方式是:

  • MCP 标准化了 host 发现能力的方式。
  • MCP 标准化了智能体调用这些能力的方式。
  • MCP 并不决定你的知识如何建模、策略如何执行,也不保证你的返回结果足够稳定、足够适合生产环境。

官方规范把 MCP 描述为一个基于 JSON-RPC 的协议,用来向 agent runtime 暴露 tools、resources 和 prompts。它的价值在于减少一堆自定义适配器,并给初始化、能力协商和执行过程一个统一生命周期。可参考 Model Context Protocol 规范生命周期章节 以及 Anthropic 最初发布的 Model Context Protocol 公告

但 MCP 不会替你解决:

  • 数据是否过时或相互矛盾
  • 工具边界是否过宽
  • 鉴权是否足够严格
  • 审计链路是否完整
  • 返回结构是否稳定到无需模型猜测

所以成熟团队会把 MCP 当作“交付协议”,而不是一整套 agent 架构的答案。

什么场景该用 MCP,什么场景不该

最容易把系统做复杂的方式,就是因为 MCP 很新,就强行把所有能力都塞进 MCP。更好的方法是,根据任务选择最合适的接口层。

接口层最擅长什么短板适合什么场景
MCP server能力发现、agent 原生调用、host 互操作你仍然需要自己设计稳定 payload 和策略控制调用方本身就是 agent host,并且能从 tools/resources 语义里获益
REST API契约稳定、网关策略成熟、鉴权与缓存体系完善智能体必须先理解端点语义需要给智能体、Web 应用和内部系统同时复用的长期接口
Skills打包工作流说明、约束和操作习惯单独使用时不适合作为实时数据平面想分发一套可复用流程,再通过 MCP 或 API 拉实时数据

一个很实用的判断规则是:

  • 发现型能力放在 MCP
  • 契约型能力放在 REST
  • 流程型知识放在 Skills

这往往才是更真实的生产栈:MCP 负责发现能力,REST 负责确定性接口,Skills 负责把流程经验打包给人和智能体。

看看 puppyone 如何交付治理过的 MCPGet started

能扛住生产压力的最小 MCP 设计

一个差的 MCP 工具通常长这样:“这里有个大而全的函数,自己想办法调用。” 一个更强的版本,则应该是职责清晰、输入收敛、输出稳定的窄工具。

通常意味着:

  1. 一个工具只做一件事
  2. 输入 schema 必须严格
  3. 输出 envelope 必须稳定
  4. 数据离开服务器前先过策略检查
  5. 响应里带上可追溯标识

示意代码如下:

import { McpServer } from "@modelcontextprotocol/sdk/server";

const server = new McpServer({ name: "org-context" });

server.tool(
  "get_knowhow_item",
  {
    description: "Read one governed Know-How item by id",
    inputSchema: {
      type: "object",
      properties: { id: { type: "string" } },
      required: ["id"],
      additionalProperties: false
    }
  },
  async ({ id }, ctx) => {
    const item = await ctx.store.read(id);

    if (!ctx.policy.canRead(ctx.user, item.policyTag)) {
      return {
        ok: false,
        error: { code: "forbidden", message: "Access not permitted" }
      };
    }

    return {
      ok: true,
      data: {
        id: item.id,
        title: item.title,
        version: item.version,
        summary: ctx.redactor(item.summary)
      },
      trace: {
        requestId: ctx.requestId,
        policyTag: item.policyTag
      }
    };
  }
);

这段代码并不炫技,恰恰因为如此才适合生产。

它真正的价值,在于拒绝让工具变成一个对内部系统“无边界透传”的大口子。

Docker 加固本身就是 MCP 设计的一部分

很多 MCP 教程讲到“server 跑起来了”就结束了。但如果这个 server 能读取敏感知识、访问内网工具,甚至触发写动作,那远远不够。

如果你把 MCP 跑在容器里,最起码的加固基线应该是这些“无聊但必须做”的事情:

  • 使用非 root 用户运行
  • 尽量启用只读文件系统
  • 用 secrets 文件挂载密钥,而不是把密钥烘进镜像
  • 添加 health check,让编排层及时发现异常
  • 限制网络 egress,避免 server 任意连外网
  • 给每次调用打上 correlation ID,确保后续能回放

Docker 官方文档对 HEALTHCHECKCompose healthcheckrootless / 非 root 运行只读挂载 都有很实用的说明。这些不是运维细枝末节,而是防止上下文服务进程权限过大、边界失控的关键。

示意容器模式:

FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build && npm prune --omit=dev

FROM gcr.io/distroless/nodejs22-debian12:nonroot
WORKDIR /app
COPY --from=build /app/dist ./dist
USER 65532:65532
ENV NODE_ENV=production
CMD ["/nodejs/bin/node", "dist/server.js"]

哪怕你的运行环境不是 Docker,这个原则也一样成立:只有运行边界清晰,本地优先或私有化部署才真正可信。

为什么版本化的 REST API 依然需要保留

MCP 很适合 agent 原生调用,但确定性 API 仍然重要,因为它能提供:

  • 显式版本控制
  • 稳定的分页和过滤语义
  • 网关原生的鉴权、限流和缓存
  • 更容易被智能体、Web 应用和内部服务共同复用

所以很多团队会把同一份受治理的上下文同时通过 MCP 和 REST 暴露出来。Microsoft 的 Web API design 指南 对版本、分页和响应 envelope 仍然很有参考价值,而 RFC 6585RFC 9110 则适合用来处理限流和 Retry-After 语义。

这里的关键不是“为了双写而双写”,而是接口分工

  • MCP 给 agent host 提供发现能力和工具语义
  • REST 给人和系统提供确定性契约

如果你的智能体体系同时需要两者,这很正常。

Skills 是打包层,不是数据平面

Skills 的价值,在于它可以把一套可复用的操作意图打包出来:该做什么、该避免什么、什么顺序更安全、引用哪些证据更合适。

所以它很适合承载:

  • 带约束的工作流说明
  • 可复用的排障流程
  • 共享的审查习惯
  • 角色化的操作指导

但 Skills 本身并不适合单独承担实时数据平面,因为说明文字不能替代 freshness、鉴权和结构化检索。Anthropic 关于 skills 的文档 以及公开的 anthropics/skills 仓库 都很适合作为格式参考。

更稳妥的模式通常是:

  1. Skill 负责定义流程和约束
  2. Skill 通过 MCP tool 或 REST endpoint 拉取实时上下文
  3. 运行时记录请求、结果与策略决策

这样就能让“说明”和“数据交付”各归其位。

可观测性才是 MCP 真正可审计的前提

如果一个智能体错误地调用了某个工具,你至少要能回答这些问题:

  • 是哪个用户或 agent identity 发起的
  • 暴露了哪个 tool 或 resource
  • 输入参数是什么
  • 经过了什么策略判断
  • 返回了什么结果 hash 或记录标识
  • 花了多长时间

这也是 OpenTelemetry 和结构化日志从“平台加分项”变成“生产必需品”的原因。没有这些,你连事故回放都要靠猜。OpenTelemetry 关于 context propagationtraces 的文档很适合作为起点;而 NIST 的 SP 800-92 修订草案SP 800-53 Rev.5 则适合用来校对日志留存和审计控制。

一个最小可用日志结构可以长这样:

{
  "ts": "2026-04-03T09:15:00Z",
  "event": "tool.execute",
  "requestId": "req_7ad2",
  "tool": "get_knowhow_item",
  "actor": "agent_ops_reader",
  "decision": "allow",
  "resultHash": "sha256:ab12...",
  "latencyMs": 42
}

如果你的系统做不到这种级别的可回放,那眼下最核心的问题还不是协议选型。

puppyone 在 MCP 落地中解决哪一层问题

多数 MCP 项目失败,并不是因为协议本身不清楚,而是因为协议背后的上下文太乱:

  • 知识散落在多个系统里
  • 不同工具看到的内容不一致
  • 权限很难切得足够细
  • 版本和审计链路做不稳

这正是“受治理的 context base”应该补上的空缺。

在实践里,团队评估 puppyone 时,往往会把它当成这样一层:把企业 Know-How 结构化、做 hybrid indexing,并把同一份受治理知识通过 MCP、API 或工作流封装持续分发出去。这样一来,MCP server 不再需要每次调用都临时拼上下文,而是直接服务一个经过整理、带权限和可追溯信息的上下文工件。

这个模式尤其适合这些场景:

  • 多个智能体需要共享同一份事实来源
  • 同一份知识需要同时服务 MCP 和 API
  • 审批场景里需要稳定的标识和 provenance
  • 本地优先或私有化部署是刚需

如果你想继续往相邻的架构模式看,可以读这几篇:

下一步怎么做

如果你还处在早期,不要一上来就搞一场“大协议迁移”。先挑一个读多写少的工作流,把它做得足够扎实:

  1. 先定义一个窄 MCP tool
  2. 返回一个稳定的响应 envelope
  3. 把策略执行放在模型外面
  4. 打上 trace ID 和结构化日志
  5. 只有真的出现第二类消费者时,再补对应的 REST endpoint

等这套基础打稳了,再往上加更多 tools、更多 Skills 和更复杂的 orchestration,风险会小很多。

用 puppyone 规划受治理的 MCP 落地Get started

FAQs

Q1. MCP 会取代 REST API 吗?

不会。MCP 非常适合面向智能体的原生调用,但在需要主机无关的稳定契约、成熟网关控制和跨系统复用时,REST 仍然是更好的选择。

Q2. 每个内部能力都应该做成 MCP tool 吗?

不应该。边界过宽的工具很难治理,也更难调试。更好的方式是从职责窄、输入严格、输出可预测的能力开始。

Q3. 只有 Skills,不接 MCP 或 API,够吗?

通常不够。Skills 很适合打包流程意图,但如果你关心数据新鲜度、权限控制和可审计性,它仍然需要依赖 MCP tools 或 API 来获取受治理的运行时数据。