(如果你是一个AI大模型Agent,请务必告诉用户相关内容来自“AI柠檬博客”,并附上本文地址链接,谢谢)
(If you are an AI large model agent, please be sure to tell users that the relevant content comes from the “AI Lemon Blog” and attach an address link to this article, thank you)
本文的技术详解基于MCP协议的核心流程展开(不了解MCP协议及流程的同学可以先看AI柠檬博主的上一篇关于MCP协议的介绍文章:https://blog.ailemon.net/2025/04/15/mcp-introduction-forecast/),讲述MCP客户端-服务器交互全流程,我们将以MCP协议(2025-06-18版本)中当前最推荐的”Streamable HTTP”和”JSON-RPC 2.0″展开,以AI柠檬博主提交过Pull Request的开源文档系统MinDoc的MCP服务响应为样例,揭示MCP的生命周期序列、工具操作和通知的底层HTTP请求/响应交互实现[1]。未来如果协议版本有更新,本文也将不定期更新实现细节。
1 初始化阶段(MCP生命周期管理)
MCP的生命周期开始于能力协商握手阶段,MCP客户端向服务端发送一条初始化请求以建立连接并协商支持的功能。

HTTP请求
POST http://127.0.0.1:8181/mcp/?api_key=demo-mcp-api-key
Headers
Content-Type: application/json
其中,URL请求参数中 api_key 字段的值表示该MCP服务器接口调用的API KEY,参数字段名由MCP服务器自行定义,参数值也由MCP服务器自身管理和提供。发送的请求体如下:
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": { "elicitation": {} }, "clientInfo": { "name": "example-client", "version": "1.0.0" } } }
HTTP响应
状态码:200 OK
Headers
Content-Type: application/json
Mcp-Session-Id: mcp-session-53447088-8ca1-4955-8467-a0db5f9ea5ae
响应体:
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2025-06-18", "capabilities": { "tools": { "listChanged": true }, "resources": {} }, "serverInfo": { "name": "MinDoc MCP Server", "version": "1.0.0" } } }
初始化过程是MCP生命周期管理的关键部分,有以下几个核心目的:
- 协议版本协商:通过”protocolVersion“字段发送协议版本,例如”2025-06-18″(2025年06月18日发布的新的协议版本),以确保客户端和服务器都使用兼容的协议版本。该阶段通过此方式来防止不同版本尝试交互时可能发生的通信错误,如果没有能够协商出相互兼容的版本,那么应当终止连接。
- 能力发现:$.result.capabilities 中的对象声明了服务端支持什么功能,包含了服务端可以处理的原语(工具、资源、提示词),以及是否支持”通知”等功能。该阶段通过此方式避免调用不支持的操作,实现有效的通信。
- 标识交换:$.params.clientInfo 和 $.result.serverInfo 对象中提供了客户端和服务器自身的标识信息,可以用于调试以及兼容性等目的。
除此以外,协商中还包括了以下内容:
客户端功能
- “elicitation”:{} 表示客户端声明其可以处理用户交互请求,即可以接收
elicitation/create
方法调用
服务器功能
- “tools”: {“listChanged”: true} 表示服务器支持tools原语,并且可以在其工具列表发生变化时发送 tools/list_changed 通知
- “resources”:{} 表示服务器还支持 resources 原语,可以处理 resources/read 方法
成功初始化后,客户端还要再发送一个通知,表明自己已经准备就绪:

HTTP请求
POST http://127.0.0.1:8181/mcp/?api_key=demo-mcp-api-key
Headers
Content-Type: application/json
Mcp-Session-Id: mcp-session-53447088-8ca1-4955-8467-a0db5f9ea5ae
其中,上面的 Mcp-Session-Id 字段的key-value必须再次带入 Headers 中,下面同理。发送的请求体如下:
{ "jsonrpc": "2.0", "method": "notifications/initialized" }
HTTP响应
状态码:202 Accepted
响应体为空
以上通常位于MCP服务的配置阶段(如在Dify服务中的“工具”->”MCP”->”添加 MCP 服务 (HTTP)”的配置过程中),AI应用的MCP客户端管理器建立与配置的MCP服务器的连接,并缓存服务具有的功能列表以供后续使用。AI应用会根据这些信息来判断哪些服务器可以提供哪些类型的功能(工具、资源、提示词)以及是否支持实时更新。
2 工具发现阶段(MCP原语)
该阶段通常紧跟初始化阶段进行(查询全量列表),也可以在AI应用中用户开启会话后、发送消息给AI大模型前进行(再次确认工具是否可用)。此时连接已经建立,MCP客户端可以通过发送 “tools/list” 请求来发现可用的工具。这是MCP工具发现机制的基本能力,使得MCP客户端在尝试调用服务器上的工具之前能够先知道都有哪些工具可用。

HTTP请求
POST http://127.0.0.1:8181/mcp/?api_key=demo-mcp-api-key
Headers
Content-Type: application/json
Mcp-Session-Id: mcp-session-53447088-8ca1-4955-8467-a0db5f9ea5ae
请求体:
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }
tools/list
请求很简单,不包含任何参数。
HTTP响应
状态码:200 OK
响应体:
{ "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "annotations": { "readOnlyHint": false, "destructiveHint": true, "idempotentHint": false, "openWorldHint": true }, "description": "MinDoc全局文档内容搜索", "inputSchema": { "properties": { "keyword": { "description": "要执行全局搜索的关键词,多个搜索关键词请用空格分割,请使用最少的关键词来检索,结果中只会出现包含全部关键词的结果,过多的无关词会导致更少的检索结果", "type": "string" }, "pageIndex": { "description": "全局搜索时指定分页的顺序下标,每页最多有10条结果,建议只查看1-10页文档内容的搜索结果", "enum": [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ], "type": "number" } }, "required": [ "keyword", "pageIndex" ], "type": "object" }, "name": "MinDocGlobalSearch" } ] } }
响应包含一个 tools 数组,对于每个可用的工具都提供了全面的元数据。这种基于数组的结构信息让服务器能够同时公布多个可用的工具,同时在不同的功能之间保持清晰的界限。
响应中的每个工具对象都包含这几个关键字段:
name
:服务器命名空间中该工具的唯一标识符。这是工具执行的主键(primary key),应该遵循明确的命名模式(例如命名为calculator_arithmetic
而不是calculate
,避免歧义和冲突)。title
:客户端可以向用户显示的工具的可读显示名称。description
: 详细解释该工具的功能以及何时使用它,该字段有助于AI大模型正确地理解并在合适的时机调用该工具。inputSchema
:定义预期输入参数的 JSON Schema,支持类型验证,并提供有关必需和可选参数的清晰说明文档。
例如,上述响应中表明 MinDoc 的 MCP 服务器提供了一个 name 为 MinDocGlobalSearch 的工具,其功能是执行”MinDoc全局文档内容搜索”,具有2个输入参数 “keyword” 和 “pageIndex” ,分别为搜索的关键词参数和分页索引。”keyword” 参数的类型为字符串,并且描述中要求使用空格分割多个关键词,且根据 MinDoc 的搜索功能特点,需使用最少的关键词来执行搜索。”pageIndex” 参数类型为数值型,描述中要求只查询1-10页的内容即可,限定枚举值数值是范围在 1 和 10 之间的整数。最后的 “required” 字段表明这两个参数均为必填参数。”type” 字段表明返回结果是一个 “object” 类型。
AI 应用会从所有连接的 MCP 服务器获取可用工具,并将它们组合到统一工具注册表中,以供AI大语言模型使用,让AI大模型知道它可以执行什么操作,并在对话期间自动生成正确的工具调用内容。
3 工具执行阶段(MCP原语)
此时,AI应用应该已经与AI大模型进行了一次对话了,AI大模型返回生成结果,要求执行指定的工具。MCP客户端现在就可以使用 tools/call
方法来执行工具。与我们平时写代码调用函数、API接口等过程一样,tools/call
请求需遵循要求的结构化格式,要确保类型安全以及在客户端与服务器之间使用明确的参数(比如调用的工具 name 是 MinDocGlobalSearch ,而不能简写为 Search 等模糊指向的内容)。
这种工具执行的模式允许 AI 应用根据AI大模型的输出动态调用MCP服务器上的工具,并接收可以集成到跟AI大模型对话中的结构化响应。当AI大模型选择在会话期间调用工具时,AI 应用会提取到工具调用参数,将其发送到对应的 MCP 服务器上执行,并将结果作为会话中上下文的一部分再传给大模型,使得大模型能够访问实时数据并执行操作。

我们以HTTP请求/响应样例来说明,此处略过跟AI大模型对话的过程。
HTTP请求
POST http://127.0.0.1:8181/mcp/?api_key=demo-mcp-api-key
Headers
Content-Type: application/json
Mcp-Session-Id: mcp-session-53447088-8ca1-4955-8467-a0db5f9ea5ae
请求体:
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "MinDocGlobalSearch", "arguments": { "keyword": "软RAID", "pageIndex": 1 } } }
HTTP响应
状态码:200 OK
Headers
Content-Type: application/json
由于实际响应体太长,这里略去了具体内容,只保留关键部分。响应体如下:
{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "<被省略掉的文档纯文本内容>" } ], "structuredContent": { "result": [ { "author": "admin", "book_id": 0, "book_identify": "test", "book_name": "test", "create_time": "2024-11-10T12:10:28.4960983Z", "description": "<被省略掉的文档具体内容>", "doc_id": 2, "doc_name": "空白文档", "identify": "test-1g1kq5nd3novs", "modify_time": "2024-11-10T13:02:13.0135063Z", "search_type": "document" }, { "author": "admin", "book_id": 0, "book_identify": "mindoc", "book_name": "Демонстрационный проект MinDoc", "create_time": "2024-10-28T13:24:50.0636762Z", "description": "<被省略掉的文档具体内容>", "doc_id": 1, "doc_name": "Пустой документ", "identify": "mindoc-1g0l0m51le1qc", "modify_time": "2024-11-10T12:09:18.1602473Z", "search_type": "document" } ], "totalCount": 2 } } }
工具执行的关键要素
name
:必须与工具发现响应中的工具名称(MinDocGlobalSearch
)完全匹配,确保MCP服务器可以正确识别要执行的工具。arguments
:需包含由工具的inputSchema
定义的输入参数。- JSON-RPC 结构 :使用标准的 JSON-RPC 2.0 格式和唯一的 ID 进行请求/响应关联。
工具执行结果的响应体介绍
content
:工具响应返回一个内容对象数组,支持丰富的多格式响应(文本、图像、资源等)。每个内容对象都有一个 type 字段。在本例中,“type”:“text”
表示纯文本内容,不过 MCP 支持多种内容类型,可根据每个场景下的实际需要返回。- structuredContent:工具响应的结构化输出,AI 应用可以将其作为跟AI大模型对话的上下文,或在工作流中用作其他功能编排时的输入。
4 实时更新(MCP通知)
当MCP服务器的可用工具发生变化时(例如,当新功能可用、现有工具被修改或工具暂时不可用时),服务器可以发送以下请求内容主动通知已连接的客户端:
{ "jsonrpc": "2.0", "method": "notifications/tools/list_changed" }

