工具

工具设计指南

如何按照统一的合约标准描述、分类和保护 MCP 工具——从低风险到禁止访问。

MCP 工具不是函数调用,而是一份合约。它描述系统能做什么、 谁可以调用它、调用时会发生什么——以及可能出什么问题。 这份合约必须在智能体或用户调用工具之前,就已经是 机器可读的、类型化的且完整的。

没有合约的工具是一个黑箱。黑箱不是 MCP-first 系统。

基本原则

工具合约标准

每个 MCP 工具按照统一 Schema 描述。该 Schema 不仅包含 输入和输出类型,还包括风险等级、权限、副作用、 审计事件和可能的错误情况。只有了解所有字段,才能安全使用工具—— 无论是通过智能体、Web 应用还是自动化 Workflow。

字段概览:

  • Name — 格式为 domain.verb 的唯一机器可读标识符
  • Description — 面向智能体和开发者的自然语言用途描述
  • Category — 业务分类(如 communicationfilesbilling
  • Risk Level — 按风险模型分类(从低到禁止)
  • Autonomous Execution — 智能体是否可以在无人工审批的情况下调用
  • Confirmation — 是否需要明确的用户确认
  • Step-up Auth — 是否需要额外身份验证及触发条件
  • Input Schema — 类型化参数,包含可选字段
  • Output Schema — 类型化返回值,包含状态码
  • Permissions — 工具所需的权限
  • Side Effects — 返回值之外的所有状态变更
  • Audit Event — 写入审计日志的事件
  • Failure Modes — 所有可能错误码的完整列表

以下示例展示了 emails.send_external 的完整合约—— 这是一个会触发外部通信的关键风险工具:

emails.send_external
Critical

向一个或多个收件人发送外部邮件。

Kategorie
communication
Autonome Ausführung
不允许
Bestätigung
Step-up Auth
可选,取决于收件人数量和附件
Audit-Event
email.external.sent

Input-Schema

  • to: string[]
  • subject: string
  • body: string
  • attachments?: fileId[]
  • projectId?: string

Output-Schema

  • emailId: string
  • status: sent | scheduled | failed

Berechtigungen

  • emails:send
  • contacts:read
  • files:read

Fehlerfälle

  • permission_denied
  • confirmation_required
  • invalid_recipient
  • attachment_too_large
  • rate_limit_exceeded
  • policy_violation

Side Effects

  • 发送外部通信。
  • 邮件成为通讯历史的一部分。
  • 生成审计事件。

每个字段在系统中都有其作用:permissions 驱动 Policy 引擎, sideEffects 为确认 UI 提供信息,failureModes 在错误处理中使用, auditEvent 写入审计日志。合约因此不仅仅是文档——它是运行时的一部分。

风险模型

MCP-first 将每个工具归入五个风险等级之一。等级决定智能体是否可以 自主调用该工具、是否需要确认,以及是否需要升级身份验证。 分级不是可选的——它是合约的一部分。

Low(低风险)

Low

这个等级的工具是纯读取的或不产生持久效果。它们可以由智能体 自主执行,无需确认或升级身份验证。典型的有列表查询、搜索和帮助资源。

低风险——示例
  • list_projects Low
  • get_current_user Low
  • search_contacts Low
  • get_help_article Low
  • create_reminder Low

Medium(中等风险)

Medium

这个等级的工具创建数据或状态,但范围严格受限且无外部影响。 当范围和上下文从 Workflow 中明确可见时,可以自主执行。 上下文不明确时建议确认。

中等风险——示例
  • create_note Medium
  • update_task_status Medium
  • generate_summary Medium
  • create_draft Medium

High(高风险)

High

这个等级的工具会更改相关系统状态或影响其他用户和外部资源。 通常需要明确确认。智能体不得静默执行这类工具。

高风险——示例
  • change_project_status High
  • invite_calendar_attendee High
  • share_file_link High
  • update_customer_data High

Critical(关键风险)

Critical

这个等级的工具会触发外部通信、支付、数据删除或权限变更。 它们始终需要明确确认,通常还需要升级身份验证。不允许自主执行。

关键风险——示例
  • emails.send_external Critical
  • bulk_export Critical
  • delete_user Critical
  • change_permissions Critical
  • execute_payment Critical
  • send_contract Critical

Forbidden for AI(禁止 AI 访问)

Forbidden for AI

这个等级的工具既不能被 AI 智能体读取,也不能被其执行。 它们在智能体的工具发现中被完全隐藏。这一分类是硬性边界—— 而非 Policy 决策。

禁止——示例
  • read_private_key Forbidden for AI
  • read_password Forbidden for AI
  • read_raw_access_token Forbidden for AI
  • disable_audit_log Forbidden for AI
  • export_full_database_without_approval Forbidden for AI

智能体不应看到的内容,它就不能找到。Forbidden 工具不出现在发现响应中。

幂等性(Idempotenz)

许多工具在智能体 Workflow 中会被多次调用——通过重试、 并行执行或错误规划。MCP-first 建议尽可能将工具设计为幂等的: 相同输入多次调用产生相同结果,不产生不必要的重复或副作用。

create_download_link 工具是一个很好的例子。如果相同 fileId 和相同 expiresAt 的有效链接已存在,工具会返回该链接, 而不是创建第二个:

create_download_link(fileId: "f_abc123", expiresAt: "2025-12-31T23:59:00Z")

→ 第一次调用:创建新链接,返回 linkId + url
→ 第二次调用(相同参数,链接仍有效):返回相同链接
→ 第三次调用(链接已过期):创建新链接

幂等性必须显式实现——它不会自动产生。 工具合约字段 sideEffects 应描述重复调用的行为, 以便智能体和客户端能够正确规划。

预演(Dry Run)

高风险工具,特别是具有批量效果的工具,应提供预演模式。 预演执行所有验证和检查,但不产生真实的副作用。 结果显示将会发生什么——但实际上什么都不会发生。

emails.bulk_send 配合 dryRun: true 提供完整预览:

// Request
{
  "tool": "emails.bulk_send",
  "params": {
    "templateId": "tmpl_newsletter_q3",
    "segmentId": "seg_active_customers",
    "dryRun": true
  }
}

// Response
{
  "dryRun": true,
  "recipientCount": 4821,
  "sampleMessages": [
    {
      "to": "[email protected]",
      "subject": "Ihr Q3-Update ist da",
      "previewText": "Liebe Anna, im dritten Quartal haben wir…"
    },
    {
      "to": "[email protected]",
      "subject": "Ihr Q3-Update ist da",
      "previewText": "Lieber Max, im dritten Quartal haben wir…"
    }
  ],
  "warnings": [
    "43 Empfänger haben keinen Vornamen – Fallback 'Hallo' wird verwendet.",
    "12 E-Mail-Adressen sind als unzustellbar markiert und werden übersprungen."
  ],
  "missingPermissions": [],
  "expectedSideEffects": [
    "4821 externe E-Mails werden versendet.",
    "4821 Audit-Events vom Typ email.external.sent werden erzeugt.",
    "Kampagnen-Status wird auf 'sent' gesetzt."
  ],
  "estimatedDurationMs": 18400
}

只有在用户审查预演结果并明确确认后,才会执行不带 dryRun 的真实调用。 如果工具将预演声明为必要条件,智能体不得跳过预演。