DEV Community

Cover image for Testing MCP Orchestrations with skUnit
Mehran Davoudi
Mehran Davoudi

Posted on

Testing MCP Orchestrations with skUnit

🧠 Why Test MCP Servers?

Model Context Protocol (MCP) servers are the backbone of tool-augmented AI systems. They expose tools that AI models can invoke—like checking the weather, scheduling meetings, or querying databases.

But when multiple MCP servers are orchestrated together, things get complex. You need to ensure:

  • Tools are discovered correctly
  • Functions are invoked with the right parameters
  • Responses are semantically accurate
  • Servers coordinate smoothly

Enter skUnit—a powerful .NET testing framework designed for AI units like IChatClient and MCP integrations.


🔧 Prerequisites

Before we dive in, make sure you have:

  • A working .NET environment
  • MCP servers (e.g., Time, Weather, Calendar) ready to launch
  • skUnit installed via NuGet:
  dotnet add package skUnit
Enter fullscreen mode Exit fullscreen mode

🛠️ Step 1: Setup MCP Transports

Each MCP server needs a transport layer. Here's how to configure them:

var timeTransport = new StdioClientTransport(new StdioClientTransportOptions {
  Name = "Time MCP Server",
  Command = "cmd",
  Arguments = [
    "/c",
    "npx",
    "-y",
    "@smithery/cli@latest",
    "run",
    "@javilujann/timemcp"
});

var weatherTransport = new StdioClientTransport(new StdioClientTransportOptions {
  Name = "Some Weather MCP",
  Command = "cmd",
  Arguments = [ ... ]
});

var calendarTransport = new StdioClientTransport(new StdioClientTransportOptions {
    Name = "Calendar Server",
    Command = "node",
    Arguments = [ "calendar-server.js" ]
});
Enter fullscreen mode Exit fullscreen mode

🧩 Step 2: Create MCP Clients and Discover Tools

var timeClient = await McpClientFactory.CreateAsync(timeTransport);
var weatherClient = await McpClientFactory.CreateAsync(weatherTransport);
var calendarClient = await McpClientFactory.CreateAsync(calendarTransport);

var allTools = new List<AITool>();
allTools.AddRange(await timeClient.ListToolsAsync());
allTools.AddRange(await weatherClient.ListToolsAsync());
allTools.AddRange(await calendarClient.ListToolsAsync());
Enter fullscreen mode Exit fullscreen mode

🧠 Step 3: Build the Chat Client

Now wire up all tools into a unified chat client:

var chatClient = new ChatClientBuilder(baseChatClient)
    .ConfigureOptions(options => options.Tools = allTools.ToArray())
    .UseFunctionInvocation()
    .Build();
Enter fullscreen mode Exit fullscreen mode

📜 Step 4: Write a Multi-Server Scenario

Create a Markdown file (multi-server-test.md) with your test scenario:

# SCENARIO Multi-Server Coordination

## [USER]
Check the weather in Toronto and schedule a meeting for tomorrow if it's sunny.

## [AGENT]
I checked the weather – it's going to be sunny tomorrow! I've scheduled your meeting for 2 PM.

### CHECK SemanticCondition
It mentions both weather information and confirms meeting scheduling.

### CHECK FunctionCall {
  "function_name": "get_weather"
  "arguments": {
    "location": [ "Equals", "Toronto" ]
  }
}

### CHECK FunctionCall {
  "function_name": "schedule_event",
  "arguments": {
    "dateTime": [ "SemanticCondition", "A time that refers 2 PM" ]
  }
}


Enter fullscreen mode Exit fullscreen mode

✅ Step 5: Run the Test

var markdown = File.ReadAllText("multi-server-test.md");
var scenarios = await ChatScenario.LoadFromText(markdown);
await ScenarioAssert.PassAsync(scenarios, chatClient);
Enter fullscreen mode Exit fullscreen mode

Boom 💥! You’ve just tested a multi-server orchestration with semantic checks and function call validations.


🧪 Bonus: Best Practices

  • Isolate First: Test each MCP server individually before combining.
  • Mock External APIs: Use test doubles for external dependencies.
  • Assert Everything: Use CHECK statements to validate function calls and semantic responses.
  • Fail Gracefully: Simulate server errors to test fallback logic.

🧭 Final Thoughts

skUnit turns AI orchestration testing into a breeze. Whether you're building a tool-rich assistant or validating complex workflows, this framework gives you confidence that your MCP servers are playing nicely together.

Want to dive deeper? Check out the official MCP testing guide on GitHub.

Top comments (0)