AI Agent 开发学习与面试指南:05-Tool Calling 与 MCP 协议实战

分析 Tool Use 的 JSON Schema 约束与副作用隔离,构建符合 MCP (Model Context Protocol) 规范的标准化工具服务,并探讨安全与幂等控制。

本文目录26 个章节

第 5 章:Tool Calling 与 MCP

Tool 让模型从“生成文本”升级为“读取真实状态、执行动作”。也正因为如此,Tool 是 Agent 系统最大的能力放大器和风险放大器。一个优秀 Tool 不仅要能调用,还要有清晰 Schema、权限、幂等、审计、错误语义和人类可理解的影响说明。

1. Tool 是受控能力接口

模型不应直接获得数据库连接、Shell 或任意 HTTP 访问。应该把业务能力包装成窄接口:

TEXT
不推荐:execute_sql(sql: string)
推荐:get_order_status(order_id: string)

不推荐:http_request(url, method, body)
推荐:create_refund_request(order_id, reason, amount)

窄接口的优势:

  • 权限边界清楚;
  • 参数容易校验;
  • 可观测和可评测;
  • 更容易实现幂等和审批;
  • 降低 Prompt Injection 造成任意操作的风险。

🔥 P0 高频必会:为什么不直接给 Agent 一个通用 SQL 工具?
通用 SQL 权限过大,难以验证查询意图、资源消耗和数据泄露风险。优先提供面向业务的只读窄工具;确需 SQL 时使用只读账号、允许表/列、查询解析、行数与超时限制、租户过滤和审计。

2. 好 Tool Schema 的六个条件

  1. 名称表达单一动作;
  2. 描述写清“何时用”和“何时不用”;
  3. 输入类型、枚举、长度和格式受约束;
  4. 输出结构稳定;
  5. 错误使用机器可读错误码;
  6. 副作用和审批要求可被应用层识别。
PYTHON
from decimal import Decimal
from typing import Literal

from pydantic import BaseModel, Field


class RefundRequest(BaseModel):
    order_id: str = Field(pattern=r"^ORD-[0-9]{8}$")
    reason: Literal["duplicate_charge", "not_received", "quality_issue", "other"]
    amount: Decimal = Field(gt=0, max_digits=10, decimal_places=2)
    idempotency_key: str = Field(min_length=16, max_length=128)


class RefundResult(BaseModel):
    request_id: str
    status: Literal["pending_review", "approved", "rejected"]
    message: str

金额不要用二进制浮点数;订单号不要只校验“非空”;幂等键应由可信应用层生成或验证,不能让模型随意重复生成新键绕过幂等。

3. Tool 返回值要帮助恢复

错误返回不要只有自然语言:

PYTHON
from typing import Literal
from pydantic import BaseModel


class ToolError(BaseModel):
    code: Literal[
        "NOT_FOUND",
        "PERMISSION_DENIED",
        "INVALID_STATE",
        "RATE_LIMITED",
        "TEMPORARY_UNAVAILABLE",
    ]
    retryable: bool
    user_fixable: bool
    message: str
    missing_fields: list[str] = []

Agent 可以根据 retryable 决定系统重试,根据 user_fixable 决定追问;PERMISSION_DENIED 必须直接拒绝,不能把错误交给模型“想办法绕过”。

4. Tool Calling 的完整执行循环

不同模型 SDK 格式不同,但应用层逻辑应一致:

PYTHON
async def run_tool_loop(model, tool_registry, messages, max_steps=6):
    for step in range(max_steps):
        response = await model.respond(
            messages=messages,
            tools=tool_registry.schemas(),
        )

        if response.final_text is not None:
            return response.final_text

        for call in response.tool_calls:
            tool = tool_registry.get(call.name)

#            # 1. 工具允许列表
            if tool is None:
                result = {"error": {"code": "UNKNOWN_TOOL", "retryable": False}}
            else:
#                # 2. Schema 校验
                args = tool.input_model.model_validate(call.arguments)

#                # 3. 权限和风险策略
                decision = await authorize_tool(tool, args)
                if decision.requires_approval:
                    return await pause_for_approval(call, decision)

#                # 4. 超时、幂等、审计由执行器负责
                result = await tool_executor.execute(tool, args)

#            # 5. 工具结果和 call_id 必须对应回传
            messages.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": result,
            })

    raise RuntimeError("agent exceeded maximum tool steps")

模型提出调用不等于系统必须执行。校验、鉴权、审批和预算都发生在可信代码中。

🔥 P0 高频必会:模型调用 Tool 前要做哪些检查?
工具是否允许;参数 Schema;用户身份与资源权限;当前业务状态;风险等级和审批;幂等键;速率/成本预算;目标是否属于当前租户;敏感字段是否需要脱敏。

