跳转到主要内容
自定义工具通过让您定义 Claude 在对话期间可以调用的自己的函数来扩展 Agent SDK。使用 SDK 的进程内 MCP 服务器,您可以让 Claude 访问数据库、外部 API、特定领域的逻辑或应用程序需要的任何其他功能。 本指南涵盖如何使用输入架构和处理程序定义工具、将它们捆绑到 MCP 服务器中、将它们传递给 query,以及控制 Claude 可以访问哪些工具。它还涵盖错误处理、工具注释和返回非文本内容(如图像)。

快速参考

创建自定义工具

工具由四个部分定义,作为参数传递给 TypeScript 中的 tool() 助手或 Python 中的 @tool 装饰器:
  • 名称: Claude 用来调用工具的唯一标识符。
  • 描述: 工具的功能。Claude 读取此内容以决定何时调用它。
  • 输入架构: Claude 必须提供的参数。在 TypeScript 中,这始终是 Zod 架构,处理程序的 args 会自动从中获得类型。在 Python 中,这是一个将名称映射到类型的字典,如 {"latitude": float},SDK 会为您将其转换为 JSON Schema。Python 装饰器还接受完整的 JSON Schema 字典,当您需要枚举、范围、可选字段或嵌套对象时。
  • 处理程序: 当 Claude 调用工具时运行的异步函数。它接收验证的参数,必须返回一个对象,包含:
    • content(必需):结果块的数组,每个块的 type"text""image""audio""resource""resource_link"。有关非文本块,请参阅返回图像和资源
    • structuredContent(可选):保存结果作为机器可读数据的 JSON 对象,与 content 一起返回。请参阅返回结构化数据
    • isError(可选):设置为 true 以表示工具失败,以便 Claude 可以对其做出反应。请参阅处理错误
定义工具后,使用 createSdkMcpServer(TypeScript)或 create_sdk_mcp_server(Python)将其包装在服务器中。服务器在应用程序内进程内运行,而不是作为单独的进程。

天气工具示例

此示例定义了一个 get_temperature 工具并将其包装在 MCP 服务器中。它仅设置工具;要将其传递给 query 并运行它,请参阅下面的调用自定义工具
有关完整的参数详细信息,包括 JSON Schema 输入格式和返回值结构,请参阅 tool() TypeScript 参考或 @tool Python 参考。
要使参数可选:在 TypeScript 中,向 Zod 字段添加 .default()。在 Python 中,字典架构将每个键视为必需的,因此将参数从架构中省略,在描述字符串中提及它,并在处理程序中使用 args.get() 读取它。下面的 get_precipitation_chance 工具展示了两种模式。

调用自定义工具

通过 mcpServers 选项将您创建的 MCP 服务器传递给 querymcpServers 中的键成为每个工具的完全限定名称中的 {server_name} 段:mcp__{server_name}__{tool_name}。在 allowedTools 中列出该名称,以便工具运行而无需权限提示。 这些代码片段重用上面示例中的 weatherServer 来询问 Claude 特定位置的天气。

添加更多工具

一个服务器在其 tools 数组中列出的工具数量不限。如果有多个工具在一个服务器上,您可以在 allowedTools 中单独列出每个工具,或使用通配符 mcp__weather__* 来覆盖服务器公开的每个工具。 下面的示例向天气工具示例中的 weatherServer 添加第二个工具 get_precipitation_chance,并使用数组中的两个工具重建它。
此数组中的每个工具在每个回合都会消耗上下文窗口空间。如果您定义了数十个工具,请参阅工具搜索以按需加载它们。

添加工具注释

工具注释是描述工具行为方式的可选元数据。在 TypeScript 中作为 tool() 助手的第五个参数传递,或在 Python 中通过 @tool 装饰器的 annotations 关键字参数传递。所有提示字段都是布尔值。 注释是元数据,不是强制执行。标记为 readOnlyHint: true 的工具如果处理程序这样做,仍然可以写入磁盘。保持注释与处理程序准确。 此示例向天气工具示例中的 get_temperature 工具添加 readOnlyHint
请参阅 TypeScriptPython 参考中的 ToolAnnotations

控制工具访问

天气工具示例注册了一个服务器并在 allowedTools 中列出了工具。本部分涵盖工具名称的构造方式以及当您有多个工具或想要限制内置工具时如何限制访问。

工具名称格式

当 MCP 工具暴露给 Claude 时,它们的名称遵循特定格式:
  • 模式:mcp__{server_name}__{tool_name}
  • 示例:服务器 weather 中名为 get_temperature 的工具变成 mcp__weather__get_temperature

配置允许的工具

