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...

相关推荐
Flynt21 分钟前
diff 里明明没有它,审查评论却落在 notify.js 上
ai编程
ControlRookie1 小时前
SyncBridge:一个 CODESYS 工程与 AI 之间工程师级的同步工具
git·ai编程·codesys·工业软件·controlrookie
xhy_07073 小时前
AI 在同一步上反复打转怎么办?WES Code 循环检测怎么用
人工智能·大模型·ai编程·wes code
孟健5 小时前
200 美元订阅实测:从 Agent 吞吐与缓存机制,算清 Claude 与 OpenAI 的算力账
人工智能·llm·ai编程
HelloWorld0018 小时前
别让上下文撑爆钱包!生产级 Agent 长上下文治理:动态窗口、注意力衰减与摘要状态机实战
ai编程
LEE8 小时前
前端转型全栈 05:SQL 与迁移,AI 写的 SQL 怎么安全上线
前端·后端·ai编程
用户721746588269 小时前
三层时间结构与静音间隔:把 ASR 词级毫秒时间戳变成 SRT 字幕轴
人工智能·ai编程
用户539418729079 小时前
.cursorrules 写了等于没写?我把“让 Cursor 读懂你项目”的规则和上下文整理成一套模板
ai编程·cursor
xiwc9 小时前
AI Helper 实战:从零搭建开源项目的双语 Wiki
开源·ai编程
过客123459 小时前
从"发现"到"处置":一个无人值守 AI 闭环的完整拆解(85 天真实数据)
后端·agent·ai编程