.NET & C# Development · Lesson 16 of 229
Build & Consume MCP Servers in .NET
Model Context Protocol (MCP) is an open standard for connecting LLMs to tools, resources, and prompt templates. .NET developers can host MCP servers that GitHub Copilot, Claude Desktop, or a custom app call over Stdio (local) or HTTP (remote).
Related: MCP vs RAG vs agents · AI-assisted development · Course lesson
Mental model
┌─────────────┐ JSON-RPC 2.0 ┌─────────────┐
│ MCP Client │ ◄──────────────────► │ MCP Server │
│ (Copilot, │ Stdio or HTTP │ (.NET app) │
│ your app) │ │ tools/data │
└─────────────┘ └─────────────┘| Capability | Purpose | |------------|---------| | Tools | Functions the model can invoke (search orders, run query) | | Resources | Read-only context (file contents, config snapshot) | | Prompts | Reusable prompt templates with parameters |
Prerequisites
dotnet --version # .NET 8+ recommended; check MCP SDK docs for latest TFMCreate a workspace folder:
mkdir McpDotNetLabs && cd McpDotNetLabs1. Stdio MCP server (local tools)
Stdio servers run as a child process — the client writes JSON-RPC to stdin and reads stdout. Ideal for local filesystem or dev tools.
dotnet new console -o OrderFlow.McpServer
cd OrderFlow.McpServer
dotnet add package ModelContextProtocol
dotnet add package Microsoft.Extensions.HostingProgram.cs (pattern — verify package README for exact API on your version):
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddMcpServer()
.WithStdioServerTransport();
builder.Services.AddSingleton<OrderTools>();
await builder.Build().RunAsync();
[McpServerToolType]
public sealed class OrderTools
{
[McpServerTool, Description("Get order count for a status")]
public static Task<string> GetOrderCount(string status) =>
Task.FromResult($"42 orders with status '{status}' (demo)");
}Build and note the DLL path — clients reference the executable.
Test with MCP Inspector
Use the MCP Inspector to list tools and invoke GetOrderCount without an LLM.
Connect from VS Code / Copilot
Add an MCP server entry in your editor config pointing at:
dotnet run --project /path/to/OrderFlow.McpServer(Exact config file format varies by client — follow Copilot or Claude Desktop MCP docs.)
2. HTTP MCP server (remote)
HTTP transport suits shared services — calendar, ticketing, internal APIs behind auth.
High-level steps:
dotnet new web(ASP.NET Core minimal host)- Register MCP with HTTP transport middleware
- Expose tools that call your existing application services via DI
- Protect with API keys, mTLS, or Entra ID — never expose raw tools to the public internet
// Illustrative — align with your SDK version
builder.Services
.AddMcpServer()
.WithHttpTransport();
var app = builder.Build();
app.MapMcp(); // extension from MCP ASP.NET integration
app.Run();Tradeoff: HTTP is easier to deploy and scale; Stdio is simpler for local-only tools with no port management.
3. Consume MCP from a .NET client
Your chat app can act as an MCP client:
- Start or connect to a server
- Discover tools via protocol handshake
- When the LLM requests a tool call, execute via MCP and return results to the model
This mirrors what Copilot does — you orchestrate the loop with Microsoft.Extensions.AI or vendor SDKs plus MCP client libraries.
Pseudo-flow:
// 1. User message → LLM
// 2. LLM returns tool_call: GetOrderCount(status: "Shipped")
// 3. Client invokes MCP tool → result string
// 4. Send tool result back to LLM → final natural language answerKeep tool implementations idempotent where possible and enforce authorization inside the server (the LLM is not trusted).
4. Production guidelines
| Topic | Guidance | |-------|------------| | Auth | Map MCP clients to service principals; audit tool calls | | Timeouts | Cap long-running tools; return structured errors | | PII | Don't expose raw customer data in resource URIs | | Versioning | Treat tool schemas as contract — breaking changes hurt clients | | Observability | Log tool name, duration, correlation ID — not secrets |
When MCP vs REST vs in-process DI
| Approach | Use when | |----------|----------| | In-process service | Same app, same trust boundary | | REST/gRPC | Standard microservice integration | | MCP | LLM clients must discover capabilities dynamically across tools |
MCP is not a replacement for your public API — it's an agent-facing integration layer.
Summary
- Stdio — local dev tools, Copilot, Claude Desktop
- HTTP — shared team servers, hosted capabilities
- Tools / resources / prompts — three extension points of the protocol
- .NET — host with
ModelContextProtocol+ generic host or ASP.NET Core