In this post, we will see what a server MCP is, when and why we should use it and how to create a server with .NET.
But first of all, what is MCP?
“The Model Context Protocol is an open protocol developed by Anthropic that standardizes how applications provide context to Large Language Models (LLMs). Think of MCP as the USB-C standard for AI integrations instead of building custom connectors for each AI platform, you build once using MCP, and any MCP-compatible client can consume your services.
Before MCP, every AI integration required custom implementation. If you wanted Claude to access your database, ChatGPT to query your API, or Copilot to interact with your Azure services, you’d need separate implementations for each. MCP eliminates this fragmentation by providing a unified protocol.“
THE MCP ARCHITECTURE
MCP follows a client-server architecture with three key components:
MCP Hosts: Applications that use MCP to access data and capabilities. Examples include Claude Desktop, Visual Studio Code with GitHub Copilot, or custom AI applications. The host manages connections to multiple MCP servers.
MCP Clients: Communication bridges that maintain 1-to-1 connections between hosts and servers. They handle the JSON-RPC 2.0 message exchange over the chosen transport layer.
MCP Servers: Lightweight programs that expose specific capabilities through the standardized protocol. These can connect to local resources (databases, filesystems) or remote services (APIs, cloud platforms).
TRANSPORT MECHANISMS
MCP supports three transport layers, each optimized for different scenarios:
stdio (Standard Input/Output): Best for local integrations where the MCP server runs as a subprocess of the client. This is ideal for development tools, CLI applications, and desktop integrations. The server communicates through stdin/stdout using JSON-RPC 2.0 messages.
HTTP with Server-Sent Events (SSE): Designed for remote servers and multi-client scenarios. The server uses SSE for server-to-client messages and HTTP POST for client-to-server requests. This approach enables cloud deployments, web services, and scenarios requiring multiple simultaneous connections.
Streamable HTTP: A newer, high-performance transport mechanism that uses standard HTTP with bidirectional streaming support. Unlike SSE which is primarily server-to-client, Streamable HTTP provides full-duplex communication over a single HTTP connection. This is ideal for enterprise applications requiring low latency and efficient message streaming, while maintaining compatibility with standard HTTP infrastructure.
WHAT AN MCP SERVER IS
An MCP server is a program that implements the MCP specification to expose capabilities that AI systems can leverage. These capabilities fall into three main categories:
[Resources]
Resources are file like data that clients can read. They provide context to AI models without requiring function calls. Examples include:
- API responses formatted as structured data
- File contents from your filesystem
- Database query results
- Configuration data
Resources support both text and binary content, making them versatile for various use cases.
[Tools]
Tools are functions that LLMs can invoke (with user approval) to perform actions. This is the most powerful capability of MCP servers. Tools enable AI to:
- Query databases and APIs
- Perform computations
- Modify external systems
- Execute business logic
In .NET, tools are implemented as methods decorated with the [McpServerTool] attribute, making them discoverable to the MCP framework.
[Prompts]
Prompts are pre-written templates that help users accomplish specific tasks. They can:
- Accept dynamic arguments
- Include context from resources
- Chain multiple interactions
- Standardize common workflows
WHEN AND WHY SHOULD WE CREATE AN MCP SERVER?
[Enterprise Data Integration]
If our organization needs to give AI systems access to internal databases, APIs, or services, an MCP server provides a secure, standardized approach. Instead of exposing raw database connections or building custom integrations for each AI platform, you create a single MCP server with controlled access.
[Cross-Platform AI Enablement]
When we want our services available across multiple AI platforms (Claude, ChatGPT, Copilot), MCP eliminates the need for platform-specific implementations. Build once, integrate everywhere.
[Azure Service Integration]
For teams heavily invested in Azure, MCP servers can provide AI-friendly interfaces to Azure Storage, Cosmos DB, Key Vault, and other services. The Azure MCP Server project demonstrates this pattern effectively.
[Agentic Workflows]
If we’re building AI agents that need to perform multi-step operations across different systems, MCP servers provide the building blocks. Tools can be composed by the AI to create complex workflows without hardcoding the logic.
Let’s see how to create a simple MCP server in .NET that demonstrates all three core capabilities: Resources, Tools, and Prompts.
We start create a Console Application project and then we add these NuGet packages:
dotnet add package ModelContextProtocol --prerelease
dotnet add package Microsoft.Extensions.Hosting
[IMPLEMENT RESOURCES]
Resources provide static or dynamic data that can be read by clients. Let’s create a simple knowledge base resource.
The code below defines two endpoints: one for static welcome text and another for a dynamic list of users.
The [Description] attribute is what makes this data discoverable because, it allows the AI to understand the content of the resource and decide if it needs to access it to answer a user’s prompt.
using ModelContextProtocol.Server;
using System.ComponentModel;
using ModelContextProtocol.Protocol;
namespace MCP_Server.Resources;
[McpServerResourceType]
public static class BaseResources
{
[McpServerResource(UriTemplate = "docs://welcome")]
[Description("Welcome to my first MCP Server")]
public static TextResourceContents GetWelcomeMessage()
{
const string content = """
# Welcome to SimpleMcpServer
This MCP server provides:
- Tools for getting current time and weather
- Resources with documentation
- Prompts for common tasks
Version: 1.0.0
""";
return new TextResourceContents()
{
Uri = "docs://welcome",
MimeType = "text/markdown",
Text = content
};
}
[McpServerResource(UriTemplate = "database://users")]
[Description("List of users from the database")]
public static ResourceContents GetUserList()
{
// Simulate database query
var users = new List<string>
{
"Alice Johnson",
"Bob Smith",
"Charlie Davis",
"Diana Martinez",
"Ethan Wilson"
};
var content = string.Join("\n", users.Select((user, index) =>
$"{index + 1}. {user}"));
return new TextResourceContents()
{
Uri = "database://users",
MimeType = "text/plain",
Text = content
};
}
}
Then, we modify the Program.cs file:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
// Check if running in stdio mode (for example for Claude Desktop)
if (args.Contains("--stdio"))
{
var builder = Host.CreateApplicationBuilder(args);
// Disable console logging to avoid interfering with stdio transport
builder.Logging.ClearProviders();
// Add MCP server with stdio transport
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly()
.WithResourcesFromAssembly()
.WithPromptsFromAssembly();
var app = builder.Build();
await app.RunAsync();
}
else
{
// HTTP/SSE mode (for browser clients, testing, etc.)
var builder = WebApplication.CreateBuilder(args);
// Configure logging
builder.Logging.AddConsole();
// Add CORS support
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
// Add MCP server with HTTP transport
builder.Services
.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly()
.WithResourcesFromAssembly()
.WithPromptsFromAssembly();
var app = builder.Build();
// Enable CORS
app.UseCors();
// Map MCP SSE endpoint
app.MapMcp("/sse");
app.Run();
}
Finally, to test the code, let’s start our MCP server, then use the MCP inspector by running the command:
npx @modelcontextprotocol/inspector@latest

