Skip to main content
カスタムツールは Agent SDK を拡張し、Claude が会話中に呼び出せる独自の関数を定義できるようにします。SDK のインプロセス MCP サーバーを使用すると、Claude にデータベース、外部 API、ドメイン固有のロジック、またはアプリケーションが必要とするその他の機能へのアクセスを提供できます。

クイックリファレンス

カスタムツールを作成する

ツールは 4 つの部分で定義され、TypeScript の tool() ヘルパーまたは Python の @tool デコレーターに引数として渡されます。
  • 名前: Claude がツールを呼び出すために使用する一意の識別子。
  • 説明: ツールが何をするか。Claude はこれを読んで、ツールをいつ呼び出すかを決定します。
  • 入力スキーマ: ツールが受け付ける引数。言語ごとに次のように宣言します。
    • TypeScript:Zod スキーマ。ハンドラーの args はここから型を取得します。フィールドに対して .describe() を呼び出すと、Claude が参照する説明をそのフィールドに付けられます。
    • Python:{"latitude": float} のような名前から型へのマッピングである dict であり、SDK が JSON Schema に変換します。{"latitude": Annotated[float, "Latitude coordinate"]} のように型を Annotated でラップすると、Claude が参照する説明をフィールドに付けられます。デコレーターは、列挙型、範囲、オプションフィールド、またはネストされたオブジェクトが必要な場合、完全な JSON Schema dict も直接受け入れます。
  • ハンドラー: Claude がツールを呼び出すときに実行される非同期関数。検証された引数を受け取り、以下を含むオブジェクトを返す必要があります。
    • content(必須):結果ブロックの配列。各ブロックは "text"、"image"、"audio"、"resource"、または "resource_link" の type を持ちます。テキスト以外のブロックについては、画像とリソースを返すを参照してください。
    • structuredContent(オプション):結果を機械可読データとして保持する JSON オブジェクト。content と一緒に返されます。構造化データを返すを参照してください。
    • isError(オプション):ツール障害を通知するために true に設定して、Claude が対応できるようにします。エラーを処理するを参照してください。
ツールを定義した後、createSdkMcpServer(TypeScript)または create_sdk_mcp_server(Python)でサーバーにラップします。サーバーはアプリケーション内でインプロセスで実行され、別のプロセスとしては実行されません。 このページの HTTP リクエストを行う Python の例では httpx を使用します。プロジェクトで使用しているパッケージマネージャーで追加してください。

天気ツールの例

この例は get_temperature ツールを定義して MCP サーバーにラップしますが、サーバーを query には渡しません。ツールを実行するには、以下の カスタムツールを呼び出すを参照してください。
完全なパラメーター詳細(JSON Schema 入力形式と戻り値の構造を含む)については、tool() TypeScript リファレンスまたは @tool Python リファレンスを参照してください。

パラメーターをオプションにする

パラメーターをオプションにするには、スキーマでオプションとして宣言し、ハンドラーでデフォルトを適用します。
  • TypeScript:Zod フィールドに .optional() を追加します。
  • Python:dict スキーマはすべてのキーを必須とします。JSON Schema 形式を使用し、パラメーターを required から除外して、args.get() で読み取ります。オプションのキーを持つ型付きスキーマについては、TypedDict クラスを参照してください。
以下の get_precipitation_chance ツールは両方のパターンを示しています。

カスタムツールを呼び出す

mcpServers オプション経由で query に作成した MCP サーバーを渡します。各ツールの完全修飾名は mcp__{server_name}__{tool_name} で、{server_name} は mcpServers でサーバーに付けたキーです。キーに . やスペースなどの文字が含まれている場合は、{server_name} を記述する際にそれらを _ に置き換えてください。完全修飾名を allowedTools にリストして、ツールが権限プロンプトなしで実行されるようにします。 これらのスニペットは、天気ツールの例の weatherServer を再利用して、特定の場所の天気について Claude に尋ねます。
このスニペットを 天気ツールの例のツールとサーバー定義と 1 つのファイル(weather.py または weather.ts)に組み合わせ、ターミナルから実行します。
Claude は get_temperature を呼び出し、スクリプトはサンフランシスコの現在の気温を含む 1 行の回答を出力します。

さらにツールを追加する

