Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build or consume Model Context Protocol (MCP) servers and clients in .NET using the official MCP C# SDK, including stdio, Streamable HTTP, tools, prompts, resources, and capability negotiation. USE FOR: .NET MCP servers or clients; stdio versus HTTP transport choices; tools, resources, prompts, completions, and capability negotiation. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run rele
.claude/skills/managedcode-mcp/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 74% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 100% | 0% |
IChatClient.NET AI quickstarts or publishing a server to the MCP Registrymcp when protocol interoperability is the requirement.microsoft-extensions-ai when you only need model/provider abstraction or local tool orchestration without the MCP wire protocol.microsoft-agent-framework when the main problem is agent orchestration; combine it with mcp only when those agents must consume or expose MCP endpoints..NET AI quickstarts for the very first vertical slice, then come back here to harden transport, capability negotiation, publishing, and host interoperability.Load only what the task needs:
| Package | Choose when | |---------|-------------| | ModelContextProtocol.Core | You only need a client or low-level server APIs and want the smallest dependency set. | | ModelContextProtocol | You want the main SDK package with hosting, DI, attribute discovery, and stdio server support. Start here for most projects. | | ModelContextProtocol.AspNetCore | You are hosting a remote MCP server in ASP.NET Core over HTTP. This includes the main package. |
| Transport | Use when | Notes | |-----------|----------|-------| | StdioClientTransport / WithStdioServerTransport() | The MCP server should run as a local child process. | Best for local tooling and editor/agent integrations. | | HttpClientTransport + HttpTransportMode.StreamableHttp | The server is remote or should be reachable over HTTP. | Recommended HTTP transport; supports streaming and session resumption. | | HttpTransportMode.Sse | You must connect to an older SSE-only server. | Legacy compatibility only; do not choose this for new servers. |
.NET AI MCP documentation separates a getting-started hub, client and server quickstarts, MCP Registry publishing, and a server-resource index. Use those pages to bootstrap a vertical slice, then return to the C# SDK docs here for exact transport, capability, authorization, and lifecycle behavior.v2.0.0 aligns with MCP 2026-07-28: HTTP is stateless by default, clients negotiate with server/discover before falling back to legacy initialize, Tasks move to ModelContextProtocol.Extensions.Tasks, and Roots, Sampling, and Logging are deprecated for the new protocol. Set HttpServerTransportOptions.Stateless = false only for an intentional stateful compatibility requirement.v2.1.0 adds an opt-in subscriptions/listen server handler, keeps AutoDetect usable after a provisional SSE failure, preserves HTTP status codes across target frameworks, and falls back to initialize when server/discover fails at the HTTP layer. Add custom notification streams only when both peers negotiate the extension.v2.2.0 adds HttpServerSessionMode so one ASP.NET Core endpoint can serve stateful and stateless clients across the MCP 2025-11-25 and 2026-07-28 protocol versions. Choose the mode explicitly, test both negotiated paths when compatibility matters, and upgrade before working around malformed percent-encoded request headers because the release fixes that decoding failure.v1.4.x, update structured-result consumers to accept non-object values directly, require Tool.inputSchema in custom payloads, move Tasks to the extension package, and test PKCE S256 plus issuer validation in OAuth metadata.IdentityAssertionGrantProvider for the Identity Assertion Authorization Grant flow. Use it only when the enterprise SSO and MCP authorization-server contract is part of the actual scenario.StdioClientTransportOptions.InheritEnvironmentVariables controls whether child-process MCP servers inherit the parent environment. Set it intentionally when launching untrusted or third-party servers.DELETE is hardened to require the same authenticated user that opened the session. Do not build custom session cleanup paths that bypass that authorization check.mermaidflowchart LR A["Need MCP interoperability in .NET"] --> B{"Role?"} B -->|"Expose MCP surface"| C{"Where will it run?"} B -->|"Consume an MCP server"| D{"Transport?"} C -->|"Local child process"| E["ModelContextProtocol\nAddMcpServer()\nWithStdioServerTransport()"] C -->|"Remote HTTP endpoint"| F["ModelContextProtocol.AspNetCore\nAddMcpServer()\nWithHttpTransport()\nMapMcp()"] D -->|"stdio"| G["StdioClientTransport\nMcpClient.CreateAsync()"] D -->|"HTTP"| H["HttpClientTransport\nAutoDetect or StreamableHttp"] E --> I["Register tools/resources/prompts"] F --> I G --> J["Check ServerCapabilities\nbefore optional features"] H --> J
ModelContextProtocol + WithStdioServerTransport().ModelContextProtocol.AspNetCore + WithHttpTransport() + MapMcp().ModelContextProtocol or ModelContextProtocol.Core.[McpServerToolType] + [McpServerTool][McpServerResourceType] + [McpServerResource][McpServerPromptType] + [McpServerPrompt]csharpusing Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using ModelContextProtocol.Server; using System.ComponentModel; var builder = Host.CreateApplicationBuilder(args); builder.Logging.AddConsole(options => { options.LogToStandardErrorThreshold = LogLevel.Trace; }); builder.Services .AddMcpServer() .WithStdioServerTransport() .WithToolsFromAssembly(); await builder.Build().RunAsync(); [McpServerToolType] public static class EchoTool { [McpServerTool, Description("Echoes the message back to the client.")] public static string Echo(string message) => $"hello {message}"; }
csharpusing ModelContextProtocol.Server; using System.ComponentModel; var builder = WebApplication.CreateBuilder(args); builder.Services .AddMcpServer() .WithHttpTransport() .WithToolsFromAssembly(); var app = builder.Build(); app.MapMcp("/mcp"); app.Run(); [McpServerToolType] public static class EchoTool { [McpServerTool, Description("Echoes the message back to the client.")] public static string Echo(string message) => $"hello {message}"; }
McpClient.CreateAsync(...) and stay capability-aware.csharpusing ModelContextProtocol.Client; using ModelContextProtocol.Protocol; var transport = new StdioClientTransport(new StdioClientTransportOptions { Name = "Everything", Command = "npx", Arguments = ["-y", "@modelcontextprotocol/server-everything"], }); await using var client = await McpClient.CreateAsync(transport); IList<McpClientTool> tools = await client.ListToolsAsync(); if (client.ServerCapabilities.Prompts is not null) { var prompts = await client.ListPromptsAsync(); }
McpClientOptions.Capabilities for roots, sampling, and elicitation.client.ServerCapabilities before using completions, logging, prompt list-change notifications, or resource subscriptions.client.NegotiatedProtocolVersion or server.NegotiatedProtocolVersion only when version-specific behavior matters.MapMcp() also serves SSE compatibility endpoints for older clients.AutoDetect by default, or force StreamableHttp / Sse.McpClient.ResumeSessionAsync(...)..NET AI MCP quickstarts as bootstrap examples.build-mcp-client and build-mcp-server are good starting points when the surrounding app is still MEAI-centric.publish-mcp-registry is the distribution step, not the design step. Stabilize the protocol surface before publishing.CallToolResult.IsError == true.McpProtocolException only for protocol-level JSON-RPC failures.McpClientTool inherits from AIFunction, so discovered tools can be passed directly into IChatClient.MCPEXP... diagnostics; suppress them intentionally, not globally by accident.JsonSerializerContext, prepend McpJsonUtilities.DefaultOptions.TypeInfoResolver so MCP protocol types keep the SDK's contract.| Anti-pattern | Why it causes trouble | Better approach | |--------------|-----------------------|-----------------| | Picking HTTP transport for a purely local child-process scenario | Adds unnecessary hosting, auth, and deployment surface | Use stdio for local/editor-hosted integrations | | Treating SSE as the default remote transport | Locks new work to legacy behavior | Prefer Streamable HTTP and keep SSE only for backward compatibility | | Writing tools without [Description] metadata | Hosts and models lose schema clarity | Describe tool purpose and parameters explicitly | | Returning huge binary/text payloads from every tool call | Bloats context and slows hosts | Return focused content and move large data to resources | | Logging to stdout on stdio servers | Corrupts the protocol stream | Send logs to stderr | | Assuming prompts/resources/logging/completions exist | Breaks against partial implementations | Check negotiated capabilities first | | Using filters for normal business logic | Makes handlers opaque and hard to reason about | Keep filters for cross-cutting policy, audit, or protocol plumbing |
Core, ModelContextProtocol, or AspNetCoreMapMcp() and are tested at the final route, for example /mcp[McpServer*] attributes or documented handler/filter alternativesServerCapabilities before using subscriptions, completions, logging, or prompt/resource list-change flowsOther measured skills in the registry, with their headline benchmark lift.