A comprehensive Model Context Protocol (MCP) server implementation demonstrating best practices for building secure, testable, and production-ready MCP servers in .NET.
This project serves as both a learning resource and a bootstrap template for developers looking to:
- Understand the Model Context Protocol specification
- Build MCP servers with dual transport support (stdio and HTTP/SSE)
- Implement enterprise-grade authentication and security
- Structure .NET projects with proper separation of concerns
- Achieve high test coverage with unit and integration tests
Warning
This code is provided as a basic example and is not guaranteed to be up to date or hardened against a constantly evolving threat landscape.
Four basic arithmetic operations exposed as MCP tools:
- Add - Add two numbers
- Subtract - Subtract second number from first
- Multiply - Multiply two numbers
- Divide - Divide first number by second
| Transport | Project | Use Case |
|---|---|---|
| stdio | McpCalculator | Local integration with Claude Desktop |
| HTTP/SSE | McpCalculator.Web | Network deployment, web clients, custom MCP clients |
- Input Validation - NaN/Infinity detection, range validation (±1e15)
- Rate Limiting - 100 requests/minute per operation with sliding window
- Resource Limits - Overflow protection, minimum denominator enforcement
- Authentication - Four authentication modes (see below)
| Type | Description |
|---|---|
| None | Development only, no authentication |
| ApiKey | Custom header validation with timing-safe comparison |
| JWT | Bearer token with configurable issuer/audience |
| Windows | NTLM/Kerberos via IIS Negotiate |
McpCalculator/
├── McpCalculator.Core/ # Shared calculator logic library
│ ├── CalculatorTools.cs # MCP tool definitions
│ ├── ResourceLimits.cs # Value validation
│ ├── RateLimiter.cs # Rate limiting implementation
│ └── ExecutionContext.cs # Timeout enforcement
│
├── McpCalculator/ # Stdio MCP Server (Console App)
│ └── Program.cs # Entry point for Claude Desktop
│
├── McpCalculator.Web/ # HTTP/SSE MCP Server (ASP.NET Core)
│ ├── Program.cs # Web application entry point
│ ├── Api/ # REST API endpoints
│ └── Authentication/ # Auth handlers and configuration
│
├── McpCalculator.Tests/ # Unit and Integration Tests
│ └── 100+ tests with xUnit
│
└── docs/ # Documentation
├── AUTHENTICATION.md # Authentication configuration guide
├── REST_API.md # REST endpoint documentation
├── HTTP_TRANSPORT.md # MCP over HTTP/SSE guide
├── CLAUDE_DESKTOP_LOCAL.md # Claude Desktop stdio setup
├── CLAUDE_DESKTOP_REMOTE.md # Custom MCP client setup
├── IIS_DEPLOYMENT.md # Production deployment guide
└── MCP_SERVER_SCAFFOLD_GUIDE.md # Create your own MCP server
- .NET 10 SDK
- Claude Desktop (for local MCP integration)
dotnet builddotnet test-
Publish the stdio server:
dotnet publish McpCalculator -c Release -r win-x64 --self-contained true -
Configure Claude Desktop (
%APPDATA%\Claude\claude_desktop_config.json):{ "mcpServers": { "BasicCalculator": { "command": "C:\\path\\to\\McpCalculator\\bin\\Release\\net10.0\\win-x64\\publish\\McpCalculator.exe", "args": [] } } } -
Restart Claude Desktop
-
Configure authentication (using User Secrets for development):
cd McpCalculator.Web dotnet user-secrets set "Authentication:ApiKey:ValidKeys:0" "your-secret-key"
-
Run the web server:
dotnet run --project McpCalculator.Web
-
Test with curl:
curl -X POST https://localhost:5001/api/calculator/add \ -H "Content-Type: application/json" \ -H "X-API-Key: your-secret-key" \ -d '{"a": 5, "b": 3}'
appsettings.json/appsettings.{Environment}.json- User Secrets (Development only)
- Environment Variables
- Azure Key Vault (optional, requires additional package)
# Authentication type
Authentication__Type=ApiKey
# API Keys
Authentication__ApiKey__ValidKeys__0=key1
Authentication__ApiKey__ValidKeys__1=key2
# JWT Settings
Authentication__Jwt__SecretKey=your-256-bit-secret| Endpoint | Method | Description |
|---|---|---|
/api/calculator/add |
POST | Add two numbers |
/api/calculator/subtract |
POST | Subtract two numbers |
/api/calculator/multiply |
POST | Multiply two numbers |
/api/calculator/divide |
POST | Divide two numbers |
/health |
GET | Health check |
/info |
GET | Server information |
/mcp |
- | MCP SSE endpoint |
// Request
{ "a": 10, "b": 5 }
// Success Response
{ "result": 15, "operation": "Add" }
// Error Response
{ "error": "ValidationError", "message": "...", "operation": "Add" }The project includes 100+ tests covering:
- Resource validation and limits
- Rate limiting behavior
- Authentication handlers
- REST API endpoints
- Integration tests with WebApplicationFactory
dotnet test --collect:"XPlat Code Coverage"# Install ReportGenerator
dotnet tool install -g dotnet-reportgenerator-globaltool
# Generate HTML report
reportgenerator -reports:"**/coverage.cobertura.xml" -targetdir:"coveragereport" -reporttypes:Html| Constraint | Value | Purpose |
|---|---|---|
| Max Input Value | ±1e15 | Prevent multiplication overflow |
| Min Denominator | 1e-10 | Prevent division overflow |
| Precision | 15 digits | IEEE 754 double precision |
- 100 requests per minute per operation
- Sliding window algorithm
- Thread-safe implementation
- Independent counters per operation
- Constant-time comparison (timing attack prevention)
- Masked logging for audit trails
- Multiple valid keys supported
- .NET 10 - Latest LTS framework
- Model Context Protocol - MCP SDK for .NET
- ASP.NET Core - Web framework for HTTP/SSE transport
- xUnit - Testing framework
- Moq - Mocking library
- Coverlet - Code coverage
| Document | Description |
|---|---|
| Authentication Guide | Configure authentication options |
| REST API Reference | API endpoints and examples |
| HTTP Transport | MCP over HTTP/SSE explained |
| Claude Desktop (Local) | Stdio setup for Claude Desktop |
| Custom MCP Clients | HTTP/SSE for custom clients |
| IIS Deployment | Production deployment guide |
| Scaffold Guide | Build your own MCP server |
This project is licensed under the MIT License.