サーバーは tools 配列にリストされているのと同じ数のツールを保持します。サーバーに複数のツールがある場合、allowedTools で各ツールを個別にリストするか、ワイルドカード mcp__weather__* を使用してサーバーが公開するすべてのツールをカバーできます。 以下の例は 2 番目のツール get_precipitation_chance を定義し、天気ツールの例の weatherServer 定義を、配列内の両方のツールをリストするものに置き換えます。
ツール検索はデフォルトで有効になっており、SDK MCP ツールを遅延させます。Claude は各ツールの名前をコンパクトなリストで表示し、必要に応じてその完全なスキーマを読み込みます。ツール検索が無効になっている場合、この配列内のすべてのツールは毎ターン、コンテキストウィンドウスペースを消費します。TypeScript では、tool() の extras 引数または createSdkMcpServer() のオプションで alwaysLoad: true を渡して、ツールの完全なスキーマを初期プロンプトに保持します。

ツール注釈を追加する

ツール注釈は、ツールの動作を説明するオプションのメタデータです。TypeScript の tool() ヘルパーの 5 番目の引数として、または Python の @tool デコレーターの annotations キーワード引数経由で渡します。すべてのヒントフィールドはブール値です。 注釈はメタデータであり、強制ではありません。readOnlyHint: true とマークされたツールでも、ハンドラーがそれを行う場合はディスクに書き込むことができます。注釈をハンドラーに正確に保つようにしてください。 この例は、天気ツールの例の get_temperature ツールに readOnlyHint を追加します。
TypeScript または Python リファレンスで ToolAnnotations を参照してください。

ツールアクセスの制御

天気ツールの例は、サーバーを登録し、allowedTools にツールをリストしました。このセクションでは、複数のツールがある場合や組み込みツールを制限したい場合のアクセス範囲の設定方法について説明します。ツール名の構成方法については、カスタムツールの呼び出しを参照してください。

許可されたツールの設定

tools オプションと許可/禁止リストは、2 つのレイヤーに影響します。可用性はツールが Claude のコンテキストに表示されるかどうかを制御し、権限は Claude がツールを試みた後に呼び出しが承認されるかどうかを制御します。tools と単純名の disallowedTools エントリは可用性を変更します。allowedTools とスコープ付き disallowedTools ルールは権限を変更します。タスク追跡ツールの 1 つを allowedTools に名前を付けた場合、Claude Code もセッションをオプトインします。 組み込みツールを完全に削除するには、tools から省略するか、disallowedTools(Python: disallowed_tools)に単純名をリストします。どちらもツールをコンテキストから除外するため、Claude はそれを試みることはありません。スコープ付き disallowedTools ルールは一致する呼び出しをブロックしますが、ツールを表示したままにするため、Claude はそれを試みるターンを無駄にする可能性があります。評価順序の詳細については、権限の設定を参照してください。

エラーを処理する

ハンドラーエラーはエージェントループを停止しません。SDK のインプロセス MCP サーバーはキャッチされない例外をキャッチし、エラー結果として返すため、エラーをどのように報告するかが Claude が読む内容を決定します。クエリが失敗するかどうかではありません。 どちらの場合でも Claude は再試行したり、別のツールを試したり、失敗を説明したりできます。生の例外メッセージが Claude が対応するのに十分でない場合は、自分でエラーをキャッチしてください。 以下の例は、ハンドラー内で 2 種類の失敗をキャッチし、Claude が読むエラーメッセージを作成します。200 以外の HTTP ステータスはレスポンスからキャッチされ、エラー結果として返されます。ネットワークエラーまたは無効な JSON は、周囲の try/except(Python)または try/catch(TypeScript)によってキャッチされ、エラー結果として返されます。どちらの場合でも Claude は、生の例外文字列の代わりに失敗を説明するメッセージを受け取ります。

画像とリソースを返す

ツール結果の content 配列は、text、image、audio、resource、および resource_link ブロックを受け入れます。同じレスポンス内でこれらを混在させることができます。TypeScript では、SDK はオーディオブロックをディスクに保存し、Claude は保存されたファイルパスを含むテキストブロックを受け取ります。Python では、SDK はツール結果からオーディオブロックを削除し、警告をログに記録します。 Claude は各リソースリンクブロックをテキストブロックとして受け取ります。このテキストブロックには、リンクの名前、URI、および説明が含まれます。TypeScript では、アプリケーションはユーザーメッセージの tool_use_result 上で resourceLinks としてリンク自体も受け取ります。Python では、SDK はそれらを CLI が結果を見る前にテキストに平坦化するため、Python の resourceLinks キー はインプロセスツールに対して生成されることはありません。

