Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】How I Built a C# MCP Server with Single-Use Order Approvals

2026年10月28日に「Dev.to」が公開したITニュース「How I Built a C# MCP Server with Single-Use Order Approvals」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

AIアシスタントが注文をキャンセルするC#製MCPサーバーを構築した。AIが許可なく操作しないよう、厳格な「外部からの単発承認」プロセスを実装。承認はファイルで管理し、利用時に排他制御し、有効期限や二重利用を防ぐ。注文の状態確認も行い、安全なシステムを追求している。

ITニュース解説

この記事は、C#と.NET 8を使って構築された、AIアシスタントが注文をキャンセルする際に特別な承認が必要となるシステムについて解説する。AIアシスタントに強力な権限を与える際、その操作が本当に許可されているのかを明確にするための工夫が凝らされている点が重要だ。単にAIが「これでいいですか?」と尋ねてきて、それに対する肯定的な返答を承認とみなすのではなく、外部からの明確な、一度きりの承認を必要とする仕組みが作られている。

このシステムは「dotnet-mcp-orders-server」という小さなMCPサーバーで、架空の注文データを扱う。提供される機能は主に三つで、注文のリスト表示、特定の注文の詳細表示、そして注文のキャンセルだ。特にキャンセル機能には、厳格な承認プロセスが組み込まれている。

重要なのは、AIアシスタント自身が承認を作成できない点だ。キャンセルツールは、単に注文IDだけを受け取る。アシスタントが「承認済み」というフラグを勝手に設定できるような仕組みにはなっていない。キャンセルを実行するには、事前にオペレーターが別の手順で承認を記録する必要がある。この記事の筆者は、このセキュリティを確保するために、ツールインターフェースを意図的に小さく保っている。つまり、アシスタントに与える権限を最小限に抑え、余計な操作をさせないようにしているのだ。

キャンセル処理の承認は、会話の外部で記録される。具体的には、オペレーターがPython製の専用コマンドを実行し、キャンセルしたい注文のIDと、その承認がいつまで有効か(通常5分後)を記述した承認ファイルを特定のディレクトリに作成する。この承認ファイルは、一時ファイルを書き込んでから最終的なJSONファイルに置き換えるという安全な方法で作成され、書き込み途中の不完全なファイルが公開されるのを防ぐ。この承認ファイル作成コマンドは、AIアシスタントがアクセスできるツールとしては提供されない。もし提供してしまうと、アシスタントが自分自身で承認を「製造」できてしまい、システムのセキュリティが損なわれるからだ。

サーバーは、指定された承認ディレクトリから承認ファイルを読み込む。このディレクトリの場所や、誰がそこに書き込めるかを適切に管理することが、本番環境でのセキュリティ設計において非常に重要となる。単なるファイルパスだけでは、誰が操作しているかを認証することはできず、ファイルシステムの権限管理が鍵となる。

承認がシステムに記録されたとしても、それを実際に利用する際にはさらに工夫が必要だ。もし二つのキャンセル要求が同時に発生し、両方が同じ承認ファイルを読み込んでしまった場合、どちらか一方が無効なキャンセルを実行してしまう可能性がある。この「競合状態」を防ぐため、この記事のシステムでは「承認を占有する」仕組みが導入されている。具体的には、サーバーが承認ファイルを読み込む前に、そのファイルの名前を一時的にユニークな名前に変更(リネーム)する。このリネームの瞬間が、複数のリクエストが同じ承認を取り合って競争する「争奪戦」のポイントとなる。リネームに成功したリクエストだけが、その承認を「占有」できたことになる。

承認を占有した後、サーバーはそのファイルの内容を検証する。キャンセルが許可されているアクションであるか、「cancel_order」であるか、指定された注文IDと承認ファイルに記録された注文IDが一致するか、そして承認がまだ有効期限内であるかを確認する。もしファイルが破損していたり、内容が不正だったり、有効期限が切れていたりした場合は、その承認は却下される。これにより、システムは常に安全側に倒れるよう設計されている。検証後、承認ファイルは削除される。もし削除に失敗しても、ファイルは元の承認ファイル名ではなく、リネームされた一時ファイル名のままで残るため、後続のリクエストが誤ってその承認を再利用する心配はない。

