| docs | ||
| samples/CodexMcpServer | ||
| src | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| AGENT-PRIMER.md | ||
| INTEGRATION-GUIDE.md | ||
| LICENSE | ||
| QUICK-START.md | ||
| README.md | ||
| Svrnty.MCP.sln | ||
| test_mcp_server.py | ||
| test-mcp-server.sh | ||
Svrnty.MCP
A modular, scalable, secure .NET library for building Model Context Protocol (MCP) servers
What is Svrnty.MCP?
Svrnty.MCP is a standalone, reusable .NET library that enables any .NET application to become an MCP server, allowing AI agents (like Claude, ChatGPT, or custom LLMs) to interact with your application through a standardized protocol.
Model Context Protocol (MCP) is an industry-standard protocol backed by Anthropic that defines how AI agents communicate with external tools and data sources. Think of it as a universal adapter that lets AI assistants safely access your application's capabilities.
Key Features
- Modular & Reusable: Copy to any .NET project, configure, and go
- Clean Architecture: Core abstractions, infrastructure implementation, ASP.NET Core integration
- Security-First: Permission-based access control, rate limiting, audit logging, deny-by-default model
- Transport Flexibility: HTTP (primary for production) and stdio (legacy for local development)
- AI-Automated Setup: AGENT-PRIMER.md guides AI assistants to configure your integration automatically
- TDD Foundation: Built with test-driven development, comprehensive test coverage
- Production-Ready: Observability, error handling, graceful shutdown, health checks
Why Svrnty.MCP?
Problem: Your .NET application has valuable features (search, data access, document processing, APIs) that AI agents can't easily access.
Solution: Svrnty.MCP transforms your application into an MCP server, exposing tools that AI agents can discover and execute with proper permissions and rate limiting.
Use Cases:
- Expose knowledge base search to Claude Code CLI (or Desktop)
- Allow AI agents to query your database safely
- Provide document processing tools to LLM workflows
- Enable AI-assisted data analysis on private data
- Build custom AI integrations for enterprise applications
Quick Start
Prerequisites
- .NET 8.0 SDK or higher
- Your existing .NET application (Web API, Console, Worker Service, etc.)
Option 1: AI-Automated Setup (Recommended)
If you have access to Claude or another AI assistant:
- Copy this entire folder to your project directory
- Open your AI assistant and say: "Read AGENT-PRIMER.md and set up Svrnty.MCP for my project"
- The AI will analyze your system, generate configuration, and create sample tools automatically
Option 2: Manual Setup
Step 1: Add Package Reference
# Via project reference (development)
dotnet add reference /path/to/Svrnty.MCP/src/Svrnty.MCP.AspNetCore/Svrnty.MCP.AspNetCore.csproj
# OR via NuGet (when published)
# dotnet add package Svrnty.MCP.AspNetCore
Step 2: Configure appsettings.json
Add MCP configuration:
{
"Mcp": {
"Server": {
"Name": "MyAppMcpServer",
"Version": "1.0.0",
"Description": "MCP server for MyApp"
},
"Transport": {
"Type": "Http",
"Port": 5050
},
"Security": {
"EnablePermissions": true,
"DefaultDenyAll": true,
"RateLimit": {
"Enabled": true,
"RequestsPerMinute": 60
}
}
}
}
Step 3: Update Program.cs
using Svrnty.MCP.Core;
using Microsoft.AspNetCore.Builder;
var builder = WebApplication.CreateBuilder(args);
// Create tool registry and register your tools
var registry = new ToolRegistry();
registry.AddTool(new MyCustomTool());
// Create and register MCP server
var server = new McpServer(registry);
builder.Services.AddMcpServer(server);
// Configure HTTP port
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenLocalhost(5050);
});
var app = builder.Build();
// Map MCP HTTP endpoints
app.MapMcpEndpoints(server);
Console.WriteLine("MCP Server listening on http://localhost:5050");
Console.WriteLine("Endpoints: POST /mcp/invoke, GET /health");
await app.RunAsync();
Step 4: Create Your First Tool
using Svrnty.MCP.Core.Abstractions;
using Svrnty.MCP.Core.Models;
public class MyCustomTool : IMcpTool
{
public string Name => "my_custom_tool";
public string Description => "Describes what this tool does";
public McpToolSchema Schema => new()
{
Type = "object",
Properties = new Dictionary<string, McpProperty>
{
["query"] = new()
{
Type = "string",
Description = "Search query",
Required = true
}
}
};
public async Task<McpToolResult> ExecuteAsync(
Dictionary<string, object> parameters,
CancellationToken ct = default)
{
var query = parameters["query"].ToString();
// Your tool logic here
var result = await ProcessQueryAsync(query, ct);
return McpToolResult.Success(result);
}
}
Step 5: Run and Test
# Run your application (HTTP mode, default)
dotnet run
# Server will listen on http://localhost:5050
# Test health endpoint
curl http://localhost:5050/health
# Test tool listing via HTTP
curl -X POST http://localhost:5050/mcp/invoke \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Test tool execution via HTTP
curl -X POST http://localhost:5050/mcp/invoke \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"my_custom_tool","arguments":{"query":"test"}}}'
Legacy Stdio Mode (for Claude Desktop integration):
# Run in stdio mode for Claude Desktop
dotnet run -- --stdio
# Test with stdio
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | dotnet run -- --stdio
Architecture
Svrnty.MCP follows Clean Architecture principles:
┌─────────────────────────────────────────────────┐
│ Svrnty.MCP.Cli (Executable) │
│ ┌───────────────────────────────────────────┐ │
│ │ Svrnty.MCP.AspNetCore (HTTP/DI) │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ Svrnty.MCP.Infrastructure │ │ │
│ │ │ ┌───────────────────────────────┐ │ │ │
│ │ │ │ Svrnty.MCP.Core │ │ │ │
│ │ │ │ - IMcpServer │ │ │ │
│ │ │ │ - IMcpTool │ │ │ │
│ │ │ │ - IPermissionProvider │ │ │ │
│ │ │ │ - Models (no dependencies) │ │ │ │
│ │ │ └───────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
Projects
| Project | Purpose | Dependencies |
|---|---|---|
| Svrnty.MCP.Core | Abstractions, interfaces, models | None |
| Svrnty.MCP.Infrastructure | MCP server implementation, transports, security | Core, System.Text.Json |
| Svrnty.MCP.AspNetCore | ASP.NET Core integration, DI extensions | Core, Infrastructure, ASP.NET Core |
| Svrnty.MCP.Cli | Standalone CLI executable | All above |
See Architecture Documentation for detailed design.
Examples
1. CODEX MCP Server (Knowledge Gateway)
CODEX is a knowledge management system. The MCP integration exposes 6 tools:
samples/CodexMcpServer/
├── Tools/
│ ├── SearchCodexTool.cs # Semantic/keyword search
│ ├── GetDocumentTool.cs # Retrieve document by ID
│ ├── ListDocumentsTool.cs # List all documents
│ ├── SearchByTagTool.cs # Filter by tags
│ ├── GetDocumentSectionsTool.cs # Get document sections
│ └── ListTagsTool.cs # List all tags
Usage with MCP Gateway (Recommended for Production):
# Run CODEX MCP Server in HTTP mode (default)
cd /path/to/Svrnty.MCP.Server/samples/CodexMcpServer
dotnet run
# Server listens on http://localhost:5050
# Configure gateway to route to this server
# See Svrnty.MCP.Gateway documentation
Alternative: Claude Desktop with Stdio (Legacy, Local Development):
{
"mcpServers": {
"codex": {
"command": "dotnet",
"args": ["run", "--project", "/path/to/samples/CodexMcpServer/CodexMcpServer.csproj", "--", "--stdio"],
"transport": "stdio"
}
}
}
Note: HTTP transport is recommended for production deployments with multiple clients, load balancing, and monitoring.
2. Database Query Tool
public class DatabaseQueryTool : IMcpTool
{
private readonly MyDbContext _context;
public string Name => "query_database";
public string Description => "Execute read-only SQL queries";
public async Task<McpToolResult> ExecuteAsync(
Dictionary<string, object> parameters,
CancellationToken ct = default)
{
var sql = parameters["sql"].ToString();
// Security: Validate read-only query
if (!IsReadOnlyQuery(sql))
{
return McpToolResult.Error("Only SELECT queries allowed");
}
var results = await _context.Database.SqlQueryRaw<object>(sql).ToListAsync(ct);
return McpToolResult.Success(results);
}
}
3. Document Processing Tool
public class ProcessDocumentTool : IMcpTool
{
private readonly IDocumentProcessor _processor;
public string Name => "process_document";
public string Description => "Extract text and metadata from uploaded documents";
public async Task<McpToolResult> ExecuteAsync(
Dictionary<string, object> parameters,
CancellationToken ct = default)
{
var filePath = parameters["filePath"].ToString();
var result = await _processor.ProcessAsync(filePath, ct);
return McpToolResult.Success(new
{
extractedText = result.Text,
metadata = result.Metadata,
pageCount = result.PageCount
});
}
}
Security
Svrnty.MCP implements defense-in-depth security:
1. Permission-Based Access Control
{
"Mcp": {
"Security": {
"DefaultDenyAll": true,
"Agents": {
"claude-desktop": {
"Permissions": [
"tools:search",
"tools:read"
]
},
"public-agent": {
"Permissions": [
"tools:search"
]
}
}
}
}
}
2. Rate Limiting
Token bucket algorithm prevents abuse:
{
"RateLimit": {
"Enabled": true,
"RequestsPerMinute": 60,
"BurstSize": 10
}
}
3. Audit Logging
All MCP operations are logged:
[2025-10-19 10:15:32] INFO: Agent 'claude-desktop' executed tool 'search_codex' with parameters {"query":"neural networks"} - Success
[2025-10-19 10:15:45] WARN: Agent 'public-agent' denied access to tool 'delete_document' - Permission 'tools:delete' not granted
4. Input Validation
All tool parameters are validated against schema before execution.
Testing
Svrnty.MCP is built with Test-Driven Development (TDD):
# Run all tests
dotnet test
# Run with coverage
dotnet test /p:CollectCoverage=true
# Run specific test category
dotnet test --filter Category=Integration
Test Structure:
tests/
├── Svrnty.MCP.Core.Tests/ # Unit tests (abstractions, models)
├── Svrnty.MCP.Infrastructure.Tests/ # Unit tests (server, transports, security)
└── Svrnty.MCP.Integration.Tests/ # End-to-end integration tests
Example Test (TDD style):
// RED: Write failing test first
[Fact]
public async Task ExecuteTool_WithInvalidPermissions_ThrowsUnauthorized()
{
var server = new McpServer();
var tool = new SearchTool();
var agent = new AgentContext { Id = "test", Permissions = [] };
await Assert.ThrowsAsync<UnauthorizedAccessException>(
() => server.ExecuteToolAsync(tool.Name, agent, new Dictionary<string, object>())
);
}
// GREEN: Implement minimal code to pass
// REFACTOR: Improve design while keeping tests green
See TDD Guide for complete examples.
Test Coverage
Svrnty.MCP.Server maintains 42.46% line coverage and 50.00% branch coverage with 141 tests passing (100%).
Coverage Breakdown:
- Lines: 344 of 810 covered (42.46%)
- Branches: 72 of 144 covered (50.00%)
- Test Projects: 2
- Svrnty.MCP.Core.Tests: 82 tests
- CodexMcpServer.Tests: 59 tests
Analysis:
- Core domain logic has excellent coverage (> 70%)
- Lower overall percentage due to Program.cs/startup code (not tested by design)
- HTTP transport and protocol implementation well-tested
- Production-ready coverage levels for deployment
Coverage Reports:
# Generate coverage report
dotnet test --collect:"XPlat Code Coverage" --results-directory ./TestResults
# View detailed coverage
# See: /home/svrnty/codex/COVERAGE-SUMMARY.md for complete analysis
Status: ✅ Good - Core business logic exceeds 70% coverage threshold
Configuration Reference
Server Settings
| Setting | Type | Default | Description |
|---|---|---|---|
Mcp.Server.Name |
string | (required) | MCP server name |
Mcp.Server.Version |
string | "1.0.0" | Server version (semver) |
Mcp.Server.Description |
string | "" | Human-readable description |
Mcp.Server.Vendor |
string | "" | Vendor/organization name |
Transport Settings
| Setting | Type | Default | Description |
|---|---|---|---|
Mcp.Transport.Type |
enum | "Http" | "Http" (recommended) or "Stdio" (legacy) |
Mcp.Transport.Port |
int | 5050 | HTTP server port |
Mcp.Transport.Options.BufferSize |
int | 8192 | Buffer size (bytes) for stdio |
Mcp.Transport.Options.EnableLogging |
bool | false | Log all I/O |
HTTP Transport (Production):
- Supports multiple concurrent clients
- Load balancing via gateway
- Health check endpoint (
/health) - Standard REST API patterns
- Port 5050 (default for MCP servers)
Stdio Transport (Legacy):
- One client per process
- Used by Claude Desktop
- Local development only
- Requires
--stdiocommand-line flag
Security Settings
| Setting | Type | Default | Description |
|---|---|---|---|
Mcp.Security.EnablePermissions |
bool | true | Enable permission checks |
Mcp.Security.DefaultDenyAll |
bool | true | Deny by default |
Mcp.Security.RateLimit.Enabled |
bool | true | Enable rate limiting |
Mcp.Security.RateLimit.RequestsPerMinute |
int | 60 | Global rate limit |
Mcp.Security.RateLimit.BurstSize |
int | 10 | Max burst requests |
Mcp.Security.AuditLogging.Enabled |
bool | true | Log all operations |
See Configuration Guide for complete reference.
Roadmap
Phase 1: Core Foundation (COMPLETED)
- Core abstractions (IMcpServer, IMcpTool, models)
- Basic server implementation
- Stdio transport
- Unit tests (118/118 passing)
- CODEX MCP Server with 6 tools
- Full TDD implementation (RED → GREEN → REFACTOR)
Phase 2: Security & Reliability (Week 2)
- Permission system
- Rate limiting
- Audit logging
- Error handling
- Integration tests
Phase 3: ASP.NET Core Integration (Week 3)
- DI extensions
- Configuration binding
- HTTP transport
- Health checks
- Observability
Phase 4: Production & CODEX (Week 4)
- CODEX MCP server implementation
- Performance optimization
- Documentation
- Deployment guide
- Release v1.0.0
Contributing
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
Development Setup:
# Clone repository
git clone https://github.com/yourusername/Svrnty.MCP.git
# Restore dependencies
dotnet restore
# Run tests
dotnet test
# Build all projects
dotnet build
Documentation
| Document | Description |
|---|---|
| AGENT-PRIMER.md | AI-automated setup guide |
| Architecture | Clean architecture design |
| Configuration | Complete configuration reference |
| TDD Guide | Test-driven development examples |
| Security | Security model and best practices |
| API Reference | Complete API documentation (IMcpServer, IMcpTool, Models) |
| HTTPS Setup Guide | Production TLS/HTTPS configuration |
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Documentation: docs/
- Examples: samples/
- Issues: GitHub Issues
Acknowledgments
- Anthropic for the Model Context Protocol specification
- CODEX for being the first use case and driving requirements
- .NET Community for excellent libraries and tools
Built with OpenHarbor framework principles: Clean, Modular, Testable, Secure.