当前位置: 首页 > news >正文

MCP是如何工作的?

MCP是如何工作的?

LLM 在调用外部工具(Tool-calling / Function-calling)时,确实经历了“口语化输入 → 结构化解析 → 运行时执行 → 结果回灌”这一闭环。MCP(Model-Calling-Protocol,或更广为人知的“Model-Context-Protocol”)正是把这一闭环标准化、可插拔化之后的产物。


从人话到函数,再从函数回到人话

—— 用 MCP 的视角拆解 LLM 工具调用

想象一下:用户说“今天北京热吗?”
你家的 AI 居然自己打开了天气 API,把温度读出来,还用中文回答:“34℃,挺热的,记得防晒。”
这背后发生了什么?为什么 AI 知道要调哪个函数、填哪些参数?
答案就藏在 MCP 的三次握手 里。


1. 口语 → 结构化:第一次握手(解析)

用户输入:
“今天北京热吗?”

在 MCP 里,这行文本首先被送进 解析器(Parser) 。解析器并不关心天气,它只干一件事:
把自然语言映射成“函数签名 + 参数”

// 解析器输出(LLM 第一次返回)
{"name": "get_weather","arguments": {"city": "北京","date": "2025-07-29"}
}

关键点

  • 解析器可以就是 LLM 自己(通过 prompt/fine-tune),也可以是独立 NLU 模型。
  • MCP 要求函数声明(JSON Schema)提前注册,LLM 像“查字典”一样匹配最符合意图的函数。
  • 对可选参数、枚举值、数组等复杂 schema,MCP 会给出完整描述,减少幻觉。

2. 结构化 → 运行时:第二次握手(执行)

解析器把 JSON 交给 MCP 运行时(Runtime)
运行时的职责是“零信任”地执行函数,并捕获三种结果:

结果类型 示例 如何处理
正常值 {"temp": 34, "unit": "℃"} 直接返回
业务错误 {"error": "城市不存在"} 包装成 message 回传
系统异常 timeout、网络不通 转成统一异常格式,避免 LLM 看到堆栈
// 运行时返回
{"tool_call_id": "call_1","content": {"temp": 34,"unit": "℃"}
}

MCP 的精妙之处

  • 统一错误码,让 LLM 可以“优雅地道歉”或“自动重试”。
  • 支持异步调用、批量调用(parallel tool calls),LLM 一次可请求 3~N 个函数。

3. 运行时 → 口语:第三次握手(生成)

现在 LLM 拿到了原始数据,但它不会把 JSON 甩给用户。
它要进行 第二次推理,把结构化结果再翻译成人话:

34℃,体感偏热,紫外线强,出门建议涂 SPF50。

至此,MCP 的三次握手 完成闭环:

  1. 人话 → 结构化(意图解析)
  2. 结构化 → 执行(函数调用)
  3. 执行结果 → 人话(总结回答)

4. 把“握手”做成协议:MCP 架构全景

为了让不同团队、不同语言的模型和工具都能互通,MCP 把上述流程固化为一套协议:

┌────────────┐     MCP Schema     ┌───────────┐
│  LLM Core  │◄──────────────────►│ Registry  │
└────┬───────┘                    └────┬──────┘│ 1. 结构化请求                   │ 2. 函数清单
┌────┴───────┐     JSON-RPC    ┌────┴───────┐
│  Runtime   │◄───────────────►│  Tool A/B  │
└────────────┘                 └────────────┘
  • Registry:函数清单 + JSON Schema,可热更新。
  • Runtime:沙箱、鉴权、限流、重试、日志。
  • LLM Core:只关心“我要调什么、结果长啥样”,其余全部交给协议层。

5. 开发者如何落地 MCP?

  1. 定义函数
    用 JSON Schema 写一个 get_weather.json​,放进 registry。

  2. 接入 Runtime
    Python/Java/Go 都有官方 SDK,三行代码起一个本地 server。

  3. 调教 LLM
    在 prompt 里加一句:

    你只能用以下函数:get_weather, book_restaurant...
    

    或者 fine-tune 一个小模型专门做解析器。


6. 小结:记住一句话

MCP 把“人话 ↔ 函数”的黑盒拆成了可观测、可插拔的三次握手。
开发者只需写好函数,剩下的事交给协议。


7. 彩蛋:如果用户问“帮我订今晚 7 点海底捞”?

  1. 解析器输出:

    {"name": "book_restaurant","arguments": {"brand": "海底捞","date": "2025-07-29","time": "19:00","people": 2}
    }
    
  2. 运行时返回:

    {"order_id": "HN12345", "wait_time": 30}
    
  3. LLM 回复:

    已为您预订今晚 7 点海底捞,预计等位 30 分钟,订单号 HN12345。
    

附 Python 代码

工具函数代码

# tools.py
def get_current_weather(location):"""获取指定城市的实时天气信息注意:实际项目中应接入真实天气 API,这里仅为示例"""# 模拟返回天气数据(实际项目中应调用高德、OpenWeatherMap 等)weather_data = {"location": location,"temperature": "26°C","condition": "多云","humidity": "65%"}return weather_datadef calculate_temperature(num1, num2, operation):"""支持加减乘除四种运算"""if operation == "add":return num1 + num2elif operation == "subtract":return num1 - num2elif operation == "multiply":return num1 * num2elif operation == "divide":if num2 == 0:raise ValueError("除数不能为零")return num1 / num2else:raise ValueError(f"未知运算类型: {operation}")if __name__ == "__main__":print(calculate_temperature(966, 69, "add"))

调用模型代码

