MCP 工具调用中的常见问题与实战解决方案

这是 MCP 落地中非常典型的问题,核心原因在于 工具描述(Tool Description)和参数 Schema 的信息密度不够,模型缺乏足够的上下文来做出正确决策。下面分两个维度系统性地拆解。


一、模型分不清类似接口

问题本质

当多个工具功能相近时,模型看到的 tool definition 可能长这样:

// 模型视角下的两个模糊工具
{ "name": "get_user",      "description": "获取用户信息" }
{ "name": "get_user_info", "description": "获取用户详细信息" }

模型无法判断该调哪个。

解决方案

1. 工具描述中写清「何时用」和「何时不用」
{
  "name": "get_user_basic",
  "description": "根据用户 ID 获取用户的基本信息(姓名、邮箱、手机号)。仅需要用户基本信息时使用。如果需要用户的订单、权限或偏好设置,请使用 get_user_profile。"
}

关键原则:描述不只是「这个工具做什么」,而是「什么时候该用它,什么时候不该用」。

2. 用 MCP 的 annotations 字段做区分

MCP 协议支持 annotations,可以给工具加元数据:

{
  "name": "search_products",
  "description": "搜索商品",
  "annotations": {
    "category": "product",
    "useCase": "用户想要找某个具体商品时使用",
    "contrastWith": "list_products(用于浏览商品列表,非搜索场景)"
  }
}
3. 合并相似工具为一个,用参数区分
// 改造前:两个容易混淆的工具
// get_user_by_id / get_user_by_email

// 改造后:一个工具,参数区分
{
  "name": "get_user",
  "description": "根据 ID 或邮箱获取用户信息。必须且只能提供 identifier_type 和 identifier 两个参数。",
  "inputSchema": {
    "type": "object",
    "properties": {
      "identifier_type": {
        "type": "string",
        "enum": ["id", "email"],
        "description": "查询方式:'id' 表示用户 ID,'email' 表示邮箱地址"
      },
      "identifier": {
        "type": "string",
        "description": "对应的查询值,需与 identifier_type 匹配"
      }
    },
    "required": ["identifier_type", "identifier"]
  }
}
4. 工具命名用动词前缀做语义分组
✅ 好的命名
user_get          → 获取用户
user_update       → 更新用户
order_list        → 列出订单
order_get_detail  → 获取订单详情

❌ 差的命名
getUser
getUserInfo
getUserDetail
getUserData

二、参数传递问题

问题 1:不知道 type 传什么

原因:枚举值没有暴露给模型
// 模糊的 Schema
{ "type": { "type": "string", "description": "类型" } }

模型完全不知道 "type" 可以取什么值。

解决方案

用 enum 把所有合法值列出来:

{
  "type": {
    "type": "string",
    "enum": ["personal", "enterprise", "government", "education"],
    "description": "账户类型。'personal'=个人用户,'enterprise'=企业用户,'government'=政府机构,'education'=教育机构。如果用户没有明确指定,默认为 'personal'。"
  }
}

如果枚举值太多或动态变化,在 description 中说明获取方式:

{
  "category_id": {
    "type": "string",
    "description": "商品分类 ID。如果用户未指定分类,请先调用 list_categories 获取可用分类列表及其 ID,再从中选择。"
  }
}

问题 2:不知道 id 传什么

这是实战中最高频的问题。模型不知道该传什么 ID,或者从哪里获取。

解决方案 A:在参数描述中写清 ID 的来源和格式
{
  "order_id": {
    "type": "string",
    "description": "订单 ID,格式为 'ORD-' 开头加 12 位数字(如 ORD-202401010001)。可通过 search_orders 或 get_user_orders 获取。"
  }
}
解决方案 B:设计「搜索 → 选择 → 操作」的工具链
工具链设计:
  search_user(name/email) → 返回 user_id 列表
  get_user(user_id)       → 返回用户详情
  update_user(user_id, …) → 更新用户

在每个工具的描述中明确写出「上游依赖」:

{
  "name": "update_user",
  "description": "更新用户信息。user_id 必须来自 search_user 的返回结果,不要猜测或编造 ID。",
  "inputSchema": {
    "properties": {
      "user_id": {
        "type": "string",
        "description": "用户 ID,必须通过 search_user 工具获取。格式示例:'usr_8a3b2c1d'"
      }
    }
  }
}
解决方案 C:提供一个「万能查询」工具兜底
{
  "name": "resolve_entity",
  "description": "当不确定某个实体(用户/订单/商品)的 ID 时,用自然语言描述来查找对应的 ID。这是 ID 解析的兜底工具。",
  "inputSchema": {
    "properties": {
      "entity_type": {
        "type": "string",
        "enum": ["user", "order", "product"],
        "description": "要查找的实体类型"
      },
      "query": {
        "type": "string",
        "description": "自然语言描述,如 '张三的账号'、'上周的退货订单'、'iPhone 15'"
      }
    },
    "required": ["entity_type", "query"]
  }
}

三、系统性最佳实践总结

┌─────────────────────────────────────────────────────────┐
│              MCP 工具设计检查清单                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  1. 每个工具的 description 是否回答了:                    │
│     ✅ 它做什么                                          │
│     ✅ 什么时候该用它                                     │
│     ✅ 什么时候不该用它(该用哪个替代工具)                  │
│                                                         │
│  2. 每个参数的 description 是否回答了:                    │
│     ✅ 取值范围是什么(enum / format)                     │
│     ✅ 从哪里获取(哪个上游工具的返回值)                   │
│     ✅ 有没有默认值                                       │
│     ✅ 给出一个示例值                                     │
│                                                         │
│  3. 工具之间的调用关系是否清晰:                           │
│     ✅ 搜索类 → 获取类 → 操作类 的链路是否完整              │
│     ✅ 是否有兜底工具处理模糊查询                          │
│                                                         │
│  4. 错误信息是否对模型友好:                               │
│     ✅ 参数不合法时返回可操作的错误提示                     │
│     ✅ 不要只返回 "error",要返回 "请提供 X,格式为 Y"     │
│                                                         │
└─────────────────────────────────────────────────────────┘

最关键的一条经验

把工具描述当作给一个「聪明但完全不了解你业务的新人」写的交接文档。

模型的能力上限,很大程度上取决于你给它的上下文质量。MCP 工具的 description 和 parameter schema,本质上就是你和模型之间的「接口契约」——写得越精确,模型调用得越准确。


四、进阶:用 System Prompt 补充业务上下文

如果工具 Schema 空间有限,可以在 MCP Server 的 instructions 或系统提示中补充:

你当前可以使用以下 MCP 工具。使用前请注意:

- 所有 ID 参数必须通过搜索类工具获取,禁止自行编造
- "type" 字段只能使用工具定义中 enum 列出的值
- 如果用户描述模糊,优先调用 search/resolve 类工具缩小范围
- 如果不确定该调哪个工具,先调用 help 工具查看工具使用指南

这样在 Schema 层面和 Prompt 层面形成双重保障。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