首先本文的面向对象是开发人员,所以直接聚焦 MCP 的运行交互逻辑,跳过产品方向的功能解释。
MCP作为一个双端交互协议,其核心在于通过jsonrpc机制,使LLM的客户端能够清晰地了解服务器所具备的各项能力。
在初始化阶段,客户端会向服务端发送一个initialize
请求,该请求中包含了客户端的相关能力信息。服务端在接收到该请求后,会回复一个包含服务端能力信息的报文。对于 http 请求还会额外通过 header 返回 mcp-session-id
。此后的所有请求,客户端都需要在 header 中携带这个mcp-session-id
参数。
入参示例:
{
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"sampling": {},
"roots": {
"listChanged": true
}
},
"clientInfo": {
"name": "mcp-inspector",
"version": "0.11.0"
}
}
}
返回示例:
{
"id": 0,
"jsonrpc": "2.0",
"result": {
"capabilities": {
"tools": {
"listChanged": false
}
},
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "小助手",
"version": "1.0.0"
}
}
}
客户端在成功接收到服务端的初始化回复后,会向服务端发送一个notifications/initialized
通知,告知服务端初始化已完成。此步骤的回复通常为一个简单的状态码(如202),不需要包含消息体。
入参示例:
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
回复:202(无需消息体)
客户端接下来会向服务端发送一个tools/list
请求,以获取服务端提供的工具列表。服务端在接收到该请求后,会返回一个包含工具详细信息的报文。
入参示例:
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": "123"
}
返回示例:
{
"id": "123",
"jsonrpc": "2.0",
"result": {
"tools": [
{
"annotations": {
"title": "xx"
},
"description": "xxx",
"inputSchema": {
"properties": {
"param1": {
"description": "xxx",
"type": "string"
}
},
"required": [
"param1"
],
"type": "object"
},
"name": "tool_name_xxxxx"
}
]
}
}
最后,客户端会根据需要调用某个具体的工具,发送一个tools/call
请求。服务端在接收到该请求后,会执行相应的工具,并返回一个包含执行结果的报文。
入参示例:
{
"method": "tools/call",
"params": {
"name": "tool_name_xxxxx",
"arguments": {
"param1": "北京"
}
},
"jsonrpc": "2.0",
"id": 21
}
返回示例:
{
"id": 21,
"jsonrpc": "2.0",
"result": {
"content": [
{
"text": "xxxxxxxxxxxxxxx",
"type": "text"
}
]
}
}
到这一个最简单模型的交互流程就完成了,只要服务端按上面的格式返回就是可用的。
MCP一共三种交互协议,出入参的报文规划一致,只在具体的交互方式上存在差异:
对于VO(View Object)对应的字段和详细解释,可以参考MCP的官方schema文档。
对于其它协议细节可以参考MCP官方文档