svrnty-mcp-server/AGENT-PRIMER.md
Svrnty 0c27de4162 refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries
- Renamed all directories: OpenHarbor.MCP.* → Svrnty.MCP.*
- Updated all namespaces in 179 C# files
- Renamed 20 .csproj files and 3 .sln files
- Updated 193 documentation references
- Updated 33 references in main CODEX codebase
- Updated Codex.sln with new paths
- Build verified: 0 errors

Preparing for extraction to standalone repositories.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:04:17 -04:00

22 KiB

AGENT-PRIMER: Svrnty.MCP Automated Setup

Purpose: This document guides AI agents to automatically analyze a target system and configure Svrnty.MCP integration with minimal human intervention.

Target Audience: AI assistants (Claude, ChatGPT, etc.) helping developers integrate MCP server capabilities into .NET applications.


Overview

Svrnty.MCP is a standalone, reusable .NET library that adds Model Context Protocol (MCP) server capabilities to any .NET application. This primer enables AI-automated configuration by walking through system analysis, configuration generation, and validation.

What you'll automate:

  1. System analysis (detect .NET version, project type, dependencies)
  2. Configuration file generation (appsettings.json, mcp-config.json, Program.cs)
  3. Sample MCP tool creation based on detected features
  4. Environment setup and validation

Step 1: System Analysis

Goal: Understand the target system to generate appropriate configuration.

Tasks for AI Agent:

1.1 Detect .NET Environment

# Check .NET SDK version
dotnet --version

# List installed SDKs
dotnet --list-sdks

# List installed runtimes
dotnet --list-runtimes

Required: .NET 8.0 SDK or higher Action if missing: Provide installation instructions for user's OS

1.2 Analyze Project Structure

# Find .csproj files
find . -name "*.csproj" -type f

# Examine project type
grep -E "<Project Sdk|<TargetFramework>" *.csproj

Detect:

  • Project type (Web API, Console, Worker Service, etc.)
  • Target framework (net8.0, net9.0)
  • Existing dependencies

1.3 Identify Integration Points

# Check for existing HTTP endpoints
grep -r "MapControllers\|MapGet\|MapPost" --include="*.cs"

# Check for dependency injection setup
grep -r "AddScoped\|AddSingleton\|AddTransient" --include="*.cs"

# Detect database usage
grep -r "DbContext\|AddDbContext" --include="*.cs"

Output: JSON summary of detected features

{
  "dotnetVersion": "8.0.100",
  "projectType": "AspNetCore.WebApi",
  "targetFramework": "net8.0",
  "features": {
    "hasDatabase": true,
    "databaseProvider": "PostgreSQL",
    "hasAuthentication": true,
    "hasSwagger": true,
    "hasCQRS": true
  },
  "dependencies": [
    "Microsoft.EntityFrameworkCore",
    "Npgsql.EntityFrameworkCore.PostgreSQL",
    "Swashbuckle.AspNetCore"
  ]
}

Step 2: Generate Configuration

Goal: Create configuration files tailored to the detected system.

2.1 NuGet Package References

Add to project's .csproj:

<ItemGroup>
  <!-- Core MCP library -->
  <ProjectReference Include="/path/to/Svrnty.MCP/src/Svrnty.MCP.AspNetCore/Svrnty.MCP.AspNetCore.csproj" />

  <!-- OR use NuGet when published -->
  <!-- <PackageReference Include="Svrnty.MCP.AspNetCore" Version="1.0.0" /> -->
</ItemGroup>

Installation command:

# Via project reference (development)
dotnet add reference /path/to/Svrnty.MCP/src/Svrnty.MCP.AspNetCore/Svrnty.MCP.AspNetCore.csproj

# Via NuGet (when published)
# dotnet add package Svrnty.MCP.AspNetCore

2.2 appsettings.json Configuration

Create/update appsettings.json with MCP section:

