Research conducted on modern AI coding assistants (Cursor, GitHub Copilot, Cline,
Aider, Windsurf, Replit Agent) to understand architecture patterns, context management,
code editing workflows, and tool use protocols.
Key Decision: Pivoted from building full CLI (40-50h) to validation-driven MCP-first
approach (10-15h). Build 5 core CODEX MCP tools that work with ANY coding assistant,
validate adoption over 2-4 weeks, then decide on full CLI if demand proven.
Files:
- research/ai-systems/modern-coding-assistants-architecture.md (comprehensive research)
- research/ai-systems/codex-coding-assistant-implementation-plan.md (original CLI plan, preserved)
- research/ai-systems/codex-mcp-tools-implementation-plan.md (approved MCP-first plan)
- ideas/registry.json (updated with approved MCP tools proposal)
Architech Validation: APPROVED with pivot to MCP-first approach
Human Decision: Approved (pragmatic validation-driven development)
Next: Begin Phase 1 implementation (10-15 hours, 5 core MCP tools)
🤖 Generated with CODEX Research System
Co-Authored-By: The Archivist <archivist@codex.svrnty.io>
Co-Authored-By: The Architech <architech@codex.svrnty.io>
Co-Authored-By: Mathias Beaulieu-Duncan <mat@svrnty.io>
22 KiB
AGENT-PRIMER: OpenHarbor.MCP Automated Setup
Purpose: This document guides AI agents to automatically analyze a target system and configure OpenHarbor.MCP integration with minimal human intervention.
Target Audience: AI assistants (Claude, ChatGPT, etc.) helping developers integrate MCP server capabilities into .NET applications.
Overview
OpenHarbor.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:
- System analysis (detect .NET version, project type, dependencies)
- Configuration file generation (appsettings.json, mcp-config.json, Program.cs)
- Sample MCP tool creation based on detected features
- 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/OpenHarbor.MCP/src/OpenHarbor.MCP.AspNetCore/OpenHarbor.MCP.AspNetCore.csproj" />
<!-- OR use NuGet when published -->
<!-- <PackageReference Include="OpenHarbor.MCP.AspNetCore" Version="1.0.0" /> -->
</ItemGroup>
Installation command:
# Via project reference (development)
dotnet add reference /path/to/OpenHarbor.MCP/src/OpenHarbor.MCP.AspNetCore/OpenHarbor.MCP.AspNetCore.csproj
# Via NuGet (when published)
# dotnet add package OpenHarbor.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": trueand 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 OpenHarbor.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 OpenHarbor.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 OpenHarbor.MCP.Core.Abstractions;
using OpenHarbor.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 OpenHarbor.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 OpenHarbor.MCP root)
Copy to target project if needed:
cp /path/to/OpenHarbor.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:
- Type: "List available tools" (should show your MCP tools)
- Execute: "Use sample_tool with parameter1='hello'"
- 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 OpenHarbor.MCP:
samples/CodexMcpServer/
├── CodexMcpServer.csproj # References OpenHarbor.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/OpenHarbor.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 OpenHarbor.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:
- Check .NET version:
dotnet --version(must be 8.0+) - Verify Program.cs has
services.AddMcpServer(...)andapp.MapMcpEndpoints() - Check appsettings.json for valid JSON syntax
- Run
dotnet buildto see specific errors
Issue: "Tools not appearing in Claude"
Solution:
- Verify
claude_desktop_config.jsonpath is correct - Check absolute path to .csproj is correct
- Restart Claude Desktop completely
- Test server manually:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | dotnet run
Issue: "Permission denied when executing tool"
Solution:
- Check
appsettings.json→Mcp.Security.Agentssection - Ensure agent has required permissions (e.g.,
"tools:codex:search") - Verify
DefaultDenyAllis set correctly - Check audit logs for permission failures
Issue: "Rate limit exceeded"
Solution:
- Increase
RateLimitOverridefor the agent in appsettings.json - Reduce request frequency from client
- Disable rate limiting temporarily:
"RateLimit.Enabled": false
Next Steps
After successful setup:
- Write Tests: Create unit tests for custom tools (see OpenHarbor.MCP test examples)
- Add Observability: Integrate logging, metrics, and tracing
- Secure Production: Review permission model, enable HTTPS for HTTP transport
- Optimize Performance: Add caching, connection pooling, batch operations
- Extend Tools: Add more domain-specific tools based on application features
References
- OpenHarbor.MCP Documentation:
/docs/folder in this repository - MCP Specification: https://spec.modelcontextprotocol.io
- CODEX Integration Example:
samples/CodexMcpServer/ - Test Examples:
tests/OpenHarbor.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.