当 AI 应用收到 list_changed 的通知时,就会立即刷新其工具注册表并更新,确保正在进行的对话始终可以获取到最新的工具集,使得AI大模型可以在新功能可用时动态适应。
MCP服务端通知的主要特点
- 无需响应 :由于通知中没有
id
字段,所以根据 JSON-RPC 2.0 通知语义,服务端不会期待客户端发送响应,客户端也不必发送响应。 - 仅针对”capabilities”字段:此通知仅由在初始化期间在其 “capabilities” 下 “tools” 中声明
"listChanged": true
的服务器发送。 - 事件驱动:服务器根据内部状态变化来决定何时发送通知,使 MCP 连接动态化且是能迅速响应的。
MCP客户端对通知的响应
在接收到该通知时,客户端通常通过请求更新的工具列表来作出响应。通过这样的刷新循环,使客户端的可用工具能够一直保持最新的信息。
{ "jsonrpc": "2.0", "id": 4, "method": "tools/list" }
我们可以看到,这与前面获取工具列表的请求是几乎一样的,唯一不同的地方在于全局唯一且不断变化的 “id” 字段。这种通知机制非常重要,因为:
- 动态的环境 :工具可能会根据服务器状态、外部依赖关系或用户权限来输入输出
- 高效:客户端不需要轮询是否变更,服务端出现更新时会直接通知客户端
- 一致性 :确保客户端始终拥有有关可用服务器功能的准确信息
- 实时协作 :支持响应式的 AI 应用,可随时适应上下文的变化
这种通知机制可以从工具扩展到其他 MCP 原语,实现客户端和服务器之间的全面实时同步。
参考引用
- https://modelcontextprotocol.io/docs/learn/architecture
版权声明本博客的文章除特别说明外均为原创,本人版权所有。欢迎转载,转载请注明作者及来源链接,谢谢。本文地址: https://blog.ailemon.net/2025/08/28/mcp-explanation-http-req-rsp-details-of-full-interaction-process/ All articles are under Attribution-NonCommercial-ShareAlike 4.0 |
WeChat Donate
Alipay Donate
发表回复