{
  "Mcp": {
    "Server": {
      "Name": "YourAppMcpServer",
      "Version": "1.0.0",
      "Description": "MCP server for YourApp - provides AI agents access to application features",
      "Vendor": "YourCompany"
    },
    "Transport": {
      "Type": "Http",
      "Options": {
        "BufferSize": 8192,
        "EnableLogging": true
      }
    },
    "Security": {
      "EnablePermissions": true,
      "DefaultDenyAll": true,
      "RateLimit": {
        "Enabled": true,
        "RequestsPerMinute": 60,
        "BurstSize": 10
      },
      "AuditLogging": {
        "Enabled": true,
        "LogLevel": "Information"
      }
    },
    "Agents": {
      "Default": {
        "Permissions": ["tools:list", "tools:execute"],
        "RateLimitOverride": null
      }
    }
  }
}

Customize based on detected features:

  • If database detected: Add "tools:database:*" permissions for agents needing DB access
  • If authentication exists: Add agent-specific scopes
  • If production: Set "DefaultDenyAll": true and explicit permissions only

2.3 mcp-config.json (Optional)

Create standalone MCP configuration (CLI usage):

{
  "mcpServers": {
    "yourapp": {
      "command": "dotnet",
      "args": ["run", "--project", "/path/to/YourApp.csproj"],
      "transport": "http",
      "permissions": {
        "allowedTools": ["tool1", "tool2"],
        "rateLimitRpm": 60
      }
    }
  }
}

2.4 Program.cs Integration

Add MCP services to dependency injection:

For ASP.NET Core Web API:

using Svrnty.MCP.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

// Existing services...
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// ADD: MCP Server
builder.Services.AddMcpServer(builder.Configuration.GetSection("Mcp"));

var app = builder.Build();

// Existing middleware...
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();

// ADD: MCP endpoints
app.MapMcpEndpoints();

app.MapControllers();

app.Run();

For Console Application (HTTP transport):

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Svrnty.MCP.Infrastructure;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        // Add MCP Server
        services.AddMcpServer(context.Configuration.GetSection("Mcp"));

        // Register custom tools
        services.AddTransient<IYourCustomTool, YourCustomToolImplementation>();
    })
    .Build();

// Start MCP server on stdio
var mcpServer = host.Services.GetRequiredService<IMcpServer>();
await mcpServer.StartAsync(CancellationToken.None);

await host.RunAsync();

Step 3: Create Sample Tools

Goal: Generate MCP tools based on detected system features.

3.1 Tool Template

Basic tool structure:

using Svrnty.MCP.Core.Abstractions;
using Svrnty.MCP.Core.Models;

namespace YourApp.Mcp.Tools;

public class SampleTool : IMcpTool
{
    public string Name => "sample_tool";
    public string Description => "Describes what this tool does for AI agents";

    public McpToolSchema Schema => new()
    {
        Type = "object",
        Properties = new Dictionary<string, McpProperty>
        {
            ["parameter1"] = new()
            {
                Type = "string",
                Description = "Description of parameter1",
                Required = true
            },
            ["parameter2"] = new()
            {
                Type = "number",
                Description = "Optional numeric parameter",
                Required = false
            }
        }
    };

    public async Task<McpToolResult> ExecuteAsync(
        Dictionary<string, object> parameters,
        CancellationToken cancellationToken = default)
    {
        // Extract parameters
        var param1 = parameters["parameter1"].ToString();
        var param2 = parameters.ContainsKey("parameter2")
            ? Convert.ToDouble(parameters["parameter2"])
            : 0.0;

        // Execute tool logic
        var result = await PerformWorkAsync(param1, param2, cancellationToken);

        // Return result
        return McpToolResult.Success(result);
    }

    private async Task<object> PerformWorkAsync(
        string param1,
        double param2,
        CancellationToken ct)
    {
        // TODO: Implement tool logic
        return new { message = "Tool executed successfully" };
    }
}

3.2 Auto-Generated Tools Based on Detected Features

If Database Detected:

public class SearchDatabaseTool : IMcpTool
{
    private readonly YourDbContext _context;

    public SearchDatabaseTool(YourDbContext context)
    {
        _context = context;
    }

    public string Name => "search_database";
    public string Description => "Search database entities by query string";

    public McpToolSchema Schema => new()
    {
        Type = "object",
        Properties = new Dictionary<string, McpProperty>
        {
            ["query"] = new()
            {
                Type = "string",
                Description = "Search query",
                Required = true
            },
            ["entityType"] = new()
            {
                Type = "string",
                Description = "Entity type to search (e.g., 'users', 'products')",
                Required = true
            },
            ["limit"] = new()
            {
                Type = "number",
                Description = "Max results to return (default: 10)",
                Required = false
            }
        }
    };

