A hands-on walkthrough builds an MCP server in C# using the official ModelContextProtocol SDK 2.1.0 on .NET 10, covering tool creation with attributes, stdio and streamable HTTP transports, dependency injection, and testing with MCP Inspector. It highlights that SDK 2.0 (released 28 July 2026) changed key defaults from 1.x: HTTP transport is now stateless by default, the initialize handshake was replaced by discovery-first negotiation, Roots/Sampling/Logging were deprecated, Tasks moved to a separate package, and Tool.inputSchema became required. A practical example builds a NuGet version-lookup tool to stop coding agents from hallucinating package versions, plus guidance on when an MCP server is worth building versus just exposing a REST API.

17m read timeFrom codewithmukesh.com
Post cover image
Table of contents
What Is an MCP Server?Why Would a .NET Developer Build One?Which ModelContextProtocol Package Do You Need?Creating the ProjectWriting Your First ToolBuilding Something You Would Actually KeepWiring Up the Stdio TransportDependency Injection in ASP.NET CoreHow Do You Test an MCP Server Without an IDE?Connecting the Server to VS Code and Claude CodeAnatomy of the .claude FolderStdio or HTTP: Which Transport Should You Use?Running the Same Tools Over HTTPAPI Key Authentication in ASP.NET CoreWhat Changed in SDK 2.0?My Take: When an MCP Server Is Worth ItWhen Your Server Does Not WorkGlobal Exception Handling in ASP.NET CoreKey TakeawaysFAQSummary

Questions this post answers

What changed in the MCP C# SDK version 2.0 compared to 1.x?

SDK 2.0.0 aligned the C# SDK with MCP specification revision 2026-07-28, making HTTP transport stateless by default (no Mcp-Session-Id header), replacing the initialize handshake with discovery-first negotiation, deprecating Roots, Sampling, and Logging (warning MCP9005), moving Tasks to a separate wire-incompatible Extensions.Tasks package, and requiring Tool.inputSchema, which now throws JsonException if missing. Stable non-deprecated 1.x APIs like AddMcpServer() and WithStdioServerTransport() still work unchanged. Track SDK breaking changes like this on daily.dev before an MCP server upgrade catches your build off guard.

Is WithHttpTransport stateless by default in ModelContextProtocol SDK 2.x?

Yes, WithHttpTransport() is stateless by default starting in SDK 2.x, meaning no Mcp-Session-Id header, no server-side session state, and no need for sticky sessions. A POST to tools/list with no initialize handshake at all is answered successfully, whereas under 1.x that request would have been rejected for having no session. This was verified by testing against a running server, and two replicas behind a plain load balancer work without session affinity. Developers scaling MCP servers horizontally can follow architecture shifts like this via daily.dev.

Why does my MCP server disconnect immediately after the client connects?

The most common cause is stdout pollution: in stdio mode, stdout is the protocol channel, so any Console.WriteLine, a logger without LogToStandardErrorThreshold, or a wrapper script echoing output corrupts the JSON-RPC stream and the client disconnects with no useful error. Fix it by routing all logging to stderr and confirming the first bytes written to stdout are valid JSON when running the server by hand. Debugging stdio protocol issues gets easier when you can find fixes for exactly this on daily.dev.

17.8K Impressions1 Comment