5. 工具风险分级

等级示例建议控制
R0 公开只读查公开天气、公开文档限流、超时、日志
R1 私有只读查用户订单、内部知识身份、租户、字段权限、审计
R2 可逆写入创建草稿、创建工单幂等、审批策略、撤销能力
R3 外部影响发邮件、改日程、提交退款明确确认、预览影响、强审计
R4 不可逆/高危删除数据、执行代码、转账默认禁止或强人工审批、沙箱、双人复核

风险应在 Tool 元数据中定义,而不是让模型判断自己是否危险。

6. 幂等、事务与补偿

工具的可靠执行需要三种机制:

  • 幂等:重复调用效果不变;
  • 事务:一组本地操作全部成功或全部回滚;
  • 补偿:跨系统无法原子回滚时,定义撤销动作。

例如“订机票并写日历”跨两个系统,无法保证分布式事务。可以:先锁定行程、写待确认记录、用户确认后订票、成功后写日历;日历失败则重试或补写,而不是取消已出票机票。

⭐ P1:Saga 和 Agent 有什么关系?
Agent 决定业务步骤时仍必须服从事务边界。跨服务流程可用 Saga 的补偿动作管理部分失败;补偿策略是确定性业务设计,不能临时让模型编造。

7. 什么是 MCP

Model Context Protocol(MCP)用标准协议连接 AI 应用与外部能力。当前教程按 2025-11-25 规范讲解。MCP 使用 JSON-RPC,规范使用 JSON Schema 进行验证。

MCP Server 主要暴露三类原语:

原语控制方用途
Tools模型请求调用执行动作或动态查询
Resources应用选择提供只读上下文,如文件、数据库 Schema、文档
Prompts用户选择预定义工作模板

官方说明可见 Understanding MCP servers。

🔥 P0 高频必会:MCP 和 Function Calling 有什么区别?
Function Calling 是模型请求调用结构化函数的能力;MCP 是客户端与外部 Server 发现并调用 Tools、Resources、Prompts 的标准协议。MCP 可以承载工具,但不替代模型的工具选择能力、应用层权限和审批。

8. MCP 架构

TEXT
用户
  -> Host(AI 应用)
      -> MCP Client A -> MCP Server A(知识库)
      -> MCP Client B -> MCP Server B(工单系统)
      -> MCP Client C -> MCP Server C(日历)
  • Host 管理模型、会话、权限与用户体验;
  • Client 与单个 Server 协议通信、协商能力;
  • Server 暴露具体 Tools/Resources/Prompts;
  • Server 不应默认信任模型或来自其他 Server 的内容。

9. 实现一个最小 MCP Server

官方 Python 教程使用 FastMCP,类型标注和 Docstring 会生成工具定义。参见 Build an MCP server。

PYTHON
from typing import Literal

from mcp.server.fastmcp import FastMCP
from pydantic import Field


mcp = FastMCP("support-tools")


@mcp.tool()
async def get_ticket_status(
    ticket_id: str = Field(pattern=r"^T-[0-9]{6}$"),
) -> dict:
    """查询工单状态。仅用于读取,不修改工单。"""
#    # 实际实现应从认证上下文获得 user_id,而不是让模型传入任意用户。
    return {
        "ticket_id": ticket_id,
        "status": "open",
        "updated_at": "2026-07-22T10:00:00Z",
    }


@mcp.tool()
async def create_ticket_draft(
    title: str = Field(min_length=5, max_length=120),
    category: Literal["billing", "technical", "other"] = "other",
) -> dict:
    """创建工单草稿,不提交;提交必须由用户在界面确认。"""
    return {
        "draft_id": "D-000001",
        "title": title,
        "category": category,
        "status": "draft",
        "requires_user_confirmation": True,
    }


if __name__ == "__main__":
    mcp.run(transport="stdio")

安装方式以官方 SDK 当前说明为准,示例通常使用:

BASH
uv add "mcp[cli]"

STDIO 日志陷阱

STDIO 传输下,标准输出承载协议消息。官方教程明确警告:不要用 print() 写 stdout,否则会破坏 JSON-RPC。日志应写 stderr 或文件。

PYTHON
import logging
import sys

logging.basicConfig(stream=sys.stderr, level=logging.INFO)

这是非常典型的 MCP 面试细节。

10. Resources 和 Tools 怎么选

使用 Resource:

  • 内容只读;
  • Host 决定何时把数据放入上下文;
  • 数据类似文件、Schema、说明文档;
  • 不希望模型把读取当“动作”。

使用 Tool:

  • 需要动态查询;
  • 有参数;
  • 会产生动作或副作用;
  • 模型需要根据任务决定是否调用。

