Skip to content

MCP Function Tools 接口设计 —— 如何用有限的接口覆盖无限的意图

在 Dotamate 的开发过程中,我们遇到了许多技术挑战。以下是一些主要问题以及我们的思考和解决方案:

Q1: MCP Function Tools 接口设计 —— 如何用有限的接口覆盖无限的意图?

背景

在使用 MCP (Model Context Protocol) 为 AI 暴露 Function Tools 时,我发现一个核心矛盾:AI 的能力很大程度上取决于你提供了多少接口、接口做了什么。 这导致我们总想着提供更多的接口,因为似乎变成了——我们提供什么,AI 才知道什么。

问题场景

以 Dota2 英雄(静态资源)查询为例,用户的意图是非常多维和发散的:

  • "查询有多少个英雄"
  • "查询影魔的具体属性"
  • "按照英雄 ID 查询"
  • "查询英雄下的某个技能详情"
  • 反向查询:"谁有 Toss 技能?列出所有英雄"

如果一个英雄有 100 个属性字段,我们很难写 100 个接口,也无法前置所有特定查询接口,因为:

  1. 总会漏掉意图 —— 用户想查什么是不确定的
  2. 接口膨胀 —— 会写大量零散的、功能重复的接口
  3. 维护成本高 —— 每增加一个字段就要加接口

解决方案

经过思考,总结出三种互补的策略:

方案一:Schema 描述增强(低成本,高收益)

在 Tool 的描述中增加结构化的文本字段说明,就像描述一张表一样,说明每个字段的含义和主要用途。

Tool: query_hero
Description: 查询 Dota2 英雄数据
Schema Fields:
  - id: 英雄唯一标识 (int)
  - name: 英雄英文名 (string)
  - localized_name: 英雄中文名 (string)
  - primary_attr: 主属性 (str/agi/int)
  - attack_type: 攻击类型 (Melee/Ranged)
  - roles: 角色定位列表 (Carry/Support/Nuker...)
  - base_health: 基础生命值 (int)
  - base_mana: 基础魔法值 (int)
  - move_speed: 移动速度 (int)
  - ... (完整字段列表)

本质上是提示词工程 —— 这段结构化描述 AI 能读懂,它会自行判断用户意图对应哪个字段,然后构造合适的查询参数。

方案二:通用查询过滤器(一套接口覆盖所有场景)

提供一个通用的查询过滤接口,定义宽泛的查询条件协议,让 AI 自己组装过滤条件:

json
{
  "tool": "query_heroes",
  "parameters": {
    "filters": [
      { "field": "primary_attr", "op": "eq", "value": "str" },
      { "field": "base_health", "op": "gte", "value": 600 }
    ],
    "fields": ["id", "name", "localized_name", "base_health"],
    "limit": 10,
    "sort": { "field": "base_health", "order": "desc" }
  }
}

支持的通用操作符:eq / neq / gt / gte / lt / lte / in / contains / startswith

核心思路:不给 AI 提供具体的查询接口,而是提供一种查询能力,让 AI 自己编写过滤器。

方案三:反向映射接口(解决"倒查"场景)

对于反向查询(如"谁有 Toss 技能"),提供专门的反向索引接口

json
{
  "tool": "reverse_lookup",
  "parameters": {
    "target_type": "ability",
    "target_value": "Toss",
    "return_fields": ["hero_id", "hero_name", "ability_slot"]
  }
}

这类接口的关键在于建立反向索引,将属性值映射到实体,而不是从实体遍历属性。

三种方案的选择建议

方案适用场景成本灵活性
Schema 描述字段含义明确、查询模式相对固定
通用过滤器数据字段多、查询组合丰富
反向映射倒查、属性到实体的映射针对性强

实践中建议组合使用 先用 Schema 描述覆盖 80% 的常见查询,再用通用过滤器兜底复杂组合查询,最后为高频倒查场景单独建反向索引。


基于 VitePress 构建