Skip to main content
工具是模型执行任务时可以调用的能力。Qoder Agent SDK 支持两类工具:
  • 内置工具:由 Qoder CLI 提供,例如读文件、搜索、执行命令、调用子 Agent。
  • 自定义工具:由 SDK 使用者通过 tool()createSdkMcpServer() 自定义工具并暴露给模型调用。
本文重点讲如何自定义工具。内置工具完整列表见 Tools Reference - 内置工具列表

内置工具

使用内置工具时,你不需要实现工具本身,只需要在 query() options 中控制本次会话能使用哪些工具、哪些工具预授权、哪些工具禁止。
常用内置工具包括 ReadEditWriteBashGlobGrepWebFetchWebSearchAgent 等。完整清单和名称以 Tools Reference - 内置工具列表 为准;输入输出结构见 内置工具输入输出类型,例如 FileReadInput / FileReadOutputBashInput / BashOutputAgentInput / AgentOutput。如果需要在 TypeScript 层统一表示工具输入或输出,参考 ToolInputSchemasToolOutputSchemas

自定义工具

当你希望模型调用自己的业务能力时,可以自定义工具。例如查询订单、搜索内部知识库、调用审批系统、访问只读数据库等。 自定义工具通常分三步:
  1. tool() 创建工具。
  2. createSdkMcpServer() 把工具注册到一个 MCP server。
  3. query({ options }) 中通过 mcpServers 接入,并用权限配置控制调用。

自定义工具接入步骤

先看一个完整的最小示例,然后按三步拆开说明每一步可以配置什么:

第一步:使用 tool() 创建工具

这一步负责定义工具本身,包括工具名、描述、输入参数、执行逻辑和工具元信息。

tool() 入参

tool() 用来定义一个工具。它有 5 个入参,完整类型见 tool()

配置输入参数

inputSchema 传 Zod raw shape,也就是字段对象,不是 z.object(...)。类型参考 AnyZodRawShape;handler 参数推导参考 InferShape
常见写法:

配置工具元信息

extras.annotations 用来传 MCP 工具注解。SDK 会把它原样保存到工具定义上,并在 createSdkMcpServer() 注册工具时传给 MCP server。完整字段见 ToolExtrasToolAnnotations 字段说明: 注意:这些字段不会替代权限配置。是否允许调用工具仍由 toolsallowedToolsdisallowedToolspermissionModecanUseTool 和 hooks 决定。当前 mcpServerStatus().tools[] 也不会把 annotations 回显给宿主应用;如果宿主 UI 需要展示这些信息,请在自己的工具定义侧保留映射。 示例

第二步:注册到 MCP server

createSdkMcpServer() 把一个或多个工具注册为同进程 MCP server。server 名会进入完整工具名,因此建议短、稳定。
完整 option 类型见 CreateSdkMcpServerOptions,返回值见 createSdkMcpServer() 返回值

第三步:接入 query()

把 server 放进 options.mcpServers 后,CLI 会发现其中的工具,并在模型需要时通过 SDK 调回你的 handler。
自定义工具的完整名称格式是:
例如 server 名是 orders,tool 名是 lookup_order,完整工具名就是 mcp__orders__lookup_order。这个完整名称会用于 allowedToolsdisallowedToolscanUseTool、hooks matcher 和子 Agent 的 tools 配置。

控制 tool 权限

当模型调用工具时,SDK 提供多层权限控制。你可以决定:
  • 本次会话提供哪些工具。
  • 哪些工具可以默认放行。
  • 哪些工具明确禁止。
  • 每次工具调用前是否交给宿主应用动态判断。

权限控制方式总览

这些方式可以组合使用。常见做法是:先用 tools 收窄可见工具集合,再用 allowedTools / disallowedTools 设置静态规则,最后用 canUseTool 做参数级判断。

方式一:toolsallowedToolsdisallowedTools

tools 控制本次会话可见的工具集合;allowedToolsdisallowedTools 控制权限规则。自定义 MCP 工具要使用完整工具名。
当同一个工具同时匹配允许和禁止规则时,禁止规则优先。

方式二:permissionMode

permissionMode 用一行配置设置整次会话的默认权限行为。

方式三:canUseTool

canUseTool 会在工具调用前执行。你可以根据工具名、参数内容和审批上下文返回允许或拒绝。
常见返回值: 在子 Agent 中使用自定义工具时,也使用完整工具名:

方式四:hooks.PreToolUse

如果你已经使用 hooks 体系,可以通过 PreToolUse 统一拦截或审计工具调用。
canUseTool 的参数结构见 CanUseToolOptions,返回结构见 PermissionResult。更完整的权限策略见 权限控制

SDK 如何处理 tool 返回的错误

工具 handler 有两类错误路径。

业务失败:返回 isError: true

可预期的业务失败推荐返回 isError: true。SDK 会把这个 CallToolResult 交给 CLI,模型能看到失败内容,并可能重试或选择其他方式。
适合使用 isError: true 的场景:
  • 参数合法但业务上找不到结果,例如订单不存在。
  • 安全策略拒绝执行,例如只允许 SELECT 查询。
  • 外部服务返回可理解的业务错误。

非预期异常:handler 抛错

如果 handler 抛出异常,MCP 层会把异常转换成错误结果,agent loop 不会因为普通工具异常直接崩掉。但模型通常只能看到异常消息,格式和内容不如显式返回 isError: true 可控。
建议:业务上可预期的失败用 isError: true;真正意外的异常再抛出。

Tool 返回值

工具 handler 返回 MCP 的 CallToolResult。最常用的是文本内容:
也可以返回结构化 JSON 字符串,方便模型理解和继续处理:
常见内容块;完整联合类型见 McpToolResultContent 完整类型定义见 Tools Reference - CallToolResult

常见踩坑

  • 权限配置里写自定义工具时,要写 mcp__server__tool 完整名称。
  • tool() 的第三个参数传 Zod raw shape,不要传 z.object(...)
  • 工具描述要写“什么时候用、做什么、返回什么”,不要只写 queryhelper 这类模糊描述。
  • readOnlyHint 是工具元信息和调度提示,不是权限开关;是否允许执行仍由权限配置决定。
  • 不要把大而全的业务入口都塞进一个万能工具。一个工具最好完成一类清晰动作。

继续阅读

  • Tools Reference:内置工具列表、tool()createSdkMcpServer()CallToolResult、内置工具输入输出类型。
  • MCP 集成:stdio、SSE、HTTP、OAuth 等 MCP server 接入方式。
  • 权限控制permissionModeallowedToolscanUseTool、权限规则更新。
  • 子 Agent 使用指南:让不同 Agent 使用不同工具集。