    public async Task<McpToolResult> ExecuteAsync(
        Dictionary<string, object> parameters,
        CancellationToken cancellationToken = default)
    {
        var query = parameters["query"].ToString();
        var entityType = parameters["entityType"].ToString();
        var limit = parameters.ContainsKey("limit")
            ? Convert.ToInt32(parameters["limit"])
            : 10;

        // Route to appropriate entity search
        var results = entityType.ToLower() switch
        {
            "users" => await SearchUsersAsync(query, limit, cancellationToken),
            "products" => await SearchProductsAsync(query, limit, cancellationToken),
            _ => throw new ArgumentException($"Unknown entity type: {entityType}")
        };

        return McpToolResult.Success(results);
    }

    private async Task<object> SearchUsersAsync(string query, int limit, CancellationToken ct)
    {
        return await _context.Users
            .Where(u => u.Name.Contains(query) || u.Email.Contains(query))
            .Take(limit)
            .Select(u => new { u.Id, u.Name, u.Email })
            .ToListAsync(ct);
    }

    private async Task<object> SearchProductsAsync(string query, int limit, CancellationToken ct)
    {
        return await _context.Products
            .Where(p => p.Name.Contains(query) || p.Description.Contains(query))
            .Take(limit)
            .Select(p => new { p.Id, p.Name, p.Description, p.Price })
            .ToListAsync(ct);
    }
}

Register in Program.cs:

services.AddTransient<IMcpTool, SearchDatabaseTool>();

If API Endpoints Detected:

public class ListEndpointsTool : IMcpTool
{
    private readonly ILogger<ListEndpointsTool> _logger;

    public string Name => "list_endpoints";
    public string Description => "List all available API endpoints in the application";

    public McpToolSchema Schema => new()
    {
        Type = "object",
        Properties = new Dictionary<string, McpProperty>()
    };

    public async Task<McpToolResult> ExecuteAsync(
        Dictionary<string, object> parameters,
        CancellationToken cancellationToken = default)
    {
        // Return list of endpoints (could introspect from routing)
        var endpoints = new[]
        {
            new { Method = "GET", Path = "/api/users", Description = "List users" },
            new { Method = "POST", Path = "/api/users", Description = "Create user" },
            new { Method = "GET", Path = "/api/products", Description = "List products" }
        };

        return McpToolResult.Success(endpoints);
    }
}

Step 4: Setup Development Environment

Goal: Configure IDE and development tools for Svrnty.MCP.

4.1 Launch Settings (launchSettings.json)

Create/update Properties/launchSettings.json:

{
  "profiles": {
    "McpStdio": {
      "commandName": "Project",
      "launchBrowser": false,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "MCP_TRANSPORT": "stdio"
      }
    },
    "McpHttp": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "MCP_TRANSPORT": "http"
      }
    }
  }
}

4.2 .editorconfig (Already provided in Svrnty.MCP root)

Copy to target project if needed:

cp /path/to/Svrnty.MCP/.editorconfig /path/to/YourApp/.editorconfig

4.3 .gitignore Updates

Add MCP-specific entries to target project's .gitignore:

# MCP logs and temp files
mcp-logs/
*.mcp.log
mcp-config.local.json

Step 5: Validation

Goal: Verify setup is correct and functional.

5.1 Build Verification

# Restore dependencies
dotnet restore

# Build project
dotnet build

# Expected: Build succeeded. 0 Warning(s). 0 Error(s).

5.2 Test MCP Server Startup

Console/Stdio Mode:

# Run MCP server
dotnet run

# Expected output:
# MCP Server started (HTTP transport)
# Registered tools: sample_tool, search_database, list_endpoints
# Ready for input...

HTTP Mode (if applicable):

# Run with HTTP transport
dotnet run --launch-profile McpHttp

# Test MCP endpoint
curl http://localhost:5000/mcp/tools

Expected response:

{
  "tools": [
    {
      "name": "sample_tool",
      "description": "Describes what this tool does for AI agents",
      "schema": { ... }
    },
    {
      "name": "search_database",
      "description": "Search database entities by query string",
      "schema": { ... }
    }
  ]
}

5.3 Test Tool Execution

Create test script test-mcp.sh:

#!/bin/bash

# Test listing tools
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | dotnet run

# Test executing a tool
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"sample_tool","arguments":{"parameter1":"test"}}}' | dotnet run

Run tests:

chmod +x test-mcp.sh
./test-mcp.sh

5.4 Integration Test (Claude Desktop Example)

If Claude Desktop is available, create MCP config:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "yourapp": {
      "command": "dotnet",
      "args": ["run", "--project", "/absolute/path/to/YourApp.csproj"],
      "transport": "http"
    }
  }
}

Restart Claude Desktop, then test:

  1. Type: "List available tools" (should show your MCP tools)
  2. Execute: "Use sample_tool with parameter1='hello'"
  3. Verify: Tool executes and returns expected result

Example: CODEX Integration Walkthrough

Scenario: CODEX is a knowledge management system that needs to expose its document search, retrieval, and tagging features to AI agents via MCP.

Step 1: System Analysis (Automated)

Run analysis:

cd /home/svrnty/codex/CODEX
dotnet --version  # Output: 8.0.100
find . -name "*.csproj" | head -5

Detected:

  • Project: ASP.NET Core Web API (Codex.Api)
  • Framework: net8.0
  • Database: PostgreSQL (Npgsql.EntityFrameworkCore.PostgreSQL)
  • Features: CQRS (OpenHarbor.CQRS), vector search (Pgvector), semantic search (ONNX)

Step 2: Generate Configuration

Created samples/CodexMcpServer/ in Svrnty.MCP:

samples/CodexMcpServer/
├── CodexMcpServer.csproj          # References Svrnty.MCP.AspNetCore
├── Program.cs                      # MCP server setup with CODEX API client
├── appsettings.json                # CODEX-specific MCP config
├── Tools/
│   ├── SearchCodexTool.cs         # search_codex tool
│   ├── GetDocumentTool.cs         # get_document tool
│   ├── ListDocumentsTool.cs       # list_documents tool
│   ├── SearchByTagTool.cs         # search_by_tag tool
│   ├── GetDocumentSectionsTool.cs # get_document_sections tool
│   └── ListTagsTool.cs            # list_tags tool
└── Services/
    └── CodexApiClient.cs          # HTTP client for CODEX API (localhost:5050)

appsettings.json:

{
  "Mcp": {
    "Server": {
      "Name": "CodexMcpServer",
      "Version": "1.0.0",
      "Description": "CODEX Knowledge Gateway - Provides AI agents secure access to CODEX documents, search, and tags",
      "Vendor": "Svrnty"
    },
    "Transport": {
      "Type": "Http"
    },
    "Security": {
      "EnablePermissions": true,
      "DefaultDenyAll": true,
      "Agents": {
        "claude-desktop": {
          "Permissions": ["tools:codex:search", "tools:codex:read", "tools:codex:tags"],
          "RateLimitOverride": 120
        },
        "public-agent": {
          "Permissions": ["tools:codex:search"],
          "RateLimitOverride": 30
        }
      }
    }
  },
  "CodexApi": {
    "BaseUrl": "http://localhost:5050",
    "Timeout": 30
  }
}

Step 3: Create CODEX Tools

SearchCodexTool.cs:

public class SearchCodexTool : IMcpTool
{
    private readonly ICodexApiClient _codexApi;

    public string Name => "search_codex";
    public string Description => "Search CODEX knowledge base using semantic or keyword search";

    public McpToolSchema Schema => new()
    {
        Type = "object",
        Properties = new Dictionary<string, McpProperty>
        {
            ["query"] = new() { Type = "string", Description = "Search query", Required = true },
            ["searchType"] = new() { Type = "string", Description = "Search type: 'semantic' or 'keyword' (default: semantic)", Required = false },
            ["limit"] = new() { Type = "number", Description = "Max results (default: 10)", Required = false }
        }
    };

    public async Task<McpToolResult> ExecuteAsync(
        Dictionary<string, object> parameters,
        CancellationToken ct = default)
    {
        var query = parameters["query"].ToString();
        var searchType = parameters.GetValueOrDefault("searchType", "semantic").ToString();
        var limit = Convert.ToInt32(parameters.GetValueOrDefault("limit", 10));

        var results = await _codexApi.SearchAsync(query, searchType, limit, ct);
        return McpToolResult.Success(results);
    }
}

