前言
在本次MCP的尝试使用过程中,大模型与相关MCP插件的结合所实现的效果是相当不错的。
通过使用支持工具调用的大模型(用模型接口的tools字段传输工具内容),将实现了MCP的插件工具传输给大模型,大模型就可以自行判断要用哪些工具,工具使用的顺序,工具使用成功与失败的自动处理等。
大模型与MCP结合后,大模型相当于一个可以思考的大脑,通过理解MCP中工具的功能,然后在适当的时机调用工具,从而实现了更高程度的自动化。
相关概念
以下概念为官网内容与相关文章理解后更通俗的表达
MCP
MCP(Model Context Protocal)是由 Anthropic 公司推动并标准化的 大语言模型 与模型外的 数据源 及 工具 交互的开源协议。该协议可以类比为一个通用的USB接口,只要实现了该协议的插件,就都可以作为大模型的挂载工具,从而为大模型附加本身不具有的额外能力,拓宽大模型的能力边界。
MCP架构中的几个概念
![image]()
(图片来自MCP官网)
MCP Hosts: 在这里 Hosts 相当于是一个集成中心,可以是一个软件程序,可以是一个智能助手,里边可以聚集多个 Client(即MCP插件)
MCP Clients: 位于Hosts 中,用于触发该 Client对应的 Server 的调用。例如 Host 中集成了一个用于 网页截图 的 Server,那它对应的 Client 就用于触发它。
MCP Servers: MCP中提供具体 工具 的部分,可以供 Host 中的 Client 进行调用。例如 Host 想要对网站 https://www.example.com 进行截图,并返回base64编码后的数据,那么就可以调用这个 Server ,来执行该操作。
Local Data Sources: 这个更多指的是 Server 所在服务器中的一些文件,例如该服务器中的 本地配置文件,某程序的日志,一些图片、视频资源 等数据文件。这种文件一般使用 stdio(标准输入输出流)就可以进行调用。
Remote Services: 这个更多指的是需要调用的API。当 Server 中需要对其他系统进行一些功能的调用时,使用的数据源大部分就是这种远程服务。
这里的大致逻辑可以使用如下描述
Host是一个支持MCP协议的集成中心。当Host不具备某种能力(例如网页截图)但希望添加某种能力时,就可以添加已经实现了MCP协议的某种插件(Server)。该插件提供了多种工具用来实现功能(例如网页截图返回base64的数据,或者截图上传到图床后返回链接),那么这些工具就可以通过Host中的Client来进行调用并返回结果。工具中的功能就和普通编程一样了,只需要实现输入某些要求的参数后,能够返回指定格式的返回值即可。
MCP中的几个其他概念
Resources
Resources 指的是MCP的 Server 暴露给 Client 或者 大模型 的一些数据,这些数据可以包括 文件内容,数据库数据,API的响应,实时的系统数据,图片视频,日志等等。
因为某些数据可能需要在 Client 或者 大模型 端作为背景上下文提供出来,以帮助它们更好的理解和处理问题,所以 Resources 的概念可以看做是 原始参考资料 的提供者。
Prompts
Prompts 指的是MCP的 Server 暴露给 Client 的一些预置好的 prompt模板。
在目前大多数的平台中,prompt模板大多用于一些智能体的设计,如 翻译助手,周报生成助手,Linux学习助手 等等。这些学习助手中被提前内置了 角色设定的prompt,再加上用户提问时的内容,会被一起发送给大模型端,然后大模型就可以生成具有某种对话风格的响应内容。
而这里更像是把这些提前设置好的prompt模板直接放到不同的Server中进行托管,同时对这些模板附加好 足够的功能描述、需要传入的参数设定、响应内容的工作流组装 等。这样大模型就可以通过自行判断在具体任务下是否需要添加某个模板,从而增强响应效果。
由于这里 Server 返回的是大模型使用的通用消息格式,所以也可以在消息中添加上边的 Resources 中的内容,以供大模型更方便的使用一些 原始参考资料。下边为一个样例格式:
折叠代码块JSON
复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| { "messages": [ { "role": "user", "content": { "type": "text", "text": "Analyze these system logs and the code file for any issues:" } }, { "role": "user", "content": { "type": "resource", "resource": { "uri": "file:///path/to/code.py", "text": "def connect_to_service(timeout=30):\n retries = 3\n for attempt in range(retries):\n try:\n return establish_connection(timeout)\n except TimeoutError:\n if attempt == retries - 1:\n raise\n time.sleep(5)\n\ndef establish_connection(timeout):\n # Connection implementation\n pass", "mimeType": "text/x-python" } } } ] }
|
Tools 指的是MCP的 Server 暴露给 Client 的一些预置好的工具。这个也是目前 社区驱动的MCP Server 收集平台 mcp.so 中大部分插件提供的功能,也是插件的核心功能。
这些工具就相当于一些功能函数,通过为工具添加 唯一标识符、相应功能描述、需要输入的参数定义 等内容,大模型就可以理解这个工具有什么用,并在有需要的时候调用该工具,从而让大模型的思考能力可以转化为具体的现实操作。
例如
让大模型初始化一个git仓库,写一段可以在网页上显示Hello MCP的服务端代码并使用python托管到本地的8043端口,如果没有问题就将git仓库的内容提交到远端的一个代码仓库
这个需求就可以通过这里的 Tools 提供的通用功能来一气呵成这个效果。
Sampling
Sampling 指的是MCP的 Server 有时候也是需要通过大模型的能力来获取某个结果的,那么这个时候 Server 就可以通过 Client 来反向请求大模型,获得结果后就可以更好的为当前 Host 的请求进行服务。
例如Server获取到的日志比较大,需要找到核心部分来供Host继续处理,这个时候就需要使用到这个概念。
Roots
Roots 指的是让MCP的 Server 可以操作的数据范围。
例如只想当Server操作某个git仓库下的某几个文件夹,而不要访问其他敏感数据,就可以用这个概念来实现。
Transports
Transports 指的是MCP的 Client 和 Server 进行交互的方式,交互时使用JSON格式进行传输。
目前常用的传输方式有两种:
- stdio: 一般用于Server的本地文件的操作,可以执行一些命令行,日志记录等等,适用于简单的交流处理。
- sse: 这种的是 Client 进行 POST 请求,然后 Server 进行流式返回
这里也可以用一些自定义的传输协议,只需要实现 Transport 接口即可。
几个通用的标准
- 对于
Server 和 Client 中一些功能的定义尽量清晰,以帮助 调用方 和 集成方 更方便的处理。
- 需要多添加一些有助于功能理解的描述,从而更好的理解功能做了什么。
- 在出现了功能性错误时,要尽可能的暴露出清晰的错误日志,以帮助开发者理解当前出现了什么情况
- 如果数据量较大的时候,最好使用分页功能来返回数据。
- 如果有速度需求的话,可以使用缓存来缩短资源的访问时间。
- 资源安全,敏感数据,权限控制,资源读取速率,超时,调用资源清理 等 安全相关的问题处理
更详细的规范可以参考该页面。
相关尝试
MCP尝试
MCP使用时工具
- 支持MCP的客户端
- CherryStudio: linux 的 1.1.19 版本
- 使用模型
- MCP相关插件
- @playwright/mcp@latest: 用于网页截图
- @amap/amap-maps-mcp-server: 高德地图的地图信息获取
- @modelcontextprotocol/server-filesystem: 本地文件系统操作
- @cherry/fetch: 用于进行网页内容抓取
- git-mcp-server: 用于进行git相关操作
- 其他辅助工具
- ollama
- deepseek-r1不同参数的模型
- deepseek-r1-tool-calling带有工具调用的模型
MCP请求流程描述
初次请求。
这里让大模型在 /home/easul/Desktop 目录下创建一个 git仓库,名称叫做 hello_mcp。
由于桌面没有该文件夹,也没有初始化仓库,所以大模型需要自行思考调用哪个MCP Server的tool,并需要决定调用顺序。
注意: 这里的请求需要大模型能够传入tools相关的内容,否则请求会失败。(这里最开始使用了ollama拉取deepseek-r1的模型,传入工具字段时报错,使用了deepseek-r1-tool-calling的模型后则问题解决)
折叠代码块JSON
复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| { "model": "qwen-qwq-32b", "messages": [ { "role": "user", "content": "请帮我在 /home/easul/Desktop 目录下创建一个 git 仓库,名称叫做 hello_mcp" } ], "stream": true, "tools": [ { "type": "function", "name": "init", "function": { "name": "fcR9g076ImRT_xUhFEigjS", "description": "Initialize a new Git repository", "parameters": { "type": "object", "properties": { "path": { "type": "string", "description": "Path to initialize the repository in. MUST be an absolute path (e.g., /Users/username/projects/my-repo)" } } } } } ] }
|
请求后返回第一次的思考和工具调用
折叠代码块JSON
复制代码
1 2 3 4 5 6 7 8 9
| data: {"id":"chatcmpl-73270bef-6838-4127-8b73-5d479dd816cd","object":"chat.completion.chunk","created":1744166304,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}],"x_groq":{"id":"req_01jrc6ke02f6c806vanhp8je74"}}
data: {"id":"chatcmpl-73270bef-6838-4127-8b73-5d479dd816cd","object":"chat.completion.chunk","created":1744166304,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"reasoning":"好的"},"logprobs":null,"finish_reason":null}]}
data: {"id":"chatcmpl-73270bef-6838-4127-8b73-5d479dd816cd","object":"chat.completion.chunk","created":1744166307,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_4756","type":"function","function":{"name":"fbAD4Bn38vBR1Mxm6E_Wjc","arguments":"{\"path\": \"/home/easul/Desktop/hello_mcp\"}"},"index":0}]},"logprobs":null,"finish_reason":null}]}
data: {"id":"chatcmpl-73270bef-6838-4127-8b73-5d479dd816cd","object":"chat.completion.chunk","created":1744166307,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"x_groq":{"id":"req_01jrc6ke02f6c806vanhp8je74","usage":{"queue_time":0.24623822,"prompt_tokens":4234,"prompt_time":0.269721582,"completion_tokens":1264,"completion_time":3.064292971,"total_tokens":5498,"total_time":3.334014553}}} data: [DONE]
|
这里Host判断大模型在理解了用户意图后首先需要进行工具调用,那么这里就先调用MCP对应的工具,然后再执行下一步。
第二次的请求,需要连带第一次的上下文以及工具调用后的结果。
这里工具调用成功了,在桌面创建了 hello_mcp 这个文件夹。所以请求大模型时也会携带工具调用成功后相关的返回信息,然后看大模型接下来需要做什么
折叠代码块JSON
复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| { "model": "qwen-qwq-32b", "messages": [ { "role": "user", "content": "请帮我在 /home/easul/Desktop 目录下创建一个 git 仓库,名称叫做 hello_mcp" }, { "role": "assistant", "tool_calls": [ { "id": "call_4756", "function": { "name": "fbAD4Bn38vBR1Mxm6E_Wjc", "arguments": "{\"path\": \"/home/easul/Desktop/hello_mcp\"}" }, "type": "function" } ] }, { "role": "tool", "content": "[{\"type\":\"text\",\"text\":\"Successfully created directory /home/easul/Desktop/hello_mcp\"}]", "tool_call_id": "call_4756" } ], "stream": true, "tools": [ { "type": "function", "name": "init", "function": { "name": "fcR9g076ImRT_xUhFEigjS", "description": "Initialize a new Git repository", "parameters": { "type": "object", "properties": { "path": { "type": "string", "description": "Path to initialize the repository in. MUST be an absolute path (e.g., /Users/username/projects/my-repo)" } } } } } ] }
|
第二次请求后,这里相当于是原本的和新的操作又思考了一遍,所以第二次思考的思考内容和第一次的比较像,同时返回调用的新的工具
折叠代码块JSON
复制代码
1 2 3 4 5
| data: {"id":"chatcmpl-73270bef-6838-4127-8b73-5d479dd816cd","object":"chat.completion.chunk","created":1744166304,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}],"x_groq":{"id":"req_01jrc6ke02f6c806vanhp8je74"}} data: {"id":"chatcmpl-73270bef-6838-4127-8b73-5d479dd816cd","object":"chat.completion.chunk","created":1744166304,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"reasoning":"好的"},"logprobs":null,"finish_reason":null}]} data: {"id":"chatcmpl-05908bad-2f00-48ac-a1cb-7a658bbf7ee9","object":"chat.completion.chunk","created":1744166309,"model":"qwen-qwq-32b","system_fingerprint":"fp_a91d9c2cfb","choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_9kkx","type":"function","function":{"name":"fcR9g076ImRT_xUhFEigjS","arguments":"{\"path\": \"/home/easul/Desktop/hello_mcp\"}"},"index":0}]},"logprobs":null,"finish_reason":null}]} data: {"id":"chatcmpl-05908bad-2f00-48ac-a1cb-7a658bbf7ee9","object":"chat.completion.chunk","created":1744166309,"model":"qwen-qwq-32b","system_fingerprint":"fp_a91d9c2cfb","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"x_groq":{"id":"req_01jrc6kj28f8ts5p80nfjh2mfz","usage":{"queue_time":0.24913554100000002,"prompt_tokens":4319,"prompt_time":0.23064825,"completion_tokens":283,"completion_time":0.689292203,"total_tokens":4602,"total_time":0.919940453}}} data: [DONE]
|
这里Host判断大模型需要调用新的MCP工具,那么这里继续执行调用,然后执行下一步
第三次的请求,会连带前两次的上下文以及工具调用后的结果
这里的工具调用也成功了,在 hello_mcp 文件夹中初始化了git仓库。所以工具返回的内容也插入到了新的请求内容中。
折叠代码块JSON
复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| { "model": "qwen-qwq-32b", "messages": [ { "role": "user", "content": "请帮我在 /home/easul/Desktop 目录下创建一个 git 仓库,名称叫做 hello_mcp" }, { "role": "assistant", "tool_calls": [ { "id": "call_4756", "function": { "name": "fbAD4Bn38vBR1Mxm6E_Wjc", "arguments": "{\"path\": \"/home/easul/Desktop/hello_mcp\"}" }, "type": "function" } ] }, { "role": "tool", "content": "[{\"type\":\"text\",\"text\":\"Successfully created directory /home/easul/Desktop/hello_mcp\"}]", "tool_call_id": "call_4756" }, { "role": "assistant", "tool_calls": [ { "id": "call_9kkx", "function": { "name": "fcR9g076ImRT_xUhFEigjS", "arguments": "{\"path\": \"/home/easul/Desktop/hello_mcp\"}" }, "type": "function" } ] }, { "role": "tool", "content": "[{\"type\":\"text\",\"text\":\"Repository initialized successfully\\nInitialized empty Git repository in /home/easul/Desktop/hello_mcp/.git/\"}]", "tool_call_id": "call_9kkx" } ], "stream": true, "tools": [ { "type": "function", "name": "init", "function": { "name": "fcR9g076ImRT_xUhFEigjS", "description": "Initialize a new Git repository", "parameters": { "type": "object", "properties": { "path": { "type": "string", "description": "Path to initialize the repository in. MUST be an absolute path (e.g., /Users/username/projects/my-repo)" } } } } } ] }
|
这里获取到思考结果和是否调用新的工具。这里不再调用新的工具,故而直接输出content并提示 停止思考
折叠代码块JSON
复制代码
1 2 3 4 5
| data: {"id":"chatcmpl-3e7133dc-66c0-467a-be2d-367a916ac0fc","object":"chat.completion.chunk","created":1744166350,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}],"x_groq":{"id":"req_01jrc6mv04em4bbhabq4y2nwye"}} data: {"id":"chatcmpl-3e7133dc-66c0-467a-be2d-367a916ac0fc","object":"chat.completion.chunk","created":1744166350,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"reasoning":"Okay"},"logprobs":null,"finish_reason":null}]} data: {"id":"chatcmpl-3e7133dc-66c0-467a-be2d-367a916ac0fc","object":"chat.completion.chunk","created":1744166350,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{"content":"仓库"},"logprobs":null,"finish_reason":null}]} data: {"id":"chatcmpl-3e7133dc-66c0-467a-be2d-367a916ac0fc","object":"chat.completion.chunk","created":1744166350,"model":"qwen-qwq-32b","system_fingerprint":"fp_07cd5d759a","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"x_groq":{"id":"req_01jrc6mv04em4bbhabq4y2nwye","usage":{"queue_time":0.24727433,"prompt_tokens":4407,"prompt_time":0.207182678,"completion_tokens":243,"completion_time":0.588138191,"total_tokens":4650,"total_time":0.795320869}}} data: [DONE]
|
MCP流程解析的总结
上边的流程描述是比较理想化的一次处理,在多次请求的尝试过程中,并不是每次都比较顺利。
可能出现的问题如下
- 对于输入内容的语义理解问题。由于我并没有明确指定桌面的路径是哪里,只是在MCP插件中指定了桌面的路径,导致大模型无法在正确的目录创建文件,且在其他目录也没有权限,故而创建失败
- 大模型输出的参数格式并不完全符合MCP插件的要求,导致某些插件操作出错
- 大模型输入上下文过长,导致模型分析的时候出错,增大上下文长度后,解决了问题。
and more…
由此也可以总结
在进行MCP开发的过程中,需要同时考虑大模型的一些问题,做好 功能描述 和 代码功能 等限制,这样才能保证大模型能够有比较稳定的输出。
同时,不同的大模型,不同的参数对同一个问题的处理效果也不一样,大模型的选用也很关键。
MCP开发
在 MCP 官方文档中,建议在进行 MCP 协议下的 Server 和 Client 开发的时候,直接使用大模型配合他们的已有的一些文档案例进行开发。
通过将 llm-full.txt 作为开发的初始参考上下文,并选择开发时使用的语言,同时添加该语言的样例代码中的 README 内容给大模型,大模型就可以通过这些内容,再配合想要构建的 Server 和 Client 的描述,就可以快速的创建所需要的结果代码。
详细内容可以参考该页面。
其他拓展
LLM通过MCP读取访问数据库
目标
对用户的相关信息进行分析
Server实现
通过集成MCP提供的官方依赖包,写了一个 MCP Server ,可以进行数据库内容的只读操作。
相关工具有
- 列出数据库所有表
- 执行任意SELECT SQL的查询
- 查询客户的详细信息
- 进行客户的搜索
同时准备了几个与用户相关的数据库表及模拟数据
体验描述
由于这里使用的是 Claude 3.7 Sonnet,所以体验效果也会好一些
![image]()
- 哪些潜在客户最有可能转化?根据销售机会的阶段和概率分析
这个问题相当于探索性任务,需要从数据中挖掘出潜在的价值,而大模型能够很好的理解并拆分该问题,然后通过查询到的数据进行深度分析,并结合任务中的抽象概念进行评分和排序,这也就显示出了大模型的理解能力在工具的加持下所发挥出的意向不到的效果。
![image]()
总结
大模型对于模糊概念的理解很强大,通过提供相应的获取参考数据的工具,大模型就能够从数据中挖掘到潜在的很多价值,从而能够帮助人类进行 具体决策判断,提供方向建议,更好的把控某个任务的结果。
与视觉模型结合的一些思考
以下内容均可以做成MCP Server供支持MCP协议的Host进行使用。
通过拆分模型相关的能力,并为不同的功能提供足够精确的描述,模型就可以自动调用相关功能并进行组合,来达到某个笼统且效果复杂的目的。
- 对于YOLO等传统视觉模型
- 对于SAM等支持非自然语言prompt的视觉模型
- 对于Qwen2.5-vl ,deepseek-vl2等多模态视觉模型
一些记录
MCP Server的配置解析
折叠代码块JSON
复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| { "mcpServers": { "weather": { "command": "uv", "args": [ "--directory", "/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather", "run", "weather.py" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>" }, "isActive": true, "name": "高德地图调用", "type": "stdio", "registryUrl": "", "description": "" } } }
|
function calling、AI Agent、MCP的区别
以下为一些粗浅的理解
- function calling 可以理解为调用的是 MCP server 的 tool,相当于只执行单一功能。但前者是在模型内部直接调用,后者通过标准化协议由外部调用。
- AI Agent 相当于是 input(输入内容) ,LLM , MCP 之间的协调者,将 input(输入内容) 传递给 LLM,得到响应再判断调用哪个 MCP,最后将所有结果交给 LLM 汇总。
- 原本的 function calling 在不同模型下可能格式与规范不一样,同一个功能,如果换到不同的模型,可能 function calling 是需要进行修改或重写的。 而 MCP 将规范统一后,同一个功能插件可以快速切换到不同的模型下,就会更方便。
MCP使用场景的一些思考
- 做测试用例自动化生成,可以借用一下视觉大模型对于原型图的理解来实现
- 接入企业微信的接口,可以通过自然语言来进行某些请求的发送
- 接入命令行执行接口,可以直接进行某些服务器状态的实时获取,HTTP请求的处理等,但需要对相关处理能力进行限制,避免造成生产事故。
本文相关参考链接
v1.5.2