ASP.NET Core WebApi 集成 MCP 协议完全指南
本文介绍了如何在 ASP.NET Core WebApi 中集成 MCP(Model Context Protocol)协议,使 API 能被 AI 客户端(如 Claude、ChatGPT)自动调用。主要内容包括:1)MCP 协议简介及其标准化、安全等优势;2)通过 NuGet 包快速集成 MCP 服务;3)定义 MCP 工具的方法和参数绑定;4)支持 HTTP 和 Stdio 双传输模式;5)
ASP.NET Core WebApi 集成 MCP 协议完全指南
本文详细介绍如何在 ASP.NET Core WebApi 项目中集成 Model Context Protocol (MCP) 支持,让你的 API 能够被 AI 客户端(如 Claude、ChatGPT)自动调用。
📖 目录
什么是 MCP?
MCP(Model Context Protocol) 是一个开放协议,旨在标准化 AI 应用与外部工具、数据源之间的通信方式。
MCP 的优势
- 🔌 标准化接口:统一的协议规范
- 🤖 AI 友好:自动工具发现和调用
- 🔒 安全可靠:内置认证和授权机制
- 🚀 易于集成:官方 SDK 支持多种语言
核心特性
本项目实现了以下功能:
| 特性 | 说明 |
|---|---|
| ✅ 官方 SDK | 使用 ModelContextProtocol.AspNetCore |
| ✅ 特性标记 | 通过 [McpServerTool] 快速定义工具 |
| ✅ 自动绑定 | 自动参数绑定和 JSON Schema 生成 |
| ✅ 双传输模式 | 支持 HTTP 和 Stdio |
| ✅ 认证授权 | 基于 Token 的安全机制 |
| ✅ 完美共存 | 与现有 WebApi 无缝集成 |
快速开始
步骤 1:安装 NuGet 包
dotnet add package ModelContextProtocol.AspNetCore --version 0.4.0-preview.3
步骤 2:配置 MCP 服务
在 Program.cs 中添加配置:
using ModelContextProtocol.Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// 添加 MCP 服务器
builder.Services
.AddMcpServer(options =>
{
options.ServerInfo = new ModelContextProtocol.Protocol.Implementation
{
Name = "Weather API",
Version = "1.0.0"
};
})
.WithHttpTransport() // HTTP 模式
.WithStdioServerTransport() // Stdio 模式
.WithToolsFromAssembly();
var app = builder.Build();
// 添加认证中间件
app.UseMiddleware<McpAuthenticationMiddleware>();
app.UseAuthorization();
app.MapControllers();
// 映射 MCP 端点
app.MapMcp("/mcp");
app.Run();
步骤 3:定义 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)
{
// 实现逻辑
}
}
步骤 4:配置认证
appsettings.json:
{
"McpAuth": {
"Enabled": true,
"ValidTokens": ["your-secret-token-here"]
}
}
appsettings.Development.json(开发环境):
{
"McpAuth": {
"Enabled": false
}
}
步骤 5:运行测试
dotnet run
访问地址:
- Swagger UI:
http://localhost:5000/swagger - MCP 端点:
http://localhost:5000/mcp
传输模式详解
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 | 环境变量/配置 |
| 网络 | 需要网络端口 | 无需网络 |
| 性能 | 网络开销 | 进程间通信,更快 |
| 调试 | 可用浏览器/Postman | 需要专门工具 |
认证和授权
实现认证中间件
创建 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;
}
// 验证 Token
var 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);
}
}
🔒 安全最佳实践
- 使用强 Token:至少 32 字符的随机字符串
- 定期轮换:定期更换 Token
- 使用 HTTPS:生产环境必须使用 HTTPS
- 环境隔离:开发和生产使用不同的 Token
- 日志安全:不要在日志中记录完整 Token
客户端集成
C# 客户端示例
using ModelContextProtocol;
using ModelContextProtocol.Client;
// 创建 HTTP 客户端传输
var transport = new HttpClientTransport(new HttpClientTransportOptions
{
BaseUrl = new Uri("http://localhost:5000/mcp"),
Headers = new Dictionary<string, string>
{
["Authorization"] = "Bearer your-secret-token-here"
}
});
// 创建 MCP 客户端
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();
foreach (var tool in tools)
{
Console.WriteLine($"工具: {tool.Name} - {tool.Description}");
}
// 调用工具
var result = await client.CallToolAsync(
"GetWeatherForecast",
new Dictionary<string, object?>()
);
Console.WriteLine($"结果: {result.Content[0].Text}");
JavaScript/Vue 客户端示例
<template>
<div class="weather-app">
<h1>天气应用</h1>
<button @click="getWeather" class="btn">获取天气预报</button>
<pre v-if="weather" class="result">{{ weather }}</pre>
</div>
</template>
<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>
<style scoped>
.weather-app {
padding: 20px;
}
.btn {
padding: 10px 20px;
background: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.result {
margin-top: 20px;
padding: 15px;
background: #f5f5f5;
border-radius: 4px;
}
</style>
Python/LangChain 集成
from langchain.tools import Tool
from langchain.agents import initialize_agent, AgentType
from langchain.llms import OpenAI
import requests
def call_mcp_tool(tool_name: str, arguments: dict = None) -> str:
"""调用 MCP 工具"""
response = requests.post(
'http://localhost:5000/mcp',
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer your-secret-token-here'
},
json={
'jsonrpc': '2.0',
'id': 1,
'method': 'tools/call',
'params': {
'name': tool_name,
'arguments': arguments or {}
}
}
)
return response.json()['result']['content'][0]['text']
# 创建 LangChain 工具
weather_tool = Tool(
name="GetWeatherForecast",
func=lambda x: call_mcp_tool("GetWeatherForecast"),
description="Get weather forecast for the next 5 days"
)
# 创建 Agent
llm = OpenAI(temperature=0)
agent = initialize_agent(
[weather_tool],
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
# 使用 Agent
result = agent.run("What's the weather forecast?")
print(result)
高级特性
依赖注入支持
工具方法可以注入服务:
[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 MyPrompts
{
[McpServerPrompt]
[Description("Creates a prompt to summarize content")]
public static ChatMessage Summarize(
[Description("The content to summarize")] string content)
{
return new ChatMessage(
ChatRole.User,
$"Please summarize: {content}");
}
}
支持的参数类型
SDK 自动支持:
- ✅ 基本类型:
string,int,bool,double等 - ✅ 复杂对象:自动序列化/反序列化
- ✅ 可选参数:使用默认值
- ✅ 数组和集合:
List<T>,T[]等
故障排除
❌ 工具未被发现
检查项:
- 类是否有
[McpServerToolType]特性 - 方法是否有
[McpServerTool]特性 - 类是否是静态的
- 是否重启了应用
❌ 认证失败
检查项:
- Token 是否正确
-
appsettings.json中Enabled设置 - Authorization header 格式:
Bearer {token} - 环境配置(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?
| 优势 | 说明 |
|---|---|
| 💡 代码更少 | 无需自定义特性和提供者 |
| 🛡️ 更可靠 | 官方维护和更新 |
| 🚀 更强大 | 自动 Schema、DI 支持 |
| 📐 更标准 | 完全符合 MCP 规范 |
| 🔧 更易维护 | 无需维护自定义代码 |
总结
通过本文,我们学习了如何在 ASP.NET Core WebApi 中集成 MCP 协议支持。主要内容包括:
- ✅ MCP 协议的基本概念和优势
- ✅ 使用官方 SDK 快速集成
- ✅ HTTP 和 Stdio 双传输模式配置
- ✅ 基于 Token 的认证和授权
- ✅ 多种客户端集成示例
- ✅ 高级特性和故障排除
使用官方 SDK,只需几行代码就能让你的 API 被 AI 客户端调用。MCP 协议的标准化特性,让 AI 应用与后端服务的集成变得前所未有的简单。
参考资源
- 📚 MCP 官方文档
- 💻 MCP C# SDK
- 📖 MCP 规范
- 📦 NuGet 包
源码地址
完整示例代码请访问:[GitHub 仓库地址]
💡 提示:如果本文对你有帮助,欢迎点赞 👍、收藏 ⭐、关注 🔔!
💬 交流:有任何问题欢迎在评论区讨论,我会及时回复。
🔗 分享:欢迎转发分享给更多需要的朋友。
标签:ASP.NET Core MCP AI WebApi Claude ChatGPT C# .NET
传输模式详解
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;
}
// 验证 Token
var 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);
}
}
安全最佳实践
- ✅ 使用强 Token:至少 32 字符的随机字符串
- ✅ 定期轮换:定期更换 Token
- ✅ 使用 HTTPS:生产环境必须使用 HTTPS
- ✅ 环境隔离:开发和生产使用不同的 Token
- ✅ 日志安全:不要在日志中记录完整 Token
MCP Tools 最佳实践 ⭐
让 AI 更准确地使用你的工具是成功的关键。以下是经过实践验证的最佳实践。
核心原则
AI 通过以下信息决定是否使用你的工具:
- 工具名称 - 清晰、描述性
- Description - 详细的功能说明
- 参数描述 - 明确的参数用途
- 使用场景 - 何时应该使用这个工具
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 trends
Examples of user queries:
- 'What's the weather forecast for the next 5 days?'
- 'Will it rain this week?'
- 'What's the temperature trend?'")]
Description 应该包含:
- 功能说明 - 工具做什么
- 使用场景 - 何时使用(“Use this tool when…”)
- 示例查询 - 用户可能的提问方式
- 支持的功能 - 特殊能力或限制
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 planning
Examples 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 weather
Examples 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. 优化检查清单
在发布工具前,检查以下项目:
- ✅ 工具名称清晰、描述性强
- ✅ Description 包含详细功能说明
- ✅ Description 包含使用场景(“Use this tool when…”)
- ✅ Description 包含示例查询
- ✅ 所有参数都有详细描述
- ✅ 参数描述包含示例值
- ✅ 返回值格式化、易读
- ✅ 包含错误处理
- ✅ 支持多语言(如果需要)
- ✅ 在 MCP Inspector 中测试通过
- ✅ 在 AI 客户端中测试通过
客户端集成
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 客户端
<template>
<div>
<h1>天气应用</h1>
<button @click="getWeather">获取天气预报</button>
<pre v-if="weather">{{ weather }}</pre>
</div>
</template>
<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>
高级特性
依赖注入支持
[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."
);
}
}
故障排除
工具未被发现
检查项:
- 类是否有
[McpServerToolType]特性 - 方法是否有
[McpServerTool]特性 - 类是否是静态的
- 是否重启了应用
认证失败
检查项:
- Token 是否正确
appsettings.json中Enabled设置- 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");
AI 没有使用我的工具?
检查:
- Description 是否足够详细?
- 是否包含使用场景说明?
- 是否包含示例查询?
- 工具名称是否清晰?
项目结构
NetCoreApiMcpDemo/
├── Controllers/
│ └── WeatherForecastController.cs # 标准 WebApi 控制器
├── Tools/
│ └── WeatherTools.cs # MCP 工具定义
├── Middleware/
│ └── McpAuthenticationMiddleware.cs # 认证中间件
├── Program.cs # 应用配置
├── appsettings.json # 配置文件
└── appsettings.Development.json # 开发配置
为什么选择官方 SDK?
- ✅ 代码更少:无需自定义特性和提供者
- ✅ 更可靠:官方维护和更新
- ✅ 更强大:自动 Schema、DI 支持
- ✅ 更标准:完全符合 MCP 规范
- ✅ 更易维护:无需维护自定义代码
总结
通过本文,我们学习了如何在 ASP.NET Core WebApi 中集成 MCP 协议支持,以及如何编写高质量的 MCP Tools。关键要点:
- 使用官方 SDK - 简化开发流程
- 详细的 Description - 让 AI 准确理解工具用途
- 清晰的命名和参数 - 提高工具可用性
- 格式化的返回值 - 让 AI 更好地理解结果
- 充分的测试 - 确保工具在真实场景中可用
记住:AI 是通过文本理解你的工具,所以文档质量直接影响工具的可用性!
参考资源
源码地址
完整示例代码请访问:[GitHub 仓库地址]
💡 提示:如果本文对你有帮助,欢迎点赞 👍、收藏 ⭐、关注 🔔!有任何问题欢迎在评论区讨论 💬。
标签:ASP.NET Core MCP AI WebApi Claude ChatGPT Model Context Protocol
更多推荐



所有评论(0)