tools 选项和允许/不允许列表影响两个层:可用性(控制工具是否出现在 Claude 的上下文中)和权限(控制 Claude 尝试调用后是否批准调用)。tools 和裸名称 disallowedTools 条目改变可用性。allowedTools 和作用域 disallowedTools 规则仅改变权限。 要完全删除内置工具,请从 tools 中省略它或在 disallowedTools 中列出其裸名称(Python:disallowed_tools);两者都将工具保留在上下文之外,以便 Claude 永远不会尝试它。作用域 disallowedTools 规则会阻止匹配的调用但保留工具可见,因此 Claude 可能会浪费一个回合尝试它。有关完整的评估顺序,请参阅配置权限

处理错误

处理程序错误不会停止代理循环。SDK 的进程内 MCP 服务器捕获未捕获的异常并将其作为错误结果返回,因此您报告错误的方式决定了 Claude 读取的内容,而不是查询是否失败: 在这两种情况下,Claude 都可以重试、尝试不同的工具或解释失败。当原始异常消息不足以让 Claude 采取行动时,请自己捕获错误。 下面的示例在处理程序内部捕获两种失败并编写 Claude 读取的错误消息。非 200 HTTP 状态从响应中捕获并作为错误结果返回。网络错误或无效 JSON 由周围的 try/except(Python)或 try/catch(TypeScript)捕获,也作为错误结果返回。在这两种情况下,Claude 都会收到描述失败的消息,而不是裸露的异常字符串。

返回图像和资源

工具结果中的 content 数组接受 textimageaudioresourceresource_link 块。您可以在同一响应中混合它们。在 TypeScript 中,音频块被保存到磁盘,Claude 接收一个包含保存文件路径的文本块;在 Python 中,SDK 从工具结果中删除音频块并记录警告。资源链接块被转换为包含链接名称、URI 和描述的文本块。

图像

图像块以 base64 编码的方式内联携带图像字节。没有 URL 字段。要返回位于 URL 的图像,在处理程序中获取它,读取响应字节,并在返回之前进行 base64 编码。结果作为视觉输入处理。

资源

资源块嵌入由 URI 标识的内容片段。URI 是 Claude 引用的标签;实际内容位于块的 textblob 字段中。当您的工具生成稍后按名称寻址有意义的内容时使用此功能,例如生成的文件或来自外部系统的记录。 此示例显示从工具处理程序内部返回的资源块。URI file:///tmp/report.md 是 Claude 可以稍后引用的标签;SDK 不从该路径读取。
这些块形状来自 MCP CallToolResult 类型。有关完整定义,请参阅 MCP 规范

返回结构化数据

structuredContent 是结果上的可选 JSON 对象,与 content 数组分开。使用它返回原始值,Claude 可以将其作为精确字段读取,而不是从文本字符串或图像中解析它们。 当设置 structuredContent 时,Claude 接收 JSON 加上来自 content 的任何图像或资源块。来自 content 的文本块不被转发,因为假设它们复制结构化数据。下面的示例将图表呈现为图像块,并从同一处理程序的 structuredContent 中返回其后面的数据点。
TypeScript
Python @tool 装饰器仅从处理程序的返回字典转发 contentis_error。要从 Python 返回 structuredContent,请运行独立 MCP 服务器而不是进程内 SDK 服务器。

示例:单位转换器

此工具在长度、温度和重量的单位之间转换值。用户可以询问”将 100 公里转换为英里”或”72°F 是多少摄氏度”,Claude 从请求中选择正确的单位类型和单位。 它演示了两种模式:
  • 枚举架构: unit_type 被限制为一组固定值。在 TypeScript 中,使用 z.enum()。在 Python 中,字典架构不支持枚举,因此需要完整的 JSON Schema 字典。
  • 不支持的输入处理: 当找不到转换对时,处理程序返回 isError: true,以便 Claude 可以告诉用户出了什么问题,而不是将失败视为正常结果。
定义服务器后,以与天气示例相同的方式将其传递给 query。此示例在循环中发送三个不同的提示,以显示同一工具处理不同的单位类型。对于每个响应,它检查 AssistantMessage 对象(包含 Claude 在该回合中进行的工具调用)并在打印最终 ResultMessage 文本之前打印每个 ToolUseBlock。这让您看到 Claude 何时使用工具与从其自己的知识中回答。

后续步骤

自定义工具在标准接口中包装异步函数。您可以在同一服务器中混合本页上的模式:单个服务器可以在彼此旁边保存数据库工具、API 网关工具和图像渲染器。 从这里:
  • 如果您的服务器增长到数十个工具,请参阅工具搜索以延迟加载它们,直到 Claude 需要它们。
  • 要连接到外部 MCP 服务器(文件系统、GitHub、Slack)而不是构建自己的,请参阅连接 MCP 服务器
  • 要控制哪些工具自动运行与需要批准,请参阅配置权限