MCP 工具不是函数调用,而是一份合约。它描述系统能做什么、 谁可以调用它、调用时会发生什么——以及可能出什么问题。 这份合约必须在智能体或用户调用工具之前,就已经是 机器可读的、类型化的且完整的。
没有合约的工具是一个黑箱。黑箱不是 MCP-first 系统。
工具合约标准
每个 MCP 工具按照统一 Schema 描述。该 Schema 不仅包含 输入和输出类型,还包括风险等级、权限、副作用、 审计事件和可能的错误情况。只有了解所有字段,才能安全使用工具—— 无论是通过智能体、Web 应用还是自动化 Workflow。
字段概览:
- Name — 格式为
domain.verb的唯一机器可读标识符 - Description — 面向智能体和开发者的自然语言用途描述
- Category — 业务分类(如
communication、files、billing) - 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 向一个或多个收件人发送外部邮件。
Input-Schema
to: string[]subject: stringbody: stringattachments?: fileId[]projectId?: string
Output-Schema
emailId: stringstatus: sent | scheduled | failed
Berechtigungen
emails:sendcontacts:readfiles:read
Fehlerfälle
permission_deniedconfirmation_requiredinvalid_recipientattachment_too_largerate_limit_exceededpolicy_violation
每个字段在系统中都有其作用:permissions 驱动 Policy 引擎,
sideEffects 为确认 UI 提供信息,failureModes 在错误处理中使用,
auditEvent 写入审计日志。合约因此不仅仅是文档——它是运行时的一部分。
风险模型
MCP-first 将每个工具归入五个风险等级之一。等级决定智能体是否可以 自主调用该工具、是否需要确认,以及是否需要升级身份验证。 分级不是可选的——它是合约的一部分。
Low(低风险)
Low这个等级的工具是纯读取的或不产生持久效果。它们可以由智能体 自主执行,无需确认或升级身份验证。典型的有列表查询、搜索和帮助资源。
-
list_projectsLow -
get_current_userLow -
search_contactsLow -
get_help_articleLow -
create_reminderLow
Medium(中等风险)
Medium这个等级的工具创建数据或状态,但范围严格受限且无外部影响。 当范围和上下文从 Workflow 中明确可见时,可以自主执行。 上下文不明确时建议确认。
-
create_noteMedium -
update_task_statusMedium -
generate_summaryMedium -
create_draftMedium
High(高风险)
High这个等级的工具会更改相关系统状态或影响其他用户和外部资源。 通常需要明确确认。智能体不得静默执行这类工具。
-
change_project_statusHigh -
invite_calendar_attendeeHigh -
share_file_linkHigh -
update_customer_dataHigh
Critical(关键风险)
Critical这个等级的工具会触发外部通信、支付、数据删除或权限变更。 它们始终需要明确确认,通常还需要升级身份验证。不允许自主执行。
-
emails.send_externalCritical -
bulk_exportCritical -
delete_userCritical -
change_permissionsCritical -
execute_paymentCritical -
send_contractCritical
Forbidden for AI(禁止 AI 访问)
Forbidden for AI这个等级的工具既不能被 AI 智能体读取,也不能被其执行。 它们在智能体的工具发现中被完全隐藏。这一分类是硬性边界—— 而非 Policy 决策。
-
read_private_keyForbidden for AI -
read_passwordForbidden for AI -
read_raw_access_tokenForbidden for AI -
disable_audit_logForbidden for AI -
export_full_database_without_approvalForbidden 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 的真实调用。
如果工具将预演声明为必要条件,智能体不得跳过预演。