It seems with rise in popularity of AI LLMs the code we generate is starting to feel language agnostic, now more than ever I can apply what I know if .Net to any other langauge, even Rust with its none garbage collection antics!
Im not ready to loose focus from .Net, I mean getting better right? :D And MCP is all the rage so why not learn to build my own MCP server?
I found this Video from Nick Chapsas | Getting Started with MCP and this blog post from James Montemagno Build a Model Context Protocol (MCP) server in C# super useful, they explain the core concepts and how to implement MCP in .Net. PS: James your monkey examples are cool 🐒
So I decided to make my own notes as I built a .Net MCP Server using STDIO transports, potentially next I will try Streamable HTTP but Im a noob, so STDIO it is!
Core Concepts
MCP is a standard protocol for connecting LLMs (clients) with external servers that expose resources, prompts, and tools in a structured, schema-validated way.
Core Concepts
Servers
- Tools, APIs, or data sources that implement MCP.
- Expose resources, prompts, and tools.
Clients
- Typically an LLM runtime (e.g., ChatGPT, Claude, or a local agent).
- Connect to servers via MCP without needing implementation details.
Resources
- Data collections that can be listed, queried, or retrieved.
- Examples: files, database rows, calendar events.
- Come with schemas so the LLM understands the structure.
Prompts
- Server-defined instruction templates.
- Help the model interact with resources consistently.
- Example: “Summarize this document in JSON with fields {title, summary}.”
Tools
- Actions the server can perform, triggered through MCP.
- Examples: send an email, create a GitHub issue, insert a DB row.
- Include input/output schemas to define expected arguments/results.
Schemas & Validation
- Structured JSON schemas for inputs and outputs.
- Ensure predictable and reliable interactions.
Transport Layer
- MCP is transport-agnostic.
- Can run over stdio, WebSockets, or other transports.
- Flexible for both local and remote integrations.
Security & Permissions
- Servers declare the resources/tools they expose.
- Clients can enforce permissions and sandboxing.
- Provides safety when handling sensitive data.
Create New Project
This is just a standard console application that can run in a Docker container, you dont have to pop it in a container, MCP can attach and run local code, this is pretty cool, expecially for debugging.
1 | cd dev && dotnet new console -n Demo.MCP |
Install Packages
You can use the dotnet add package
commands like below but Im pretty lazy and just update the .csproj and rebuild
1 | <ItemGroup> |
Proper way, dont follow my antics:
1 | dotnet add package ModelContextProtocol --prerelease |
ModelContextProtocol is a pre release package (0.3.0-preview.4) as of 14/09/2025. Its the official C# SDK for the Model Context Protocol, enabling .NET applications, services, and libraries to implement and interact with MCP clients and servers. - nuget.org
Microsoft.Extensions.Hosting contains the .NET Generic Host HostBuilder which layers on the Microsoft.Extensions.Hosting.Abstractions package. - nuget.org
Microsoft.Extensions.Http provides AddHttpClient extension methods for IServiceCollection, IHttpClientFactory interface and its default implementation. - nuget.org
Add Your first Tool
I try group things in my applications by WHAT THEY DO
as apposed to WHAT THEY ARE
, some devs follow this, some dont. Just do whats right for your future maintainability. Or talk about it like I did and then just add it to the root anyway ( ͡° ͜ʖ ͡°)
1 | dotnet new class -n CarlBlogSearchTool |
Then update the class with the tool function and annotation. So here SearchCarlPatonBlog
is the tool and the annotations McpServerToolType
and McpServerTool
will be used, probably with reflection to find all the tools in the console app.
1 | using ModelContextProtocol.Server; |
… notice how I promoted my own blog but actually just copied James? Its almost like thats what developers do every day 🤫
Scaffold Program.cs
Here I just copied what James published, AddMcpServer
, WithStdioServerTransport
and WithToolsFromAssembly
are fluent api extension methods from IMcpServerBuilder
I then added AddHttpClient
to resolve the HttpClient
in my tool.
1 | using Microsoft.Extensions.DependencyInjection; |
Add the MCP Server
You can do this in two ways
- Add the source locally as mentioned earlier
- Add from a container registry
Add the source locally
From VS Code -> Ctrl
+Shift
+P
-> type MCP
-> MCP: List Servers
-> Add Server
-> Command (STDIO)
-> Name it DemoMCP
-> Enter, Enter -> Global
The IDE then opens mcp.json
which is what configures these servers, you can start the server there. I like to attach to the console.
1 | { |
Add from a container registry
This is useful if you have published the MCP to a container registry
Call the MCP
Now that I have configured the DemoMcp
it can be called from Co-Pilot
Make sure the MCP is runnnig From VS Code ->
Ctrl
+Shift
+P
-> typeMCP
->MCP: List Servers
->DemoMCP
->Start Server
Then execute an example prompt like
find blog posts with the keyword "C#"
I dont have auto allow set, so it asks for permission each time
- This will then list out the responses
- Because you are using a LLM, you can prompt something like
show me the contents of the post about hosted services
To be fair, this shows my MCP is pretty useless as it stands because the LLM has a intrinsic fetch tool
that allows it to fetch contents over HTTP.
However this is just an example tool showing how to build a MCP Server with a tool SearchCarlPatonBlog
Testing
When I was testing I just wrote an integration test CarlBlogSearchToolTests:
1 | namespace Demo.MCP.Tests; |
Source Code
The full source code for Demo.MCP is at https://github.com/carlpaton/Demo.MCP