MCP原理解析
回顾
回顾前面两篇文章:
我们通过实践的方式,从浅入深的方式一步步与MCP初相识、学会使用MCP Server、同时也跟着一起编写了第一个MCP Server,到这里你应该对MCP有一定的感知了。
通过实践->反馈这样的正向循环的方式,可以帮助我们快速掌握一门新的技术,这也是学习一个新技术最快的方式之一。如果你还没有跟着一起实践过,那强烈推荐你先从前面两篇开始,然后再来内化MCP的底层原理。
为什么要深入了解MCP的底层原理?上一篇中,我们已经学会了如何开发一个MCP Server,如果你是作为一个开发者,那么了解底层原理可以帮助我们更加有效地开发MCP Server,然后将MCP Server对接到大模型系统中,让大模型正确地调用,这一点非常重要。如果你是非开发者,那么掌握MCP的底层原理,可以让你最大化AI工具以及MCP的价值,当使用异常时,你可以有一定的判断和解决问题的能力。
阅读本篇文章,你将会:
- 深入了解MCP架构和组件深入了解MCP底层原理
MCP架构解析
大家还记不记得在5分钟快速入门MCP这篇文章里面放过这张图,当时还留了一个小疑问,就是这里的MCP Hosts和MCP Clients是什么关系?
这里使用官网的图就很可以更加清晰地了解它们的关系
从如上这张图可以知道
MCP是遵循Server-Client的架构模式
- MCP HOST:类似 Cursor/Claude/Cherry-stuido这些AI工具,需要通过MCP访问外部的工具或者数据,这里不要误以为是我们的电脑主机😂MCP Server:如果你实践过笔者的这篇文章5分钟编写你的第一个MCP Server,MCP Server其实并不神秘,就是我们人为编写的一个应用程序。这里使用的基于MCP协议的Python SDK,当然你可以换成社区支持的比如Java/Golang SDK等都可以,将需要公开给大模型的tools/prompt/resources注册到MCP Server中MCP Client:每一个MCP Server都对应一个MCP Client,是1:1的连接关系,像类似Cursor/Claude/Cherry-stuido这些AI工具就可以通过MCP Client获取所有MCP Server的tools工具列表,这样大模型就知道有哪些工具可以调用了Local Data Source 或者 Remote Service C:MCP Server既可以访问你的本地数据源,也可以访问外部系统
接下来我们主要围绕两个问题来进行探索底层原理:
1、大语言模型LLM是如何知道有哪些工具可用的?
2、大语言模型LLM怎么知道什么时候调用这些工具的?
MCP源码分析
这里为啥拿cherry-studio来做演示,就是因为cherry-studio的代码都是开源,方便我们用来学习和理解MCP Server调用的深层次原理
下载cherry-studio开源代码
$ git clone https://github.com/CherryHQ/cherry-studio.git$ cd cherry-studio## 使用cursor或者trae打开源代码进行分析$ cursor . # or trae .
这里在使用AI IDE分析代码的时候,发现这里其实可以分为两个流程来进行分析,分别是注册工具和调用工具流程
提示词prompt参考
请阅读这个项目的代码,并梳理出cherryStudio这个AI客户端是如何调用mcp server的工具整个流程,使用markdown mermaid画出这个时序图,请注意不需要过于细节的流程展示,抽象出来主要的组件调用即可 拆分为两个时序图: 1、mcp server 工具注册时序图:大语言模型LLM是如何知道有哪些工具可用的 2、mcp server 工具调用时序图:大语言模型LLM怎么知道什么时候调用这些工具的
然后你可以沿着生成的初版本在AI IDE里面进行提问,得到最终的流程时序图
MCP Server工具注册流程
sequenceDiagram title MCP Server 工具注册时序图 participant Client as CherryStudio客户端 participant AIProvider as AI Provider participant MCPService as MCPService participant MCPClient as MCP Client(SDK) participant Server as MCP Server participant Store as 状态管理Store participant LLM as 大语言模型(LLM) Client->>MCPService: 初始化MCP服务 MCPService->>MCPClient: 初始化MCP Client(initClient) alt 内存型服务器 MCPService->>Server: createInMemoryMCPServer MCPClient->>Server: InMemoryTransport.createLinkedPair Server-->>MCPClient: 建立内存连接 else 外部服务器(HTTP/SSE) MCPClient->>Server: 使用SSE/HTTP建立连接 Server-->>MCPClient: 返回连接状态 else 外部进程(STDIO) MCPClient->>Server: 使用StdioClientTransport创建进程 Server-->>MCPClient: 进程启动成功 end MCPClient->>Server: listTools请求 Server-->>MCPClient: 返回可用工具列表 MCPClient-->>MCPService: 工具列表返回 MCPService->>Store: 存储工具信息(addMCPServer) Client->>AIProvider: 准备发送消息给LLM Client->>Store: 获取可用的MCP工具 Store-->>Client: 返回MCP工具列表
MCP Server工具调用流程
sequenceDiagram title MCP Server 工具调用时序图 participant User as 用户 participant Client as CherryStudio客户端 participant AIProvider as AI Provider participant LLM as 大语言模型(LLM) participant Handler as 工具调用处理器 participant MCPService as MCPService participant MCPClient as MCP Client(SDK) participant Server as MCP Server User->>Client: 发送带有工具需求的请求 Client->>AIProvider: 转发用户请求及可用工具定义 Note over AIProvider: 基于工具数量和模型能力决定<br/>如何向LLM传递工具信息 alt 工具数量超过阈值或模型不支持原生函数调用 AIProvider->>AIProvider: 调用buildSystemPrompt<br/>将工具描述添加到系统提示词 Note over AIProvider: 包含工具名称、描述、<br/>参数结构和使用示例 else 模型支持原生函数调用API AIProvider->>AIProvider: 将工具转换为模型专用格式<br/>(OpenAI/Claude/Gemini等) end AIProvider->>LLM: 准备请求,包含工具定义或系统提示词 LLM->>LLM: 1. 理解用户需求<br/>2. 参考系统提示词中的工具信息<br/>3. 决定是否调用工具 alt LLM决定调用工具 alt 通过系统提示词调用工具 LLM-->>AIProvider: 返回带有工具调用XML格式的文本<br/><tool_use>...<arguments>...</arguments></tool_use> AIProvider->>Handler: processToolUses处理XML格式工具调用 Handler->>Handler: parseToolUse解析工具调用参数 else 通过函数调用API调用工具 LLM-->>AIProvider: 返回标准函数调用请求 AIProvider->>Handler: processToolCalls处理 Handler->>Handler: 解析工具调用参数 end Handler->>Handler: 准备MCPToolResponse对象 Handler->>MCPService: callMCPTool调用 MCPService->>MCPClient: 执行callTool MCPClient->>Server: 发送工具调用请求 Server->>Server: 执行工具逻辑 Server-->>MCPClient: 返回工具执行结果 MCPClient-->>MCPService: 返回执行结果 MCPService-->>Handler: 返回MCPCallToolResponse Handler->>Handler: 转换工具调用结果(mcpToolCallResponseToMessage) Handler->>AIProvider: 发送工具调用结果 alt 文本格式工具调用 AIProvider->>LLM: 以<tool_use_result>格式发送工具结果 else 函数API格式工具调用 AIProvider->>LLM: 以函数返回值格式发送工具结果 end LLM->>LLM: 根据工具调用结果生成回复 LLM-->>AIProvider: 返回最终回复 AIProvider-->>Client: 转发LLM回复 else LLM不需要调用工具 LLM-->>AIProvider: 直接返回生成的回复 AIProvider-->>Client: 转发LLM回复 end Client-->>User: 显示最终回复
通过如上的时序图,同时向AI IDE提问,我们大致可以知道:
1、大语言模型LLM是如何知道有哪些工具可用的?
LLM通过两种主要方式了解可用工具:
- 1)通过系统提示词(System Prompt) - 当工具数量超过阈值默认128个或模型不支持原生函数调用时:将工具信息添加到系统提示词中,系统提示词包含了工具的详细信息:名称、描述、参数结构和使用示例格式化为XML标签结构,让LLM能够理解工具的用途和调用方式例如:
<tool> <n>工具ID</n> <description>工具描述</description> <arguments> 参数结构 </arguments> </tool>
- 2)通过函数调用API - 当模型支持原生函数调用时:不同AI提供商有不同的工具格式转换函数:mcpToolsToOpenAIChatTools:转换为OpenAI兼容格式mcpToolsToAnthropicTools:转换为Anthropic Claude格式mcpToolsToGeminiTools:转换为Google Gemini格式工具信息直接通过API调用参数传递给LLM工具信息直接嵌入到API请求中,如OpenAI的tools参数
// OpenAI API请求示例 - 包含工具定义{ "model": "gpt-4o", "messages": [ { "role": "system", "content": "你是一个有用的助手。" }, { "role": "user", "content": "我想查找北京今天的天气情况" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的天气信息", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "城市名称,如北京、上海等" }, "date": { "type": "string", "description": "日期,格式为YYYY-MM-DD。如果不提供,默认为今天" } }, "required": ["location"] } } }, { "type": "function", "function": { "name": "search_nearby", "description": "搜索指定位置附近的设施或服务", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "位置名称" }, "service": { "type": "string", "description": "要搜索的服务或设施,如餐厅、医院、酒店等" }, "radius": { "type": "number", "description": "搜索半径,单位为公里" } }, "required": ["location", "service"] } } } ], "temperature": 0.7, "max_tokens": 1000}
2、大语言模型LLM怎么知道什么时候调用这些工具的?
工作流程图中明确指出LLM会:
- 理解用户需求参考系统提示词/函数调用API请求中的工具信息自行决定是否调用工具这个决策是LLM基于其训练和推理能力自行做出的
了解这两个问题之后,对我们又有什么启示呢?
我们可以基于这个时序图,进一步在AI IDE里面进行提问
作为一名mcp server开发者,基于 @workflow.md 这个时序图,对我们开发mcp server有什么启示吗?
可以看到最核心的两点启示:
- 工具描述清晰决定了LLM是否能够正确理解和调用,这个是非常关键的另外我们在使用MCP的时候,笔者在尝试一些开源的MCP Server时,报错信息非常不友好或者干脆没有输出,这样就会让使用者一头雾水,所以工具执行失败时,请一定一定要输出清晰友好的错误信息
如果是非mcp server开发者,对我们又有什么启示?可以进一步提问:
作为一名使用MCP的用户,基于 @workflow.md 这个时序图,对我们用户使用mcp server有什么启示吗?
总的来说,对我们使用MCP的用户来说:
- 控制使用MCP工具的数量,这个也是当前使用MCP工具的一些局限,工具多了之后,LLM的决策链路难度也会指数上涨学会如何提问,明确自己的请求,让LLM能够更加清晰地理解你的需求,并调用合适的工具当调用工具出现了问题之后,由于你理解了整个流程,所以你可以知道哪个环节出现了问题,可以更好地处理使用过程中的问题,并对MCP有一个合理的期望
今天这篇文章就分享到这里啦,魔法的乐趣在于寻找的过程✨✨希望大家可以借助AI IDE边学边理解MCP的底层原理和一些关键要点:)