mcpField
M
mcp-csharp-test

mcp-csharp-test

github.com/dotnetテスト・品質5.8k706 回インストール1 日前に更新
リポジトリ

mcp-csharp-test について

C# MCP サーバーをテストするスキルで、ツールメソッドの単体テストと MCP プロトコルを使う統合テストを扱います。LLM 評価と CI テストの設定方法も説明します。

主な機能

  1. 01個別ツールメソッドの単体テスト
  2. 02ツール依存関係のモック
  3. 03MCP の一覧表示と呼び出しのテスト
  4. 04テストの絞り込みとカバレッジ計測
  5. 05読み取り専用 LLM 評価の設計

活用シーン

  1. 01サーバーへの自動テスト追加
  2. 02モックによるツール動作の検証
  3. 03プロトコル経由のツール呼び出し検証
  4. 04CI テストの設定

MCP 対応

MCP クライアントを使った統合テストを説明し、ツール一覧の確認やプロトコル経由のツール呼び出しを検証します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dotnet/skills --skill mcp-csharp-test

インストール後、Claude Code で/mcp-csharp-testを入力して読み込まれたか確認します。

同梱ファイルreferences/evaluations.mdreferences/test-patterns.md

詳細

C# MCP サーバーのテスト

MCP サーバーは、個々のツールメソッドを対象とする単体テストと、メモリ内で MCP プロトコル全体を実行する統合テストの 2 つのレベルでテストします。

使用する場面

  • MCP サーバーに自動テストを追加する場合
  • モックした依存関係を使って個々のツールメソッドをテストする場合
  • MCP プロトコル経由でツールの一覧表示と呼び出しを検証する統合テストを作成する場合
  • MCP サーバーの CI テストパイプラインを設定する場合

中止条件

  • サーバーがまだありませんか? → 先に mcp-csharp-create を使用してください

入力

入力必須説明
MCP サーバープロジェクトのパスはいテスト対象のサーバー .csproj へのパス
テストフレームワーク推奨デフォルト:xUnit。NUnit または MSTest もサポートしています
トランスポートの種類推奨統合テストの方法(stdio または HTTP)を決定します

ワークフロー

ステップ 1:テストプロジェクトを作成する
dotnet new xunit -n <ServerName>.Tests
cd <ServerName>.Tests
dotnet add reference ../<ServerName>/<ServerName>.csproj
dotnet add package ModelContextProtocol
dotnet add package Moq
dotnet add package FluentAssertions
ステップ 2:ツールメソッドの単体テストを作成する

ツールメソッドを直接テストします。最も高速で、分離性にも優れています。

public class MyToolTests
{
    [Fact]
    public void Echo_ReturnsFormattedMessage()
    {
        var result = MyTools.Echo("Hello");
        result.Should().Be("Echo: Hello");
    }

    [Theory]
    [InlineData("")]
    [InlineData("   ")]
    public void Echo_HandlesEdgeCases(string input)
    {
        var result = MyTools.Echo(input);
        result.Should().StartWith("Echo:");
    }
}

DI 依存関係のあるツールでは、その依存関係をモックします。

public class ApiToolTests
{
    [Fact]
    public async Task FetchData_ReturnsApiResponse()
    {
        var handler = new MockHttpMessageHandler("""{"id": 1}""");
        var httpClient = new HttpClient(handler);

        var result = await ApiTools.FetchData(httpClient, "resource-1");
        result.Should().Contain("id");
    }
}
ステップ 3:MCP クライアントを使った統合テストを作成する

クライアントとサーバーを接続して、MCP プロトコル全体をテストします。

using ModelContextProtocol.Client;

public class ServerIntegrationTests : IAsyncLifetime
{
    private McpClient _client = null!;

    public async Task InitializeAsync()
    {
        var transport = new StdioClientTransport(new StdioClientTransportOptions
        {
            Name = "TestClient",
            Command = "dotnet",
            Arguments = ["run", "--project", "../<ServerName>/<ServerName>.csproj"]
        });
        _client = await McpClient.CreateAsync(transport);
    }

    public async Task DisposeAsync() => await _client.DisposeAsync();

    [Fact]
    public async Task Server_ListsExpectedTools()
    {
        var tools = await _client.ListToolsAsync();
        tools.Should().Contain(t => t.Name == "echo");
    }

    [Fact]
    public async Task Tool_ReturnsExpectedResult()
    {
        var result = await _client.CallToolAsync("echo",
            new Dictionary<string, object?> { ["message"] = "Test" });
        var text = result.Content.OfType<TextContentBlock>().First().Text;
        text.Should().Contain("Test");
    }
}

SDK の ClientServerTestBase(メモリ内テスト)と WebApplicationFactory を使った HTTP テストについては、 references/test-patterns.md を参照してください。

ステップ 4:テストを実行する
# Run all tests
dotnet test

# Run a specific test class
dotnet test --filter "FullyQualifiedName~MyToolTests"

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"
ステップ 5:評価を作成する

評価では、LLM がツールをどの程度うまく使用するかを測定します。適切な評価用の質問は、次の条件を満たす必要があります。

  • 読み取り専用で非破壊的 — 副作用としてデータを変更しない
  • 決定論的 — 検証可能な正解が 1 つだけある
  • 複数ステップ — LLM に複数のツールを呼び出させるか、結果をまたいで推論させる

評価の形式、質問例、詳しいガイダンスについては、references/evaluations.md を参照してください。

検証

  • エッジケースも含め、すべてのツールメソッドが単体テストでカバーされている
  • 統合テストで ListToolsAsync() によるツール一覧表示を検証している
  • 統合テストで CallToolAsync() によるツール呼び出しを検証している
  • すべてのテストが合格する:dotnet test
  • 手動設定なしで CI 上でテストを実行できる

よくある落とし穴

落とし穴解決策
CreateAsync で統合テストが停止するサーバーの起動に失敗しています。まず dotnet build が成功することを確認してください。stdio の場合、stdout にログを出力しないようにしてください
StdioClientTransport がプロジェクトを見つけられないテストプロジェクトのディレクトリから .csproj への正しい相対パスを使用してください
ローカルでは合格するが CI では失敗するテスト実行前に dotnet build を実行してください。明示的なビルド手順の後に限り、--no-build を使用してください
HttpClient のモックが扱いにくいHttpClient ではなく HttpMessageHandler をモックしてください。references/test-patterns.md を参照してください
テストスイート全体の実行に時間がかかる開発時は --filter を使用してください。テストスイート全体の実行は CI での検証時に限ってください

関連スキル

  • mcp-csharp-create — 新しい MCP サーバープロジェクトを作成する
  • mcp-csharp-publish — NuGet、Docker、Azure へのデプロイ

参考ファイル

  • references/test-patterns.md — テストコードの完全な例:ClientServerTestBase によるメモリ内パターン、HTTP 用の WebApplicationFactory、MockHttpMessageHandler ヘルパー、テストの分類、カバレッジレポート。次の場合に読み込んでください: 統合テストを作成する場合、または詳しいモックのパターンが必要な場合。
  • references/evaluations.md — 評価の形式、質問設計の原則、評価用の質問例。次の場合に読み込んでください: ユーザーが評価、評価用の質問、またはツールの品質測定について尋ねた場合。

詳細情報

コメント