Step 4: Register Tools in Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMcpServer(builder.Configuration.GetSection("Mcp"));
builder.Services.AddSingleton<ICodexApiClient, CodexApiClient>();

// Register CODEX tools
builder.Services.AddTransient<IMcpTool, SearchCodexTool>();
builder.Services.AddTransient<IMcpTool, GetDocumentTool>();
builder.Services.AddTransient<IMcpTool, ListDocumentsTool>();
builder.Services.AddTransient<IMcpTool, SearchByTagTool>();
builder.Services.AddTransient<IMcpTool, GetDocumentSectionsTool>();
builder.Services.AddTransient<IMcpTool, ListTagsTool>();

var app = builder.Build();
app.MapMcpEndpoints();
app.Run();

Step 5: Validate

cd samples/CodexMcpServer
dotnet run

# Test with echo
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | dotnet run

# Expected: 6 tools listed (search_codex, get_document, etc.)

Claude Desktop Integration:

{
  "mcpServers": {
    "codex": {
      "command": "dotnet",
      "args": ["run", "--project", "/home/svrnty/codex/Svrnty.MCP/samples/CodexMcpServer/CodexMcpServer.csproj"],
      "transport": "http"
    }
  }
}

Result: Claude can now search CODEX, retrieve documents, filter by tags, and access document sections with full permission enforcement and rate limiting.


AI Agent Checklist

Use this checklist when assisting a developer with Svrnty.MCP integration:

  • System Analysis Complete

    • .NET 8.0 SDK detected
    • Project type identified
    • Dependencies analyzed
    • Feature detection done (DB, auth, API, etc.)
  • Configuration Generated

    • NuGet package/project reference added
    • appsettings.json updated with MCP section
    • Program.cs modified for MCP registration
    • launchSettings.json created/updated
  • Tools Created

    • At least 1 sample tool implemented
    • Tools registered in DI container
    • Tool permissions configured in appsettings.json
    • Tool documentation written
  • Validation Passed

    • Project builds successfully
    • MCP server starts without errors
    • Tools are listed correctly
    • Sample tool execution succeeds
    • (Optional) Claude Desktop integration works
  • Documentation Updated

    • README.md includes MCP setup instructions
    • Tool usage examples documented
    • Configuration options explained

Troubleshooting

Issue: "MCP server not starting"

Solution:

  1. Check .NET version: dotnet --version (must be 8.0+)
  2. Verify Program.cs has services.AddMcpServer(...) and app.MapMcpEndpoints()
  3. Check appsettings.json for valid JSON syntax
  4. Run dotnet build to see specific errors

Issue: "Tools not appearing in Claude"

Solution:

  1. Verify claude_desktop_config.json path is correct
  2. Check absolute path to .csproj is correct
  3. Restart Claude Desktop completely
  4. Test server manually: echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | dotnet run

Issue: "Permission denied when executing tool"

Solution:

  1. Check appsettings.jsonMcp.Security.Agents section
  2. Ensure agent has required permissions (e.g., "tools:codex:search")
  3. Verify DefaultDenyAll is set correctly
  4. Check audit logs for permission failures

Issue: "Rate limit exceeded"

Solution:

  1. Increase RateLimitOverride for the agent in appsettings.json
  2. Reduce request frequency from client
  3. Disable rate limiting temporarily: "RateLimit.Enabled": false

Next Steps

After successful setup:

  1. Write Tests: Create unit tests for custom tools (see Svrnty.MCP test examples)
  2. Add Observability: Integrate logging, metrics, and tracing
  3. Secure Production: Review permission model, enable HTTPS for HTTP transport
  4. Optimize Performance: Add caching, connection pooling, batch operations
  5. Extend Tools: Add more domain-specific tools based on application features

References

  • Svrnty.MCP Documentation: /docs/ folder in this repository
  • MCP Specification: https://spec.modelcontextprotocol.io
  • CODEX Integration Example: samples/CodexMcpServer/
  • Test Examples: tests/Svrnty.MCP.Integration.Tests/

AI Agent Note: This primer is designed for you to execute autonomously. When a developer asks "set up MCP for my project," follow this guide step-by-step, adapting configurations to their specific environment. Always validate each step before proceeding to the next.