🎛️

C# で作った stdio な MCP サーバーを MCP Inspector から参照する方法

に公開

はじめに

C# で Model Context Protocol (MCP) のサーバーを実装する際、通信方式として標準入出力 (stdio) を採用することがあります。これはシンプルなコンソールアプリケーションとして実装でき、手軽で便利ですよね。

しかし、この C# による stdio ベースのサーバーを公式のデバッグツールである MCP Inspector から利用しようとすると、いくつか戸惑うポイントがあったりします。

というわけでこの記事では、C# で実装した stdio な MCP サーバーに MCP Inspector から接続する方法と、その際に発生しがちな問題や注意点について紹介します。

なお本稿は、MCP の仕様や C# によるコンソールアプリケーション開発の基本的な知識については、読者がすでに理解しているものとして話を進めます。

前提: MCP Inspector と C# の stdio サーバー

本題に入る前に、今回の話の前提となる要素について簡単におさらいしておきます。

MCP Inspector とは

MCP Inspector は、MCP の開発チームから公式に提供されているデバッグ・検査ツールです。Web ベースの UI を持ち、MCP サーバーに接続して、サーバーが公開しているモデルやツールを一覧したり、実際にメソッドを叩いてリクエストやレスポンスの内容を確認したりできます。MCP サーバーを開発する上で、事実上の標準ツールと言えるでしょう。

MCP Inspector の Web UI を開いた様子

npm パッケージとして公開されており、npx @modelcontextprotocol/inspector コマンドで手軽に起動できます。

https://github.com/model-context-protocol/inspector

C# における stdio な MCP サーバー

C# で stdio を利用する MCP サーバーを実装する場合、そのプログラムは dotnet run コマンドで実行可能な、ごく普通のコンソールアプリケーションプロジェクトとなります。プログラムが起動すると、標準入力から MCP のリクエストメッセージ (JSON) を受け取り、処理結果をレスポンスメッセージ (JSON) として標準出力へ書き出す、という動作をするわけですね。

実際の実装は、"ModelContextProtocol" NuGet パッケージのおかげで、とてもシンプルに実装できます。具体的には以下のリンク先の Microsoft 公式ドキュメントに解説がありますので、参照してください。

https://learn.microsoft.com/ja-jp/dotnet/ai/quickstarts/build-mcp-server

MCP Inspector から接続する方法

それでは、この C# 製 MCP サーバーに MCP Inspector から接続する具体的な手順を見ていきましょう。

まず、接続対象の C# プロジェクトが存在するフォルダをカレントディレクトリとして、ターミナルから以下のコマンドを実行します。

npx @modelcontextprotocol/inspector

npx @modelcontextprotocol/inspector を実行したところ

