游乐游手机版
首页/AI教程/文章详情

MCP协议全面拆解:从JSON-RPC信封到智能体全链路实战

时间:2026-06-04 16:58
MCP协议采用三层架构,Host、Client、Server各司其职。底层通信基于JSON-RPC2 0信封格式,经历初始化、操作、关闭三阶段。六大原语中Tools为核心,Resources为只读数据。ToolSchema需遵循snake_case命名、两句话描述、原子粒度及参数描述原则。完整调用链路由LLM自主决策,Host转发至Client翻译并执行。

MCP 协议拆解:从 JSON-RPC 信封到 Agent 全链路

本文是 Agent 工程化学习(Phase 04)的阶段性总结。核心目标是将对 MCP 协议的理解,从“能用 SDK 跑起来”提升到“能看懂每条消息的具体作用、每层抽象解决什么问题”的层面。内容源自实际课程练习与代码编写过程,并非规范翻译。

MCP 协议拆解:从 JSON-RPC 信封到 Agent 全链路

这篇文章适合那些已经能运行一个 MCP Server,但还不清楚其内部运作原理的读者。

MCP 解决了什么问题

AI Agent 要调用外部能力(如读文件、查数据库、发请求),每个 Host 应用都需各自实现一套工具接口。同一个工具在不同应用里要重复编写——这就像 USB 标准出现之前,每个外设都配有专属接口。

MCP(Model Context Protocol)正是这个统一接口标准。任何 Host(CatDesk、Cursor、Claude Desktop)都能连接任何 MCP Server。一个 Server 编写一次,到处可用。

它的定位与 HTTP 类似:HTTP 统一了浏览器和服务器之间的通信格式,MCP 统一了 AI 应用与工具提供者之间的通信格式。

三层架构:Host、Client、Server

MCP 将参与方划分为三层,每层各自负责本职:

flowchart LR
subgraph Host["Host (CatDesk / Cursor)"]
UI["UI + 对话管理"]
LLM["LLM 调用"]
C1["MCP Client A"]
C2["MCP Client B"]
end
subgraph Servers["独立进程"]
S1["MCP Server A
(文件系统)"] S2["MCP Server B
(数据库)"] end C1 <-->|"stdio / HTTP"| S1 C2 <-->|"stdio / HTTP"| S2

Host 是用户面对的 AI 应用,负责 UI 展示、对话历史管理以及 LLM 调用,其内部包含一个或多个 Client 实例。

Client 是协议适配层。每个 Client 对应一个 Server 连接,主要承担三件事:管理连接生命周期、转换工具格式(MCP Schema ↔ AI SDK Schema)、将调用请求路由到正确的 Server。

Server 是能力提供者。它作为独立进程运行,通过传输层与 Client 通信,暴露 Tools、Resources、Prompts 这三类能力。

为什么要单独抽取出 Client?核心在于关注点分离。Host 只关心“我有哪些工具可用”,Server 只关心“收到请求该如何执行”,而中间的连接管理、格式转换、传输层适配全部封装在 Client 中。这样一来,更换 LLM 框架只需修改 Client 的翻译逻辑,更换传输方式只需改动 Client 的底层实现,上下两层无需调整。

可以类比一下浏览器:你写前端代码只管发 fetch 和收数据,TCP 连接池、TLS 握手、HTTP/2 多路复用这些,都是浏览器网络栈(Client 层)帮你完成的。

底层通信格式:JSON-RPC 2.0

MCP 中所有消息,无论走 stdio 还是 HTTP,均采用 JSON-RPC 2.0 格式封装。这堪称 MCP 的“血管系统”——理解它,就能明白消息在网络上真正的样子。

JSON-RPC 只有三种信封格式:

Request(请求)——包含 id,期望对方返回 Response:

{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "read_file", "arguments": { "path": "config.json" } } }

Response(响应)——id 与 Request 配对,标明是对哪个请求的回复:

