> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ツール（Tools）

ツールは、モデルがタスク実行中に呼び出せる能力です。Qoder Agent SDK は次の2種類のツールをサポートします。

* **組み込みツール**：Qoder CLI が提供します。ファイル読み取り、検索、コマンド実行、サブ Agent 呼び出しなどがあります。
* **カスタムツール**：SDK 利用者が `tool()` と `createSdkMcpServer()` で定義し、モデルに公開します。

このガイドでは、主にカスタムツールの定義方法を説明します。組み込みツールの完全な一覧は [Tools Reference - 組み込みツール一覧](/ja/cli/sdk/references#組み込みツール一覧) を参照してください。

<div id="組み込みツール" />

## 組み込みツール

組み込みツールを使う場合、自分でツールを実装する必要はありません。`query()` options で、このセッションが利用できるツール、事前承認するツール、禁止するツールを制御します。

```typescript theme={null}
query({
  prompt: 'Read this repository and summarize risks in the authentication module. Do not modify files.',
  options: {
    auth: accessTokenFromEnv(),
    cwd: '/path/to/project',
    tools: ['Read', 'Grep', 'Glob'],
    allowedTools: ['Read', 'Grep', 'Glob'],
  },
});
```

よく使われる組み込みツールには `Read`、`Edit`、`Write`、`Bash`、`Glob`、`Grep`、`WebFetch`、`WebSearch`、`Agent` などがあります。完全な一覧と名称は [Tools Reference - 組み込みツール一覧](/ja/cli/sdk/references#組み込みツール一覧) を参照してください。入力/出力構造は [組み込みツール入力出力タイプ](/ja/cli/sdk/references#組み込みツール入力出力型) にあります。たとえば [`FileReadInput` / `FileReadOutput`](/ja/cli/sdk/references#filereadinput-filereadoutput)、[`BashInput` / `BashOutput`](/ja/cli/sdk/references#bashinput-bashoutput)、[`AgentInput` / `AgentOutput`](/ja/cli/sdk/references#agentinput-agentoutput) です。TypeScript 層でツール入力や出力を統一的に表したい場合は、[`ToolInputSchemas`](/ja/cli/sdk/references#toolinputschemas) と [`ToolOutputSchemas`](/ja/cli/sdk/references#tooloutputschemas) を参照してください。

***

<div id="カスタムツール" />

## カスタムツール

モデルに自分の業務能力を呼び出させたい場合は、カスタムツールを定義します。たとえば注文検索、内部ナレッジベース検索、承認システム呼び出し、読み取り専用データベースアクセスなどです。

カスタムツールは通常、次の3ステップで構成します。

1. `tool()` でツールを作成する。
2. `createSdkMcpServer()` でツールを MCP server に登録する。
3. `query({ options })` の `mcpServers` で接続し、権限設定で呼び出しを制御する。

***

<div id="カスタムツール接続手順" />

## カスタムツール接続手順

まず完全な最小例を示し、その後で各ステップの設定項目を説明します。

```typescript theme={null}
import {
  accessTokenFromEnv,
  createSdkMcpServer,
  query,
  tool,
} from '@qoder-ai/qoder-agent-sdk';
import { z } from 'zod';

const lookupOrder = tool(
  'lookup_order',
  'Look up an order by order ID.',
  {
    orderId: z.string().describe('Order ID, such as O-1001'),
  },
  async ({ orderId }) => {
    const order = await orders.find(orderId);

    if (!order) {
      return {
        isError: true,
        content: [{ type: 'text', text: `Order not found: ${orderId}` }],
      };
    }

    return {
      content: [{ type: 'text', text: JSON.stringify(order) }],
    };
  },
  { annotations: { readOnlyHint: true } },
);

const orderTools = createSdkMcpServer({
  name: 'orders',
  tools: [lookupOrder],
});

const messages = query({
  prompt: 'Check the status of order O-1001 and summarize it in one sentence.',
  options: {
    auth: accessTokenFromEnv(),
    mcpServers: { orders: orderTools },
    allowedTools: ['mcp__orders__lookup_order'],
  },
});

for await (const message of messages) {
  if (message.type === 'result') {
    console.log(message.result);
  }
}
```

<div id="ステップ1tool-でツールを作成する" />

### ステップ1：`tool()` でツールを作成する

このステップでは、ツール名、説明、入力パラメータ、実行ロジック、ツールメタ情報を定義します。

<div id="tool-の引数" />

#### `tool()` の引数

`tool()` はツール定義に使います。5つの引数があります。完全な型は [`tool()`](/ja/cli/sdk/references#tool) を参照してください。

| 引数            | 型                               | 必須  | 意味                                         |
| ------------- | ------------------------------- | --- | ------------------------------------------ |
| `name`        | `string`                        | はい  | 現在の MCP server 内で一意なツール識別子                 |
| `description` | `string`                        | はい  | モデル向けのツール説明。いつ使うか、何をするか、何を返すかを説明します        |
| `inputSchema` | `Schema extends AnyZodRawShape` | はい  | ツール入力パラメータを定義する Zod raw shape              |
| `handler`     | Function                        | はい  | 解析済みパラメータを受け取り `CallToolResult` を返す非同期実行関数 |
| `extras`      | `ToolExtras`                    | いいえ | ツール追加メタ情報。現在は `annotations` に使用します         |

<div id="入力パラメータの設定" />

#### 入力パラメータの設定

`inputSchema` には Zod raw shape、つまりフィールドオブジェクトを渡します。`z.object(...)` ではありません。型は [`AnyZodRawShape`](/ja/cli/sdk/references#anyzodrawshape)、handler パラメータ推論は [`InferShape`](/ja/cli/sdk/references#infershape) を参照してください。

```typescript theme={null}
{
  query: z.string().describe('Search keywords'),
  maxResults: z.number().int().min(1).max(10).optional()
    .describe('Maximum number of snippets to return'),
  source: z.enum(['docs', 'tickets', 'wiki']).default('docs')
    .describe('Where to search'),
}
```

よくある書き方：

| 要件      | 書き方                                     |
| ------- | --------------------------------------- |
| 必須文字列   | `z.string().describe('...')`            |
| 任意パラメータ | `z.string().optional().describe('...')` |
| デフォルト値  | `z.number().default(5)`                 |
| 列挙値     | `z.enum(['docs', 'tickets'])`           |
| 数値範囲    | `z.number().min(1).max(10)`             |

<div id="ツールメタ情報の設定" />

#### ツールメタ情報の設定

`extras.annotations` は MCP ツール注釈を渡すために使います。SDK はこれをツール定義に保持し、`createSdkMcpServer()` で MCP server に登録するときに渡します。完全なフィールドは [`ToolExtras`](/ja/cli/sdk/references#toolextras) と [`ToolAnnotations`](/ja/cli/sdk/references#toolannotations) を参照してください。

| フィールド             | 型         | 任意 | 意味                                |
| ----------------- | --------- | -- | --------------------------------- |
| `title`           | `string`  | はい | ツールの人間可読タイトル                      |
| `readOnlyHint`    | `boolean` | はい | ツールが読み取り専用で、状態を変更しないことを示します       |
| `destructiveHint` | `boolean` | はい | ツールがデータを変更または削除する可能性を示します         |
| `openWorldHint`   | `boolean` | はい | ツールが外部システムまたはネットワークにアクセスすることを示します |

これらのフィールドは権限設定の代替ではありません。ツール呼び出しを許可するかどうかは、引き続き `tools`、`allowedTools`、`disallowedTools`、`permissionMode`、`canUseTool`、hooks によって決まります。現在の `mcpServerStatus().tools[]` は annotations をホストアプリケーションへ返しません。ホスト UI で表示したい場合は、ツール定義側で独自の対応表を保持してください。

例：

```typescript theme={null}
tool(
  'search_docs',
  'Search internal product documentation.',
  { query: z.string().describe('Search keywords') },
  async ({ query }) => ({ content: [{ type: 'text', text: query }] }),
  {
    annotations: {
      readOnlyHint: true,
      destructiveHint: false,
      openWorldHint: false,
    },
  },
);
```

<div id="ステップ2mcp-server-に登録する" />

### ステップ2：MCP server に登録する

[`createSdkMcpServer()`](/ja/cli/sdk/references#createsdkmcpserver) は、1つ以上のツールを同一プロセスの MCP server として登録します。server 名は完全なツール名に入るため、短く安定した名前を推奨します。

```typescript theme={null}
const kbTools = createSdkMcpServer({
  name: 'kb',
  version: '1.0.0',
  tools: [searchDocs],
});
```

| フィールド     | 設定例                         | 説明                                           |
| --------- | --------------------------- | -------------------------------------------- |
| `name`    | `kb`、`orders` など            | server 名。`mcp__{name}__{tool}` の完全ツール名を構成します |
| `version` | `'1.0.0'` など                | 情報用バージョン。省略できます                              |
| `tools`   | `[searchDocs, lookupOrder]` | この server に登録するツール一覧                         |

完全な option 型は [`CreateSdkMcpServerOptions`](/ja/cli/sdk/references#createsdkmcpserveroptions)、戻り値は [`createSdkMcpServer()` 戻り値](/ja/cli/sdk/references#createsdkmcpserver-return-value) を参照してください。

<div id="ステップ3query-に接続する" />

### ステップ3：`query()` に接続する

server を `options.mcpServers` に入れると、CLI がその中のツールを検出し、モデルが必要としたときに SDK 経由で handler を呼び戻します。

```typescript theme={null}
query({
  prompt: 'Search docs for the refund policy and summarize it.',
  options: {
    auth: accessTokenFromEnv(),
    mcpServers: { kb: kbTools },
    allowedTools: ['mcp__kb__search_docs'],
  },
});
```

カスタムツールの完全名形式は次のとおりです。

```text theme={null}
mcp__{serverName}__{toolName}
```

たとえば server 名が `orders`、tool 名が `lookup_order` の場合、完全名は `mcp__orders__lookup_order` です。この完全名は `allowedTools`、`disallowedTools`、`canUseTool`、hooks matcher、サブ Agent の `tools` 設定で使います。

***

<div id="tool-権限の制御" />

## tool 権限の制御

モデルがツールを呼び出すとき、SDK は複数層の権限制御を提供します。次のことを決められます。

* このセッションに提供するツール。
* デフォルトで許可するツール。
* 明示的に禁止するツール。
* 各ツール呼び出し前にホストアプリケーションが動的判断するかどうか。

<div id="権限制御方式の概要" />

### 権限制御方式の概要

| 方式                                                | 作用                            | 粒度    | 適した場面                           |
| ------------------------------------------------- | ----------------------------- | ----- | ------------------------------- |
| `tools`                                           | このセッションに見えるツール集合を制限           | セッション | モデルに見えるツールを元から絞りたい              |
| `allowedTools` / `disallowedTools`                | 指定ツールを事前承認または禁止               | ツール   | 許可または禁止したいツールが明確                |
| `permissionMode`                                  | セッション全体のデフォルト権限ポリシーを設定        | 全体    | 計画モード、編集自動承認、権限スキップなどを素早く切り替えたい |
| [`canUseTool`](/ja/cli/sdk/references#canusetool) | 各呼び出し前にカスタム判断ロジックを実行          | 呼び出し  | パラメータ内容に基づいて動的判断したい             |
| `hooks.PreToolUse`                                | hooks ライフサイクルでツール呼び出しをインターセプト | 呼び出し  | hooks 体系を使っており、監査やブロックを統一したい    |

これらは組み合わせられます。よくある構成は、まず `tools` で見えるツール集合を絞り、`allowedTools` / `disallowedTools` で静的ルールを設定し、最後に `canUseTool` でパラメータ単位の判断を行う形です。

<div id="方式1toolsallowedtoolsdisallowedtools" />

### 方式1：`tools`、`allowedTools`、`disallowedTools`

`tools` はこのセッションに見えるツール集合を制御します。`allowedTools` と `disallowedTools` は権限ルールを制御します。カスタム MCP ツールには完全名を使います。

```typescript theme={null}
// Only expose read/search tools to this session.
query({
  prompt: 'Analyze the repository without editing files.',
  options: {
    tools: ['Read', 'Glob', 'Grep'],
    allowedTools: ['Read', 'Glob', 'Grep'],
  },
});

// Explicitly deny high-risk tools.
query({
  prompt: 'Review the project and report issues.',
  options: {
    disallowedTools: ['Bash', 'Write', 'Edit'],
  },
});

// Use full names for custom MCP tools.
query({
  prompt: 'Check order O-1001.',
  options: {
    mcpServers: { orders: orderTools },
    allowedTools: ['mcp__orders__lookup_order'],
  },
});

// Disable all tools. The model can only answer from its context.
query({
  prompt: 'Explain what this SDK does at a high level.',
  options: { tools: [] },
});
```

同じツールが許可ルールと禁止ルールの両方に一致した場合、禁止ルールが優先されます。

<div id="方式2permissionmode" />

### 方式2：`permissionMode`

`permissionMode` は、1行の設定でセッション全体のデフォルト権限挙動を設定します。

```typescript theme={null}
query({
  prompt: 'Refactor the code.',
  options: {
    permissionMode: 'acceptEdits',
  },
});
```

| モード                   | 効果                                                                                  |
| --------------------- | ----------------------------------------------------------------------------------- |
| `'default'`           | 標準権限挙動。機密操作はルールまたは実行時ポリシーで処理されます                                                    |
| `'acceptEdits'`       | ファイル編集系操作を自動承認します。その他の機密操作は引き続き権限ポリシーに従います                                          |
| `'bypassPermissions'` | 権限チェックをスキップします。`allowDangerouslySkipPermissions: true` も同時に設定する必要があります              |
| `'yolo'`              | `'bypassPermissions'` の互換エイリアスです。こちらも `allowDangerouslySkipPermissions: true` が必要です |
| `'plan'`              | 計画モード。まずモデルに方針を出させる場面に適しています                                                        |
| `'dontAsk'`           | 対話的に質問しません。事前承認されていない、またはルールで許可されていない操作は拒否されます                                      |
| `'auto'`              | 実行時能力により allow または deny を自動判断します                                                    |

<div id="方式3canusetool" />

### 方式3：`canUseTool`

[`canUseTool`](/ja/cli/sdk/references#canusetool) はツール呼び出し前に実行されます。ツール名、パラメータ内容、承認コンテキストに基づいて許可または拒否できます。

```typescript theme={null}
query({
  prompt: 'Check order O-1001.',
  options: {
    auth: accessTokenFromEnv(),
    mcpServers: { orders: orderTools },
    allowedTools: ['mcp__orders__lookup_order'],
    async canUseTool(toolName, input, options) {
      if (toolName !== 'mcp__orders__lookup_order') {
        return {
          behavior: 'deny',
          message: 'Only order lookup is allowed in this workflow.',
          toolUseID: options.toolUseID,
        };
      }

      return {
        behavior: 'allow',
        updatedInput: input,
        toolUseID: options.toolUseID,
      };
    },
  },
});
```

よく使う戻り値：

| 戻り値                                                        | 効果                       |
| ---------------------------------------------------------- | ------------------------ |
| `{ behavior: 'allow' }`                                    | 元のパラメータで実行を許可            |
| `{ behavior: 'allow', updatedInput: {...} }`               | 実行を許可し、ツールパラメータを置き換え     |
| `{ behavior: 'deny', message: 'reason' }`                  | 実行を拒否。モデルは理由を見て別の方法を試せます |
| `{ behavior: 'deny', message: 'reason', interrupt: true }` | 拒否し、現在の agent loop を中断   |

サブ Agent 内でカスタムツールを使う場合も完全ツール名を使います。

```typescript theme={null}
query({
  prompt: 'Use the order-support agent to check order O-1001.',
  options: {
    auth: accessTokenFromEnv(),
    mcpServers: { orders: orderTools },
    allowedTools: ['Agent'],
    agents: {
      'order-support': {
        description: 'Handles order lookup and explains order status.',
        prompt: 'Use order tools to answer order status questions clearly.',
        tools: ['mcp__orders__lookup_order'],
      },
    },
  },
});
```

<div id="方式4hookspretooluse" />

### 方式4：`hooks.PreToolUse`

すでに hooks 体系を使っている場合は、`PreToolUse` でツール呼び出しを統一的にインターセプトまたは監査できます。

```typescript theme={null}
query({
  prompt: 'Run the test command.',
  options: {
    allowedTools: ['Bash'],
    hooks: {
      PreToolUse: [
        {
          matcher: 'Bash',
          hooks: [
            async (input) => {
              const command = (input.tool_input as { command: string }).command;
              if (command.includes('rm -rf')) {
                return {
                  hookSpecificOutput: {
                    hookEventName: 'PreToolUse',
                    permissionDecision: 'deny',
                    permissionDecisionReason: 'rm -rf is not allowed',
                  },
                };
              }

              return {
                hookSpecificOutput: {
                  hookEventName: 'PreToolUse',
                  permissionDecision: 'allow',
                },
              };
            },
          ],
        },
      ],
    },
  },
});
```

`canUseTool` のパラメータ構造は [`CanUseToolOptions`](/ja/cli/sdk/references#canusetooloptions)、戻り値構造は [`PermissionResult`](/ja/cli/sdk/references#permissionresult) を参照してください。より完全な権限戦略は [権限制御](/ja/cli/sdk/permissions) を参照してください。

***

<div id="sdk-が-tool-のエラー戻り値を処理する方法" />

## SDK が tool のエラー戻り値を処理する方法

ツール handler には2種類のエラー経路があります。

<div id="業務上の失敗iserror-true-を返す" />

### 業務上の失敗：`isError: true` を返す

予期できる業務上の失敗には `isError: true` を返すことを推奨します。SDK はこの [`CallToolResult`](/ja/cli/sdk/references#calltoolresult) を CLI に渡します。モデルは失敗内容を見て、再試行したり別の方法を選んだりできます。

```typescript theme={null}
return {
  isError: true,
  content: [{
    type: 'text',
    text: JSON.stringify({
      error: 'VALIDATION_ERROR',
      message: 'Only SELECT statements are allowed.',
    }),
  }],
};
```

`isError: true` が適している場面：

* パラメータは正しいが、業務上の結果がない。たとえば注文が存在しない場合。
* セキュリティポリシーが実行を拒否する。たとえば `SELECT` クエリだけを許可する場合。
* 外部サービスが理解可能な業務エラーを返す場合。

<div id="予期しない例外handler-が-throw-する" />

### 予期しない例外：handler が throw する

handler が例外を投げると、MCP 層は例外をエラー結果に変換します。通常のツール例外だけで agent loop が直接クラッシュすることはありません。ただし、モデルが見られるのは通常例外メッセージだけで、明示的に `isError: true` を返す場合ほど形式や内容を制御できません。

```typescript theme={null}
const toolThatMayThrow = tool(
  'fetch_user',
  'Fetch a user by ID.',
  { userId: z.string() },
  async ({ userId }) => {
    const response = await userService.fetch(userId);
    if (!response.ok) {
      throw new Error('User service failed');
    }
    return { content: [{ type: 'text', text: await response.text() }] };
  },
);
```

推奨：業務上予期できる失敗には `isError: true` を使い、本当に予期しない例外だけを throw してください。

***

<div id="tool-戻り値" />

## Tool 戻り値

ツール handler は MCP の [`CallToolResult`](/ja/cli/sdk/references#calltoolresult) を返します。最もよく使うのはテキスト content です。

```typescript theme={null}
return {
  content: [{ type: 'text', text: 'done' }],
};
```

構造化 JSON 文字列を返すこともできます。モデルが理解し、処理を続けやすくなります。

```typescript theme={null}
return {
  content: [{
    type: 'text',
    text: JSON.stringify({
      orderId: 'O-1001',
      status: 'shipped',
      eta: '2026-05-20',
    }),
  }],
};
```

よく使う content block。完全な union 型は [`McpToolResultContent`](/ja/cli/sdk/references#mcptoolresultcontent) を参照してください。

| 種類       | 形状                                                               | 説明                            |
| -------- | ---------------------------------------------------------------- | ----------------------------- |
| テキスト     | `{ type: 'text', text }`                                         | 最も一般的。自然言語または JSON 文字列に適しています |
| 画像       | `{ type: 'image', data, mimeType }`                              | `data` は base64               |
| 音声       | `{ type: 'audio', data, mimeType }`                              | `data` は base64               |
| リソースリンク  | `{ type: 'resource_link', uri, name?, description?, mimeType? }` | 参照可能なリソースを返します                |
| 埋め込みリソース | `{ type: 'resource', resource }`                                 | テキストまたはバイナリリソース内容を返します        |

完全な型定義は [Tools Reference - CallToolResult](/ja/cli/sdk/references#calltoolresult) を参照してください。

***

<div id="よくある落とし穴" />

## よくある落とし穴

* 権限設定でカスタムツールを書くときは、`mcp__server__tool` の完全名を使ってください。
* `tool()` の3番目の引数には Zod raw shape を渡し、`z.object(...)` は渡さないでください。
* ツール説明には「いつ使うか、何をするか、何を返すか」を書いてください。`query` や `helper` のような曖昧な説明は避けてください。
* `readOnlyHint` はツールメタ情報およびスケジューリングヒントであり、権限スイッチではありません。実行を許可するかどうかは権限設定で決まります。
* 大きすぎる万能の業務入口を1つのツールに詰め込まないでください。1つのツールは明確な一種類のアクションを完了するのが理想です。

***

<div id="続きを読む" />

## 続きを読む

* [Tools Reference](/ja/cli/sdk/references)：組み込みツール一覧、`tool()`、`createSdkMcpServer()`、`CallToolResult`、組み込みツール入力出力タイプ。
* [MCP 統合](/ja/cli/sdk/mcp)：stdio、SSE、HTTP、OAuth などの MCP server 接続方式。
* [権限制御](/ja/cli/sdk/permissions)：`permissionMode`、`allowedTools`、`canUseTool`、権限ルール更新。
* [サブ Agent 使用ガイド](/ja/cli/sdk/agents)：異なる Agent に異なるツール集合を使わせる方法。
