Skip to main content
自定义工具通过让您定义 Claude 在对话期间可以调用的自己的函数来扩展 Agent SDK。使用 SDK 的进程内 MCP 服务器,您可以让 Claude 访问数据库、外部 API、特定领域的逻辑或应用程序需要的任何其他功能。

快速参考

创建自定义工具

工具由四个部分定义,作为参数传递给 TypeScript 中的 tool() 辅助函数或 Python 中的 @tool 装饰器:
  • 名称: Claude 用来调用工具的唯一标识符。
  • 描述: 工具的功能。Claude 读取此内容以决定何时调用它。
  • 输入模式: Claude 必须提供的参数。在 TypeScript 中,这始终是一个 Zod schema,处理程序的 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 特定位置的天气。
将此代码片段与天气工具示例中的工具和服务器定义结合在一个文件中,然后使用 python weather.py(Python)或 npx tsx weather.ts(TypeScript)运行它。Claude 调用 get_temperature,脚本打印一行答案,显示旧金山的当前温度。

添加更多工具

服务器可以容纳您在其 tools 数组中列出的任意数量的工具。当服务器上有多个工具时,您可以在 allowedTools 中单独列出每个工具,或使用通配符 mcp__weather__* 来覆盖服务器公开的每个工具。 下面的示例定义了第二个工具 get_precipitation_chance,并用列出数组中两个工具的工具替换了天气工具示例中的 weatherServer 定义。
工具搜索默认启用,并延迟 SDK MCP 工具:Claude 在紧凑列表中看到每个工具的名称,并按需加载其完整模式。禁用工具搜索后,此数组中的每个工具在每个回合都会消耗上下文窗口空间。在 TypeScript 中,在 tool()extras 参数或 createSdkMcpServer() 的选项中传递 alwaysLoad: true,以在初始提示中保持工具的完整模式。

添加工具注释

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

控制工具访问

天气工具示例注册了一个服务器,并在allowedTools中列出了工具。本节介绍当您有多个工具或想要限制内置工具时如何限制访问范围。有关工具名称的构造方式,请参阅调用自定义工具

配置允许的工具

tools选项和允许/禁止列表影响两个层级:可用性(控制工具是否出现在Claude的上下文中)和权限(控制Claude尝试调用后是否批准该调用)。tools和裸名称disallowedTools条目改变可用性。allowedTools和作用域disallowedTools规则改变权限。如果您在allowedTools中命名其中一个任务跟踪工具,Claude Code也会选择加入该会话。 要完全移除内置工具,请从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 中,SDK 将音频块保存到磁盘,Claude 接收包含已保存文件路径的文本块;在 Python 中,SDK 从工具结果中删除音频块并记录警告。 Claude 将每个资源链接块作为包含链接名称、URI 和描述的文本块接收。在 TypeScript 中,您的应用程序还会在用户消息的 tool_use_result 上以 resourceLinks 的形式接收链接本身;在 Python 中,SDK 在 CLI 看到结果之前将它们展平为文本,因此 Python resourceLinks永远不会为进程内工具生成。

图像

图像块以 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 中返回其后面的数据点。在代码片段中,chartPngBuffer 是一个包含呈现的 PNG 字节的 Buffer
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 何时使用工具与何时从自己的知识中回答。 因为 tool search 默认启用,输出也可能包括 ToolSearch 调用,因为 Claude 加载延迟的工具模式。

后续步骤

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