{ "jsonrpc": "2.0", "id": 1, "result": { "content": [{ "type": "text", "text": "文件内容..." }] } }

Notification(通知)——没有 id,不需要回复:

{ "jsonrpc": "2.0", "method": "notifications/initialized" }

这里有几个关键认知点:

id 是异步配对机制。Client 同时发出 3 个请求(id=1,2,3),Server 可以乱序返回,Client 依靠 id 匹配“这条回复对应我哪个请求”。Notification 没有 id,因为没人需要回复它。

错误码是标准化的。-32601 Method not found-32602 Invalid params 都是 JSON-RPC 规范定义的,Server 返回错误时应使用这些码,不能随便编造数字。

SDK 帮你处理了所有序列化和反序列化。生产环境中你无需手动解析,但理解信封格式能帮助你在 Inspector 中看懂消息流,并在出现问题时知道去哪里排查。

三阶段生命周期

一个 MCP 连接从建立到关闭,会经历三个清晰的阶段:

sequenceDiagram
participant C as Client
participant S as Server
rect rgb(230,245,255)
Note over C,S: Phase 1: Initialize(能力协商)
C->>S: initialize { protocolVersion, capabilities, clientInfo }
S-->>C: result { protocolVersion, capabilities, serverInfo }
C->>S: notifications/initialized
end
rect rgb(230,255,230)
Note over C,S: Phase 2: Operation(正常工作)
C->>S: tools/list
S-->>C: result { tools: [...] }
C->>S: tools/call { name, arguments }
S-->>C: result { content: [...] }
C->>S: resources/read { uri }
S-->>C: result { contents: [...] }
end
rect rgb(255,240,230)
Note over C,S: Phase 3: Shutdown(关闭)
Note over C,S: 传输层信号:EOF / HTTP disconnect
end

Phase 1 的核心是能力协商。Client 告知 Server“我支持 roots 和 sampling”,Server 告知 Client“我有 tools 和 resources”。后续操作不能超出对方声明的能力——比如 Client 未声明 sampling,Server 就不能调用 sampling/createMessage。这是一项硬性约束。

initialized 为什么是 Notification 而非 Request?因为 Server 不需要确认,Client 只是单向通知“我准备好了,可以进入工作阶段”。一个简单的“我好了”信号而已。

Phase 3 没有结构化的 shutdown 方法。关闭由传输层信号完成——stdio 场景下关闭 stdin/stdout,HTTP 场景下 DELETE session。简单但足够。

六大原语

MCP 定义了六种能力原语,分为两组:

Server 暴露给 Client 的(3 个):

  • Tools:Agent 主动调用的操作,可能有副作用(写文件、发请求)。LLM 在推理过程中自主决定是否调用。
  • Resources:只读数据,用 URI 寻址(如 file://workspace/info)。通常在对话开始前预加载给 LLM 当作背景知识,也可在推理过程中按需读取。
  • Prompts:预定义的提示词模板。Host 展示给用户选择,用户触发后注入对话。

Client 暴露给 Server 的(3 个):

  • Roots:告知 Server 可访问哪些工作区路径。
  • Sampling:Server 请求 Client 侧的 LLM 生成内容(反向调用)。
  • Elicitation:Server 向用户提问以获取输入。

日常开发中最常接触的是前三个。其中 Tool 是核心——Agent 的“动手能力”全靠 Tool 实现。

Resource 和 Tool 的区别

有一个容易混淆的点:Resource 的 URI(如 file://workspace/info)看起来像文件路径,但实际上是 Server 自己定义的虚拟地址。当 Client 调用 readResource("file://workspace/info") 时,Server 并非去磁盘找文件,而是执行注册时绑定的 async 函数——可能是读目录拼 JSON、查数据库、调 API,什么都可能。

Tool 和 Resource 的本质区别在于谁触发以及是否有副作用:

  • Resource:Host 在对话开始前预加载,为 LLM 提供背景知识。无副作用,类似 GET 请求。
  • Tool:LLM 在推理过程中自主决定调用。可能有副作用(写文件、删记录),类似 POST 请求。

Tool Schema 设计原则

Tool 的 Schema 决定了 LLM 能否在正确时机选对正确的工具。下面这四条规则值得参考:

命名使用 snake_case 加动宾结构。read_filelist_directorysearch_files——LLM 扫一眼名字就知道工具用途。避免 fileManagerhandleData 这类模棱两可的命名。

描述采用两句话公式。 第一句说明使用场景,第二句划定边界:

Use when you need to read the contents of a file at a given path.
Do not use for directories or binary files.

第二句“不要用来做什么”至关重要——LLM 经常在相似工具之间犹豫不决,边界描述能帮它快速排除错误选项。

粒度选 Atomic 而非 Monolithic。 read_file + write_file 优于 file_manager(action: "read"|"write"|"delete")。原因是 LLM 更容易直接选对精确的工具,而不是先选到一个大工具再决定传什么 action 参数。

inputSchema 中每个字段都要有 description。 LLM 需要知道每个参数是什么、什么格式、有哪些约束。用 required 明确必选参数,用 enum 约束取值范围。清晰度直接影响工具调用成功率。

完整调用链路:一条消息的旅程

把所有层级串起来,看一次完整的调用过程:

sequenceDiagram
participant User as 用户
participant Host as Host (CatDesk)
participant LLM as LLM (DeepSeek)
participant Client as MCP Client
participant Server as MCP Server
User->>Host: "帮我读一下 config.json"
Note over Host,LLM: Host 把工具菜单 + 用户消息一起发给 LLM
Host->>LLM: messages + tools 列表
Note over LLM: LLM 自主判断需要调用 read_file
LLM-->>Host: tool_call: read_file(path="config.json")
Note over Host,Client: Host 把 LLM 的决策交给 Client 执行
Host->>Client: 转发 tool_call
Note over Client,Server: Client 翻译成 JSON-RPC 格式发给 Server
Client->>Server: {"method":"tools/call","params":{...}}
Server-->>Client: {"result":{"content":[...]}}
Note over Host,Client: Client 提取结果返回
Client-->>Host: 文件内容
Note over Host,LLM: Host 把工具结果塞回 LLM context
Host->>LLM: tool_result 放入 context
Note over LLM: LLM 基于结果组织自然语言回答
LLM-->>Host: "config.json 的内容是..."
Host-->>User: 展示回答

有几个容易误解的点:

LLM 并非“建议你用工具”,而是直接输出调用指令。整个过程是自动化的 Agent Loop,用户几乎无感知。

Host 拿到工具结果后不是直接展示给用户,而是先塞回 LLM。让 LLM 基于结果组织回答——它可能总结、可能继续调另一个工具,直到认为任务完成才输出文本。

一次对话可能循环多轮。用户说“帮我找所有 .ts 文件然后读 package.json”,LLM 会先调 search_files,看到结果后再调 read_file,两轮工具调用完成后给出最终回答。

如何观测每一层

调试 MCP 应用时,不同层需要不同的观测工具:

想看的层观测方式能看到什么
LLM 决策(Host 层)AI SDK 的 onStepFinish 回调每轮选了什么工具、传了什么参数、finishReason 是 tool-calls 还是 stop
Client ↔ Server 通信Client 的 verbose 模式或 JSON-RPC 追踪工具调用耗时、返回内容预览、错误信息
JSON-RPC 原始信封traceJsonRpc 模式或 MCP Inspector每条消息的完整 JSON:id、method、params、result

MCP Inspector 是官方提供的图形化调试工具,使用方法很简单:

npx @modelcontextprotocol/inspector npx tsx src/04-tools-mcp/03-file-server/index.ts .

它能让你手动扮演 Client 角色:点击 tools/list 查看已注册的工具,点击 tools/call 填写参数测试执行。Inspector 能观察到 Client↔Server 之间的所有 JSON-RPC 消息,但无法看到 LLM 决策——那部分需要在 Host 代码中添加 onStepFinish 回调。

写一个 MCP Server 的标准流程

五步即可完成:

1. 声明身份——创建 McpServer 实例,赋予名称和版本号。

2. 注册能力——使用 registerTool / registerResource / registerPrompt 挂载能力。每个 Tool 需定义 name、description、inputSchema 和 handler。

3. 连接传输层——new StdioServerTransport()server.connect(transport)。SDK 会自动处理 initialize 握手。

4. Inspector 调试——无需编写 Client 代码即可验证 Server 是否正确。手动测试每个 Tool 的输入输出。

5. 接入 Host——将 Server 配置到 CatDesk / Cursor 的 MCP 配置中,Agent 即可使用。

生产环境中,你编写的代码 90% 都在做两件事:定义 Schema(告诉 LLM 我能干什么)和实现 Handler(真正干活的逻辑)。握手、路由、序列化这些全部交给 SDK 处理。

收束

MCP 的核心设计哲学很清晰:Server 声明自己能做什么(Schema),Client 负责连接和翻译,Host 让 LLM 自主决定调用什么。每层只负责自己的事,依靠 JSON-RPC 信封在中间传递。

理解到这个层次后,后续的 Inspector 实操和自定义 Server 开发,就是在这个骨架上填充血肉了。

来源:https://juejin.cn/post/7647054707223330835
上一篇AI可见性测量体系搭建思路:从盲猜到可量化 下一篇第二回 Session Assistant工具链三节点设计的深度解读与实现
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
年最新JetBrains AI助手Windows本地详细安装配置教程(含下载与环境要求)
AI教程 · 2026-07-03

年最新JetBrains AI助手Windows本地详细安装配置教程(含下载与环境要求)

JetBrainsAIAssistant可在Windows上通过IDE内置市场或离线包安装,需匹配新版JetBrainsIDE、账号登录与稳定网络。配置时应关注版本兼容、隐私设置、项目索引、快捷键和代码提交前复核,避免上传密钥与敏感业务资料。

Amazon Q Developer新手安装指南:从下载到首次运行的保姆级教程
AI教程 · 2026-07-03

Amazon Q Developer新手安装指南:从下载到首次运行的保姆级教程

AmazonQDeveloper可为编码、调试、解释项目和生成测试提供辅助。安装前需确认账号、开发环境和插件来源,按IDE或命令行路径完成配置,并在首次运行时注意权限、数据与项目安全。

Amazon Q Developer安装失败怎么办?报错日志排查与升级回滚方案
AI教程 · 2026-07-03

Amazon Q Developer安装失败怎么办?报错日志排查与升级回滚方案

AmazonQDeveloper安装失败通常与版本兼容、网络连接、身份登录、插件残留或权限配置有关。排查时应先确认环境,再查看IDE与终端日志,必要时采用清理重装、固定版本升级或回滚方案。

Amazon Q Developer本地模型运行:下载、路径与性能优化
AI教程 · 2026-07-03

Amazon Q Developer本地模型运行:下载、路径与性能优化

AmazonQDeveloper以云端能力为主,本地模型方案更适合离线补充、代码检索和私有环境辅助。配置时需确认版本、模型来源、路径权限、硬件资源与IDE集成方式,并通过量化、上下文控制和缓存策略优化性能。

Amazon Q Developer插件安装全流程:浏览器编辑器扩展市场配置
AI教程 · 2026-07-03

Amazon Q Developer插件安装全流程:浏览器编辑器扩展市场配置

AmazonQDeveloper可在浏览器控制台、VSCode、JetBrains等环境中辅助写代码、解释项目和生成测试。安装前需确认账号权限、编辑器版本与网络环境,配置时重点关注登录授权、工作区信任、数据权限和团队使用规范。