不要把大文件通过 Tool 一次性返回。可以用 Resource URI 或搜索 Tool 返回摘要与引用,再由客户端选择读取。

11. MCP 授权

对 HTTP 传输,2025-11-25 规范定义了基于 OAuth 2.1 的授权框架和 Protected Resource Metadata。核心安全点:

  • Access Token 必须绑定目标资源;
  • Server 必须验证 Token Audience;
  • 禁止把收到的 Token 直接透传给下游;
  • 使用最小权限 Scope;
  • HTTPS、PKCE、短期 Token、安全存储;
  • 不在日志中记录 Token、授权码或密钥。

参见 MCP Authorization。STDIO 通常从环境或宿主安全上下文获取凭据,不套用 HTTP OAuth 流程。

🔥 P0 高频必会:为什么 Token Passthrough 危险?
下游可能错误接受并非为它签发的 Token,造成权限混淆和 confused deputy。MCP Server 应验证入站 Token 只用于自己;访问下游时使用单独、面向下游签发的凭据。

12. Tool 描述注入与供应链风险

MCP Server 的 Tool 描述也属于外部输入。Host 不应连接任意未知 Server 后自动授予高权限。需要:

  • Server 允许列表和签名/来源校验;
  • 展示 Server 与 Tool 权限;
  • 用户确认高风险能力;
  • Tool 描述与 Schema 审查;
  • 依赖锁定和漏洞扫描;
  • 连接隔离、网络限制和速率限制;
  • 审计 Server 版本变化。

13. Tool 评测

至少评测四层:

  1. 选择正确性:是否选对工具;
  2. 参数正确性:字段、类型、业务约束;
  3. 执行正确性:超时、重试、幂等、权限;
  4. 轨迹效率:是否重复调用、步骤是否过多。

示例数据:

JSON
{
  "input": "查询工单 T-123456 的状态",
  "expected_tool": "get_ticket_status",
  "expected_arguments": {"ticket_id": "T-123456"},
  "forbidden_tools": ["create_ticket_draft"],
  "max_tool_calls": 1
}

14. 本章练习

练习 A:工具注册表

实现包含 Tool Schema、风险等级、权限 Scope、超时和幂等属性的 Registry。执行前统一做验证。

练习 B:MCP Server

实现三个能力:只读工单查询 Tool、创建草稿 Tool、客服政策 Resource。STDIO 下日志只能写 stderr。

练习 C:安全红队

测试:未知 Tool、越权订单号、重复幂等键、恶意 Tool 参数、工具描述注入、模型重复写调用和审批绕过。

15. 面试高频问答

🔥 P0:如何设计一个可靠 Tool?

窄业务能力、严格输入/输出 Schema、明确错误码、最小权限、服务端身份上下文、超时、有限重试、幂等、风险分级、审批和审计。再用工具选择、参数与副作用测试验证。

🔥 P0:MCP 的 Tools、Resources、Prompts 分别是什么?

Tools 是模型可请求执行的动作;Resources 是应用控制的只读上下文;Prompts 是用户选择的模板。三者控制方不同,不能把所有能力都塞成 Tool。

🔥 P0:Tool 调用失败后怎么办?

先分类:瞬时错误系统重试;参数错误可让模型有限修正;缺信息向用户追问;权限错误直接拒绝;副作用不确定先按幂等键查询结果,不能盲目重复写。

⭐ P1:MCP 为什么不能自动解决安全问题?

协议提供发现、调用和授权机制,但 Server 是否可信、Tool 是否过权、用户是否批准、业务参数是否合法、是否沙箱执行仍由 Host/Server 实现。标准化连接不等于标准化信任。

⭐ P1:如何控制 Tool 数量过多导致的选择退化?

按场景动态暴露小工具集;先路由再提供 Tools;改进描述与互斥边界;按权限过滤;评测混淆矩阵;把高度相近的工具合并或增加确定性规则。

16. 本章完成标准

  • 能设计窄、类型化、幂等的工具;
  • 能实现模型请求—校验—授权—审批—执行—回传闭环;
  • 能解释 MCP Host/Client/Server 和三类原语;
  • 能实现并运行最小 MCP Server;
  • 能说明 HTTP 授权、Token Audience 和禁止透传;
  • 有工具选择、参数、权限和重复调用测试。

REFERENCES

参考链接

  1. 012025-11-25 规范
  2. 02Understanding MCP servers
  3. 03Build an MCP server
  4. 04MCP Authorization

所属系列

AI Agent 开发学习与面试指南

下一步

继续浏览相关主题

沿着同一主题继续阅读。

查看最新资讯