ClaudeのC# SDKをIChatClientでMCPツールと統合する
C# / .NET向け公式SDKのIChatClient統合・自動ページネーション・レスポンス検証・リトライ設定を実装例で解説します。
C# SDKの導入 — インストールと動作要件
Anthropic公式のC# SDKは、.NET Standard 2.0以上のアプリケーションからClaude APIへアクセスするためのライブラリです。NuGetパッケージ Anthropic として配布されています。
このSDKが担うのは、リクエストを組み立てて送り、応答を受け取るところまでです。ツールの実行結果を踏まえて次の判断を自律的に下し続けるようなエージェントの実行基盤そのものは含みません。エージェントループやセッション管理まで欲しい場合は、Python・TypeScript向けのAgent SDKやClaude Codeの領分になります。既存の.NETアプリケーションやASP.NET Coreのサービスの一機能としてClaudeを呼び出す構成には、今回扱うクライアントSDKが向いています。
dotnet add package Anthropicusing System;
using Anthropic;
using Anthropic.Models.Messages;
AnthropicClient client = new();
MessageCreateParams parameters = new()
{
MaxTokens = 1024,
Messages =
[
new()
{
Role = Role.User,
Content = "Hello, Claude",
},
],
Model = Model.ClaudeOpus5,
};
var message = await client.Messages.Create(parameters);
foreach (var block in message.Content)
{
if (block.TryPickText(out var textBlock))
{
Console.WriteLine(textBlock.Text);
}
}クライアント設定は環境変数 ANTHROPIC_API_KEY ・ANTHROPIC_AUTH_TOKEN ・ANTHROPIC_BASE_URL から自動で読み込まれます。new AnthropicClient { ApiKey = "..." } で明示的に渡すこともできます。個人・サービスアカウントキーが複数ワークスペースにアクセスできる場合は、anthropic-workspace-id ヘッダーでワークスペースを指定します。ワークスペースを指定し忘れると、意図しないワークスペースの利用量として計上されることがあるため、複数ワークスペースを運用しているチームでは特に注意が必要です。一時的に設定を変えたいだけなら、WithOptions で上書きできます。コネクションやスレッドプールは使い回されたままです。
var message = await client
.WithOptions(options =>
options with
{
BaseUrl = "https://example.com",
Timeout = TimeSpan.FromSeconds(42),
}
)
.Messages.Create(parameters);IChatClient統合でMCPツールをそのまま渡す
C# SDKの特徴が、Microsoft.Extensions.AI.Abstractions の IChatClient インターフェース実装です。これにより AnthropicClient を、この抽象化に対応した他のライブラリとそのまま組み合わせられます。代表的な例が、MCP C# SDK(ModelContextProtocol)が公開するツールを直接 IChatClient 経由でClaudeに渡すパターンです。
using Anthropic;
using Microsoft.Extensions.AI;
using ModelContextProtocol.Client;
AnthropicClient client = new();
IChatClient chatClient = client.AsIChatClient("claude-opus-5")
.AsBuilder()
.UseFunctionInvocation()
.Build();
// MCP C# SDKのMcpClientをそのまま使う
McpClient learningServer = await McpClient.CreateAsync(
new HttpClientTransport(new() { Endpoint = new("https://learn.microsoft.com/api/mcp") }));
ChatOptions options = new() { Tools = [.. await learningServer.ListToolsAsync()] };
Console.WriteLine(await chatClient.GetResponseAsync("Tell me about IChatClient", options));C# SDKは Microsoft.Extensions.AI.Abstractions の IChatClient を実装しています。他言語のSDKページ(Python・TypeScript・Ruby・PHP・Go・Java)には、同種のフレームワーク横断抽象化への統合は記載がありません。ツール定義をClaude固有の形式に変換するコードを書かずに、IChatClient を受け付ける.NETエコシステムの資産(MCPクライアントに限らず)へそのまま接続できる点がC# SDKの特徴です。MCPサーバー自体を自作する場合の手順はMCPサーバー自作ガイドを参照してください。
IChatClient は元々、Microsoft.Extensions.AI が複数のチャットモデルプロバイダーを同じインターフェースの背後に隠すために定義した抽象化です。この仕組みに乗ることで、AnthropicClientを直接呼ぶコードとは別に、IChatClient だけを知っているミドルウェアやライブラリ側のコードを書けます。呼び出し側のコードをモデルプロバイダーの実装詳細から切り離せます。将来的にプロバイダーを差し替える可能性がある設計や、複数のAIプロバイダーを併用するアプリケーションで恩恵が大きくなります。UseFunctionInvocation() を挟むひと手間だけで、Claude固有のツール呼び出しループを意識せずに済む点も、C#エコシステムに寄せた設計だと言えます。
ストリーミングとレスポンス検証
ストリーミングメソッドは名前に必ず Streaming サフィックスが付き、IAsyncEnumerable を返します。
await foreach (var message in client.Messages.CreateStreaming(parameters))
{
Console.WriteLine(message);
}APIのレスポンスが期待した型と一致しない場合、SDKはデフォルトでは例外を投げず、該当プロパティに実際にアクセスしたタイミングで初めて AnthropicInvalidDataException を送出します。レスポンス全体が型どおりかを事前に確認したい場合は、message.Validate() を呼ぶか、クライアントの ResponseValidation オプションを有効にします。
AnthropicClient client = new() { ResponseValidation = true };この「アクセス時まで例外を遅延させる」挙動では、実際に使うプロパティだけがアクセスされる典型的なコードパスにおいて、型不一致があっても気づかれないまま実行が進むことがあります。テストコードやAPIの互換性を厳密にチェックしたい統合レイヤーでは、ResponseValidation を有効にして即座に検出できるようにします。通常のアプリケーションコードでは、デフォルトの遅延検証のままにする使い分けが妥当です。
エラー処理・リトライ・タイムアウト
SDKはカスタムの非チェック例外を投げます。HTTPステータスコードごとの対応は次の通りです。
| ステータス | 例外クラス |
|---|---|
| 400 | 例外クラスAnthropicBadRequestException |
| 401 | 例外クラスAnthropicUnauthorizedException |
| 403 | 例外クラスAnthropicForbiddenException |
| 404 | 例外クラスAnthropicNotFoundException |
| 422 | 例外クラスAnthropicUnprocessableEntityException |
| 429 | 例外クラスAnthropicRateLimitException |
| 5xx | 例外クラスAnthropic5xxException |
| その他 | 例外クラスAnthropicUnexpectedStatusCodeException |
4xx系の例外はすべて Anthropic4xxException を継承するので、個別のステータスコードを区別せずまとめてクライアントエラーとして扱いたい場合は、この基底クラスで一括catchできます。このほかの例外もあります。SSEストリーミング中のエラーを表す AnthropicSseException、I/Oエラーの AnthropicIOException、レスポンスの解釈に失敗したときの AnthropicInvalidDataException です。いずれも AnthropicException を最上位の基底クラスとして継承しています。SDK由来の例外を丸ごと捕捉したいだけであれば、この最上位クラスで受ける設計も可能です。
接続エラー・408・409・429・5xxはデフォルトで2回まで短い指数バックオフとともに自動リトライされます。APIが明示的にリトライの可否を指示することもあります。回数は MaxRetries プロパティで、タイムアウト(デフォルト10分)は Timeout プロパティで変更できます。
AnthropicClient client = new() { MaxRetries = 3, Timeout = TimeSpan.FromSeconds(42) };自動ページネーションと生レスポンスへのアクセス
一覧取得系のメソッドは、全ページを自動で辿る Paginate と、1ページずつ手動で進める Items / HasNext / Next の両方をサポートします。件数が読めない一覧を全件処理したいバッチ処理では前者、画面のページ送りのように1ページ分だけ都度取得したいUIでは後者が使いやすい構成です。
// 自動ページネーション
var page = await client.Messages.Batches.List(parameters);
await foreach (var item in page.Paginate())
{
Console.WriteLine(item);
}レスポンスヘッダーやステータスコード、生のレスポンスボディにアクセスしたい場合は、メソッド呼び出しの前に WithRawResponse を付けます。
var response = await client.WithRawResponse.Messages.Create(parameters);
var statusCode = response.StatusCode;
var headers = response.Headers;非ストリーミングのレスポンスは response.Deserialize() で通常のC#クラスに変換でき、ストリーミングのレスポンスは response.Enumerate() で IAsyncEnumerable として扱えます。
var response = await client.WithRawResponse.Messages.Create(parameters);
Message deserialized = await response.Deserialize();
Console.WriteLine(deserialized);バイナリレスポンスをファイルへ保存する
JSON以外の生データを返すメソッドは HttpResponse を返します。ファイルのダウンロードのように、レスポンスをパースせずそのまま扱いたい場合に使う仕組みです。
FileDownloadParams parameters = new() { FileID = "file_id" };
var response = await client.Files.Download(parameters);レスポンスの内容をファイルや任意の Stream へ保存するには CopyToAsync を使います。
using var response = await client.Files.Download(parameters);
using var contentStream = await response.ReadAsStream();
using var fileStream = File.Open(path, FileMode.OpenOrCreate);
await contentStream.CopyToAsync(fileStream);Bedrock・Vertex・AWS・Foundryへのプラットフォーム統合
C# SDKは4つのクラウドプラットフォームを、それぞれ別のNuGetパッケージとして提供しています。
| プラットフォーム | パッケージ | クライアント |
|---|---|---|
| Vertex | パッケージAnthropic.Vertex | クライアントGoogle Cloud向けクライアント設定を使用 |
| Bedrock | パッケージAnthropic.Bedrock | クライアントAnthropicBedrockMantleClient(新規)/ AnthropicBedrockClient(既存) |
| Claude Platform on AWS | パッケージAnthropic.Aws | クライアントAnthropicAwsClient。ベータ |
| Foundry | パッケージAnthropic.Foundry | クライアントAnthropicFoundryClient |
新規プロジェクトは AnthropicBedrockMantleClient を使い、AnthropicBedrockClient は既存の InvokeModel API利用アプリのための後方互換クライアントです。Claude Platform on AWSはワークスペースIDを WorkspaceId プロパティか環境変数 ANTHROPIC_AWS_WORKSPACE_ID で指定します。
どのプラットフォームを選ぶかは、すでに稼働しているクラウドインフラとの兼ね合いで決まります。単体でAnthropicのAPIキーを発行して直接呼び出す構成と比べ、Bedrock・Vertex・Foundry経由の構成は認証とコスト管理の経路がそのクラウドプロバイダー側に一本化されます。そのため、社内の課金体系や監査要件によって選択が変わってきます。パッケージがプラットフォームごとに分かれているので、複数プラットフォーム対応が不要であれば依存関係を最小限に保てるのも実務上のメリットです。
よくあるつまずき
- IChatClient経由のツール呼び出しが反映されない:
AsBuilder().UseFunctionInvocation().Build()を挟み忘れると、渡したToolsが自動実行されません。ChatOptionsにツールを渡しただけでは呼び出しループは組み立てられないので、ビルダーチェーンの組み立て順を確認してください - レスポンス検証を有効にし忘れて実行時例外に驚く: デフォルトでは型不一致は該当プロパティへのアクセス時まで表面化しないため、事前検証が必要な用途では
ResponseValidation = trueかValidate()を明示します。原因調査に時間がかかる典型パターンです - BedrockClientとBedrockMantleClientの取り違え: 新規実装は
AnthropicBedrockMantleClientが前提で、旧AnthropicBedrockClientはInvokeModelAPI利用アプリの後方互換用です。両者はコンストラクタの引数構成も異なるため、サンプルコードを混在させるとビルドエラーになります - デバッグログを本番の判定ロジックに使う:
ANTHROPIC_LOG=debugで有効になるログはリリースごとにフォーマットが変わりうるため、パースして分岐に使わないでください。障害調査時の一時的な確認用途にとどめるのが安全です
まとめ
C# SDKは dotnet add package Anthropic で導入でき、.NET Standard 2.0以上が前提条件です。IChatClient 統合が特徴で、MCP C# SDKのようなMicrosoft.Extensions.AIエコシステムのツールをそのまま接続できます。他言語のSDKページには同種の統合の記載がありません。レスポンス検証・自動ページネーション・リトライ設定はいずれもプロパティか WithOptions で一箇所から制御できるため、環境ごとの挙動差分をコードの散らばりなく管理できます。
導入の判断基準をまとめると、既存の.NETアプリケーションの一機能としてClaudeを呼び出したいならこのSDKが最短経路になります。IChatClient を介して他のAI関連ライブラリと組み合わせたいという要求がある場合も、このSDKの強みが活きます。逆に自律的にツールを連鎖実行するエージェントを組みたいなら、別の言語のAgent SDKかClaude Codeを検討することになります。パッケージのバージョンが10未満のtryAGI製クライアントを使っている場合は、移行のタイミングでこれらの機能差も含めて棚卸ししておくと、後から作り直す手戻りを避けられます。
ツール呼び出し全般の設計パターンはClaudeツールを組み合わせるパターン、コスト最適化の観点ではAnthropic APIのPrompt Cachingを理解するもあわせて参照してください。