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.
ツールは、モデルがタスク実行中に呼び出せる能力です。Qoder Agent SDK は次の2種類のツールをサポートします。
- 組み込みツール:Qoder CLI が提供します。ファイル読み取り、検索、コマンド実行、サブ Agent 呼び出しなどがあります。
- カスタムツール:SDK 利用者が
tool() と createSdkMcpServer() で定義し、モデルに公開します。
このガイドでは、主にカスタムツールの定義方法を説明します。組み込みツールの完全な一覧は Tools Reference - 組み込みツール一覧 を参照してください。
組み込みツール
組み込みツールを使う場合、自分でツールを実装する必要はありません。query() options で、このセッションが利用できるツール、事前承認するツール、禁止するツールを制御します。
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 - 組み込みツール一覧 を参照してください。入力/出力構造は 組み込みツール入力出力タイプ にあります。たとえば FileReadInput / FileReadOutput、BashInput / BashOutput、AgentInput / AgentOutput です。TypeScript 層でツール入力や出力を統一的に表したい場合は、ToolInputSchemas と ToolOutputSchemas を参照してください。
カスタムツール
モデルに自分の業務能力を呼び出させたい場合は、カスタムツールを定義します。たとえば注文検索、内部ナレッジベース検索、承認システム呼び出し、読み取り専用データベースアクセスなどです。
カスタムツールは通常、次の3ステップで構成します。
tool() でツールを作成する。
createSdkMcpServer() でツールを MCP server に登録する。
query({ options }) の mcpServers で接続し、権限設定で呼び出しを制御する。
カスタムツール接続手順
まず完全な最小例を示し、その後で各ステップの設定項目を説明します。
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);
}
}
このステップでは、ツール名、説明、入力パラメータ、実行ロジック、ツールメタ情報を定義します。
tool() はツール定義に使います。5つの引数があります。完全な型は tool() を参照してください。
| 引数 | 型 | 必須 | 意味 |
|---|
name | string | はい | 現在の MCP server 内で一意なツール識別子 |
description | string | はい | モデル向けのツール説明。いつ使うか、何をするか、何を返すかを説明します |
inputSchema | Schema extends AnyZodRawShape | はい | ツール入力パラメータを定義する Zod raw shape |
handler | Function | はい | 解析済みパラメータを受け取り CallToolResult を返す非同期実行関数 |
extras | ToolExtras | いいえ | ツール追加メタ情報。現在は annotations に使用します |
入力パラメータの設定
inputSchema には Zod raw shape、つまりフィールドオブジェクトを渡します。z.object(...) ではありません。型は AnyZodRawShape、handler パラメータ推論は InferShape を参照してください。
{
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) |
ツールメタ情報の設定
extras.annotations は MCP ツール注釈を渡すために使います。SDK はこれをツール定義に保持し、createSdkMcpServer() で MCP server に登録するときに渡します。完全なフィールドは ToolExtras と ToolAnnotations を参照してください。
| フィールド | 型 | 任意 | 意味 |
|---|
title | string | はい | ツールの人間可読タイトル |
readOnlyHint | boolean | はい | ツールが読み取り専用で、状態を変更しないことを示します |
destructiveHint | boolean | はい | ツールがデータを変更または削除する可能性を示します |
openWorldHint | boolean | はい | ツールが外部システムまたはネットワークにアクセスすることを示します |
これらのフィールドは権限設定の代替ではありません。ツール呼び出しを許可するかどうかは、引き続き tools、allowedTools、disallowedTools、permissionMode、canUseTool、hooks によって決まります。現在の mcpServerStatus().tools[] は annotations をホストアプリケーションへ返しません。ホスト UI で表示したい場合は、ツール定義側で独自の対応表を保持してください。
例:
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,
},
},
);
ステップ2:MCP server に登録する
createSdkMcpServer() は、1つ以上のツールを同一プロセスの MCP server として登録します。server 名は完全なツール名に入るため、短く安定した名前を推奨します。
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、戻り値は createSdkMcpServer() 戻り値 を参照してください。
ステップ3:query() に接続する
server を options.mcpServers に入れると、CLI がその中のツールを検出し、モデルが必要としたときに SDK 経由で handler を呼び戻します。
query({
prompt: 'Search docs for the refund policy and summarize it.',
options: {
auth: accessTokenFromEnv(),
mcpServers: { kb: kbTools },
allowedTools: ['mcp__kb__search_docs'],
},
});
カスタムツールの完全名形式は次のとおりです。
mcp__{serverName}__{toolName}
たとえば server 名が orders、tool 名が lookup_order の場合、完全名は mcp__orders__lookup_order です。この完全名は allowedTools、disallowedTools、canUseTool、hooks matcher、サブ Agent の tools 設定で使います。
モデルがツールを呼び出すとき、SDK は複数層の権限制御を提供します。次のことを決められます。
- このセッションに提供するツール。
- デフォルトで許可するツール。
- 明示的に禁止するツール。
- 各ツール呼び出し前にホストアプリケーションが動的判断するかどうか。
権限制御方式の概要
| 方式 | 作用 | 粒度 | 適した場面 |
|---|
tools | このセッションに見えるツール集合を制限 | セッション | モデルに見えるツールを元から絞りたい |
allowedTools / disallowedTools | 指定ツールを事前承認または禁止 | ツール | 許可または禁止したいツールが明確 |
permissionMode | セッション全体のデフォルト権限ポリシーを設定 | 全体 | 計画モード、編集自動承認、権限スキップなどを素早く切り替えたい |
canUseTool | 各呼び出し前にカスタム判断ロジックを実行 | 呼び出し | パラメータ内容に基づいて動的判断したい |
hooks.PreToolUse | hooks ライフサイクルでツール呼び出しをインターセプト | 呼び出し | hooks 体系を使っており、監査やブロックを統一したい |
これらは組み合わせられます。よくある構成は、まず tools で見えるツール集合を絞り、allowedTools / disallowedTools で静的ルールを設定し、最後に canUseTool でパラメータ単位の判断を行う形です。
tools はこのセッションに見えるツール集合を制御します。allowedTools と disallowedTools は権限ルールを制御します。カスタム MCP ツールには完全名を使います。
// 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: [] },
});
同じツールが許可ルールと禁止ルールの両方に一致した場合、禁止ルールが優先されます。
方式2:permissionMode
permissionMode は、1行の設定でセッション全体のデフォルト権限挙動を設定します。
query({
prompt: 'Refactor the code.',
options: {
permissionMode: 'acceptEdits',
},
});
| モード | 効果 |
|---|
'default' | 標準権限挙動。機密操作はルールまたは実行時ポリシーで処理されます |
'acceptEdits' | ファイル編集系操作を自動承認します。その他の機密操作は引き続き権限ポリシーに従います |
'bypassPermissions' | 権限チェックをスキップします。allowDangerouslySkipPermissions: true も同時に設定する必要があります |
'yolo' | 'bypassPermissions' の互換エイリアスです。こちらも allowDangerouslySkipPermissions: true が必要です |
'plan' | 計画モード。まずモデルに方針を出させる場面に適しています |
'dontAsk' | 対話的に質問しません。事前承認されていない、またはルールで許可されていない操作は拒否されます |
'auto' | 実行時能力により allow または deny を自動判断します |
canUseTool はツール呼び出し前に実行されます。ツール名、パラメータ内容、承認コンテキストに基づいて許可または拒否できます。
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 内でカスタムツールを使う場合も完全ツール名を使います。
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'],
},
},
},
});
すでに hooks 体系を使っている場合は、PreToolUse でツール呼び出しを統一的にインターセプトまたは監査できます。
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、戻り値構造は PermissionResult を参照してください。より完全な権限戦略は 権限制御 を参照してください。
ツール handler には2種類のエラー経路があります。
業務上の失敗:isError: true を返す
予期できる業務上の失敗には isError: true を返すことを推奨します。SDK はこの CallToolResult を CLI に渡します。モデルは失敗内容を見て、再試行したり別の方法を選んだりできます。
return {
isError: true,
content: [{
type: 'text',
text: JSON.stringify({
error: 'VALIDATION_ERROR',
message: 'Only SELECT statements are allowed.',
}),
}],
};
isError: true が適している場面:
- パラメータは正しいが、業務上の結果がない。たとえば注文が存在しない場合。
- セキュリティポリシーが実行を拒否する。たとえば
SELECT クエリだけを許可する場合。
- 外部サービスが理解可能な業務エラーを返す場合。
予期しない例外:handler が throw する
handler が例外を投げると、MCP 層は例外をエラー結果に変換します。通常のツール例外だけで agent loop が直接クラッシュすることはありません。ただし、モデルが見られるのは通常例外メッセージだけで、明示的に isError: true を返す場合ほど形式や内容を制御できません。
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 してください。
ツール handler は MCP の CallToolResult を返します。最もよく使うのはテキスト content です。
return {
content: [{ type: 'text', text: 'done' }],
};
構造化 JSON 文字列を返すこともできます。モデルが理解し、処理を続けやすくなります。
return {
content: [{
type: 'text',
text: JSON.stringify({
orderId: 'O-1001',
status: 'shipped',
eta: '2026-05-20',
}),
}],
};
よく使う content block。完全な union 型は 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 を参照してください。
よくある落とし穴
- 権限設定でカスタムツールを書くときは、
mcp__server__tool の完全名を使ってください。
tool() の3番目の引数には Zod raw shape を渡し、z.object(...) は渡さないでください。
- ツール説明には「いつ使うか、何をするか、何を返すか」を書いてください。
query や helper のような曖昧な説明は避けてください。
readOnlyHint はツールメタ情報およびスケジューリングヒントであり、権限スイッチではありません。実行を許可するかどうかは権限設定で決まります。
- 大きすぎる万能の業務入口を1つのツールに詰め込まないでください。1つのツールは明確な一種類のアクションを完了するのが理想です。
続きを読む
- Tools Reference:組み込みツール一覧、
tool()、createSdkMcpServer()、CallToolResult、組み込みツール入力出力タイプ。
- MCP 統合:stdio、SSE、HTTP、OAuth などの MCP server 接続方式。
- 権限制御:
permissionMode、allowedTools、canUseTool、権限ルール更新。
- サブ Agent 使用ガイド:異なる Agent に異なるツール集合を使わせる方法。