DotnetFastMCP
A lightweight .NET framework for building Model Context Protocol (MCP) servers. Integrates seamlessly with Azure AD, AWS Cognito, Auth0, OpenAI and other providers
Ask AI about DotnetFastMCP
Powered by Claude Β· Grounded in docs
I know everything about DotnetFastMCP. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
DotnetFastMCP - Enterprise-Grade Model Context Protocol Server Framework
A modern, production-ready C#/.NET framework for building secure, scalable, and observable Model Context Protocol (MCP) servers with enterprise-grade authentication.
π― Overview
DotnetFastMCP provides a clean, attribute-based approach to building MCP servers that implement the JSON-RPC 2.0 protocol. It includes a native .NET Client Library client for consuming MCP servers, making it a complete solution for building both sides of the Model Context Protocol. Built on ASP.NET Core, it leverages modern .NET features for high performance, reliability, and comprehensive OAuth 2.0 / OpenID Connect authentication out of the box.
β Key Features
Core Framework
- β
Simple Attribute-Based API - Declare tools and resources with
[McpTool]and[McpResource]attributes - β
First-Class Prompts Support - Define prompts with
[McpPrompt]for LLM interaction templates - β Automatic Component Discovery - Reflection-based scanning of assemblies
- β JSON-RPC 2.0 Compliant - Full protocol compliance with proper error handling
- β Flexible Parameter Binding - Supports both array and named parameters
- β Built on ASP.NET Core - Leverage the powerful ASP.NET Core hosting model
- β Production Ready - Comprehensive error handling and logging
- β Type-Safe - Full C# type system integration
π Enterprise Authentication
- β 6 OAuth Providers Supported - Azure AD, Google, GitHub, Auth0, Okta, AWS Cognito
- β OAuth Proxy Built-In - Automatic Dynamic Client Registration (DCR) for non-DCR providers
- β JWT Token Verification - Automatic token validation with JWKS caching
- β Zero Configuration - Set environment variables and go
- β Sensible Defaults - Pre-configured scopes for common use cases
- β
Fine-Grained Authorization - Protect tools with
[Authorize]attribute - β Claims-Based Access - Access user information from authenticated requests
- β MFA Support - Enforce Multi-Factor Authentication for sensitive tools
π Native Client Library
- β McpClient - Type-safe .NET client for consuming any MCP server
- β Transport Agnostic - Support for both Stdio and SSE connections
- β Notification Handling - Events for real-time logs and progress
- β
Tool Invocation - Clean
CallToolAsync<T>API
π€ LLM Integration
- β 8 LLM Providers - Ollama, OpenAI, Azure OpenAI, Anthropic Claude, Google Gemini, Cohere, Hugging Face, Deepseek
- β Latest Models (Feb 2026) - Claude Opus 4.6, Gemini 3 Pro/Flash, Command A, DeepSeek V3.2
- β
Unified Interface - Single
ILLMProviderAPI for all providers - β
Streaming Support - Real-time token streaming with
IAsyncEnumerable<string> - β Production-Ready - HttpClientFactory, Polly retry policies, connection pooling
- β
Plug-and-Play - Simple extension methods:
builder.AddAnthropicProvider()
π‘ Observability (v1.14.0)
- β OpenTelemetry Integration - First-class metrics and distributed tracing
- β 5 Auto-Tracked Metrics - Tool invocations, duration, errors, prompt requests, resource reads
- β
One-Line Setup -
builder.WithTelemetry()β zero boilerplate - β Exporter Agnostic - Plug in Prometheus, Application Insights, Grafana, Jaeger, or any OTLP backend
- β OTel Semantic Conventions - Standard tag names, exception events, span status
- β Zero Overhead When Disabled - Fully opt-in, no performance cost if unused
- β Stdio + HTTP - Metrics work across both transports
π₯ Health Checks & Diagnostics (NEW! v1.15.0)
- β
Built-In Health Endpoint -
GET /mcp/healthexposed automatically - β
One-Line Setup -
builder.WithHealthChecks()β no configuration required - β Plug-In Custom Checks - Add any check as a simple lambda (no interfaces needed)
- β Parallel Execution - All checks run concurrently with per-check timeout
- β Standard HTTP Status Codes - 200 Healthy / 207 Degraded / 503 Unhealthy
- β Kubernetes & Docker Ready - Drop-in for liveness/readiness probes
- β Auto Server Diagnostics - Tool count, uptime, framework version included
- β Zero Overhead When Disabled - Fully opt-in, endpoint not registered unless configured
π Quick Start
Installation
git clone https://github.com/tekspry/.NetFastMCP.git
cd DotnetFastMCP
dotnet build -c Release
Create Your First MCP Server
1. Define Your Tools
Create a static class with [McpTool]-decorated static methods:
using FastMCP.Attributes;
public static class MyTools
{
[McpTool(Description = "Adds two numbers")]
public static int Add(int a, int b) => a + b;
[McpTool(Description = "Returns an echo of the input")]
public static string Echo(string message) => message;
}
2. Create Program.cs
using FastMCP.Hosting;
using FastMCP.Server;
using System.Reflection;
var server = new FastMCPServer("MyMcpServer");
var builder = McpServerBuilder.Create(server, args);
builder.WithComponentsFrom(Assembly.GetExecutingAssembly());
var app = builder.Build();
await app.RunMcpAsync(args);
Running the Example Server
cd examples/BasicServer
dotnet run
The server will start on http://localhost:5000.
π Architecture
Core Components
DotnetFastMCP/
βββ src/
β βββ FastMCP/
β β βββ Attributes/ # Component declaration attributes
β β βββ Client/ # π Client library implementation
β β βββ Hosting/ # Server hosting and middleware
β β βββ Protocol/ # JSON-RPC protocol implementation
β β βββ Server/ # FastMCPServer core class
β β βββ FastMCP.csproj
β βββ FastMCP.CLI/ # Command-line utilities
βββ examples/
β βββ BasicServer/ # Example MCP server implementation
βββ tests/
β βββ McpIntegrationTest/ # Integration tests
βββ LAUNCH_TESTS.ps1 # PowerShell test suite launcher
βββ RUN_AND_TEST.ps1 # PowerShell integration test script
Project Structure
| Project | Purpose |
|---|---|
FastMCP | Core framework library |
FastMCP.CLI | Command-line interface tools |
BasicServer | Example MCP server implementation |
McpIntegrationTest | Integration tests |
ClientDemo | Example Client consuming BasicServer |
π§ Creating an MCP Server
1. Define Components
For better organization, split your components into multiple files (e.g., Tools.cs, Resources.cs). The framework will discover them automatically.
File: Tools.cs
using FastMCP.Attributes;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
public static class MyTools
{
/// <summary>
/// Public tool - no authentication required
/// </summary>
[McpTool]
public static int Add(int a, int b) => a + b;
public static class Resources
{
/// <summary>
/// Protected tool - requires authentication
/// </summary>
[McpTool]
[Authorize]
public static object GetUserProfile(ClaimsPrincipal user)
{
return new
{
Name = user.Identity?.Name,
Email = user.FindFirst("email")?.Value,
IsAuthenticated = user.Identity?.IsAuthenticated
};
}
}
2. Configure Server with Authentication
using FastMCP.Hosting;
using FastMCP.Server;
using System.Reflection;
var mcpServer = new FastMCPServer(name: "My Secure MCP Server");
var builder = McpServerBuilder.Create(mcpServer, args);
// Add authentication (choose your provider)
builder.AddAzureAdTokenVerifier(); // or AddGoogleTokenVerifier(), AddGitHubTokenVerifier(), etc.
// Register tools
builder.WithComponentsFrom(Assembly.GetExecutingAssembly());
var app = builder.Build();
app.Urls.Add("http://localhost:5002");
await app.RunAsync();
3. Set Environment Variables
# Windows PowerShell
$env:FASTMCP_SERVER_AUTH_AZUREAD_TENANT_ID="your-tenant-id"
$env:FASTMCP_SERVER_AUTH_AZUREAD_CLIENT_ID="your-client-id"
$env:FASTMCP_SERVER_AUTH_AZUREAD_CLIENT_SECRET="your-client-secret"
# Linux/Mac
export FASTMCP_SERVER_AUTH_AZUREAD_TENANT_ID="your-tenant-id"
export FASTMCP_SERVER_AUTH_AZUREAD_CLIENT_ID="your-client-id"
export FASTMCP_SERVER_AUTH_AZUREAD_CLIENT_SECRET="your-client-secret"
4. Run and Test
dotnet run
Your server is now running with OAuth Proxy endpoints:
- MCP endpoint:
http://localhost:5002/mcp - OAuth authorization:
http://localhost:5002/oauth/authorize - OAuth token:
http://localhost:5002/oauth/token - Discovery:
http://localhost:5002/.well-known/oauth-authorization-server
Stdio Mode
You can also run the server in Stdio mode (for local LLM clients):
dotnet run -- --stdio
Create an MCP Client
Connect to any MCP server using the C# Client Library:
using FastMCP.Client;
using FastMCP.Client.Transports;
// 1. Connect (via Stdio or SSE)
var transport = new StdioClientTransport("dotnet", "run --project examples/BasicServer -- --stdio");
await using var client = new McpClient(transport);
await client.ConnectAsync();
// 2. List & Call Tools
var tools = await client.ListToolsAsync();
var result = await client.CallToolAsync<int>("add_numbers", new { a = 10, b = 20 });
π Authentication Providers
DotnetFastMCP supports 6 enterprise-grade OAuth providers out of the box:
| Provider | Method | Use Case | Default Scopes |
|---|---|---|---|
| Azure AD | AddAzureAdTokenVerifier() | Enterprise apps, Microsoft 365 | openid, profile, email, offline_access |
AddGoogleTokenVerifier() | Consumer apps, Google Workspace | openid, profile, email, userinfo.profile | |
| GitHub | AddGitHubTokenVerifier() | Developer tools, repositories | read:user, user:email |
| Auth0 | AddAuth0TokenVerifier() | Multi-tenant SaaS, custom identity | openid, profile, email, offline_access |
| Okta | AddOktaTokenVerifier() | Enterprise SSO, workforce identity | openid, profile, email, offline_access |
| AWS Cognito | AddAwsCognitoTokenVerifier() | AWS-native apps, user pools | openid, profile, email |
Quick Setup Examples
Azure AD
builder.AddAzureAdTokenVerifier();
Environment Variables:
FASTMCP_SERVER_AUTH_AZUREAD_TENANT_ID=your-tenant-id
FASTMCP_SERVER_AUTH_AZUREAD_CLIENT_ID=your-client-id
FASTMCP_SERVER_AUTH_AZUREAD_CLIENT_SECRET=your-client-secret
Example: examples/Auth/AzureAdOAuth
builder.AddGoogleTokenVerifier();
Environment Variables:
FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET=your-client-secret
Example: examples/Auth/GoogleOAuth
GitHub
builder.AddGitHubTokenVerifier();
Environment Variables:
FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID=your-github-client-id
FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRET=your-github-client-secret
Example: examples/Auth/GitHubOAuth
The project includes a comprehensive PowerShell-based integration test suite that validates a running server end-to-end.
-
Publish the server (from the root of the
DotnetFastMCPproject):dotnet publish -c Release -o ..\publish examples\BasicServer -
Run the tests: Open a PowerShell terminal and run the launcher script from the project root:
.\LAUNCH_TESTS.ps1
This will open a new window, start the BasicServer, and run a series of tests covering all tools and resources, including error handling.
Example Manual Test
Auth0
builder.AddAuth0TokenVerifier();
Environment Variables:
FASTMCP_SERVER_AUTH_AUTH0_DOMAIN=your-tenant.auth0.com
FASTMCP_SERVER_AUTH_AUTH0_AUDIENCE=https://your-api-identifier
FASTMCP_SERVER_AUTH_AUTH0_CLIENT_ID=your-client-id
FASTMCP_SERVER_AUTH_AUTH0_CLIENT_SECRET=your-client-secret
Example: examples/Auth/Auth0OAuth
Okta
builder.AddOktaTokenVerifier();
Environment Variables:
FASTMCP_SERVER_AUTH_OKTA_DOMAIN=dev-123456.okta.com
FASTMCP_SERVER_AUTH_OKTA_AUDIENCE=api://default
FASTMCP_SERVER_AUTH_OKTA_CLIENT_ID=your-client-id
FASTMCP_SERVER_AUTH_OKTA_CLIENT_SECRET=your-client-secret
Example: examples/Auth/OktaOAuth
AWS Cognito
builder.AddAwsCognitoTokenVerifier();
Environment Variables:
FASTMCP_SERVER_AUTH_AWSCOGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
FASTMCP_SERVER_AUTH_AWSCOGNITO_REGION=us-east-1
FASTMCP_SERVER_AUTH_AWSCOGNITO_CLIENT_ID=your-app-client-id
FASTMCP_SERVER_AUTH_AWSCOGNITO_CLIENT_SECRET=your-app-client-secret
FASTMCP_SERVER_AUTH_AWSCOGNITO_DOMAIN=myapp.auth.us-east-1.amazoncognito.com
Example: examples/Auth/AwsCognitoOAuth
π Architecture
Project Structure
DotnetFastMCP/
βββ src/
β βββ FastMCP/
β βββ Attributes/ # Component declaration attributes
β βββ Authentication/ # π OAuth providers & token verification
β β βββ Providers/ # Azure AD, Google, GitHub, Auth0, Okta, AWS
β β βββ Proxy/ # OAuth Proxy for DCR
β β βββ Verification/ # JWT token validation
β βββ Hosting/ # Server hosting and middleware
β βββ Protocol/ # JSON-RPC protocol implementation
β βββ Server/ # FastMCPServer core class
βββ examples/
β βββ BasicServer/ # Simple MCP server
β βββ Auth/ # π Authentication examples
β βββ AzureAdOAuth/ # Azure AD example
β βββ GoogleOAuth/ # Google OAuth example
β βββ GitHubOAuth/ # GitHub OAuth example
β βββ Auth0OAuth/ # Auth0 example
β βββ OktaOAuth/ # Okta example
β βββ AwsCognitoOAuth/ # AWS Cognito example
βββ tests/
βββ McpIntegrationTest/ # Integration tests
Project Structure (Client)
The FastMCP framework now includes a complete client implementation in src/FastMCP/Client.
graph TD
App[Your App] -->|Uses| Client[McpClient]
Client -->|IClientTransport| Trans[Transport Layer]
Trans -->|Stdio| Local[Local Process]
Trans -->|SSE/HTTP| Remote[Remote Server]
Authentication Flow
sequenceDiagram
participant Client
participant MCP Server
participant OAuth Provider
Client->>MCP Server: Request with Bearer Token
MCP Server->>Token Verifier: Validate Token
Token Verifier->>OAuth Provider: Fetch JWKS (if needed)
OAuth Provider-->>Token Verifier: Public Keys
Token Verifier-->>MCP Server: Validated Claims
MCP Server-->>Client: Protected Resource
π§ Creating an MCP Server
Basic Server (No Authentication)
using FastMCP.Hosting;
using FastMCP.Server;
using System.Reflection;
var mcpServer = new FastMCPServer(name: "My MCP Server");
var builder = McpServerBuilder.Create(mcpServer, args);
builder.WithComponentsFrom(Assembly.GetExecutingAssembly());
var app = builder.Build();
await app.RunAsync();
Secure Server (With Authentication)
using FastMCP.Hosting;
using FastMCP.Server;
using System.Reflection;
var mcpServer = new FastMCPServer(name: "My Secure MCP Server");
var builder = McpServerBuilder.Create(mcpServer, args);
// Add authentication - automatically configures OAuth Proxy
builder.AddAzureAdTokenVerifier(); // or any other provider
builder.WithComponentsFrom(Assembly.GetExecutingAssembly());
var app = builder.Build();
app.Urls.Add("http://localhost:5002");
await app.RunMcpAsync(args);
Protected Tools
using FastMCP.Attributes;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
public static class SecureTools
{
/// <summary>
/// Public tool - anyone can call
/// </summary>
[McpTool]
public static string Echo(string message) => message;
/// <summary>
/// Protected tool - requires valid OAuth token
/// </summary>
[McpTool]
[Authorize]
public static object GetUserInfo(ClaimsPrincipal user)
{
return new
{
Name = user.Identity?.Name ?? "Unknown",
Email = user.FindFirst("email")?.Value ?? "Not available",
IsAuthenticated = user.Identity?.IsAuthenticated ?? false,
Claims = user.Claims.Select(c => new { c.Type, c.Value }).ToList()
};
}
/// <summary>
/// Role-based authorization
/// </summary>
[McpTool]
[Authorize(Roles = "Admin")]
public static string AdminOnly() => "Admin access granted";
}
π‘ JSON-RPC Protocol
Prompts
Prompts allow servers to provide templates that LLMs can use.
using FastMCP.Attributes;
using FastMCP.Protocol;
public static class MyPrompts
{
[McpPrompt("analyze_code")]
public static GetPromptResult Analyze(string code)
{
return new GetPromptResult
{
Description = "Analyze the given code",
Messages = new List<PromptMessage>
{
new PromptMessage
{
Role = "user",
Content = new { type = "text", text = $"Please analyze this code:\n{code}" }
}
}
};
}
}
Calling Tools
Public Tool (No Auth):
POST /mcp
{
"jsonrpc": "2.0",
"method": "Echo",
"params": ["Hello World"],
"id": 1
}
Protected Tool (With Auth):
POST /mcp
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
{
"jsonrpc": "2.0",
"method": "GetUserInfo",
"params": [],
"id": 2
}
π§ͺ Testing
Run All Tests
dotnet test
Test Authentication Flow
Each authentication example includes a comprehensive .rest file for testing:
# Open in VS Code with REST Client extension
code examples/Auth/AzureAdOAuth/azure-ad-auth-tests.rest
Test files include:
- β Discovery endpoints
- β Public tool tests
- β Protected tool tests (should fail without auth)
- β OAuth authorization flow
- β Token exchange
- β Provider-specific API calls
π Documentation
Complete Authentication Guide
See MFA Support Guide for enforcing Multi-Factor Authentication on sensitive tools, and the individual provider README files under examples/Auth/ for detailed OAuth setup instructions.
Example Projects
| Example | Description | Port |
|---|---|---|
| BasicServer | Simple MCP server without authentication | 5000 |
| HealthChecksDemo | π₯ Health monitoring & diagnostics demo | 5000 |
| TelemetryDemo | π‘ OpenTelemetry metrics & tracing demo | 5000 |
| AzureAdOAuth | Azure AD authentication example | 5002 |
| GoogleOAuth | Google OAuth example | 5000 |
| GitHubOAuth | GitHub OAuth example | 5001 |
| Auth0OAuth | Auth0 authentication example | 5005 |
| OktaOAuth | Okta authentication example | 5007 |
| AwsCognitoOAuth | AWS Cognito example | 5006 |
ποΈ Advanced Features
π₯ Health Checks & Diagnostics (NEW! v1.15.0)
FastMCP ships with a built-in production health check endpoint. Enable with one line and plug in any custom check as a simple lambda.
using FastMCP.Health;
// Zero-config β exposes GET /mcp/health automatically
builder.WithHealthChecks();
// With custom checks (database, LLM provider, memory, etc.)
builder.WithHealthChecks(checks =>
{
checks.AddCheck("memory", () =>
GC.GetTotalMemory(false) < 500_000_000L); // sync: < 500 MB
checks.AddAsyncCheck("database", async ct =>
await dbContext.Database.CanConnectAsync(ct));
checks.AddAsyncCheck("llm_provider", async ct =>
await llmProvider.IsHealthyAsync(ct));
});
Response JSON (HTTP 200 β Healthy):
{
"status": "Healthy",
"timestamp": "2026-04-19T20:00:00Z",
"checks": [
{ "name": "mcp_server", "status": "Healthy", "durationMs": 0 },
{ "name": "memory", "status": "Healthy", "durationMs": 0.1 },
{ "name": "database", "status": "Healthy", "durationMs": 4.9 },
{ "name": "llm_provider", "status": "Healthy", "durationMs": 22.3 }
],
"diagnostics": {
"serverName": "my-mcp-server",
"frameworkVersion": "1.15.0.0",
"toolCount": 12,
"uptimeSeconds": 3721.4
}
}
HTTP status code mapping:
| Status | HTTP Code | Meaning |
|---|---|---|
Healthy | 200 | All checks passed |
Degraded | 207 | Server up, β₯1 check timed out |
Unhealthy | 503 | β₯1 check failed or threw |
Kubernetes liveness / readiness probe:
livenessProbe:
httpGet:
path: /mcp/health
port: 5000
initialDelaySeconds: 15
periodSeconds: 30
readinessProbe:
httpGet:
path: /mcp/health
port: 5000
periodSeconds: 10
See Health Checks Guide for full documentation, including Docker Compose, Azure Container Apps, per-check timeout configuration, unit testing patterns, and complete validation examples.
π‘ Observability β OpenTelemetry (v1.14.0)
FastMCP ships with built-in OpenTelemetry instrumentation. Enable with one line and connect to any backend.
using FastMCP.Telemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
// 1. Enable FastMCP telemetry (one line)
builder.WithTelemetry(t =>
{
t.ServiceName = "my-mcp-server";
t.EnableMetrics = true;
t.EnableTracing = true;
});
// 2. Configure your exporter of choice
builder.Services.AddOpenTelemetry()
.WithMetrics(m =>
{
m.AddMcpInstrumentation(); // FastMCP extension method
m.AddPrometheusExporter(); // or AddConsoleExporter(), AddOtlpExporter()
})
.WithTracing(t =>
{
t.AddMcpInstrumentation(); // FastMCP extension method
t.AddOtlpExporter(); // or AddJaeger(), AddZipkin()
});
Metrics automatically tracked:
| Metric | Type | Tag | Description |
|---|---|---|---|
mcp.tool.invocations | Counter | tool.name | Total tool calls |
mcp.tool.duration | Histogram (ms) | tool.name | Tool execution time |
mcp.tool.errors | Counter | tool.name | Failed tool calls |
mcp.prompt.requests | Counter | β | Prompt template requests |
mcp.resource.reads | Counter | β | Resource read requests |
Validate with dotnet-counters (no exporter needed):
dotnet-counters monitor -n YourAppName --counters FastMCP
See Observability Guide for full documentation, including production exporter setup, distributed tracing details, and real request/response validation examples.
Middleware Interception
Middleware allows you to intercept and modify JSON-RPC messages (requests and responses) flowing through the server pipeline. This is useful for logging, validation, modification, or custom monitoring.
- Define Middleware: Implement
IMcpMiddleware. - Register Middleware: Use
builder.AddMcpMiddleware<T>().
public class LoggingMiddleware : IMcpMiddleware
{
public async Task<JsonRpcResponse> InvokeAsync(McpMiddlewareContext context, McpMiddlewareDelegate next, CancellationToken ct)
{
Console.Error.WriteLine($"[LOG] Incoming: {context.Request.Method}");
// Pass to next handler
var response = await next(context, ct);
Console.Error.WriteLine($"[LOG] Completed. Error: {response.Error != null}");
return response;
}
}
// In Program.cs:
builder.AddMcpMiddleware<LoggingMiddleware>();
Server Composition (NEW!)
Mount other MCP servers into your main server instantiation. This supports a "Micro-MCP" architecture where you can compose a robust agent from smaller, focused modules.
// 1. Create Sub-Server (e.g. GitHub Tools)
var githubServer = new FastMCPServer("GitHub");
// ... register tools ...
// 2. Import into Main Server with "gh" prefix
builder.AddServer(githubServer, prefix: "gh");
// Result:
// The client sees tools named: "gh_create_issue", "gh_get_repo", etc.
MFA Support (NEW!)
Enforce Multi-Factor Authentication for sensitive tools.
[McpTool("transfer_funds")]
[AuthorizeMcpTool(RequireMfa = true)]
public static string TransferFunds()
{
return "Transferred!";
}
- MFA Check: Verifies
amrclaim containsmfa. - Security: Provides granular protection for critical operations.
Storage Abstraction (NEW!)
FastMCP now includes a built-in state persistence layer. Tools can request McpContext to access IMcpStorage.
[McpTool]
public static async Task<string> SetValue(string key, string value, McpContext context)
{
await context.Storage.SetAsync(key, value);
return "Saved!";
}
The default implementation is In-Memory, but you can swap it for Redis, SQL, or File storage:
builder.AddMcpStorage<MyRedisStorage>();
LLM Integration (NEW!)
FastMCP includes a powerful LLM integration system with 8 providers supporting the latest models (Feb 2026).
Quick Setup
using FastMCP.AI;
// Option 1: Local (Ollama)
builder.AddOllamaProvider(options =>
{
options.BaseUrl = "http://localhost:11434";
options.DefaultModel = "llama3.1:8b";
});
// Option 2: Cloud (Anthropic Claude Opus 4.6 - Latest)
builder.AddAnthropicProvider(options =>
{
options.ApiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY")!;
options.DefaultModel = "claude-opus-4.6"; // 1M context, Feb 2026
});
// Option 3: Google Gemini 3
builder.AddGeminiProvider(options =>
{
options.ApiKey = Environment.GetEnvironmentVariable("GEMINI_API_KEY")!;
options.DefaultModel = "gemini-3-flash"; // Fast, cost-effective
});
Use in Tools
public class AITools
{
private readonly ILLMProvider _llm;
public AITools(ILLMProvider llm) => _llm = llm;
[McpTool("generate_story")]
public async Task<string> GenerateStory(string topic)
{
return await _llm.GenerateAsync(
$"Write a story about {topic}",
new LLMGenerationOptions
{
SystemPrompt = "You are a creative storyteller.",
Temperature = 0.8,
MaxTokens = 500
});
}
[McpTool("stream_response")]
public async IAsyncEnumerable<string> StreamResponse(string prompt)
{
await foreach (var token in _llm.StreamAsync(prompt))
{
yield return token;
}
}
}
Supported Providers (Feb 2026)
| Provider | Extension Method | Latest Model | Best For |
|---|---|---|---|
| Ollama | AddOllamaProvider() | llama3.1:8b | Local, privacy, offline |
| OpenAI | AddOpenAIProvider() | gpt-4-turbo | Production, function calling |
| Azure OpenAI | AddAzureOpenAIProvider() | gpt-4 | Enterprise, compliance |
| Anthropic | AddAnthropicProvider() | claude-opus-4.6 | Deep reasoning, 1M context |
| Google Gemini | AddGeminiProvider() | gemini-3-flash | Multimodal, high-volume |
| Cohere | AddCohereProvider() | command-a | Enterprise RAG, agents |
| Hugging Face | AddHuggingFaceProvider() | Any model | Open-source, flexibility |
| Deepseek | AddDeepseekProvider() | deepseek-v3.2 | Cost-effective, reasoning |
See LLM Integration Guide for complete documentation.
Background Tasks (NEW!)
FastMCP allows tools to fire-and-forget long running operations using RunInBackground.
[McpTool]
public static async Task<string> ProcessFile(string file, McpContext context)
{
await context.RunInBackground(async (ct) =>
{
// This runs without blocking the client
await HeavyProcessing(file, ct);
});
return "Processing started!";
}
Icons Support (NEW!)
Enhance the user interface of clients by providing icons for your server and tools.
// Server Icon
server.Icon = "https://myserver.com/logo.png";
// Tool Icon
[McpTool(Icon = "https://myserver.com/tools/calc.png")]
public static int Add(int a, int b) => a + b;
Binary Content Support (NEW!)
Return rich content like Images from your tools and prompts.
[McpTool]
public static CallToolResult GetSnapshot()
{
return new CallToolResult
{
Content = new List<ContentItem>
{
new ImageContent { Data = "base64...", MimeType = "image/png" }
}
};
}
OAuth Proxy
DotnetFastMCP includes a built-in OAuth Proxy that provides:
- β Dynamic Client Registration (DCR) - Automatic client registration for MCP clients
- β Authorization Code Flow - Full OAuth 2.0 authorization code flow with PKCE
- β Token Management - Automatic token exchange, refresh, and revocation
- β Discovery Endpoints - RFC 8414 compliant OAuth discovery
Automatically Available Endpoints:
/.well-known/oauth-authorization-server- OAuth server metadata/oauth/authorize- Authorization endpoint/oauth/token- Token endpoint/oauth/register- Dynamic client registration/oauth/userinfo- User information endpoint
Custom Scopes
Override default scopes for any provider:
builder.AddAzureAdTokenVerifier(new AzureAdAuthOptions
{
RequiredScopes = new[] { "openid", "profile", "email", "User.Read", "Calendars.Read" }
});
Multiple Authentication Schemes
// Support multiple providers simultaneously
builder.AddAzureAdTokenVerifier();
builder.AddGoogleTokenVerifier();
builder.AddGitHubTokenVerifier();
π Security Best Practices
Development
- β Use environment variables for secrets
- β Never commit credentials to source control
- β
Use
.envfiles for local development - β Test with short-lived tokens
Production
- β Use HTTPS for all communication
- β Store secrets in Azure Key Vault / AWS Secrets Manager
- β Enable MFA for OAuth providers
- β Implement rate limiting
- β Monitor authentication logs
- β Use separate app registrations per environment
- β Validate token scopes match required permissions
π¦ NuGet Package
Install from NuGet (when published):
dotnet add package DotnetFastMCP
π€ Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
π License
This project is licensed under the MIT License - see the LICENSE file for details.
π Resources
Official Documentation
- Model Context Protocol Specification
- JSON-RPC 2.0 Specification
- OAuth 2.0 RFC 6749
- OpenID Connect Core 1.0
Framework Documentation
- Health Checks Guide π v1.15.0
- Observability Guide v1.14.0
- LLM Integration Guide
- Protocol Discovery Guide
- Client Library Guide
- Context & Interaction Guide
- Middleware Interception Guide
- SSE Transport Guide
- Stdio Transport Guide
- ASP.NET Core Documentation
- .NET 8.0 Documentation
Provider Documentation
π Issues & Support
For bug reports and feature requests, please use GitHub Issues.
β¨ What's New
v1.15.0 - Health Checks & Diagnostics (Latest - Apr 2026)
- π₯ Built-In Health Endpoint -
GET /mcp/healthexposed with a singlebuilder.WithHealthChecks()call - π Lambda-Based Custom Checks - Add any check (
database,llm,memory, external API) as a simple lambda with no interface to implement - β‘ Parallel Execution - All checks run concurrently; a slow check never delays a fast one
- β±οΈ Per-Check Timeout - Configurable
MaxResponseTimeMs; hanging checks reported asDegraded, not left blocking - π Standard HTTP Status Codes - 200 Healthy / 207 Degraded / 503 Unhealthy; understood natively by Kubernetes, load balancers, and APM tools
- π Auto Server Diagnostics - Automatically includes server name, framework version, tool/resource/prompt counts, and uptime
- π‘οΈ Always Reachable - Endpoint marked
AllowAnonymous()so infrastructure probes bypass authentication - π― Zero Overhead - Fully opt-in; endpoint is not registered unless
WithHealthChecks()is called - π Comprehensive Docs - Full guide covering Kubernetes, Docker, ACA probes, validation walkthrough, and unit tests
v1.14.0 - OpenTelemetry Observability (Mar 2026)
- π‘ OpenTelemetry Integration - First-class metrics and distributed tracing built in
- π 5 Auto-Tracked Metrics - Tool invocations, duration, errors, prompt requests, resource reads
- β¨ One-Line Setup -
builder.WithTelemetry()with zero boilerplate - π Exporter Agnostic - Works with Prometheus, App Insights, Grafana, Jaeger, any OTLP backend
- π Distributed Tracing - Full span support with OTel semantic convention tags
- π‘οΈ PII Safe Defaults - Tool inputs never logged unless explicitly enabled
- π― Zero Overhead - Fully opt-in, no cost when not used
- π Comprehensive Docs - Full guide with validation examples and production checklist
v1.13.0 - LLM Integration (Feb 2026)
- π€ 8 LLM Providers - Ollama, OpenAI, Azure OpenAI, Anthropic Claude, Google Gemini, Cohere, Hugging Face, Deepseek
- β¨ Latest Models - Claude Opus 4.6 (1M context), Gemini 3 Pro/Flash, Command A, DeepSeek V3.2
- π Unified Interface - Single
ILLMProviderAPI for all providers - π‘ Streaming Support - Real-time token streaming with
IAsyncEnumerable<string> - ποΈ Production-Ready - HttpClientFactory, Polly retry policies, connection pooling
- π― Plug-and-Play - Simple registration:
builder.AddAnthropicProvider() - π Comprehensive Docs - Complete integration guide with examples
v1.12.0 - MFA Support
- π‘οΈ MFA Enforcement - Require
mfaAMR claim for sensitive tools - β
Granular Control - Enable per-tool using
[AuthorizeMcpTool(RequireMfa=true)] - π Enhanced Security - Standards-based multi-factor authentication check
v1.11.0 - Binary Content Support
- β Polymorphic Content - Support for mixed Text and Image responses
- β Image Support - Return Base64 encoded images from tools
- β Multimodal Prompts - Embbed images in prompts for LLM context
v1.10.0 - Icons Support
- β Server Icons - Define a brand icon for your MCP server
- β Tool/Resource Icons - Visually distinguish capabilities
- β UI/UX Enhancement - Enable richer client experiences
v1.9.0 - Background Tasks
- β Fire-and-Forget - Offload long-running operations from tools
- β Non-Blocking - Return immediate responses to clients
- β Hosted Service - Built-in queuing mechanism using Channels
v1.8.0 - Storage Abstractions
- β
State Persistence - Tools can now persist data via
McpContext.Storage - β Pluggable Backends - Swap in Redis/SQL/File storage easily
- β In-Memory Default - Zero-config built-in storage for development
v1.7.0 - Server Composition
- β Server Composition - Mount other MCP servers as modules (Micro-MCPs)
- β
Namespacing - Automatically prefix imported tools (e.g.,
github_createIssue) - β Zero-Overhead - High-performance internal dictionary routing (O(1))
v1.6.0 - Middleware Interception
- β Middleware Pipeline - Intercept and modify requests/responses
- β Critical Fixes - Resolved Stdio transport initialization deadlocks
- β
Builder API - Easy registration with
AddMcpMiddleware<T>
v1.5.0 - Native Client Library
- β McpClient - Type-safe .NET client for consuming MCP servers
- β Transport Agnostic - Support for both Stdio and SSE connections
- β Notification Handling - Events for real-time logs and progress
v1.4.0 - Server-Sent Events (SSE)
- β SSE Transport - Real-time server-to-client streaming transport
- β Async Notifications - Push logs and progress updates to HTTP clients
v1.3.0 - Context & Interaction
- β
Context System -
McpContextinjection for logging and progress - β IMcpSession - Transport-agnostic interaction abstraction
v1.2.0 - Protocol Discovery
- β Dynamic Discovery - Auto-discovery of Tools, Resources, and Prompts
- β Prompts/List - Full support for prompt templates
v1.1.0 - Stdio Transport & Authentication
- β Stdio Transport - Initial support for stdio communication
- π 6 OAuth Providers - Azure AD, Google, GitHub, Auth0, Okta, AWS Cognito
- π OAuth Proxy - Built-in DCR support
v1.0.0 - Core Framework
- β Attribute-based API
- β JSON-RPC 2.0 compliance
- β ASP.NET Core integration
Made with β€οΈ by the DotnetFastMCP team
β Star this repo if you find it useful!