# qwq_mcp.py
import os
import json
from openai import OpenAI
from tools import get_current_weather, calculate_temperature# 初始化客户端
client = OpenAI(api_key="sk-0f0dac238000000000000000000000",  # 替换为你的实际 API Keybase_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)# 定义可用工具
tools = [{"type": "function","function": {"name": "get_current_weather","description": "获取指定城市的实时天气信息","parameters": {"type": "object","properties": {"location": {"type": "string", "description": "城市名称,如杭州市"}},"required": ["location"]}}},{"type": "function","function": {"name": "get_current_time","description": "获取当前时间","parameters": {}}},{"type": "function","function": {"name": "calculate","description": "执行两个数字的加减乘除运算","parameters": {"type": "object","properties": {"num1": {"type": "number", "description": "第一个操作数"},"num2": {"type": "number", "description": "第二个操作数"},"operation": {"type": "string","description": "运算类型:'add', 'subtract', 'multiply', 'divide'","enum": ["add", "subtract", "multiply", "divide"]}},"required": ["num1", "num2", "operation"]}}}
]# 用户提问
messages = [{"role": "user", "content": "588+222 等于多少?"}]# 第一次请求:让模型判断是否需要调用工具
completion = client.chat.completions.create(model="qwen3-235b-a22b-instruct-2507",messages=messages,tools=tools,tool_choice='auto'  # 可选:auto, none, 或指定工具
)response_message = completion.choices[0].message    # 获取模型回复
print(" 模型回复:", response_message)# 检查是否需要调用工具
if response_message.tool_calls:# 添加工具调用结果到消息历史messages.append(response_message)# 遍历所有 tool_callsfor tool_call in response_message.tool_calls:function_name = tool_call.function.namefunction_args = json.loads(tool_call.function.arguments)# 执行对应的工具函数if function_name == "get_current_weather":# 这里可以接入真实天气 APIlocation = function_args.get("location", "未知城市")# 模拟返回天气数据(实际项目中应调用高德、OpenWeatherMap 等)weather_data = get_current_weather(location)tool_response_content = json.dumps(weather_data, ensure_ascii=False)elif function_name == "get_current_time":from datetime import datetimecurrent_time = datetime.now().strftime("北京时间 %Y年%m月%d日 %H:%M:%S")tool_response_content = json.dumps({"time": current_time}, ensure_ascii=False)elif function_name == "calculate_temperature":num1= function_args.get("num1", 0)num2 = function_args.get("num2", 0)operation = function_args.get("operation", "add")result = calculate_temperature(num1, num2, operation)tool_response_content = json.dumps(result, ensure_ascii=False)else:tool_response_content = json.dumps({"error": "未知工具"}, ensure_ascii=False)# 将工具执行结果以 role="tool" 的形式加入对话messages.append({"role": "tool","content": tool_response_content,"tool_call_id": tool_call.id  # 必须匹配})# 第二次请求:将工具结果传回模型,生成最终回答final_response = client.chat.completions.create(model="qwen3-235b-a22b-instruct-2507",messages=messages)print("✅ 最终回答:")print(final_response.choices[0].message.content)
else:# 如果模型没有调用工具,直接输出其回复print(" 模型直接回复:")print(response_message.content)

执行后的返回如下

(mcp-test) zy@ztg2:~/mycode/MCP_test$ python qwq_mcp.py 模型回复: ChatCompletionMessage(content='', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_2ba108ca775e465aa1ac0c', function=Function(arguments='{"num1": 588, "num2": 222, "operation": "add"}', name='calculate'), type='function', index=0)])
✅ 最终回答:
588 + 222 = 810。

可以看到第一次请求大模型后,它就把用户的口语完整地解析成工具所需的函数参数格式;运行时(qwq_mcp.py)执行函数后,把结果再次回传给大模型,最终由大模型生成回答。

http://www.vanclimg.com/news/1360.html

相关文章:

  • OBS
  • 屏幕翻译 安卓app
  • 微算法科技(NASDAQ:MLGO)应用区块链联邦学习(BlockFL)架构,实现数据的安全传输
  • 星球助手发布更新 v1.7.0
  • 使用Spring Cloud和Resilience4j实现微服务容错与降级 - spiderMan1
  • WinForm自定义控件实现类似百度网盘客户端菜单组件
  • 【比赛记录】2025CSP-S模拟赛29
  • 树形dp练习
  • python中 命令行参数解析模块 argparse
  • 基于YOLOv8的狗狗品种(多达60种常见犬类)品种鉴别识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
  • 公钥和私钥的部分作用
  • 使用 Kiro AI IDE 3小时实现全栈应用Admin系统
  • soildworks建模界面添加图片
  • 从0开始构建技术
  • Fastmcp 案例二(SSe)
  • Anaconda历史版本
  • 输入未知数目的数据
  • 常见的结构光编解码算法
  • 七月
  • HCIE学习之路:一个NAT实验
  • HCIE学习之路:配置基于静态路由的GRE隧道
  • TOP10迪士尼动画电影下载_公主系列迪士尼电影大全列表在线观看
  • python中pandas包的基本用法
  • 如何用两年时间面试一个人(by jobleap.cn)
  • 2025年PLM合规性管理,6大策略,确保项目合法合规!
  • 如果你还有一些困惑 / 请贴着我的心倾听 - Urd
  • 【IEEE出版】第五届计算机应用、视觉与算法国际学术会议(CVAA 2025)
  • 【SPIE出版】第二届生物医药和智能技术国际学术会议(ICBIT 2025)
  • AI 赋能的云原生应用:技术趋势与实践
  • 移远EC800K, EG800AK的 openSDK 编译