MCP Quickstart 源码解析:processQuery 如何完成 Claude Tool Calling

理解 Anthropic Tool Use 消息流

本文结合源码,分析 processQuery() 的完整执行流程,并解释 Anthropic Tool Use API 的消息模型。

核心职责

processQuery() 的职责可以概括为:

  1. 接收用户问题
  2. 发送给 Claude
  3. 处理 Claude 发起的 Tool Use
  4. 调用 MCP Tool
  5. 将工具结果返回给 Claude
  6. 获取最终答案

整个流程本质上是一个标准的 Tool Calling 循环。


第一步:用户发起请求

用户输入:

复制代码
北京天气怎么样?

客户端构造消息:

ini 复制代码
const messages = [
  {
    role: "user",
    content: "北京天气怎么样?"
  }
];

当前消息历史:

sql 复制代码
user
└─ 北京天气怎么样?

第二步:Claude 请求调用工具

客户端调用:

csharp 复制代码
const response = await anthropic.messages.create(...)

Claude 判断需要查询天气,因此返回:

json 复制代码
{
  "type": "tool_use",
  "id": "toolu_001",
  "name": "weather",
  "input": {
    "city": "北京"
  }
}

此时源码执行:

php 复制代码
messages.push({
  role: "assistant",
  content: response.content as ContentBlockParam[]
});

消息历史变为:

scss 复制代码
user
└─ 北京天气怎么样?

assistant
└─ tool_use(weather)

这里保存的是 Claude 的完整响应内容,而不仅仅是工具名称。


第三步:调用 MCP Tool

客户端根据 Tool Use 信息调用 MCP Server:

php 复制代码
const result = await this.mcp.callTool({
  name: "weather",
  arguments: {
    city: "北京"
  }
});

工具返回:

json 复制代码
{
  "temperature": 28,
  "condition": "Sunny"
}

第四步:构造 Tool Result

这是很多人最容易疑惑的地方。

源码会把工具执行结果作为新的消息加入:

php 复制代码
messages.push({
  role: "user",
  content: [
    {
      type: "tool_result",
      tool_use_id: content.id,
      content: result.content
    }
  ]
});

注意:

vbnet 复制代码
role: "user"

而不是:

vbnet 复制代码
role: "tool"

这是 Anthropic Tool Use API 的设计要求。

消息历史变为:

scss 复制代码
user
└─ 北京天气怎么样?

assistant
└─ tool_use(weather)

user
└─ tool_result(28°C Sunny)

第五步:获取最终答案

再次调用 Claude:

csharp 复制代码
const finalResponse =
  await anthropic.messages.create(...)

Claude 收到工具结果后生成最终回复:

复制代码
北京当前温度为 28°C,天气晴朗。

消息流最终变成:

scss 复制代码
user
assistant(tool_use)
user(tool_result)
assistant(final answer)

为什么 Tool Result 的 Role 是 User?

很多开发者接触 OpenAI API 后会习惯这种模式:

scss 复制代码
user
assistant(tool_call)
tool
assistant

而 Anthropic 的设计不同:

scss 复制代码
user
assistant(tool_use)
user(tool_result)
assistant

原因是 Anthropic 将工具结果视为"外部环境返回的信息",统一由 user 角色提交给模型。

因此 Tool Result 必须放在:

vbnet 复制代码
role: "user"

中,并使用:

bash 复制代码
type: "tool_result"

进行标识。


processQuery 的本质

从架构角度看,processQuery() 实现的是一个最基础的 Agent Loop:

sql 复制代码
User Query
    ↓
Claude
    ↓
Tool Use
    ↓
MCP Tool
    ↓
Tool Result
    ↓
Claude
    ↓
Final Answer

其中最关键的两步是:

php 复制代码
messages.push({
  role: "assistant",
  content: response.content
});

保存 Claude 的 Tool Use 请求。

以及:

php 复制代码
messages.push({
  role: "user",
  content: [{
    type: "tool_result",
    ...
  }]
});

将工具执行结果返回给 Claude。

理解这两个消息的作用后,整个 MCP Client 的执行流程就非常清晰了。

总结

processQuery() 遵循的是 Anthropic Tool Use 标准协议,其完整角色流为:

scss 复制代码
user
assistant(tool_use)
user(tool_result)
assistant(final answer)

与 OpenAI 的 tool 角色不同,Anthropic 将工具执行结果包装为 user + tool_result 消息重新提交给模型。理解这一点,是理解 MCP Client、Claude Tool Calling 以及后续 Agent 框架实现的关键基础。

源码:github.com/modelcontex...

相关推荐
唐老板2 小时前
MCP协议实战:从零写个Agent工具
ai编程·mcp
counterxing2 小时前
最近发现一个 Mac 工具,有点像把 Raycast、语音输入法、截图和录屏塞到了一起
macos·ai编程·claude
薛定喵的谔2 小时前
Term Proxy — 用 Tauri 2 打造跨平台终端配置管理工具
electron·ai编程·全栈
小溪彼岸3 小时前
CC Switch可视化管理Skill、提示词、会话
aigc·ai编程
码哥字节6 小时前
为什么 Claude Code 读你的代码库,光靠 embedding 根本不够?
claude·代码规范
aqi006 小时前
15天学会AI应用开发(九)利用Chroma持久化向量数据
人工智能·python·大模型·ai编程·ai应用
kfaino8 小时前
你好,我叫 Prompt——其实,你一直在给 AI 写程序
后端·openai·ai编程
kfaino17 小时前
你好,我叫Token——AI世界里最忙的搬砖工
aigc·openai·ai编程
程序员老刘18 小时前
Flutter版本选择指南:3.44系列继续观望 | 2026年6月
flutter·ai编程·客户端