ASP.NET Core WebApi 集成 MCP 协议完全指南

news/2025/10/28 16:41:11/文章来源:https://www.cnblogs.com/saodiseng2015/p/19172165

前言

Model Context Protocol (MCP) 是一个标准化协议,让 AI 客户端(如 Claude、ChatGPT 等)能够通过统一的接口调用你的 API。本文将详细介绍如何在 ASP.NET Core WebApi 项目中集成 MCP 支持,实现 AI 与你的服务无缝对接。

什么是 MCP?

MCP(Model Context Protocol)是一个开放协议,旨在标准化 AI 应用与外部工具、数据源之间的通信方式。通过 MCP,你的 API 可以:

  • 被 AI 助手自动发现和调用
  • 提供标准化的工具描述和参数定义
  • 支持多种传输模式(HTTP、Stdio)
  • 实现安全的认证和授权

核心特性

本项目实现了以下功能:

  • ✅ 使用官方 ModelContextProtocol.AspNetCore SDK
  • ✅ 通过 [McpServerTool] 特性快速定义工具
  • ✅ 自动参数绑定和 JSON Schema 生成
  • ✅ 支持 HTTP 和 Stdio 双传输模式
  • ✅ 基于 Token 的认证和授权
  • ✅ 与现有 WebApi 完美共存

快速开始

第一步:安装 NuGet 包

dotnet add package ModelContextProtocol.AspNetCore --version 0.4.0-preview.3

第二步:配置 MCP 服务

Program.cs 中添加 MCP 配置:

using ModelContextProtocol.Server;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();// 添加 MCP 服务器(支持 HTTP 和 Stdio 双模式)
builder.Services.AddMcpServer(options =>{options.ServerInfo = new ModelContextProtocol.Protocol.Implementation{Name = "Weather API",Version = "1.0.0"};}).WithHttpTransport()           // HTTP 模式:用于 Web 客户端.WithStdioServerTransport()    // Stdio 模式:用于 Kiro IDE 等本地工具.WithToolsFromAssembly();var app = builder.Build();// 添加认证中间件(可选)
app.UseMiddleware<McpAuthenticationMiddleware>();app.UseAuthorization();
app.MapControllers();// 映射 MCP 端点
app.MapMcp("/mcp");app.Run();

第三步:定义 MCP 工具

创建 Tools/WeatherTools.cs

using System.ComponentModel;
using ModelContextProtocol.Server;[McpServerToolType]
public static class WeatherTools
{[McpServerTool][Description("Get weather forecast for the next 5 days")]public static IEnumerable<WeatherForecast> GetWeatherForecast(){var rng = new Random();return Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),TemperatureC = rng.Next(-20, 55),Summary = Summaries[rng.Next(Summaries.Length)]}).ToArray();}[McpServerTool][Description("Get current weather for a specific city")]public static WeatherForecast GetWeatherByCity([Description("The name of the city")] string city){var rng = new Random();return new WeatherForecast{Date = DateOnly.FromDateTime(DateTime.Now),TemperatureC = rng.Next(-20, 55),Summary = $"Weather in {city}: {Summaries[rng.Next(Summaries.Length)]}"};}private static readonly string[] Summaries = new[]{"Freezing", "Bracing", "Chilly", "Cool", "Mild","Warm", "Balmy", "Hot", "Sweltering", "Scorching"};
}

第四步:配置认证(可选)

appsettings.json 中配置:

{"McpAuth": {"Enabled": true,"ValidTokens": ["your-secret-token-here"]}
}

开发环境可以禁用认证(appsettings.Development.json):

{"McpAuth": {"Enabled": false}
}

第五步:运行和测试

dotnet run

应用启动后,可以访问:

  • Swagger UI: http://localhost:5000/swagger
  • WebApi: http://localhost:5000/weatherforecast
  • MCP 端点: http://localhost:5000/mcp

传输模式详解

