- 組み込みツール:Qoder CLI が提供します。ファイルの読み取り、検索、コマンド実行、サブエージェントの呼び出しなどがあります。
- カスタムツール:SDK の利用者が
@tool()とcreate_sdk_mcp_server()を使って Python 関数を定義し、インプロセス MCP サーバーとしてモデルに公開します。
組み込みツール
組み込みツールを使う場合、自分でツールを実装する必要はありません。QoderAgentOptions で、このセッションが利用できるツール、事前承認するツール、禁止するツールを制御するだけです。
Read、Edit、Write、Bash、Glob、Grep、WebFetch、WebSearch、Agent などがあります。ツール名は底層の Qoder CLI によって決定されます。権限設定では CLI がモデルに公開しているツール名(例:Read、Write、Bash)を使用してください。組み込みツールの完全な一覧は Tools Reference - 組み込みツール一覧 を参照してください。
カスタムツール
モデルに自分の業務能力を呼び出させたい場合は、カスタムツールを定義します。たとえば注文検索、内部ナレッジベース検索、承認システム呼び出し、読み取り専用データベースアクセスなどです。 Python 版のカスタムツールは通常、次の 3 ステップで構成します。@tool()でasync defの handler を装飾する。create_sdk_mcp_server()で 1 つ以上のツールをインプロセス MCP サーバーに登録する。QoderAgentOptionsのmcp_serversに組み込み、権限設定で呼び出しを制御する。
カスタムツールの接続手順
まず完全な最小例を示し、その後で各ステップで設定可能な内容を説明します。ステップ 1:@tool() でツールを作成する
このステップでは、ツール本体を定義します。ツール名、説明、入力パラメータ、実行ロジック、ツールメタ情報が含まれます。
@tool() の引数
@tool() はデコレーターです。4 つの引数を持ちます。
| 引数 | 型 | 必須 | 意味 |
|---|---|---|---|
name | str | はい | 現在の MCP サーバー内で一意なツール識別子 |
description | str | はい | モデル向けのツール説明。いつ使うか、何をするか、何を返すかを説明します |
input_schema | type | dict[str, Any] | はい | ツールの入力パラメータを定義。シンプルな dict、TypedDict、完全な JSON Schema dict をサポート |
annotations | ToolAnnotations | None | いいえ | MCP ツールアノテーション。例:readOnlyHint、destructiveHint、openWorldHint |
SdkMcpTool 型については Tools Reference - tool() を参照してください。
ツール handler は async 関数である必要があり、通常は args dict を 1 つ受け取ります。
ToolInvocationContext を渡します。その中の signal は asyncio.Event で、CLI が実行中のツール呼び出しをキャンセルするとセットされます。長時間タスクで能動的に停止する場合に適しています。
入力パラメータの設定
Python 版のinput_schema は 3 種類の書き方をサポートします。これらは最終的に MCP プロトコルの JSON Schema に正規化されます。
書き方 1:シンプルな dict
いくつかの単純なパラメータの場合に適しています。dict のキーがパラメータ名、値が Python 型です。この書き方ではすべてのキーが required になります。
typing.Annotated を使ってフィールドに説明を追加できます。
| Python の書き方 | JSON Schema の意味 |
|---|---|
str | {"type": "string"} |
int | {"type": "integer"} |
float | {"type": "number"} |
bool | {"type": "boolean"} |
list[str] | 文字列配列 |
dict | オブジェクト |
Annotated[T, "..."] | T のスキーマに description を追加 |
TypedDict
フィールド数が多い場合、オプションフィールドが必要な場合、または型定義を再利用したい場合に適しています。オプションフィールドには NotRequired を使います。
typing から直接 NotRequired をインポートできます。Python 3.10 では typing_extensions からインポートする必要があります。
書き方 3:完全な JSON Schema dict
enum、数値範囲、文字列フォーマット制約、ネストされたオブジェクトが必要な場合は、完全な JSON Schema を使用します。
TypedDict + NotRequired または完全な JSON Schema の required リストを優先して使用してください。
ツールメタ情報の設定
annotations には mcp.types.ToolAnnotations を使用します。SDK はこれを MCP tool 定義に格納し、CLI がスケジューリング、権限、状態表示に利用できます。
| フィールド | 型 | 意味 |
|---|---|---|
title | str | ツールの人間可読タイトル |
readOnlyHint | bool | ツールが読み取り専用で、状態を変更しないことを示します |
destructiveHint | bool | ツールがデータを変更または削除する可能性があることを示します |
openWorldHint | bool | ツールが外部システムやネットワークにアクセスすることを示します |
maxResultSizeChars | int | Python SDK は _meta["anthropic/maxResultSizeChars"] を介して CLI に渡し、ツール戻り値の長さ制限を緩和するために使用 |
tools、allowed_tools、disallowed_tools、permission_mode、can_use_tool、hooks によって決まります。get_mcp_status() / MCP status で返される annotations のフィールド名は CLI で投影された readOnly、destructive、openWorld であり、MCP オリジナルの *Hint 名ではない可能性があります。
ステップ 2:MCP サーバーへの登録
create_sdk_mcp_server() は 1 つ以上のツールを同一プロセスの MCP サーバーとして登録します。サーバー名は完全なツール名に組み込まれるため、短く安定した名前を推奨します。
| フィールド | 設定例 | 説明 |
|---|---|---|
name | kb、orders など | サーバー名。完全なツール名 mcp__{name}__{tool} を構成します |
version | "1.0.0" など | 情報用バージョン番号。デフォルトは "1.0.0" |
tools | [search_docs, lookup_order] | このサーバーに登録するツール一覧 |
McpSdkServerConfig で、そのまま QoderAgentOptions.mcp_servers に渡せます。
完全な戻り値の型は Tools Reference - create_sdk_mcp_server() を参照してください。
create_sdk_mcp_server() は同期的に検証を行います。
- サーバー名は空でない文字列でなければなりません。
- ツール名は空でない文字列でなければなりません。
- ツール説明は空でない文字列でなければなりません。
- 同じサーバー内にツール名の重複があってはなりません。
ステップ 3:query() への接続
サーバーを options.mcp_servers に入れると、CLI がその中のツールを発見し、モデルが必要としたときに SDK 経由で handler を呼び戻します。
orders、ツール名が lookup_order の場合、完全名は mcp__orders__lookup_order です。この完全名は allowed_tools、disallowed_tools、can_use_tool、hooks matcher、サブエージェントの tools 設定で使用します。
QoderSDKClient のマルチターン会話でも同じ mcp_servers 設定を使用します。
ツール権限の制御
モデルがツールを呼び出すとき、SDK は複数層の権限制御を提供します。次のことを決められます。- このセッションで提供するツール。
- デフォルトで許可するツール。
- 明示的に禁止するツール。
- 各ツール呼び出し前にホストアプリケーションが動的判断を行うかどうか。
権限制御方式の概要
| 方式 | 作用 | 粒度 | 適した場面 |
|---|---|---|---|
tools | このセッションに見えるツール集合を制限 | セッション | モデルに見えるツールを元から絞りたい |
allowed_tools / disallowed_tools | 指定ツールを事前承認または禁止 | ツール | 許可または禁止したいツールが明確 |
permission_mode | セッション全体のデフォルト権限ポリシーを設定 | 全体 | 計画モード、編集自動承認、権限スキップなどを素早く切り替えたい |
can_use_tool | 各呼び出し前にカスタム判断ロジックを実行 | 呼び出し | パラメータ内容に基づいて動的に判断したい |
hooks["PreToolUse"] | hooks ライフサイクルでツール呼び出しをインターセプト | 呼び出し | hooks 体系をすでに使用しており、監査やインターセプトを統一したい |
tools で見えるツール集合を絞り、allowed_tools / disallowed_tools で静的ルールを設定し、最後に can_use_tool でパラメータレベルの判断を行う形です。
方式 1:tools、allowed_tools、disallowed_tools
tools はこのセッションに見えるツール集合を制御します。allowed_tools と disallowed_tools は権限ルールを制御します。カスタム MCP ツールには完全名を使用します。
方式 2:permission_mode
permission_mode は 1 行の設定でセッション全体のデフォルト権限挙動を設定します。
| モード | 効果 |
|---|---|
"default" | 標準権限挙動。機密操作はルールまたは実行時ポリシーで処理されます |
"acceptEdits" | ファイル編集系操作を自動承認します。その他の機密操作は引き続き権限ポリシーに従います |
"bypassPermissions" | 権限チェックをスキップします。allow_dangerously_skip_permissions=True を同時に設定する必要があります |
"yolo" | "bypassPermissions" の互換エイリアス。同じく allow_dangerously_skip_permissions=True を設定する必要があります |
"plan" | 計画モード。まずモデルに方針を出させる場面に適しています |
"dontAsk" | 対話的に質問しません。事前承認されていない、またはルールで許可されていない操作は拒否されます |
"auto" | 実行時の能力に基づいて allow または deny を自動判断します |
方式 3:can_use_tool
can_use_tool はツール呼び出し前に実行されます。ツール名、パラメータ内容、承認コンテキストに基づいて許可または拒否を返すことができます。
| 戻り値 | 効果 |
|---|---|
PermissionResultAllow() | 元のパラメータで実行を許可 |
PermissionResultAllow(updated_input={...}) | 実行を許可し、ツールパラメータを置き換え |
PermissionResultDeny(message="reason") | 実行を拒否。モデルは理由を見て他の方法を試せます |
PermissionResultDeny(message="reason", interrupt=True) | 拒否し、現在の agent loop を中断 |
ToolPermissionContext のよく使うフィールドには tool_use_id、agent_id、signal、title、display_name、description、suggestions、blocked_path、decision_reason などがあります。より完全な権限戦略は 権限制御 を参照してください。
サブエージェント内でカスタムツールを使用する場合も、完全ツール名を使用します。
方式 4:hooks["PreToolUse"]
すでに hooks 体系を使用している場合、PreToolUse でツール呼び出しを統一的にインターセプトまたは監査できます。
PreToolUse の permissionDecision は "allow"、"deny"、"ask"、"defer" のいずれかです。
SDK が tool 戻り値のエラーを処理する方法
ツール handler には 3 種類のエラー経路があります。業務上の失敗:is_error: True を返す
予期できる業務上の失敗には is_error: True を返すことを推奨します。SDK はこの結果を MCP の CallToolResult に変換して CLI に渡します。モデルは失敗内容を見て、再試行したり別の方法を選んだりできます。
is_error: True が適している場面:
- パラメータは正しいが、業務上の結果がない。たとえば注文が存在しない場合。
- セキュリティポリシーが実行を拒否する。たとえば
SELECTクエリだけを許可する場合。 - 外部サービスが理解可能な業務エラーを返す場合。
予期しない例外:handler が throw する
handler が例外を投げると、MCP 層は例外をエラー結果に変換するため、通常のツール例外だけで agent loop が直接クラッシュすることはありません。ただし、モデルが見られるのは通常例外メッセージだけで、明示的にis_error: True を返す場合ほど形式や内容を制御できません。
is_error: True を使い、本当に予期しない例外だけを throw してください。
不正な戻り値:SDK がエラーにラップする
Python SDK はランタイムで handler の戻り値をフォールバックチェックします。Noneを返す:handler は"content"を含む dict を返す必要があるという内容のエラーテキストに変換されます。- 非 dict(文字列、数値、リストなど)を返す:テキスト content に変換され、
isError=Trueがマークされます。 "content"を持たない dict を返す:実際のキー一覧を含むエラーテキストに変換されます。- サポートされていない content 型を返す:そのコンテンツブロックはスキップされ、warning ログが記録されます。
Tool 戻り値
ツール handler は dict を返し、SDK がそれを MCP のCallToolResult に変換します。最もよく使うのはテキスト content です。
| 種類 | 形状 | Python SDK の挙動 |
|---|---|---|
| テキスト | {"type": "text", "text": "..."} | TextContent に変換 |
| 画像 | {"type": "image", "data": "...", "mimeType": "image/png"} | ImageContent に変換。data は base64 |
| リソースリンク | {"type": "resource_link", "uri": "...", "name": "...", "description": "..."} | テキストにフォールバックされ、name / uri / description を結合してモデルに渡す |
| 埋め込みテキストリソース | {"type": "resource", "resource": {"text": "..."}} | TextContent に変換 |
- handler が返す dict のトップレベル
_metaはCallToolResultに透過されません。 - handler がエラーマークを返す際は Python のフィールド名
"is_error": Trueを使用します。MCP/TypeScript 風のisErrorではありません。SDK 内部で MCP の結果にマッピングされます。
よくある落とし穴
- 権限設定でカスタムツールを書くときは、
mcp__server__toolの完全名を使ってください。 - Python のシンプル dict スキーマではすべてのフィールドが required です。オプションフィールドが必要な場合は
TypedDict + NotRequiredまたは完全な JSON Schema を使ってください。 - enum、数値範囲、ネストされたオブジェクト、文字列の pattern/format が必要な場合は完全な JSON Schema dict を使用してください。
- handler は
async defでなければならず、"content"リストを含む dict を返す必要があります。 - ツール説明には「いつ使うか、何をするか、何を返すか」を書いてください。
query、helperのような曖昧な説明は避けてください。 readOnlyHintはツールメタ情報およびスケジューリング/権限ヒントであり、権限スイッチではありません。実行を許可するかどうかは権限設定で決まります。- 大きすぎる万能の業務入口を 1 つのツールに詰め込まないでください。1 つのツールは明確な一種類のアクションを完了するのが理想です。
続きを読む
- MCP 統合:インプロセス、stdio、SSE、HTTP、OAuth などの MCP サーバー接続方式。
- 権限制御:
permission_mode、allowed_tools、can_use_tool、hooks、権限ルール更新。 - Hooks:
PreToolUse、PostToolUse、PermissionRequestなどのライフサイクル拡張。 - サブエージェント使用ガイド:異なる Agent に異なるツール集合を使わせる方法。