What MCP Solves
Every AI agent needs tools. In Semantic Kernel, you write plugins — C# methods decorated with [KernelFunction]. These work well for tools that live in your application process: database queries, business logic, internal calculations.
But what about tools that live outside your application? A file system browser running on a different machine. A Kubernetes management tool. A documentation search service maintained by another team. Each of these requires custom integration code — authentication, serialization, error handling, retries.
MCP eliminates this integration tax. It defines a standard protocol for AI tool communication. Write a tool server once, and any MCP-compatible agent can discover and invoke it. Think of MCP as USB-C for AI tools — one port, many devices.
The Architecture
MCP uses a three-tier model:
Host — Your AI application. This is the Semantic Kernel app, the Agent Framework agent, or any program that needs AI tool access.
Client — The MCP client that connects to servers. Handles transport negotiation, capability discovery, and tool invocation. In C#, this is the McpClient class.
Server — A process that exposes tools via the MCP protocol. Servers can be local (running as a subprocess) or remote (hosted as HTTP endpoints).
The separation is important: servers are independent processes. A file system MCP server can serve tools to any host — your Semantic Kernel app, a colleague’s Agent Framework pipeline, or a VS Code extension. Write the server once, consume it everywhere.
MCP vs Direct API Integration
The honest comparison:
| Aspect | Direct API Integration | MCP |
|---|---|---|
| Setup cost per tool | High (custom code) | Low (standardized) |
| Discovery | Manual (read docs) | Automatic (list tools) |
| Schema | Provider-specific | JSON Schema standard |
| Authentication | Per-provider | Protocol-level |
| Tool reuse across apps | Requires copy-paste | Automatic |
| Overhead | None | Protocol layer |
| Maturity | Proven | Young but growing |
For one or two tools, direct integration is simpler. For five or more tools, or tools that serve multiple applications, MCP reduces total integration effort significantly.
The C# SDK
The MCP C# SDK v1.0 shipped on March 5, 2026 with two primary packages:
ModelContextProtocol— Client and server coreModelContextProtocol.AspNetCore— HTTP hosting for servers
Building an MCP Client
Connect to an MCP server and discover its tools:
using ModelContextProtocol.Client;
using ModelContextProtocol.Configuration;
// Connect to a local MCP server via stdio
var client = await McpClientFactory.CreateAsync(
new McpServerConfig
{
Id = "weather-server",
Name = "Weather Tools",
TransportType = TransportType.StdIO,
TransportOptions = new Dictionary<string, string>
{
["command"] = "dotnet",
["arguments"] = "run --project ../WeatherMcpServer"
}
});
// Discover available tools
var tools = await client.ListToolsAsync();
foreach (var tool in tools)
{
Console.WriteLine($"Tool: {tool.Name}");
Console.WriteLine($" Description: {tool.Description}");
Console.WriteLine($" Parameters: {tool.InputSchema}");
}
// Invoke a tool
var result = await client.CallToolAsync("get_weather",
new Dictionary<string, object> { ["city"] = "Seattle" });
Console.WriteLine(result.Content);
Connecting MCP Tools to Semantic Kernel
The real power of MCP shows when you bridge it to SK. MCP tools become kernel functions:
using Microsoft.SemanticKernel;
using ModelContextProtocol.Client;
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion("chat-deployment", endpoint, apiKey)
.Build();
// Connect to MCP server
var mcpClient = await McpClientFactory.CreateAsync(serverConfig);
var mcpTools = await mcpClient.ListToolsAsync();
// Convert MCP tools to SK kernel functions
kernel.Plugins.AddFromFunctions("remote_tools",
mcpTools.Select(tool => tool.AsKernelFunction()));
// Now the AI can invoke MCP tools as if they were native plugins
var settings = new AzureOpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
var response = await kernel.InvokePromptAsync(
"What's the weather in Seattle?", new(settings));
The AsKernelFunction() extension method bridges MCP’s tool schema to SK’s function model. The LLM sees MCP tools alongside native plugins — it doesn’t know or care which is which.
Building an MCP Server
MCP servers expose tools that clients can discover and invoke. Here’s a minimal server that exposes a weather tool:
using ModelContextProtocol.Server;
using Microsoft.Extensions.Hosting;
using System.ComponentModel;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMcpServer()
.WithStdioTransport()
.WithTools();
var host = builder.Build();
await host.RunAsync();
[McpServerToolType]
public static class WeatherTools
{
[McpServerTool("get_weather")]
[Description("Get current weather for a city")]
public static string GetWeather(string city)
{
// Production: call a real weather API
return $"{city}: 65°F, Partly Cloudy";
}
[McpServerTool("get_forecast")]
[Description("Get 5-day weather forecast")]
public static string GetForecast(string city, int days = 5)
{
return $"{city} {days}-day forecast: Sunny → Cloudy → Rain → Sunny → Cloudy";
}
}
Run this as a standalone console app. MCP clients connect via stdio and can invoke get_weather and get_forecast.
HTTP Hosting with ASP.NET Core
For remote or multi-client scenarios, host MCP servers over HTTP:
dotnet add package ModelContextProtocol.AspNetCore
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithTools();
var app = builder.Build();
app.MapMcp("/mcp");
app.Run();
Clients connect via HTTP SSE (Server-Sent Events), which supports the full MCP feature set including streaming responses and long-running requests.
v1.0 Features That Matter
Authorization Server Discovery
MCP servers can declare their authorization requirements. Clients discover these automatically — no hardcoded auth flows per server:
{
"authorization": {
"server": "https://auth.example.com",
"type": "oauth2",
"scopes": ["tools:read", "tools:invoke"]
}
}
Tool Sampling
Servers can request LLM completions from the client. This enables agents where the MCP server itself needs AI reasoning — for example, a document server that summarizes content before returning it.
Long-Running Requests
Tools that take significant time (file processing, database migrations) can use the long-running request pattern. The client receives progress updates while the tool executes, rather than blocking on a synchronous response.
Production Patterns
Health Checks
For HTTP-hosted MCP servers in production, add health monitoring:
app.MapGet("/health", () => Results.Ok(new { status = "healthy" }));
app.MapMcp("/mcp");
Tool Observability
Track which tools are being called, by which agents, with what latency:
[McpServerTool("query_database")]
[Description("Query the customer database")]
public static async Task<string> QueryDatabaseAsync(
string query, ILogger<WeatherTools> logger)
{
var sw = Stopwatch.StartNew();
logger.LogInformation("MCP tool invoked: query_database, query={Query}", query);
// Execute query...
var result = "...";
logger.LogInformation("MCP tool completed: query_database, elapsed={Elapsed}ms",
sw.ElapsedMilliseconds);
return result;
}
Multi-Server Configuration
Production agents often connect to multiple MCP servers:
var fileServer = await McpClientFactory.CreateAsync(fileServerConfig);
var dbServer = await McpClientFactory.CreateAsync(dbServerConfig);
var searchServer = await McpClientFactory.CreateAsync(searchServerConfig);
// Add all tools to the kernel
var fileTools = await fileServer.ListToolsAsync();
var dbTools = await dbServer.ListToolsAsync();
var searchTools = await searchServer.ListToolsAsync();
kernel.Plugins.AddFromFunctions("files", fileTools.Select(t => t.AsKernelFunction()));
kernel.Plugins.AddFromFunctions("database", dbTools.Select(t => t.AsKernelFunction()));
kernel.Plugins.AddFromFunctions("search", searchTools.Select(t => t.AsKernelFunction()));
Next Steps
- Build an MCP Server in .NET — Full hands-on workshop building a production MCP server
- MCP C# SDK v1.0 Released — Release details and what’s new in v1.0
- Microsoft Agent Framework Guide — Agent Framework’s native MCP support
- Function Calling in Semantic Kernel — How tool invocation works under the hood