Token导航 LogoToken导航TokenDH.com
Coa MCP Framework logo
AI代理未说明官方级别未说明来源级核验

Coa MCP Framework

MCP Server

一个用于构建和消费模型上下文协议(MCP)服务器的.NET框架,提供类型安全、AI友好响应和开发者优先设计

工具数

0

提示词数

0

GitHub Stars

1

资源数

0
服务器开发C#Claude类型安全Claude DesktopClaude

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

anortham

提供方

anortham

最后核验

2026/5/17 20:21

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

详细介绍

COA MCP 框架

一个全面的.NET框架,用于构建和消费模型上下文协议(MCP)服务器,内置了令牌优化、AI友好型响应、强类型支持以及以开发者为中心的设计。

](https://www.nuget.org/packages/COA.Mcp.Framework) ![Build Status](https://github.com/anortham/COA-Mcp-Framework) ![Tests](https://github.com/anortham/COA-Mcp-Framework) ![.NET 9.0](https://dotnet.microsoft.com/download)

🚀 快速入门

之前从未使用过MCP吗? 关注我们的 5分钟快速入门指南 👈

超级简单的例子

  1. 安装: dotnet add package COA.Mcp.Framework
  1. 复制这段代码 翻译成中文为:到 Program.cs 中:
using COA.Mcp.Framework.Server;
using COA.Mcp.Framework.Base;
using COA.Mcp.Framework.Models;

public class EchoTool : McpToolBase
{
    public override string Name => "echo";
    public override string Description => "Echoes back your message";
    
    protected override async Task ExecuteInternalAsync(
        EchoParams parameters, CancellationToken cancellationToken)
    {
        await Task.CompletedTask;
        return new EchoResult 
        { 
            Success = true, 
            Response = $"You said: {parameters.Text}" 
        };
    }
}

public class EchoParams { public string Text { get; set; } = ""; }
public class EchoResult : ToolResultBase 
{ 
    public override string Operation => "echo";
    public string Response { get; set; } = "";
}

class Program
{
    static async Task Main(string[] args)
    {
        // Easy start with optimized defaults
        var builder = McpServerBuilder.CreateMinimal("My First MCP Server", "1.0.0");
        
        builder.RegisterToolType();
        await builder.RunAsync();
    }
}
  1. 运行它: dotnet run

🎉 就这样! 您已经有一个正常工作的MCP服务器。

下一步

想要更多例子吗?

需要帮助吗?

准备好生产了吗?高级功能 在......下面

🆕 专业行为指导

将您的MCP服务器转变为智能助手,引导用户走向最佳工作流程:

var builder = new McpServerBuilder()
    .WithServerInfo("My MCP Server", "1.0.0")
    
    // 🆕 Load instructions from template files
    .WithInstructionsFromTemplate("Templates/server-instructions.scriban", templateVariables)
    
    // Advanced template-based instructions with built-in tool awareness
    .WithTemplateInstructions(options =>
    {
        options.ContextName = "codesearch"; // Built-in: general, codesearch, database
        options.EnableConditionalLogic = true;
        options.CustomVariables["ProjectType"] = "C# Library";
    })
    
    // 🆕 Professional tool comparisons (no manipulation!)
    .WithToolComparison(
        task: "Find code patterns",
        serverTool: "text_search",
        builtInTool: "grep", 
        advantage: "Lucene-indexed with Tree-sitter parsing",
        performanceMetric: "100x faster, searches millions of lines in 
    {
        config.EnableWorkflowSuggestions = true;
        config.EnableToolPriority = true;
        config.UseDefaultDescriptionProvider = true; // 🆕 Imperative descriptions
    })
    
    // Smart error recovery
    .WithAdvancedErrorRecovery(options =>
    {
        options.EnableRecoveryGuidance = true;
        options.Tone = ErrorRecoveryTone.Professional;
    });

为何这很重要:

  • 🎯 目标(靶心) 专业工具推广基于证据的比较显示了服务器工具为何优于内置工具
  • 📈 这个符号在中文里通常被用来表示“图表”或“上升趋势”,在社交媒体和网络交流中,它也常被用作一种表情符号,表达积极、上升或增长的情绪或状态。 智能工作流执行三个级别(建议/推荐/强烈建议)以提供适当的指导力度
  • 🏫 代表“学校”的意思。 教育性的通过性能指标教授最佳模式,而非情感操控
  • ⚡(闪电符号,常用于表示速度、能量或惊喜等含义) 高效代币减少来回修正次数可节省代币(实测减少43%)
  • 🔧 修理工具或螺丝刀的符号 情境感知指令根据服务器能力和可用工具动态调整
  • 📊 表格/数据图表 以绩效为导向诸如“100倍更快”和“\, IPrioritizedTool

{ public override string Description => DefaultToolDescriptionProvider.TransformToImperative( "Searches for code patterns with Tree-sitter parsing", Priority);

// IPrioritizedTool implementation public int Priority => 90; // High priority (1-100 scale) public string[] PreferredScenarios => new[] { "code_exploration", "type_verification" }; }


**可用的模板变量:**

- `{{builtin_tools}}` - Claude 内置的工具(读取、Grep、Bash 等)
- `{{tool_comparisons}}` - 专业服务器与内置(功能)的对比
- `{{enforcement_level}}` - 当前工作流执行设置
- `{{available_tools}}` - 您服务器上的可用工具
- `{{#has_builtin "grep"}}` - 内置工具检测的条件逻辑

### 🆕 基于人工智能的中间件

添加智能类型检查并强制实施TDD(测试驱动开发):

var builder = new McpServerBuilder() .WithServerInfo("My MCP Server", "1.0.0") .AddTypeVerificationMiddleware(options => { options.Mode = TypeVerificationMode.Strict; // or Warning options.WhitelistedTypes.Add("MyCustomType"); }) .AddTddEnforcementMiddleware(options => { options.Mode = TddEnforcementMode.Warning; // or Strict options.TestFilePatterns.Add("**/*Spec.cs"); // Custom test patterns });


**益处:**

- 🛡️ 译为中文是“盾牌”。这个符号通常用来表示防御、保护或防护的概念。 **类型安全**在代码生成失败前捕获未定义类型
- 🧪 表示“实验瓶”或“化学实验”(根据上下文可能有所不同)。 **质量保证**强制执行正确的测试实践
- 🚀 表情符号“🚀”在中文中通常被翻译为“火箭”或直接保留为“🚀”(因其本身为国际通用表情符号,无需特定翻译)。在没有具体上下文的情况下,可以简单地将其理解为“火箭”的意思,或者直接使用该符号本身来表达。 **对人工智能友好**提供包含恢复步骤的清晰错误信息
- ⚡ 闪电符号(表示快速、活力、电或能量等含义,具体根据上下文而定) **演出**具有文件修改检测的智能缓存

## 📦 NuGet 包

- COA.Mcp.Framework —— 包含MCP协议的核心框架
- COA.Mcp.Protocol — 低级协议类型和JSON-RPC
- COA.Mcp.Client — 用于MCP服务器的强类型C#客户端
- COA.Mcp.Framework.TokenOptimization — 高级令牌管理与AI响应优化
- COA.Mcp.Framework.Testing — 测试辅助工具、断言和基准测试
- COA.Mcp.Framework.Templates — 快速启动项目模板
- COA.Mcp.Framework.Migration — 用于从旧版本升级的迁移工具

## ✨ 主要特点

### 🔒(锁形符号,常用于表示安全、保密或锁定状态) **类型安全工具开发**

- 通用基类 `McpToolBase` 确保编译时的类型安全
- 使用数据注解进行自动参数验证
- 无需手动解析JSON

### 🏗️ 这个表情符号通常代表“建筑工地”或“建造中”的意思,可以翻译为“建筑工地”或“正在建造”。 **清洁架构**

- 单一统一的工具注册表,具备自动处理功能
- 流利服务器构建器API
- 依赖注入支持
- 职责清晰分离
- 支持IAsyncDisposable进行资源管理

### 🛡️ 译为中文是“盾牌”。 **全面错误处理**

- 带有(或:采用)标准化误差模型的 `ErrorInfo` 并且 `RecoveryInfo`
- 包含恢复步骤的友好型AI错误消息
- **内置的验证辅助工具** - `ValidateRequired()`, `ValidatePositive()`, `ValidateRange()`, `ValidateNotEmpty()`
- **错误结果辅助工具** - `CreateErrorResult()`, `CreateValidationErrorResult()` 附带恢复步骤
- **可定制的错误消息** 以(权力)否决 `ErrorMessages` 针对特定工具的指导属性

### 🎯(目标/靶心) **泛型类型安全性**

- **通用参数验证**: `IParameterValidator` 通过强类型验证消除类型转换
- **通用资源缓存**: `IResourceCache` 支持任何资源类型,且在编译时保证安全
- **通用响应建筑**: `BaseResponseBuilder` 和 `AIOptimizedResponse` 防止对象转换
- **向后兼容**所有泛型接口都包含非泛型版本,以实现无缝迁移

### 🧠 表示“大脑”或“思考”。 **令牌管理**

- 预估以防止上下文溢出
- 对于大型数据集的渐进式缩减
- 使用资源URI的智能截断
- **每种工具的代币预算** - 通过(某种方式)设置限制 `ConfigureTokenBudgets()` 在服务器构建器中
- **分层配置** - 工具特定、类别和默认预算设置

### 🔗(链接符号,无具体含义,可直译为“链接”或根据上下文保留原样) **生命周期钩子与中间件**

- **可扩展的执行管道** - 使用简单的中间件添加横切关注点
- **内置中间件** - 日志记录,性能监控
- **自定义中间件支持** - 实施 `ISimpleMiddleware` 用于自定义逻辑
- **每种工具的配置** 以(权力)否决 `ToolSpecificMiddleware` 用于特定工具的钩子(或插件)
- 见 **[生命周期钩子指南](docs/lifecycle-hooks.md)** 用于详细文档说明

### 💬 **交互式提示**

- 使用即时模板引导用户完成复杂操作
- 可定制的参数,带验证功能
- 内置的消息构建器用于系统/用户/助手角色
- 模板中的变量替换

### 🚀 这个符号本身在中文中通常被用作表示火箭、快速前进或宇宙探索的象征,直接翻译可能没有确切的对应词汇,但可以理解为“火箭”或“飞速前进”。在具体语境中,它可能传达出一种快速、有力或向前发展的意味。 **自助服务管理** 新

- 后台服务的自动启动
- 健康监测和自动重启功能
- 端口冲突检测
- 支持多种托管服务

### 🚄 表示火车或高速列车的符号。 **快速发展**

- 最少的样板代码
- 内置的验证辅助工具
- 全面的IntelliSense支持
- 丰富的示例项目

## 🎯 客户端库

### 使用COA.Mcp.Client连接到MCP服务器

该框架包含一个强类型的C#客户端库,用于与MCP服务器进行交互:

// Create a typed client with fluent configuration var client = await McpClientBuilder .Create("http://localhost:5000") .WithTimeout(TimeSpan.FromSeconds(30)) .WithRetry(maxAttempts: 3, delayMs: 1000) .WithApiKey("your-api-key") .BuildAndInitializeAsync();

// List available tools var tools = await client.ListToolsAsync();

// Call a tool with type safety var result = await client.CallToolAsync("weather", new { location = "Seattle" });


### 强类型客户端操作

// Define your types public class WeatherParams { public string Location { get; set; } public string Units { get; set; } = "celsius"; }

public class WeatherResult : ToolResultBase { public override string Operation => "get_weather"; public double Temperature { get; set; } public string Description { get; set; } }

// Create a typed client var typedClient = McpClientBuilder .Create("http://localhost:5000") .BuildTyped();

// Call with full type safety var weather = await typedClient.CallToolAsync("weather", new WeatherParams { Location = "Seattle" });

if (weather.Success) { Console.WriteLine($"Temperature: {weather.Temperature}°"); }


## 📝 交互式提示

### 创建自定义提示

提示提供交互式模板,引导用户完成复杂操作:

// Define a prompt to help users generate code public class CodeGeneratorPrompt : PromptBase { public override string Name => "code-generator"; public override string Description => "Generate code snippets based on requirements";

public override List Arguments => new() { new PromptArgument { Name = "language", Description = "Programming language (csharp, python, js)", Required = true }, new PromptArgument { Name = "type", Description = "Type of code (class, function, interface)", Required = true }, new PromptArgument { Name = "name", Description = "Name of the component", Required = true } };

public override async Task RenderAsync( Dictionary? arguments = null, CancellationToken cancellationToken = default) { var language = GetRequiredArgument(arguments, "language"); var type = GetRequiredArgument(arguments, "type"); var name = GetRequiredArgument(arguments, "name");

return new GetPromptResult { Description = $"Generate {language} {type}: {name}", Messages = new List

{ CreateSystemMessage($"You are an expert {language} developer."), CreateUserMessage($"Generate a {type} named '{name}' in {language}."), CreateAssistantMessage("I'll help you create that component...") } }; } }

// Register prompts in your server builder.RegisterPromptType();


### 变量替换

使用内置变量替换来实现动态模板:

var template = "Hello {{name}}, your project {{project}} is ready!"; var result = SubstituteVariables(template, new Dictionary { ["name"] = "Developer", ["project"] = "MCP Server" }); // Result: "Hello Developer, your project MCP Server is ready!"


## 🔗 生命周期钩子与中间件

该框架为您的工具提供了一个强大的中间件系统,用于添加跨切面关注点:

### 为工具添加中间件

public class MyTool : McpToolBase { private readonly ILogger? _logger;

public MyTool(IServiceProvider? serviceProvider, ILogger? logger = null) : base(serviceProvider, logger) { _logger = logger; }

// Configure middleware for this specific tool protected override IReadOnlyList? ToolSpecificMiddleware => new List { // Built-in token counting middleware new TokenCountingSimpleMiddleware(),

// Custom timing middleware new TimingMiddleware(_logger!) };

// Your tool implementation... }


### 内置中间件

- **“TokenCountingSimpleMiddleware”可以翻译为“简单令牌计数中间件”**估算和记录令牌使用情况
- **简单日志记录中间件**全面的执行日志记录

### 自定义中间件

public class TimingMiddleware : SimpleMiddlewareBase { private readonly ILogger _logger;

public TimingMiddleware(ILogger logger) { _logger = logger; Order = 50; // Controls execution order }

public override Task OnBeforeExecutionAsync(string toolName, object? parameters) { _logger.LogInformation("🚀 Starting {ToolName}", toolName); return Task.CompletedTask; }

public override Task OnAfterExecutionAsync(string toolName, object? parameters, object? result, long elapsedMs) { var performance = elapsedMs { public override string Name => "calculator"; public override string Description => "Performs basic arithmetic operations"; public override ToolCategory Category => ToolCategory.Utility;

protected override async Task ExecuteInternalAsync( CalculatorParameters parameters, CancellationToken cancellationToken) { // Validate inputs using base class helpers ValidateRequired(parameters.Operation, nameof(parameters.Operation)); ValidateRequired(parameters.A, nameof(parameters.A)); ValidateRequired(parameters.B, nameof(parameters.B));

var a = parameters.A!.Value; var b = parameters.B!.Value;

double result = parameters.Operation.ToLower() switch { "add" or "+" => a + b, "subtract" or "-" => a - b, "multiply" or "*" => a * b, "divide" or "/" => b != 0 ? a / b : throw new DivideByZeroException("Cannot divide by zero"), _ => throw new NotSupportedException($"Operation '{parameters.Operation}' is not supported") };

return new CalculatorResult { Success = true, Operation = parameters.Operation, Expression = $"{a} {parameters.Operation} {b}", Result = result, Meta = new ToolMetadata { ExecutionTime = $"{stopwatch.ElapsedMilliseconds}ms" } }; } }


### 设置您的服务器

// Program.cs for your MCP server var builder = new McpServerBuilder() .WithServerInfo("My MCP Server", "1.0.0") .ConfigureLogging(logging => { logging.ClearProviders(); logging.AddConsole(); logging.SetMinimumLevel(LogLevel.Information); });

// Register your services builder.Services.AddSingleton();

// Register your tools (two options)

// Option 1: Manual registration (recommended for explicit control) builder.RegisterToolType(); builder.RegisterToolType(); builder.RegisterToolType (); // Example with middleware

// Option 2: Automatic discovery (scans assembly for tools) builder.DiscoverTools(typeof(Program).Assembly);

// Build and run await builder.RunAsync();


### 传输配置

该框架支持多种传输类型,以提供灵活性:

// Default: Standard I/O (for Claude Desktop and CLI tools) var builder = new McpServerBuilder() .WithServerInfo("My Server", "1.0.0"); // Uses stdio transport by default

// HTTP Transport (for web-based clients) var builder = new McpServerBuilder() .WithServerInfo("My Server", "1.0.0") .UseHttpTransport(options => { options.Port = 5000; options.EnableWebSocket = true; options.EnableCors = true; options.Authentication = AuthenticationType.ApiKey; options.ApiKey = "your-api-key"; });

// WebSocket Transport (for real-time communication) var builder = new McpServerBuilder() .WithServerInfo("My Server", "1.0.0") .UseWebSocketTransport(options => { options.Port = 8080; options.Host = "localhost"; options.UseHttps = false; });


### 与服务提供商访问相关的配置

该框架提供了增强的配置方法,使您能够访问依赖注入容器,从而避免了诸如手动(配置)等反模式的做法 `BuildServiceProvider()` 通话:

// Register your dependencies first var builder = new McpServerBuilder() .WithServerInfo("My Server", "1.0.0");

builder.Services.AddSingleton(); builder.Services.AddScoped();

// Enhanced configuration with service provider access builder .ConfigureTools((registry, serviceProvider) => { // ✅ Clean: Access services without BuildServiceProvider() var dataService = serviceProvider.GetRequiredService(); var customTool = new CustomTool(dataService); registry.RegisterTool(customTool); }) .ConfigureResources((registry, serviceProvider) => { // ✅ Access repository for dynamic resource registration var repository = serviceProvider.GetRequiredService(); var provider = new DatabaseResourceProvider(repository); registry.RegisterProvider(provider); }) .ConfigurePrompts((registry, serviceProvider) => { // ✅ Configure prompts with access to services var dataService = serviceProvider.GetRequiredService(); var dynamicPrompt = new DataDrivenPrompt(dataService); registry.RegisterPrompt(dynamicPrompt); });


#### 从手动调用 BuildServiceProvider() 迁移

如果你有现有的代码手动调用了 `BuildServiceProvider()`您可以迁移到增强版的API:

// ❌ Before: Anti-pattern with duplicate singletons builder.ConfigureResources(registry => { #pragma warning disable ASP0000 var serviceProvider = builder.Services.BuildServiceProvider(); var provider = serviceProvider.GetRequiredService(); registry.RegisterProvider(provider); #pragma warning restore ASP0000 });

// ✅ After: Clean with proper dependency injection builder.ConfigureResources((registry, serviceProvider) => { var provider = serviceProvider.GetRequiredService(); registry.RegisterProvider(provider); });


增强的API提供:

- **无重复的单例**单个DI容器,符合单例模式的行为
- **无ASP0000警告**消除关于 BuildServiceProvider 的编译器警告
- **更好的性能**减少内存使用和对象分配
- **更简洁的代码**遵循.NET依赖注入的最佳实践

### 日志配置

该框架提供了对日志记录的精细控制,以减少干扰并提升调试体验:

var builder = new McpServerBuilder() .WithServerInfo("My Server", "1.0.0") .ConfigureLogging(logging => { // Standard logging configuration logging.AddConsole(); logging.SetMinimumLevel(LogLevel.Information);

// Optional: Configure specific categories logging.AddFilter("COA.Mcp.Framework", LogLevel.Warning); // Quiet framework logging.AddFilter("MyApp", LogLevel.Debug); // Verbose for your code }) .ConfigureFramework(options => { // Framework-specific logging options options.FrameworkLogLevel = LogLevel.Warning; // Default framework log level options.EnableDetailedToolLogging = false; // Reduce tool execution noise options.EnableDetailedMiddlewareLogging = false; // Reduce middleware noise options.EnableDetailedTransportLogging = false; // Reduce transport noise

// Advanced options options.EnableFrameworkLogging = true; // Enable/disable framework logging entirely options.ConfigureLoggingIfNotConfigured = true; // Don't override existing logging config options.SuppressStartupLogs = false; // Show/hide startup messages });


#### 日志类别

该框架使用这些日志类别来进行细粒度控制:

- `COA.Mcp.Framework.Pipeline.Middleware` - 中间件操作(类型检查、TDD(测试驱动开发)强制执行等)
- `COA.Mcp.Framework.Transport` - 传输层操作(HTTP、WebSocket、stdio)
- `COA.Mcp.Framework.Base` - 工具执行和生命周期事件
- `COA.Mcp.Framework.Server` - 服务器启动与管理
- `COA.Mcp.Framework.Pipeline` - 请求/响应管道处理

#### 快速配置示例

// Minimal logging (production) builder.ConfigureFramework(options => { options.FrameworkLogLevel = LogLevel.Error; options.EnableDetailedToolLogging = false; options.EnableDetailedMiddlewareLogging = false; options.EnableDetailedTransportLogging = false; });

// Debug mode (development) builder.ConfigureFramework(options => { options.FrameworkLogLevel = LogLevel.Debug; options.EnableDetailedToolLogging = true; options.EnableDetailedMiddlewareLogging = true; options.EnableDetailedTransportLogging = true; });

// Completely disable framework logging builder.ConfigureFramework(options => { options.EnableFrameworkLogging = false; });


### 🚀 自助服务管理

该框架现已支持自动服务启动,能够实现双模式架构,其中MCP服务器既可以作为STDIO客户端,也可以作为HTTP服务提供者:

// Configure auto-started services alongside your MCP server var builder = new McpServerBuilder() .WithServerInfo("My MCP Server", "1.0.0") .UseStdioTransport() // Primary transport for Claude .UseAutoService(config => { config.ServiceId = "my-http-api"; config.ExecutablePath = Assembly.GetExecutingAssembly().Location; config.Arguments = new[] { "--mode", "http", "--port", "5100" }; config.Port = 5100; config.HealthEndpoint = "http://localhost:5100/health"; config.AutoRestart = true; config.MaxRestartAttempts = 3; });

await builder.RunAsync();


#### 主要特点:

- **自动启动**当MCP服务器启动时,服务会自动开始
- **健康监测**可配置间隔的定期健康检查
- **自动重启**服务故障时自动恢复,带重试限制
- **端口检测**在启动前检查端口是否已被使用
- **优雅地关闭**当MCP服务器停止时,执行干净的服务终止
- **多项服务**支持多个自动启动的服务

#### 配置选项:

public class ServiceConfiguration { public string ServiceId { get; set; } // Unique service identifier public string ExecutablePath { get; set; } // Path to executable public string[] Arguments { get; set; } // Command-line arguments public int Port { get; set; } // Service port public string HealthEndpoint { get; set; } // Health check URL public int StartupTimeoutSeconds { get; set; } // Startup timeout (default: 30) public int HealthCheckIntervalSeconds { get; set; } // Health check interval (default: 60) public bool AutoRestart { get; set; } // Enable auto-restart (default: true) public int MaxRestartAttempts { get; set; } // Max restart attempts (default: 3) public Dictionary EnvironmentVariables { get; set; } // Environment vars }


#### 多个服务示例:

var builder = new McpServerBuilder() .WithServerInfo("Multi-Service MCP", "1.0.0") .UseStdioTransport() .UseAutoServices( config => { config.ServiceId = "api-service"; config.ExecutablePath = "api.exe"; config.Port = 5100; config.HealthEndpoint = "http://localhost:5100/health"; }, config => { config.ServiceId = "worker-service"; config.ExecutablePath = "worker.exe"; config.Port = 5200; config.HealthEndpoint = "http://localhost:5200/health"; } );


#### 自定义健康检查:

// Register a custom health check for advanced scenarios // Use the enhanced configuration API with service provider access builder.ConfigureResources((registry, serviceProvider) => { var serviceManager = serviceProvider.GetRequiredService();

serviceManager.RegisterHealthCheck("my-service", async () => { // Custom health check logic var client = new HttpClient(); var response = await client.GetAsync("http://localhost:5100/custom-health"); return response.IsSuccessStatusCode; }); });


这一功能非常适合:

- **双模架构**需要暴露HTTP API的MCP服务器
- **微服务协调**共同管理相关服务
- **开发环境**简化本地开发环境设置
- **联邦场景**相互通信的MCP服务器

## 🔥 高级功能

### 泛型类型安全 - 消除对象类型转换

该框架提供了关键接口的通用版本,以消除对象类型转换并提高类型安全性:

#### 通用参数验证

// Before: Non-generic parameter validation (still supported) public class LegacyTool : McpToolBase { protected override Task ExecuteInternalAsync( MyParams parameters, CancellationToken cancellationToken) { // Parameters already validated and strongly typed! return ProcessParameters(parameters); // No casting needed } }

// New: Explicit generic parameter validator for advanced scenarios public class CustomValidationTool : McpToolBase { private readonly IParameterValidator _validator;

public CustomValidationTool(IParameterValidator validator) { _validator = validator; // Strongly typed, no object casting }

protected override async Task ExecuteInternalAsync( ComplexParams parameters, CancellationToken cancellationToken) { // Custom validation with no object casting var validationResult = _validator.Validate(parameters);

if (!validationResult.IsValid) { return CreateErrorResult("VALIDATION_FAILED", string.Join(", ", validationResult.Errors.Select(e => e.Message))); }

// Process strongly-typed parameters return ProcessComplexParameters(parameters); } }


#### 通用资源缓存

// Cache any resource type with compile-time safety public class SearchResultResourceProvider : IResourceProvider { private readonly IResourceCache _cache; // Strongly typed cache! private readonly ISearchService _searchService;

public SearchResultResourceProvider( IResourceCache cache, // No more object casting ISearchService searchService) { _cache = cache; _searchService = searchService; }

public async Task ReadResourceAsync(string uri, CancellationToken ct) { // Check cache first - strongly typed, no casting var cached = await _cache.GetAsync(uri); if (cached != null) { return CreateReadResourceResult(cached); // Type-safe operations }

// Generate new data var searchData = await _searchService.SearchAsync(ExtractQuery(uri));

// Store in cache - type-safe storage await _cache.SetAsync(uri, searchData, TimeSpan.FromMinutes(10));

return CreateReadResourceResult(searchData); }

private ReadResourceResult CreateReadResourceResult(SearchResultData data) { return new ReadResourceResult { Contents = new List { new ResourceContent { Uri = data.OriginalQuery, Text = JsonSerializer.Serialize(data), // Type-safe serialization MimeType = "application/json" } } }; } }

// Register the strongly-typed cache builder.Services.AddSingleton, InMemoryResourceCache>();


#### 通用响应建筑

// Before: Object-based response building (still supported for backward compatibility) public class LegacyResponseBuilder : BaseResponseBuilder { public override async Task BuildResponseAsync(object data, ResponseContext context) { return new AIOptimizedResponse // Returns object, requires casting { Data = new AIResponseData { Results = data, // object type, requires casting later Meta = new AIResponseMeta { /* ... */ } } }; } }

// New: Strongly-typed response building public class TypedResponseBuilder : BaseResponseBuilder { public override async Task BuildResponseAsync(SearchData data, ResponseContext context) { return new SearchResult // Strongly typed return, no casting needed { Success = true, Operation = "search_data", Query = data.Query, Results = data.Items, // Type-safe property access TotalFound = data.Items.Count, ExecutionTime = context.ElapsedTime, // No object casting anywhere! }; } }

// Using the generic AIOptimizedResponse public class OptimizedSearchTool : McpToolBase> { protected override async Task> ExecuteInternalAsync( SearchParams parameters, CancellationToken cancellationToken) { var searchData = await SearchAsync(parameters.Query);

return new AIOptimizedResponse // Generic type, no casting! { Success = true, Operation = "search_optimized", Data = new AIResponseData { Results = new SearchResultSummary { Query = parameters.Query, TotalMatches = searchData.Count, TopResults = searchData.Take(5).ToList() }, Meta = new AIResponseMeta { TokenUsage = EstimateTokens(searchData), OptimizationApplied = searchData.Count > 100, ResourceUri = searchData.Count > 100 ? StoreAsResource(searchData) : null } } }; } }


#### 迁移示例

// Easy migration from non-generic to generic interfaces public class MigrationExample { public void ConfigureServices(IServiceCollection services) { // Option 1: Use generic interface directly services.AddSingleton, DefaultParameterValidator>(); services.AddSingleton, InMemoryResourceCache>();

// Option 2: Keep existing non-generic registrations (fully backward compatible) services.AddSingleton(); services.AddSingleton();

// Option 3: Convert existing non-generic to generic using extension methods var nonGenericValidator = serviceProvider.GetService(); var typedValidator = nonGenericValidator.ForType(); // Extension method conversion } }


#### 主要优势

- **🎯 编译时安全性**在构建时而不是运行时捕获类型错误
- **🚀 更佳性能**无需装箱/拆箱或基于反射的转换
- **🧠 增强的 IntelliSense(智能感知)**在集成开发环境(IDE)中可获取完整的类型信息
- **🔄 无缝迁移**非泛型接口仍然可以工作,您可以按自己的节奏进行升级
- **🛠️ 更整洁的代码**消除类型转换操作周围的try-catch块

### 可定制的错误消息

覆盖/重写 `ErrorMessages` 在您的工具中设置属性,以提供针对特定上下文的错误信息和恢复指导:

public class DatabaseTool : McpToolBase { // Custom error message provider protected override ErrorMessageProvider ErrorMessages => new DatabaseErrorMessageProvider();

// ... tool implementation }

public class DatabaseErrorMessageProvider : ErrorMessageProvider { public override string ToolExecutionFailed(string toolName, string details) { return $"Database operation '{toolName}' failed: {details}. Check connection status."; }

public override RecoveryInfo GetRecoveryInfo(string errorCode, string? context = null, Exception? exception = null) { return errorCode switch { "CONNECTION_FAILED" => new RecoveryInfo { Steps = new[] { "Verify database connection string", "Check network connectivity", "Ensure database server is running" }, SuggestedActions = new[] { new SuggestedAction { Tool = "test_connection", Description = "Test database connectivity", Parameters = new { timeout = 30 } } } }, _ => base.GetRecoveryInfo(errorCode, context, exception) }; } }


### 代币预算配置

使用服务器构建器为每个工具、类别或全局配置令牌限制:

var builder = new McpServerBuilder() .WithServerInfo("My Server", "1.0.0") .ConfigureTokenBudgets(budgets => { // Tool-specific limits (highest priority) budgets.ForTool() .MaxTokens(20000) .WarningThreshold(16000) .WithStrategy(TokenLimitStrategy.Truncate) .Apply();

budgets.ForTool() .MaxTokens(5000) .WithStrategy(TokenLimitStrategy.Throw) .Apply();

// Category-based limits (medium priority) budgets.ForCategory(ToolCategory.Analysis) .MaxTokens(15000) .WarningThreshold(12000) .Apply();

budgets.ForCategory(ToolCategory.Query) .MaxTokens(8000) .Apply();

// Default limits (lowest priority) budgets.Default() .MaxTokens(10000) .WarningThreshold(8000) .WithStrategy(TokenLimitStrategy.Warn) .EstimationMultiplier(1.2) // Conservative estimates .Apply(); });


#### 代币预算策略

- **警告**记录警告并继续(默认)
- **投掷**抛出异常以阻止执行
- **截断**截断输出以保持在限制范围内
- **忽略**不强制执行令牌限制

#### 每工具令牌预算覆盖

public class HighVolumeAnalysisTool : McpToolBase { // Override the default token budget for this specific tool protected override TokenBudgetConfiguration TokenBudget => new() { MaxTokens = 50000, WarningThreshold = 40000, Strategy = TokenLimitStrategy.Truncate, EstimationMultiplier = 1.5 };

// ... tool implementation }


### 内置的验证辅助工具

该框架提供了多个验证辅助工具 `McpToolBase` 简化参数验证的类:

public class DataProcessingTool : McpToolBase { protected override async Task ExecuteInternalAsync( DataParams parameters, CancellationToken cancellationToken) { // Validate required parameters (throws ValidationException if null/empty) var filePath = ValidateRequired(parameters.FilePath, nameof(parameters.FilePath)); var query = ValidateRequired(parameters.Query, nameof(parameters.Query));

// Validate positive numbers var maxResults = ValidatePositive(parameters.MaxResults, nameof(parameters.MaxResults));

// Validate ranges var priority = ValidateRange(parameters.Priority, 1, 10, nameof(parameters.Priority));

// Validate collections aren't empty var tags = ValidateNotEmpty(parameters.Tags, nameof(parameters.Tags));

// All validation passed - process the data return await ProcessDataAsync(filePath, query, maxResults, priority, tags); } }


#### 可用的验证辅助工具

| 辅助函数 | 用途 | 抛出(异常) |
|--------|---------|--------|
| `ValidateRequired(value, paramName)` 确保值不为空或空字符串 `ValidationException` |
| `ValidatePositive(value, paramName)` 确保数值大于0 `ValidationException` |
| `ValidateRange(value, min, max, paramName)` | 确保值在范围内 | `ValidationException` |
| `ValidateNotEmpty(collection, paramName)` | 确保收藏中有物品 | `ValidationException` |

### 内置错误结果辅助工具

该框架提供了辅助工具,用于创建包含恢复信息的标准化错误结果:

public class DatabaseTool : McpToolBase { protected override async Task ExecuteInternalAsync( DbParams parameters, CancellationToken cancellationToken) { try { var connectionString = ValidateRequired(parameters.ConnectionString, nameof(parameters.ConnectionString));

// Attempt database operation var result = await ExecuteDatabaseQuery(connectionString, parameters.Query);

return new DbResult { Success = true, Operation = "database_query", Data = result }; } catch (SqlException ex) when (ex.Number == 2) // Connection timeout { // Create standardized error with recovery steps return new DbResult { Success = false, Operation = "database_query", Error = CreateErrorResult( "database_query", $"Database connection timeout: {ex.Message}", "Verify database server is running and accessible" ) }; } catch (ArgumentException ex) { // Create validation error with specific guidance return new DbResult { Success = false, Operation = "database_query", Error = CreateValidationErrorResult( "database_query", "connectionString", "Must be a valid SQL Server connection string" ) }; } } }


#### 可用的错误结果辅助工具

| 辅助工具 | 用途 | 返回值 |
|--------|---------|---------|
| `CreateErrorResult(operation, error, recoveryStep?)` | 创建 `ErrorInfo` 附带恢复指南 | `ErrorInfo` |
| `CreateValidationErrorResult(operation, paramName, requirement)` | 创建特定于验证的错误 | `ErrorInfo` |
| `CreateSuccessResult(data, message?)` | 成功创建 `ToolResult` | `ToolResult` |
| `CreateErrorResult(errorMessage, errorCode?)` 创建失败 `ToolResult` | `ToolResult` |

### 带恢复步骤的错误处理

public class FileAnalysisTool : McpToolBase { protected override async Task ExecuteInternalAsync( FileAnalysisParams parameters, CancellationToken cancellationToken) { try { var filePath = ValidateRequired(parameters.FilePath, nameof(parameters.FilePath));

if (!File.Exists(filePath)) { // Return AI-friendly error with recovery steps return new FileAnalysisResult { Success = false, Operation = "analyze_file", Error = new ErrorInfo { Code = "FILE_NOT_FOUND", Message = $"File not found: {filePath}", Recovery = new RecoveryInfo { Steps = new[] { "Verify the file path is correct", "Check if the file exists", "Ensure you have read permissions" }, SuggestedActions = new[] { new SuggestedAction { Tool = "list_files", Description = "List files in directory", Parameters = new { path = Path.GetDirectoryName(filePath) } } } } } }; }

// Perform analysis... var analysis = await AnalyzeFileAsync(filePath);

return new FileAnalysisResult { Success = true, Operation = "analyze_file", FilePath = filePath, Analysis = analysis, Insights = GenerateInsights(analysis), Actions = GenerateNextActions(analysis) }; } catch (UnauthorizedAccessException ex) { return CreateErrorResult( "PERMISSION_DENIED", $"Access denied: {ex.Message}", new[] { "Check file permissions", "Run with appropriate privileges" } ); } } }


### 资源提供者

#### 自动资源缓存(v1.4.8+)

该框架现在为资源提供了自动的单例级缓存,解决了作用域提供者与单例注册表之间生命周期不匹配的问题:

// Resource caching is automatically configured by McpServerBuilder // No additional setup required - just implement your provider!

public class SearchResultResourceProvider : IResourceProvider { private readonly ISearchService _searchService; // Can be scoped!

public SearchResultResourceProvider(ISearchService searchService) { _searchService = searchService; // Scoped dependency is OK }

public string Scheme => "search-results"; public string Name => "Search Results Provider"; public string Description => "Provides search result resources";

public bool CanHandle(string uri) => uri.StartsWith($"{Scheme}://");

public async Task ReadResourceAsync(string uri, CancellationToken ct) { // No need to implement caching - framework handles it! var sessionId = ExtractSessionId(uri); var results = await _searchService.LoadResultsAsync(sessionId);

return new ReadResourceResult { Contents = new List { new ResourceContent { Uri = uri, Text = JsonSerializer.Serialize(results), MimeType = "application/json" } } }; }

public async Task

ListResourcesAsync(CancellationToken ct)

{ // List available resources var sessions = await _searchService.GetActiveSessionsAsync(); return sessions.Select(s => new Resource { Uri = $"{Scheme}://{s.Id}", Name = $"Search Results {s.Id}", Description = $"Results for query: {s.Query}", MimeType = "application/json" }).ToList(); } }

// Register your provider - caching is automatic! builder.Services.AddScoped();

// Optional: Configure cache settings builder.Services.Configure(options => { options.DefaultExpiration = TimeSpan.FromMinutes(10); options.SlidingExpiration = TimeSpan.FromMinutes(5); options.MaxSizeBytes = 200 * 1024 * 1024; // 200 MB });


#### 为什么需要资源缓存?

- **解决寿命不匹配问题**作用域提供者可以与单例注册表一起工作
- **提高性能**昂贵操作的自动缓存
- **内存高效**内置大小限制和过期功能
- **透明的**无需在现有提供者中进行代码更改
- **具有韧性的**缓存故障不会影响核心功能

### 代币优化(可选包)

// Add the TokenOptimization package //

public class SearchTool : McpToolBase { protected override async Task ExecuteInternalAsync( SearchParams parameters, CancellationToken cancellationToken) { var results = await SearchAsync(parameters.Query);

// Use token management from base class return await ExecuteWithTokenManagement(async () => { // Automatically handles token limits return new SearchResult { Success = true, Results = results, // Auto-truncated if needed TotalCount = results.Count, ResourceUri = results.Count > 100 ? await StoreAsResourceAsync(results) : null }; }); } }


### 测试你的工具

using COA.Mcp.Framework.Testing; using FluentAssertions;

[TestFixture] public class WeatherToolTests { private WeatherTool _tool; private Mock _weatherService;

[SetUp] public void Setup() { _weatherService = new Mock(); _tool = new WeatherTool(_weatherService.Object); }

[Test] public async Task GetWeather_WithValidLocation_ReturnsWeatherData() { // Arrange var parameters = new WeatherParameters { Location = "Seattle", ForecastDays = 3 };

_weatherService .Setup(x => x.GetWeatherAsync("Seattle", 3)) .ReturnsAsync(new WeatherData { /* ... */ });

// Act var result = await _tool.ExecuteAsync(parameters);

// Assert result.Should().NotBeNull(); result.Success.Should().BeTrue(); result.Location.Should().Be("Seattle"); result.Forecast.Should().HaveCount(3); }

[Test] public async Task GetWeather_WithMissingLocation_ReturnsError() { // Arrange var parameters = new WeatherParameters { Location = null };

// Act var result = await _tool.ExecuteAsync(parameters);

// Assert result.Success.Should().BeFalse(); result.Error.Should().NotBeNull(); result.Error.Code.Should().Be("VALIDATION_ERROR"); } }


## 📚 文档

### 框架结构

COA.Mcp.Framework/ ├── Base/ │ └── McpToolBase.Generic.cs # Generic base class for tools ├── Server/ │ ├── McpServer.cs # Main server implementation │ ├── McpServerBuilder.cs # Fluent builder API │ └── Services/ # Auto-service management │ ├── ServiceManager.cs # Service lifecycle management │ ├── ServiceConfiguration.cs # Service config model │ └── ServiceLifecycleHost.cs # IHostedService integration ├── Registration/ │ └── McpToolRegistry.cs # Unified tool registry ├── Interfaces/ │ ├── IMcpTool.cs # Tool interfaces │ └── IResourceProvider.cs # Resource provider pattern ├── Models/ │ ├── ErrorModels.cs # Error handling models │ └── ToolResultBase.cs # Base result class └── Enums/ └── ToolCategory.cs # Tool categorization


### 关键组件

- **\`McpToolBase\\` 可以翻译为:“基于参数TParams和结果TResult的MCP工具基类”。这里,“MCP”可能代表某种特定的工具、框架或系统(具体含义需根据上下文确定),“TParams”表示模板参数类型,“TResult”表示模板结果类型**类型安全工具实现的通用基类
- **McpServerBuilder(可译为“MCP服务器构建器”或根据具体上下文调整为更贴切的表述)**服务器配置的流畅API
- **McpToolRegistry(可译为“Mcp工具注册表”)**管理工具注册与发现
- **工具结果基类**标准结果格式,包含错误处理
- **IResourceProvider(接口)**自定义资源提供程序的接口

## 🏆 现实世界中的例子

该框架为生产MCP服务器提供动力:

- **CodeSearch MCP(代码搜索MCP)**使用Lucene索引进行文件和文本搜索
- **CodeNav MCP(注:此处“MCP”可能是一个特定上下文中的缩写或专有名词,根据常规理解,可直接保留原样,若需具体翻译需更多上下文信息)**使用 Roslyn 进行 C# 代码导航
- **SimpleMcpServer(可译为“简易MCP服务器”)**示例项目,包含计算器、数据存储和系统信息工具

## 📈 表现

| 指标 | 目标 | 实际 |
|--------|--------|--------|
| 构建时间 | \<3秒 | 2.46秒 |
| 测试套件 | 100% 通过 | 562/562 ✓ |
| 警告 | 0 | 0 ✓ |
| 框架开销 | \<5% | ~3% |

## 🤝 贡献(或:参与贡献)

我们欢迎投稿!重点领域:

- 额外的工具示例
- 性能优化
- 文档改进
- 测试覆盖率扩展

## 📄 许可证

MIT 许可证 - 详见 [许可证](LICENSE) 请查阅文件以获取详细信息。

## 🙏 致谢

基于以下经验构建:

- COA CodeSearch MCP - 令牌优化模式
- COA CodeNav MCP - Roslyn 集成模式
- MCP社区 - 反馈与建议

______________________________________________________________________

## 📖 文档

如需全面的文档、指南和示例,请参阅 **[文档中心](docs/README.md)**。

**准备好构建您的MCP服务器了吗?** 克隆仓库并查看示例:

git clone https://github.com/anortham/COA-Mcp-Framework.git cd COA-Mcp-Framework/examples/SimpleMcpServer dotnet run


如需详细指南,请参阅 [CLAUDE.md(文件名,可译为“克劳德.md”文件,但通常文件名直接保留原样,不进行翻译)](CLAUDE.md) 用于获取AI辅助的开发提示。

目录标签

目录标签

服务器开发C#Claude类型安全MCP协议本地部署.NET框架AI集成

支持客户端

Claude DesktopClaude

接入字段

传输方式(transport,传输协议)

未说明

鉴权方式(authType,认证方式)

token

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

未说明token部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

仍需确认:installCommand

来源信息

继续浏览同类 MCP