HTTP 模式

适用于 Web 应用、Claude Desktop、远程访问等场景。

测试示例

# 列出所有工具
curl -X POST http://localhost:5000/mcp \-H "Content-Type: application/json" \-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'# 调用工具
curl -X POST http://localhost:5000/mcp \-H "Authorization: Bearer your-secret-token-here" \-H "Content-Type: application/json" \-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"GetWeatherForecast","arguments":{}}}'

Claude Desktop 配置

编辑配置文件(Windows: %APPDATA%\Claude\claude_desktop_config.json):

{"mcpServers": {"weather-api": {"url": "http://localhost:5000/mcp","headers": {"Authorization": "Bearer your-secret-token-here"}}}
}

Stdio 模式

适用于 Kiro IDE、本地命令行工具等场景,无需网络端口。

Kiro IDE 配置

编辑 .kiro/settings/mcp.json

{"mcpServers": {"weather-api": {"command": "dotnet","args": ["run", "--project", "path/to/NetCoreApiMcpDemo.csproj"],"env": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
}

模式对比

特性 HTTP 模式 Stdio 模式
传输方式 HTTP POST 标准输入/输出
适用场景 Web 应用、远程访问 本地工具、IDE 集成
认证 HTTP Header 环境变量/配置
网络 需要网络端口 无需网络
性能 网络开销 进程间通信,更快

认证和授权

实现认证中间件

创建 Middleware/McpAuthenticationMiddleware.cs

public class McpAuthenticationMiddleware
{private readonly RequestDelegate _next;private readonly IConfiguration _configuration;private readonly ILogger<McpAuthenticationMiddleware> _logger;public McpAuthenticationMiddleware(RequestDelegate next,IConfiguration configuration,ILogger<McpAuthenticationMiddleware> logger){_next = next;_configuration = configuration;_logger = logger;}public async Task InvokeAsync(HttpContext context){// 只对 MCP 端点进行认证if (!context.Request.Path.StartsWithSegments("/mcp")){await _next(context);return;}// 检查是否启用认证var authEnabled = _configuration.GetValue<bool>("McpAuth:Enabled");if (!authEnabled){await _next(context);return;}// 验证 Tokenvar authHeader = context.Request.Headers["Authorization"].FirstOrDefault();if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ")){context.Response.StatusCode = 401;await context.Response.WriteAsJsonAsync(new { error = "Unauthorized" });return;}var token = authHeader.Substring("Bearer ".Length).Trim();var validTokens = _configuration.GetSection("McpAuth:ValidTokens").Get<string[]>();if (validTokens == null || !validTokens.Contains(token)){context.Response.StatusCode = 401;await context.Response.WriteAsJsonAsync(new { error = "Invalid token" });return;}await _next(context);}
}

安全最佳实践

  1. 使用强 Token:至少 32 字符的随机字符串
  2. 定期轮换:定期更换 Token
  3. 使用 HTTPS:生产环境必须使用 HTTPS
  4. 环境隔离:开发和生产使用不同的 Token
  5. 日志安全:不要在日志中记录完整 Token

客户端集成示例

C# 客户端

using ModelContextProtocol;
using ModelContextProtocol.Client;var transport = new HttpClientTransport(new HttpClientTransportOptions
{BaseUrl = new Uri("http://localhost:5000/mcp"),Headers = new Dictionary<string, string>{["Authorization"] = "Bearer your-secret-token-here"}
});var client = await McpClient.CreateAsync(transport);await client.InitializeAsync(new InitializeParams
{ProtocolVersion = "2025-06-18",ClientInfo = new Implementation{Name = "MyApp",Version = "1.0.0"}
});// 列出工具
var tools = await client.ListToolsAsync();// 调用工具
var result = await client.CallToolAsync("GetWeatherForecast",new Dictionary<string, object?>()
);

JavaScript/Vue 客户端

<script setup>
import { ref } from 'vue';const weather = ref('');
const MCP_URL = 'http://localhost:5000/mcp';
const TOKEN = 'your-secret-token-here';const callMcp = async (method, params = {}) => {const response = await fetch(MCP_URL, {method: 'POST',headers: {'Content-Type': 'application/json',Authorization: `Bearer ${TOKEN}`,},body: JSON.stringify({jsonrpc: '2.0',id: Date.now(),method,params,}),});return response.json();
};const getWeather = async () => {const data = await callMcp('tools/call', {name: 'GetWeatherForecast',arguments: {},});weather.value = data.result.content[0].text;
};
</script>

MCP Tools 最佳实践

让 AI 更准确地使用你的工具是成功的关键。以下是经过实践验证的最佳实践。

核心原则

AI 通过以下信息决定是否使用你的工具:

  1. 工具名称 - 清晰、描述性
  2. Description - 详细的功能说明
  3. 参数描述 - 明确的参数用途
  4. 使用场景 - 何时应该使用这个工具

1. 使用清晰的命名

// ❌ 不好 - 名称模糊
[McpServerTool]
public static string Get() { }// ✅ 好 - 动词开头,描述清晰
[McpServerTool]
public static string GetWeatherForecast() { }// ✅ 更好 - 包含具体信息
[McpServerTool]
public static string GetWeatherForecastForNextDays() { }

命名建议:

  • 使用动词开头:Get, Search, Calculate, Compare, Analyze
  • 包含操作对象:Weather, Temperature, Forecast
  • 避免缩写和简称
  • 使用 PascalCase

2. 编写详细的 Description(最重要!)

这是最关键的部分!AI 主要通过 Description 判断是否使用工具。

// ❌ 不好 - 太简短
[Description("Get weather")]// ⚠️ 一般 - 有基本信息但不够
[Description("Get weather forecast for the next 5 days")]// ✅ 好 - 包含详细信息和使用场景
[Description(@"Get detailed weather forecast for the next several days including temperature, weather conditions, and trends.Use this tool when users ask about:
- Future weather (tomorrow, next week, upcoming days)
- Weather predictions or forecasts
- Planning activities based on weather
- Temperature trendsExamples of user queries:
- 'What's the weather forecast for the next 5 days?'
- 'Will it rain this week?'
- 'What's the temperature trend?'")]

Description 应该包含:

  1. 功能说明 - 工具做什么
  2. 使用场景 - 何时使用("Use this tool when...")
  3. 示例查询 - 用户可能的提问方式
  4. 支持的功能 - 特殊能力或限制

3. 详细的参数描述

[McpServerTool]
public static string GetWeatherByCity(// ❌ 不好[Description("city")] string city,// ✅ 好[Description("The name of the city in English or Chinese (e.g., 'Beijing', '北京', 'Shanghai', 'New York')")]string city,// ✅ 更好 - 包含默认值说明[Description("Number of days to forecast (1-7 days). Default is 5 days if not specified.")]int days = 5
)

参数描述应该包含:

  • 参数的用途
  • 支持的格式或值范围
  • 示例值
  • 默认值(如果有)

4. 返回格式化、易读的结果

// ❌ 不好 - 返回原始对象
public static WeatherForecast GetWeather(string city)
{return new WeatherForecast { ... };
}// ✅ 好 - 返回格式化的文本
public static string GetWeather(string city)
{var weather = GetWeatherData(city);return $@"🌍 Current Weather in {city}
📅 Date: {weather.Date:yyyy-MM-dd}
🌡️ Temperature: {weather.TemperatureC}°C ({weather.TemperatureF}°F)
☁️ Conditions: {weather.Summary}
⏰ Updated: {DateTime.Now:HH:mm:ss}";
}

5. 完整示例:查询工具

[McpServerTool]
[Description(@"Get detailed weather forecast for the next several days including temperature, weather conditions, and trends.Use this tool when users ask about:
- Future weather (tomorrow, next week, upcoming days)
- Weather predictions or forecasts
- Planning activities based on weather
- Temperature trends
- Weather conditions for travel planningExamples of user queries:
- 'What's the weather forecast for the next 5 days?'
- 'Will it rain this week?'
- 'What's the temperature trend?'
- 'Should I bring a jacket tomorrow?'
- '未来几天天气怎么样?'
- '这周会下雨吗?'")]
public static string GetWeatherForecast([Description("Number of days to forecast (1-7 days). Default is 5 days if not specified.")]int days = 5)
{var forecasts = GenerateForecasts(days);var result = new StringBuilder();result.AppendLine($"🌤️ Weather Forecast for Next {days} Days");result.AppendLine();foreach (var forecast in forecasts){result.AppendLine($"📅 {forecast.Date:yyyy-MM-dd (ddd)}");result.AppendLine($"   🌡️ Temperature: {forecast.TemperatureC}°C ({forecast.TemperatureF}°F)");result.AppendLine($"   ☁️ Conditions: {forecast.Summary}");result.AppendLine();}return result.ToString();
}

6. 完整示例:比较工具

[McpServerTool]
[Description(@"Compare weather conditions between two cities to help with travel decisions or general comparison.Use this tool when users want to:
- Compare weather between cities
- Decide which city has better weather
- Plan travel between cities
- Compare temperatures
- Choose destination based on weatherExamples of user queries:
- 'Compare weather between Beijing and Shanghai'
- 'Which city is warmer, Tokyo or Seoul?'
- 'Weather difference between New York and London'
- '北京和上海哪个城市天气更好?'
- '东京和首尔哪里更暖和?'")]
public static string CompareWeatherBetweenCities([Description("First city name (English or Chinese)")] string city1,[Description("Second city name (English or Chinese)")] string city2)
{var weather1 = GetWeatherData(city1);var weather2 = GetWeatherData(city2);return $@"🌍 Weather Comparison📍 {city1}:🌡️ Temperature: {weather1.TemperatureC}°C☁️ Conditions: {weather1.Summary}📍 {city2}:🌡️ Temperature: {weather2.TemperatureC}°C☁️ Conditions: {weather2.Summary}📊 Difference: {Math.Abs(weather1.TemperatureC - weather2.TemperatureC)}°C
{(weather1.TemperatureC > weather2.TemperatureC ? $"🔥 {city1} is warmer" : $"🔥 {city2} is warmer")}";
}

7. Description 模板

基础模板:

[Description(@"[简短功能说明]Use this tool when users ask about:
- [使用场景1]
- [使用场景2]
- [使用场景3]Examples of user queries:
- '[示例问题1]'
- '[示例问题2]'
- '[示例问题3]'")]

完整模板:

[Description(@"[详细功能说明,包括返回的数据类型和格式]Use this tool when users want to:
- [使用场景1]
- [使用场景2]
- [使用场景3]Supports:
- [支持的功能1]
- [支持的功能2]Examples of user queries:
- '[英文示例1]'
- '[英文示例2]'
- '[中文示例1]'
- '[中文示例2]'Note: [特殊说明或限制]")]

8. 优化检查清单

在发布工具前,检查以下项目:

高级特性

依赖注入支持

工具方法可以注入服务:

[McpServerTool]
[Description("Get weather with logging")]
public static string GetWeatherWithLogging(ILogger<WeatherTools> logger,IWeatherService weatherService,string city)
{logger.LogInformation("Getting weather for {City}", city);return weatherService.GetWeather(city);
}

添加 Prompts

[McpServerPromptType]
public static class WeatherPrompts
{[McpServerPrompt][Description("Creates a prompt to help plan outdoor activities based on weather")]public static ChatMessage PlanOutdoorActivity([Description("The city name")] string city,[Description("The activity type")] string activity){return new ChatMessage(ChatRole.User,$@"I want to plan a {activity} activity in {city}.Please check the weather forecast and suggest the best day and time.Consider temperature, conditions, and provide detailed recommendations.");}
}

复杂参数类型

SDK 自动支持:

  • 基本类型:string, int, bool, double
  • 复杂对象:自动序列化/反序列化
  • 可选参数:使用默认值
  • 数组和集合

故障排除

工具未被发现

检查项:

  • 类是否有 [McpServerToolType] 特性
  • 方法是否有 [McpServerTool] 特性
  • 类是否是静态的
  • 是否重启了应用

认证失败

检查项:

  • Token 是否正确
  • appsettings.jsonEnabled 设置
  • Authorization header 格式
  • 环境配置(Development vs Production)

CORS 问题

Program.cs 中添加 CORS 支持:

builder.Services.AddCors(options =>
{options.AddPolicy("AllowMcpClients", policy =>{policy.WithOrigins("http://localhost:3000").AllowAnyHeader().AllowAnyMethod();});
});app.UseCors("AllowMcpClients");

项目结构

NetCoreApiMcpDemo/
├── Controllers/
│   └── WeatherForecastController.cs  # 标准 WebApi 控制器
├── Tools/
│   └── WeatherTools.cs                # MCP 工具定义
├── Middleware/
│   └── McpAuthenticationMiddleware.cs # 认证中间件
├── Program.cs                          # 应用配置
├── appsettings.json                    # 配置文件
└── appsettings.Development.json        # 开发配置

为什么选择官方 SDK?

  1. 代码更少:无需自定义特性和提供者
  2. 更可靠:官方维护和更新
  3. 更强大:自动 Schema、DI 支持
  4. 更标准:完全符合 MCP 规范
  5. 更易维护:无需维护自定义代码

总结

通过本文,我们学习了如何在 ASP.NET Core WebApi 中集成 MCP 协议支持。使用官方 SDK,只需几行代码就能让你的 API 被 AI 客户端调用。MCP 协议的标准化特性,让 AI 应用与后端服务的集成变得前所未有的简单。

参考资源

  • MCP 官方文档
  • MCP C# SDK
  • MCP 规范
  • NuGet 包

源码地址

完整示例代码请访问:[GitHub 仓库地址]


如果本文对你有帮助,欢迎点赞、收藏、关注!有任何问题欢迎在评论区讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/948940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入解析:数字信号处理 第一章(离散时间信号与系统)【上】

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

goldengate(ogg)日常维护

1.修改源端抽取进程从某个位置开始抽取GGSCI (rac01) 29> info extepEXTRACT EXTEP Last Started 2025-10-28 16:24 Status STOPPED Checkpoint Lag 00:00:03 (updated 00:00:36 ago) Log Read Chec…

关于curl-一个网址-报错-OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to

关于curl-一个网址-报错-OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection toPosted on 2025-10-28 16:32 520_1351 阅读(0) 评论(0) 收藏 举报背景:今天在一台Azure虚拟机上,使用curl 一个https网址时,…

电脑截图怎么往下拖着截图?4种方法教你轻松实现长页面截图(滚动截图超全教程)

想知道电脑截图怎么往下拖着截图?本文详细介绍4种实现长页面截图 / 滚动截图的方法,包括专业截图软件、浏览器扩展、系统拼接与QQ/微信截图。支持Win10/Win11,图文教程+下载链接,轻松截取网页、文档、代码等完整长…

2025年云南旅游租车公司最新服务推荐榜:芒市旅游包车/芒市旅游租车/云南旅游包车/专注体验与可靠,打造无忧旅途

随着旅游消费升级及个性化出行需求增长,旅游包车与租车服务已从传统旅游配套逐步发展为提升旅行体验的重要环节。2025年,随着云南旅游市场持续回暖与服务品质不断提升,游客对车辆安全、服务专业度、线路适配性等方面…

102302125 苏琎宇 数据采集第1次作业

用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。 在分析网站的数据结构和请求方式后,发现无法像普通分页网页那样简单…

哈希优化策略

哈希优化策略哈希优化策略算法题中,我们常通过将线性查找替换为哈希查找来降低算法的时间复杂度。我们借助一个算法题来加深理解。Q:给定一个整数数组 nums 和一个目标元素 target ,请在数组中搜索“和”为 target …

一站式开发速查表大全 - 覆盖主流编程语言与工具

这是一个全面的编程速查表集合项目,涵盖了从基础编程语言到现代开发框架的完整参考资料。包含JavaScript、Python、Java、Go等主流语言,以及React、Vue、Angular等前端框架,还有Docker、Kubernetes、Git等开发工具的…

gcc系编译器、调试器的应用和c/c++编译原理

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

JAVA FX初次使用并制作辅助工具指南

JAVA FX初次使用并制作辅助工具指南先上功能截图讲讲第一次使用的体验。 JAVA FX还是非常友好很好使用的 IDEA新建FX项目的时候就能把很多功能都选上。 这些pom是适配了jdk21的,不同版本的fx组件适配jdk也不一样,我是…

Day6综合案例1-体育新闻列表

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">…

题解:AT_agc015_e [AGC015E] Mr.Aoki Incubator

原题链接:link。 自然想到建立坐标系,以速度为纵轴,初始点为横轴。 以样例二为例来分析:考虑将点两两连线: ` 其中红线为斜率为负数的线,容易知道点 \((x_i,v_i)\) 与点 \((x_j,v_j)\) 所连成的线的斜率为 \(\fr…

SNP特征通道数是什么意思

在《【已阅】cropformer.pdf》的基因组预测场景中,“SNP特征通道数”本质是SNP基因型经过编码后,每个SNP位点对应的数值特征所占用的“维度/通道数量”,是Hyena算子、CNN等模型组件处理SNP数据时的核心维度参数(d_…

CF1482E Skyline Photo

绝世唐题,为啥没有人写题解啊。 首先发现划分成若干个段,设一个 DP \(f_i\) 表示以 \(i\) 结尾的分段方式的最大贡献,那么朴素转移就是你去枚举区间取 \(\max\)。 发现是求 \(h\) 的最小值所对应的 \(b\),比较典的…

sqlserver 添加或修改字段

添加字段ALTER TABLE 表名 ADD 列名 数据类型 [约束];修改字段 ALTER TABLE 表名 ALTER COLUMN 列名 新数据类型;

最小瓶颈生成树

作业是鸽子更新的动力。\(\text{MBST}\)(\(\text{Minimum Bottleneck Spanning Tree}\))指的是求一颗生成树,其中最大的边权最小(所以也叫 \(\text{min-max spanning tree}\))。和最小树形图一样,也有有向图版本…

Linux系统常用操作指令简明指南

Linux系统常用操作指令简明指南 熟练掌握Linux命令是每个开发者的基本功。这份指南凝聚了我多年开发经验中的精华,将帮助您提高工作效率,解决实际问题。请记住,Linux哲学的核心在于"每个工具做好一件事,然后将…

小程序语音通话让智能设备会“说话”

小程序语音通话让智能设备会“说话”在万物互联的智能时代,如何让智能设备与用户建立更自然、更高效的连接,成为产品脱颖而出的关键。传统的APP推送常因步骤繁琐、易被淹没而效率低下,微信小程序语音通话应运而生,…

易基因: NG (IF29):颠覆认知!深圳仙湖植物园刘阳团队WGBS及超级泛基因组分析揭示苔藓植物基因家族比维管植物更丰富|项目文章

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 近日,由深圳市中国科学院仙湖植物园董珊珊博士等为第一作者、刘阳研究员等为通讯作者,在国际著名期刊《Nature Genetics》(自然-遗传学)上发表题…