Now, if we open the browser, we will see the MCP inspector:



Of course, if we have installed software like Claude Desktop, we can use our MCP directly in the application.
For Claude, we just need to add this value to the configuration file called “claude_desktop_config.json”:
{
"mcpServers": {
"MCP_Server": {
"command": "/usr/local/share/dotnet/dotnet",
"args": ["run", "--project", "/Users/commander/Developments/Projects_net/MCP_Server", "--", "--stdio"]
}
}
}



[IMPLEMENT TOOLS]
Tools are functions that the AI can call with user approval.
The code below defines two executable functions: one to retrieve the current time and another to perform a simple calculation.
Unlike Resources (which are read-only), Tools allow the AI to perform actions or compute new information. The [Description] attributes on the method parameters are especially important here, as they teach the AI exactly what arguments it needs to provide when calling the function.
using System.ComponentModel;
using ModelContextProtocol.Server;
namespace MCP_Server.Resources;
[McpServerToolType]
public static class BaseTools
{
[McpServerTool]
[Description("Get the current date and time")]
public static string GetTime()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
[McpServerTool]
[Description("Calculate the sum of two numbers")]
public static double Add(
[Description("First number")] double a,
[Description("Second number")] double b)
{
return a + b;
}
}
Now let’s start our MCP server and then check the Tools directly in Claude Desktop:




[IMPLEMENT PROMPTS]
Prompts are predefined templates that help users accomplish specific tasks.
The code below creates two reusable prompt templates: one for summarizing text and another for explaining technical concepts.
Unlike Resources (data) or Tools (actions), Prompts act as menu items or templates that help users interact with the AI effectively. They take user input and structure it into a standardized ChatMessage to ensure high-quality results from the LLM.
using System.ComponentModel;
using Microsoft.Extensions.AI;
using ModelContextProtocol.Server;
namespace MCP_Server.Resources;
[McpServerPromptType]
public class BasePrompts
{
[McpServerPrompt]
[Description("Summarize the provided text concisely")]
public static ChatMessage SummarizeText(
[Description("The text to summarize")] string text)
{
return new ChatMessage(
ChatRole.User,
$"Please provide a concise summary of the following text:\n\n{text}");
}
[McpServerPrompt]
[Description("Explain a technical concept in simple terms")]
public static ChatMessage ExplainConcept(
[Description("The concept to explain")] string concept)
{
return new ChatMessage(
ChatRole.User,
$"Explain '{concept}' in simple terms that a beginner can understand.");
}
}
Now let’s start our MCP server and then check the Prompts directly in Claude Desktop:



The code examples in this post are intentionally simple to focus on the fundamentals of creating an MCP server. In a real-world scenario, we would add proper error handling, logging, authentication, and connect to actual databases or external APIs instead of using hardcoded data.
However, this simple implementation demonstrates all the core concepts you need to get started. MCP provides a powerful way to extend AI assistants with custom capabilities.