画像

画像ブロックは、画像バイトをインラインで、base64 としてエンコードされた形式で保持します。URL フィールドはありません。URL に存在する画像を返すには、ハンドラー内でそれをフェッチし、レスポンスバイトを読み取り、返す前に base64 エンコードしてください。PNG、JPEG、GIF、または WebP 画像は視覚入力として Claude に到達します。他の種類の画像はディスクに保存され、Claude はそのファイルパスをテキストとして受け取ります。

リソース

リソースブロックは、URI で識別されるコンテンツを埋め込みます。実際のコンテンツはブロックの text または blob フィールドに含まれます。ツールが生成されたファイルや外部システムのレコードなど、後で名前で参照することが理にかなったものを生成する場合に使用します。 この例は、ツールハンドラー内から返されるリソースブロックを示しています。SDK は例の URI file:///tmp/report.md から読み取りません。
これらのブロック形状は MCP CallToolResult 型から来ています。完全な定義については、MCP 仕様を参照してください。

構造化データを返す

structuredContent は結果のオプションの JSON オブジェクトで、content 配列とは別です。テキスト文字列または画像から解析する代わりに、Claude が正確なフィールドとして読み取ることができる生の値を返すために使用します。 structuredContent が設定されている場合、Claude は JSON と content からのすべての画像またはリソースブロックを受け取ります。content のテキストブロックは転送されません。これらは構造化データを複製していると想定されているためです。以下の例は、チャートを画像ブロックとしてレンダリングし、同じハンドラーから structuredContent でその背後にあるデータポイントを返します。スニペットでは、chartPngBuffer はレンダリングされた PNG バイトを保持する Buffer です。
TypeScript
Python の @tool デコレーターは、ハンドラーの戻り値の辞書から content と is_error のみを転送します。Python から structuredContent を返すには、in-process SDK サーバーの代わりにスタンドアロン MCP サーバーを実行してください。

例:単位変換ツール

このツールは、長さ、温度、重さの単位間で値を変換します。ユーザーは「100 キロメートルをマイルに変換して」または「72°F は摂氏温度で何度ですか」と尋ねることができ、Claude はリクエストから正しい単位タイプと単位を選択します。 2 つのパターンを示しています:
  • Enum スキーマ: unit_type は固定値のセットに制限されます。TypeScript では、z.enum() を使用します。Python では、dict スキーマは enum をサポートしていないため、完全な JSON Schema dict が必要です。
  • サポートされていない入力の処理: 変換ペアが見つからない場合、ハンドラーは isError: true を返すため、Claude は失敗を通常の結果として扱うのではなく、ユーザーに何が間違ったかを伝えることができます。
サーバーが定義されたら、天気の例と同じ方法で query に渡します。この例は、同じツールが異なる単位タイプを処理することを示すために、ループで 3 つの異なるプロンプトを送信します。各レスポンスについて、AssistantMessage オブジェクト(Claude がそのターン中に行ったツール呼び出しを含む)を検査し、各 ToolUseBlock を出力してから最終的な ResultMessage テキストを出力します。これにより、Claude がツールを使用している場合と独自の知識から回答している場合を確認できます。 ツール検索はデフォルトで有効になっているため、出力には Claude が遅延ツールスキーマを読み込む際の ToolSearch 呼び出しも含まれる場合があります。

次のステップ

このページのパターンを同じサーバー内で組み合わせることができます。単一のサーバーは、データベースツール、API ゲートウェイツール、画像レンダラーを並行して保持できます。 ここから:
  • サーバーが数十個のツールに成長する場合は、ツール検索を参照して、Claude がそれらを必要とするまで読み込みを遅延させてください。
  • 独自に構築する代わりに外部 MCP サーバー(ファイルシステム、GitHub、Slack)に接続するには、MCP サーバーを接続を参照してください。
  • どのツールが自動的に実行されるか、または承認が必要かを制御するには、権限を設定を参照してください。