さらに、システムは注文IDに特定の文字(ASCII文字、数字、ハイフンのみ)と長さに制限を設けることで、../outsideのような不正なパスが構築されるのを防ぎ、ファイルシステムへの攻撃を防ぐ基本的なセキュリティ対策を講じている。

承認が存在し有効であることだけでは、キャンセルは実行されない。システムは、注文自体の「ビジネス状態」もチェックする。つまり、注文が本当にキャンセル可能な「保留中」の状態であるかを確認するのだ。もし注文がすでに発送済みであったり、他の理由でキャンセルできない状態であれば、承認があったとしてもキャンセルは拒否される。この状態チェックは、サービス内のロック機構を使って行われ、同じサービスインスタンス内での複数の操作が同時にデータに矛盾を生じさせないように調整される。これは分散システム全体での排他制御とは異なるが、単一のサービス内での整合性を保つには有効な手段だ。

エラーが発生した場合、システムは単に処理を拒否するだけでなく、その理由を明確なメッセージで返す。たとえば、「承認が見つからない」のか、「注文が見つからない」のか、「注文がキャンセルできない状態である」のかを区別して伝える。これにより、AIアシスタントは拒否された理由を理解し、同じ誤った操作を繰り返すのではなく、適切な説明をユーザーに返すことができるようになる。

このシステムの信頼性を保証するために、合計12のテストケースが用意されている。これらのテストは、実際のファイルシステム上に一時的な承認ディレクトリを作成し、ツールのメソッドと承認フローの動作を直接検証する。AIアシスタントとのインタラクティブな接続は含まれていない。具体的には、注文のリスト表示、特定の注文の読み込み、不明なIDの拒否、承認なしでのキャンセル拒否、有効な承認でのキャンセル実行、発送済み注文のキャンセル拒否といった、正常系と異常系のさまざまなシナリオが網羅されている。さらに、有効期限切れ、異なる注文ID、異なるアクション、不正なJSON形式の承認ファイルなど、無効な承認に関する四つのテストケースや、安全でないIDに関する二つのケースも追加されている。これらのテストはGitHub ActionsというCI/CDツール上で自動実行され、すべてパスすることが確認されている。

本番環境にこのシステムを適用する際には、いくつかの重要な考慮事項がある。第一に、承認ファイルを保存するディレクトリは、AIモデルやそのシェルアクセスから絶対に書き換えられないように、厳重なセキュリティで保護される必要がある。このサンプルではOSレベルのセキュリティ境界は確立されていないため、もしAIと同じユーザー権限で任意のシェルアクセスが可能であれば、簡単に承認を偽造できてしまう。

また、このサンプルシステムでは注文データはメモリ上に保持されるため、サーバーを再起動すると注文データはリセットされる。一方、使われなかった承認ファイルはファイルシステム上に残る。そのため、セッションを再開する前に、残っている承認ファイルを削除するなどの運用上の注意が必要だ。承認ファイルの消費とメモリ上の状態変更は、一連の永続的なトランザクションとしては扱われていない。もし承認を消費した直後にシステムがクラッシュした場合、承認は失われたにもかかわらず、注文のキャンセルは完了しない可能性がある。

本番環境では、注文データを永続的に保存する仕組み(データベースなど)、オペレーターの厳格な認証、操作の履歴を記録する監査ログ、そしてシステムがクラッシュした場合でもデータの整合性を保つための明確なリカバリプロセスが必要となる。さらに、ネットワークを通じた通信のテストや、他のクライアントシステムとの連携テストも不可欠だ。この記事の作者は、このシステムが単なる概念実証であり、本番環境で求められる多くの要件をまだ満たしていないことを明確に伝えている。

この解説は、AIアシスタントに重要な操作をさせる際に、いかに安全な承認フローを設計し、実装するかについて、実践的な知識とセキュリティ上の考慮事項を教えてくれる。特に、外部からの明確な承認、一度きりの使用、競合状態の防止、そしてビジネスロジックとセキュリティの組み合わせが、信頼性の高いシステムを構築する上でいかに重要であるかを理解できるだろう。

関連コンテンツ

関連IT用語

関連ITニュース