コマンドが実行されると、ローカルで Web サーバーが起動するので、ブラウザで MCP Inspector の UI (既定だと http://127.0.0.1:6274 になるでしょうか) を開きます。

UI が表示されたら、接続設定を以下のように入力します。

  • Transport Type: STDIO
  • Command: dotnet
  • Arguments: run

入力後、"Connect" ボタンをクリックします。

MCP Inspector の設定画面

これにより、MCP Inspector は内部で dotnet run コマンドを実行して C# プログラムを子プロセスとして起動し、その標準入出力を自身の I/O に接続します。接続が成功すると、以降、MCP Inspector の UI をとおして、その MCP サーバーの様々な動作確認が行えるようになります。

MCP Inspector で、MCP サーバーに接続し、ツールを実行した様子

補足: C# 製 MCP サーバープログラムの実行方法

上記手順では、dotnet run コマンドによって、C# プロジェクトファイル (.csproj) およびソースファイル (.cs) をもとにビルドして実行する手順となっています。他の実行方法としては、予め dotnet build や dotnet publish などでビルド・発行済みにした C# プログラムを実行する方法もあるでしょう。いずれにしても、CLI で C# プログラムを実行できればよいこととなります。

ただ、MCP Inspector と接続するシーンは、多くの場合、開発中の動作確認で使うことが多いと想像されます。そのため、気軽に実行できる dotnet run 方式を本記事では紹介しています。

発生しがちな問題と、その対処法

基本的な接続方法は上記の通りですが、実際の開発シーンではいくつかの問題に直面することがあります。ここでは、代表的な問題を2つ取り上げ、その原因と対処法を解説します。

問題 1: MCP Inspector を起動した場所と違うプロジェクトに接続できない

先の設定手順ですと、MCP Inspector はカレントディレクトリにあるプロジェクトを dotnet run しようとします。そのため、例えばツールの都合などで、MCP Inspector を起動したディレクトリとは別の場所にある C# プロジェクトに接続したい場合、単純な設定ではうまくいきません。

どうすればよいか

この問題は、dotnet run コマンドが持つ --project スイッチを利用することで解決できます。
MCP Inspector の Arguments 入力欄に、以下のように --project スイッチと、対象プロジェクトファイル (.csproj) へのパスを追記します。

  • Arguments: run --project C:/Path/To/Your/McpProject.csproj

MCP Server の Arguments にプロジェクトファイルのパスを指定している様子

こうすることで、MCP Inspector は指定されたパスのプロジェクトを対象として dotnet run を実行してくれます。

注意点: Windows 環境でのパス区切り文字

Windows 環境でこのパスを指定する際、"C:\Path\To\Your\McpProject.csproj" のように、区切り文字として "\" (バックスラッシュ) を使いたくなりますが、そうするとビルドに失敗のエラーが表示されて動作しませんでした。

"The build faild" のエラーがログに表示されている様子

どうやら、内部的にエスケープシーケンスと誤認されているようです。

代わりに、Windows であっても、パス区切り文字は "/" (スラッシュ) を使用してください。"C:/Path/To/Your/McpProject.csproj" と記述すれば、正しく動作するようになりました。

問題 2: コンソールログ出力によるプロトコルパースエラー

C# サーバー側について、既定の設定でコンソールにログが出力される場合、MCP Inspector 側で問題が発生するかもしれません。

何が起きるのか

MCP Inspector は、接続した子プロセス(C# サーバー)の標準出力から流れてくるデータが、すべて MCP のプロトコルに準拠した JSON 文字列であることを期待しています。

しかし、.NET の標準的なロギング機構を使ってコンソールにログが出力されている場合、以下のようなテキストが標準出力に書き込まれます。

info: MyMcpServer.Services.MyTool[0]
      Executing tool method...

プロトコルメッセージを待っている MCP Inspector にとって、このログ出力は未知の文字列でしかありません。結果として、「JSON としてパースできないデータを受信した」という趣旨のエラーが MCP Inspector のサーバーコンソールに表示されてしまいます。

MCP Inspector のサーバープロセスで JSON RPC のパースでエラーが表示されている様子

ただ、自分が確認できた範囲では、上記のとおり MCP Inspector のサーバー側コンソールにパース失敗のエラーは表示されるものの、Web UI 上はとくにエラーが表示されることもなく、各種操作も普通にできていました。

とはいうものの、やはり上記のようなエラーが表示されるのは、今後なにかの問題に至らないか心配です。

どうすればよいか

この問題にはいくつかの対処法が考えられますが、ひとまず、標準出力に出力されるログレベルを調節するのが簡単です。具体的には、C# 製 MCP サーバープログラムの Program.cs 内でアプリケーションホストを構成するタイミングで、以下のような感じで、ログに出力されるログレベルを "Warning" (警告) 以上とします。

var builder = Host.CreateApplicationBuilder(args);
...
builder.Logging
    .SetMinimumLevel(LogLevel.Warning); // 👈警告以上の場合のみ出力
...

さらに、その警告以上のログが発生した際の出力を、標準出力ではなく、標準エラー出力に行なうように追加の構成を行ないます。

var builder = Host.CreateApplicationBuilder(args);
...
builder.Logging
    // 👇すべてのコンソールへのログ出力を標準エラー出力にする
    .AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace)
    .SetMinimumLevel(LogLevel.Warning);
...

このようにすることで、標準出力には MCP Inspector (MCP クライアント) が期待する JSON 文字列だけが行き交うようになり、安定した動作が期待できるようになります。また、もしも警告レベル以上のログ出力が発生した場合は、それは標準出力ではなく標準エラー出力に出力されるようになりましたので、別途標準エラー出力も監視している MCP Inspector の Web UI 上に、適切に表示されるようにもなります。

補足: appsettings.json によるログレベルの調整

.NET アプリケーションにおいて、出力されるログレベルの調整は、一般的には appsettings.json を構成することで行ないます (下記例)。

{
  "Logging": {
    "Console": {
      "LogToStandardErrorThreshold": "Trace",
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

しかしながらこの方法は、--project スイッチを使って、MCP Inspector のサーバープロセスのカレントディレクトリにないプロジェクトファイルを指定して実行する場合は、うまく機能しません。dotnet run で C# プロジェクトを実行する場合は、読み取る appsettings.json は、カレントディレクトリを探してしまうためです。そのため本記事では Program.cs 内に C# コードで直接、ログレベルをハードコーディングする例で紹介しました。

ただ、やはり、ログレベルを C# コード内にハードコードするのは好ましくないかもしれません。ログレベルの調整は C# コード内にハードコードせず appsettings.json で行なうこととし、まめにカレントディレクトリを正しく移動してから MCP Inspector を起動するほうがよいのかもしれません。

あるいはまた、dotnet run コマンドで C# 製 MCP サーバーを実行する形ではなく、dotnet build ないしは dotnet publish 後のアプリケーションファイルを dotnet exec コマンドで実行する形態の場合であれば、アプリケーションファイルがあるフォルダにあるアプリケーション構成ファイルを読み取るようにホストが構成されていれば、MCP Inspector のサーバープロセスのカレントディレクトリに依存することなく、appsettings.json ファイルによってログレベルを構成できます。

まとめ

今回は、C# で実装した stdio ベースの MCP サーバーに MCP Inspector から接続する方法と、その際の注意点について解説しました。

  • 基本的な接続は、カレントディレクトリをその C# 製 MCP サーバープロジェクトがあるフォルダにして MCP Inspector を起動、Web UI からは Command に dotnet、Arguments に run を指定する。
  • MCP Inspector を起動したのとは別のカレントディレクトリにあるプロジェクトに接続するには、--project スイッチで .csproj ファイルへのパスを指定する。その際、パス区切り文字は Windows 環境であっても / を使用する。
  • サーバー側のコンソールログ出力が MCP 通信を阻害する問題は、出力されるログレベルを Warning 以上に引き上げ、且つ、標準エラー出力に出力するよう構成する。

これらのポイントを押さえておくことで、C# での MCP サーバー開発をよりスムーズに進められるかと思います。

Happy Coding :)

Discussion