Install
$ agentstack add skill-managedcode-dotnet-skills-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
MCP C# SDK for .NET
Trigger On
- building or consuming MCP servers from a .NET application or library
- choosing between stdio and HTTP transport for MCP
- exposing tools, resources, prompts, completions, or logging to an MCP host
- connecting a .NET app to an existing MCP server and passing discovered tools into
IChatClient - bootstrapping a minimal MCP client/server from the
.NET AIquickstarts or publishing a server to the MCP Registry - implementing capability-aware flows such as roots, sampling, elicitation, subscriptions, session resumption, or enterprise managed authorization
Use This Skill Instead Of
- Use
mcpwhen protocol interoperability is the requirement. - Use
microsoft-extensions-aiwhen you only need model/provider abstraction or local tool orchestration without the MCP wire protocol. - Use
microsoft-agent-frameworkwhen the main problem is agent orchestration; combine it withmcponly when those agents must consume or expose MCP endpoints. - Use the
.NET AIquickstarts for the very first vertical slice, then come back here to harden transport, capability negotiation, publishing, and host interoperability.
Documentation
- MCP C# SDK overview
- Getting Started
- API reference
- Conceptual docs
- Versioning policy
- Experimental APIs
- MCP C# SDK repository
- Model Context Protocol specification
References
Load only what the task needs:
- [references/patterns.md](references/patterns.md) - current server/client patterns, transports, capabilities, filters, and chat-client integration
- [references/security.md](references/security.md) - safe error handling, auth boundaries, stdio logging hygiene, and defensive tool/resource patterns
Package Selection
| 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 Selection
| 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. |
Current v1.4 Notes
- Enterprise managed authorization now has an SDK surface through
IdentityAssertionGrantProviderfor 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.InheritEnvironmentVariablescontrols whether child-process MCP servers inherit the parent environment. Set it intentionally when launching untrusted or third-party servers.- Streamable HTTP session
DELETEis hardened to require the same authenticated user that opened the session. Do not build custom session cleanup paths that bypass that authorization check. - Stdio transport no longer logs child-process environment variables at trace level, but server authors should still treat environment variables as secrets.
flowchart 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
Workflow
- Pick the package and transport first.
- Local child-process server:
ModelContextProtocol+WithStdioServerTransport(). - Remote server:
ModelContextProtocol.AspNetCore+WithHttpTransport()+MapMcp(). - Client-only app: start with
ModelContextProtocolorModelContextProtocol.Core. - Registry distribution: pair a minimal server with the MCP Registry publishing flow only after the server contract is stable.
- Model the MCP surface explicitly.
- Tools:
[McpServerToolType]+[McpServerTool] - Resources:
[McpServerResourceType]+[McpServerResource] - Prompts:
[McpServerPromptType]+[McpServerPrompt] - Use custom handlers or filters only for cross-cutting behavior, protocol extensions, or advanced routing.
- Prefer attribute discovery for straightforward servers.
using 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}";
}
- For HTTP servers, use the ASP.NET Core transport and map the endpoint directly.
using 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}";
}
- When consuming a server, use
McpClient.CreateAsync(...)and stay capability-aware.
using 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 tools = await client.ListToolsAsync();
if (client.ServerCapabilities.Prompts is not null)
{
var prompts = await client.ListPromptsAsync();
}
- Treat optional features as negotiated capabilities, not assumptions.
- Client capabilities: configure
McpClientOptions.Capabilitiesfor roots, sampling, and elicitation. - Server capabilities are inferred from registered features.
- Check
client.ServerCapabilitiesbefore using completions, logging, prompt list-change notifications, or resource subscriptions. - Use
client.NegotiatedProtocolVersionorserver.NegotiatedProtocolVersiononly when version-specific behavior matters.
- Keep HTTP guidance current.
- Streamable HTTP is the recommended transport for remote servers.
MapMcp()also serves SSE compatibility endpoints for older clients.- HTTP clients can use
AutoDetectby default, or forceStreamableHttp/Sse. - Session resumption is available for Streamable HTTP through
McpClient.ResumeSessionAsync(...). - For authenticated Streamable HTTP sessions, cleanup and resume operations must preserve the same user boundary.
- Treat the
.NET AIMCP quickstarts as bootstrap examples.
build-mcp-clientandbuild-mcp-serverare good starting points when the surrounding app is still MEAI-centric.publish-mcp-registryis the distribution step, not the design step. Stabilize the protocol surface before publishing.
- Respect current error and serialization rules.
- Tool exceptions normally come back as
CallToolResult.IsError == true. - Throw
McpProtocolExceptiononly for protocol-level JSON-RPC failures. McpClientToolinherits fromAIFunction, so discovered tools can be passed directly intoIChatClient.- Experimental APIs use
MCPEXP...diagnostics; suppress them intentionally, not globally by accident. - If you use a custom
JsonSerializerContext, prependMcpJsonUtilities.DefaultOptions.TypeInfoResolverso MCP protocol types keep the SDK's contract.
Anti-Patterns To Avoid
| 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 |
Deliver
- a correctly packaged MCP server or client that matches the deployment topology
- explicit tool/resource/prompt definitions with descriptions and bounded payloads
- capability-aware handling for optional MCP features
- validation notes for transport, auth boundary, and host/client interoperability
Validate
- chosen package matches the topology:
Core,ModelContextProtocol, orAspNetCore - stdio servers do not write logs or diagnostics to stdout
- HTTP servers use
MapMcp()and are tested at the final route, for example/mcp - tools, resources, and prompts use current
[McpServer*]attributes or documented handler/filter alternatives - client code checks
ServerCapabilitiesbefore using subscriptions, completions, logging, or prompt/resource list-change flows - Streamable HTTP is the default for new remote servers; SSE is used only for legacy compatibility
- experimental APIs and custom serialization settings are reviewed intentionally rather than copied blindly
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: managedcode
- Source: managedcode/dotnet-skills
- License: MIT
- Homepage: https://skills.managed-code.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.