廖翚凤 發表於 2025-10-28 16:35:00

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

<h2 id="前言">前言</h2>
<p>Model Context Protocol (MCP) 是一个标准化协议,让 AI 客户端(如 Claude、ChatGPT 等)能够通过统一的接口调用你的 API。本文将详细介绍如何在 ASP.NET Core WebApi 项目中集成 MCP 支持,实现 AI 与你的服务无缝对接。</p>
<h2 id="什么是-mcp">什么是 MCP?</h2>
<p>MCP(Model Context Protocol)是一个开放协议,旨在标准化 AI 应用与外部工具、数据源之间的通信方式。通过 MCP,你的 API 可以:</p>
<ul>
<li>被 AI 助手自动发现和调用</li>
<li>提供标准化的工具描述和参数定义</li>
<li>支持多种传输模式(HTTP、Stdio)</li>
<li>实现安全的认证和授权</li>
</ul>
<h2 id="核心特性">核心特性</h2>
<p>本项目实现了以下功能:</p>
<ul>
<li>✅ 使用官方 ModelContextProtocol.AspNetCore SDK</li>
<li>✅ 通过 <code></code> 特性快速定义工具</li>
<li>✅ 自动参数绑定和 JSON Schema 生成</li>
<li>✅ 支持 HTTP 和 Stdio 双传输模式</li>
<li>✅ 基于 Token 的认证和授权</li>
<li>✅ 与现有 WebApi 完美共存</li>
</ul>
<h2 id="快速开始">快速开始</h2>
<h3 id="第一步安装-nuget-包">第一步:安装 NuGet 包</h3>
<pre><code class="language-bash">dotnet add package ModelContextProtocol.AspNetCore --version 0.4.0-preview.3
</code></pre>
<h3 id="第二步配置-mcp-服务">第二步:配置 MCP 服务</h3>
<p>在 <code>Program.cs</code> 中添加 MCP 配置:</p>
<pre><code class="language-csharp">using ModelContextProtocol.Server;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// 添加 MCP 服务器(支持 HTTP 和 Stdio 双模式)
builder.Services
    .AddMcpServer(options =&gt;
    {
      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&lt;McpAuthenticationMiddleware&gt;();

app.UseAuthorization();
app.MapControllers();

// 映射 MCP 端点
app.MapMcp("/mcp");

app.Run();
</code></pre>
<h3 id="第三步定义-mcp-工具">第三步:定义 MCP 工具</h3>
<p>创建 <code>Tools/WeatherTools.cs</code>:</p>
<pre><code class="language-csharp">using System.ComponentModel;
using ModelContextProtocol.Server;


public static class WeatherTools
{
   
   
    public static IEnumerable&lt;WeatherForecast&gt; GetWeatherForecast()
    {
      var rng = new Random();
      return Enumerable.Range(1, 5).Select(index =&gt; new WeatherForecast
      {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries
      }).ToArray();
    }

   
   
    public static WeatherForecast GetWeatherByCity(
       string city)
    {
      var rng = new Random();
      return new WeatherForecast
      {
            Date = DateOnly.FromDateTime(DateTime.Now),
            TemperatureC = rng.Next(-20, 55),
            Summary = $"Weather in {city}: {Summaries}"
      };
    }

    private static readonly string[] Summaries = new[]
    {
      "Freezing", "Bracing", "Chilly", "Cool", "Mild",
      "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };
}
</code></pre>
<h3 id="第四步配置认证可选">第四步:配置认证(可选)</h3>
<p>在 <code>appsettings.json</code> 中配置:</p>
<pre><code class="language-json">{
"McpAuth": {
    "Enabled": true,
    "ValidTokens": ["your-secret-token-here"]
}
}
</code></pre>
<p>开发环境可以禁用认证(<code>appsettings.Development.json</code>):</p>
<pre><code class="language-json">{
"McpAuth": {
    "Enabled": false
}
}
</code></pre>
<h3 id="第五步运行和测试">第五步:运行和测试</h3>
<pre><code class="language-bash">dotnet run
</code></pre>
<p>应用启动后,可以访问:</p>
<ul>
<li><strong>Swagger UI</strong>: <code>http://localhost:5000/swagger</code></li>
<li><strong>WebApi</strong>: <code>http://localhost:5000/weatherforecast</code></li>
<li><strong>MCP 端点</strong>: <code>http://localhost:5000/mcp</code></li>
</ul>
<h2 id="传输模式详解">传输模式详解</h2>
<h3 id="http-模式">HTTP 模式</h3>
<p>适用于 Web 应用、Claude Desktop、远程访问等场景。</p>
<p><strong>测试示例</strong>:</p>
<pre><code class="language-bash"># 列出所有工具
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":{}
    }
}'
</code></pre>
<p><strong>Claude Desktop 配置</strong>:</p>
<p>编辑配置文件(Windows: <code>%APPDATA%\Claude\claude_desktop_config.json</code>):</p>
<pre><code class="language-json">{
"mcpServers": {
    "weather-api": {
      "url": "http://localhost:5000/mcp",
      "headers": {
      "Authorization": "Bearer your-secret-token-here"
      }
    }
}
}
</code></pre>
<h3 id="stdio-模式">Stdio 模式</h3>
<p>适用于 Kiro IDE、本地命令行工具等场景,无需网络端口。</p>
<p><strong>Kiro IDE 配置</strong>:</p>
<p>编辑 <code>.kiro/settings/mcp.json</code>:</p>
<pre><code class="language-json">{
"mcpServers": {
    "weather-api": {
      "command": "dotnet",
      "args": ["run", "--project", "path/to/NetCoreApiMcpDemo.csproj"],
      "env": {
      "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
}
}
</code></pre>
<h3 id="模式对比">模式对比</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th>HTTP 模式</th>
<th>Stdio 模式</th>
</tr>
</thead>
<tbody>
<tr>
<td>传输方式</td>
<td>HTTP POST</td>
<td>标准输入/输出</td>
</tr>
<tr>
<td>适用场景</td>
<td>Web 应用、远程访问</td>
<td>本地工具、IDE 集成</td>
</tr>
<tr>
<td>认证</td>
<td>HTTP Header</td>
<td>环境变量/配置</td>
</tr>
<tr>
<td>网络</td>
<td>需要网络端口</td>
<td>无需网络</td>
</tr>
<tr>
<td>性能</td>
<td>网络开销</td>
<td>进程间通信,更快</td>
</tr>
</tbody>
</table>
<h2 id="认证和授权">认证和授权</h2>
<h3 id="实现认证中间件">实现认证中间件</h3>
<p>创建 <code>Middleware/McpAuthenticationMiddleware.cs</code>:</p>
<pre><code class="language-csharp">public class McpAuthenticationMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IConfiguration _configuration;
    private readonly ILogger&lt;McpAuthenticationMiddleware&gt; _logger;

    public McpAuthenticationMiddleware(
      RequestDelegate next,
      IConfiguration configuration,
      ILogger&lt;McpAuthenticationMiddleware&gt; 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&lt;bool&gt;("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&lt;string[]&gt;();

      if (validTokens == null || !validTokens.Contains(token))
      {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsJsonAsync(new { error = "Invalid token" });
            return;
      }

      await _next(context);
    }
}
</code></pre>
<h3 id="安全最佳实践">安全最佳实践</h3>
<ol>
<li><strong>使用强 Token</strong>:至少 32 字符的随机字符串</li>
<li><strong>定期轮换</strong>:定期更换 Token</li>
<li><strong>使用 HTTPS</strong>:生产环境必须使用 HTTPS</li>
<li><strong>环境隔离</strong>:开发和生产使用不同的 Token</li>
<li><strong>日志安全</strong>:不要在日志中记录完整 Token</li>
</ol>
<h2 id="客户端集成示例">客户端集成示例</h2>
<h3 id="c-客户端">C# 客户端</h3>
<pre><code class="language-csharp">using ModelContextProtocol;
using ModelContextProtocol.Client;

var transport = new HttpClientTransport(new HttpClientTransportOptions
{
    BaseUrl = new Uri("http://localhost:5000/mcp"),
    Headers = new Dictionary&lt;string, string&gt;
    {
      ["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&lt;string, object?&gt;()
);
</code></pre>
<h3 id="javascriptvue-客户端">JavaScript/Vue 客户端</h3>
<pre><code class="language-vue">&lt;script setup&gt;
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 = {}) =&gt; {
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 () =&gt; {
const data = await callMcp('tools/call', {
    name: 'GetWeatherForecast',
    arguments: {},
});
weather.value = data.result.content.text;
};
&lt;/script&gt;
</code></pre>
<h2 id="mcp-tools-最佳实践">MCP Tools 最佳实践</h2>
<p>让 AI 更准确地使用你的工具是成功的关键。以下是经过实践验证的最佳实践。</p>
<h3 id="核心原则">核心原则</h3>
<p>AI 通过以下信息决定是否使用你的工具:</p>
<ol>
<li><strong>工具名称</strong> - 清晰、描述性</li>
<li><strong>Description</strong> - 详细的功能说明</li>
<li><strong>参数描述</strong> - 明确的参数用途</li>
<li><strong>使用场景</strong> - 何时应该使用这个工具</li>
</ol>
<h3 id="1-使用清晰的命名">1. 使用清晰的命名</h3>
<pre><code class="language-csharp">// ❌ 不好 - 名称模糊

public static string Get() { }

// ✅ 好 - 动词开头,描述清晰

public static string GetWeatherForecast() { }

// ✅ 更好 - 包含具体信息

public static string GetWeatherForecastForNextDays() { }
</code></pre>
<p>命名建议:</p>
<ul>
<li>使用动词开头:Get, Search, Calculate, Compare, Analyze</li>
<li>包含操作对象:Weather, Temperature, Forecast</li>
<li>避免缩写和简称</li>
<li>使用 PascalCase</li>
</ul>
<h3 id="2-编写详细的-description最重要">2. 编写详细的 Description(最重要!)</h3>
<p>这是最关键的部分!AI 主要通过 Description 判断是否使用工具。</p>
<pre><code class="language-csharp">// ❌ 不好 - 太简短


// ⚠️ 一般 - 有基本信息但不够


// ✅ 好 - 包含详细信息和使用场景
[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?'")]
</code></pre>
<p>Description 应该包含:</p>
<ol>
<li><strong>功能说明</strong> - 工具做什么</li>
<li><strong>使用场景</strong> - 何时使用("Use this tool when...")</li>
<li><strong>示例查询</strong> - 用户可能的提问方式</li>
<li><strong>支持的功能</strong> - 特殊能力或限制</li>
</ol>
<h3 id="3-详细的参数描述">3. 详细的参数描述</h3>
<pre><code class="language-csharp">
public static string GetWeatherByCity(
    // ❌ 不好
    string city,

    // ✅ 好
   
    string city,

    // ✅ 更好 - 包含默认值说明
   
    int days = 5
)
</code></pre>
<p>参数描述应该包含:</p>
<ul>
<li>参数的用途</li>
<li>支持的格式或值范围</li>
<li>示例值</li>
<li>默认值(如果有)</li>
</ul>
<h3 id="4-返回格式化易读的结果">4. 返回格式化、易读的结果</h3>
<pre><code class="language-csharp">// ❌ 不好 - 返回原始对象
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}";
}
</code></pre>
<h3 id="5-完整示例查询工具">5. 完整示例:查询工具</h3>
<pre><code class="language-csharp">
[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(
   
    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();
}
</code></pre>
<h3 id="6-完整示例比较工具">6. 完整示例:比较工具</h3>
<pre><code class="language-csharp">
[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(
    string city1,
    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 &gt; weather2.TemperatureC ? $"🔥 {city1} is warmer" : $"🔥 {city2} is warmer")}";
}
</code></pre>
<h3 id="7-description-模板">7. Description 模板</h3>
<p>基础模板:</p>
<pre><code class="language-csharp">

Use this tool when users ask about:
- [使用场景1]
- [使用场景2]
- [使用场景3]

Examples of user queries:
- '[示例问题1]'
- '[示例问题2]'
- '[示例问题3]'")]
</code></pre>
<p>完整模板:</p>
<pre><code class="language-csharp">

Use this tool when users want to:
- [使用场景1]
- [使用场景2]
- [使用场景3]

Supports:
- [支持的功能1]
- [支持的功能2]

Examples of user queries:
- '[英文示例1]'
- '[英文示例2]'
- '[中文示例1]'
- '[中文示例2]'

Note: [特殊说明或限制]")]
</code></pre>
<h3 id="8-优化检查清单">8. 优化检查清单</h3>
<p>在发布工具前,检查以下项目:</p>
<ul class="contains-task-list">
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 工具名称清晰、描述性强</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> Description 包含详细功能说明</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> Description 包含使用场景("Use this tool when...")</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> Description 包含示例查询</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 所有参数都有详细描述</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 参数描述包含示例值</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 返回值格式化、易读</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 包含错误处理</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 支持多语言(如果需要)</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 在 MCP Inspector 中测试通过</label></li>
<li class="task-list-item"><input class="task-list-item-checkbox" disabled="" type="checkbox"><label> 在 AI 客户端中测试通过</label></li>
</ul>
<h2 id="高级特性">高级特性</h2>
<h3 id="依赖注入支持">依赖注入支持</h3>
<p>工具方法可以注入服务:</p>
<pre><code class="language-csharp">

public static string GetWeatherWithLogging(
    ILogger&lt;WeatherTools&gt; logger,
    IWeatherService weatherService,
    string city)
{
    logger.LogInformation("Getting weather for {City}", city);
    return weatherService.GetWeather(city);
}
</code></pre>
<h3 id="添加-prompts">添加 Prompts</h3>
<pre><code class="language-csharp">
public static class WeatherPrompts
{
   
   
    public static ChatMessage PlanOutdoorActivity(
       string city,
       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."
      );
    }
}
</code></pre>
<h3 id="复杂参数类型">复杂参数类型</h3>
<p>SDK 自动支持:</p>
<ul>
<li>基本类型:<code>string</code>, <code>int</code>, <code>bool</code>, <code>double</code> 等</li>
<li>复杂对象:自动序列化/反序列化</li>
<li>可选参数:使用默认值</li>
<li>数组和集合</li>
</ul>
<h2 id="故障排除">故障排除</h2>
<h3 id="工具未被发现">工具未被发现</h3>
<p>检查项:</p>
<ul>
<li>类是否有 <code></code> 特性</li>
<li>方法是否有 <code></code> 特性</li>
<li>类是否是静态的</li>
<li>是否重启了应用</li>
</ul>
<h3 id="认证失败">认证失败</h3>
<p>检查项:</p>
<ul>
<li>Token 是否正确</li>
<li><code>appsettings.json</code> 中 <code>Enabled</code> 设置</li>
<li>Authorization header 格式</li>
<li>环境配置(Development vs Production)</li>
</ul>
<h3 id="cors-问题">CORS 问题</h3>
<p>在 <code>Program.cs</code> 中添加 CORS 支持:</p>
<pre><code class="language-csharp">builder.Services.AddCors(options =&gt;
{
    options.AddPolicy("AllowMcpClients", policy =&gt;
    {
      policy.WithOrigins("http://localhost:3000")
            .AllowAnyHeader()
            .AllowAnyMethod();
    });
});

app.UseCors("AllowMcpClients");
</code></pre>
<h2 id="项目结构">项目结构</h2>
<pre><code>NetCoreApiMcpDemo/
├── Controllers/
│   └── WeatherForecastController.cs# 标准 WebApi 控制器
├── Tools/
│   └── WeatherTools.cs                # MCP 工具定义
├── Middleware/
│   └── McpAuthenticationMiddleware.cs # 认证中间件
├── Program.cs                        # 应用配置
├── appsettings.json                  # 配置文件
└── appsettings.Development.json      # 开发配置
</code></pre>
<h2 id="为什么选择官方-sdk">为什么选择官方 SDK?</h2>
<ol>
<li><strong>代码更少</strong>:无需自定义特性和提供者</li>
<li><strong>更可靠</strong>:官方维护和更新</li>
<li><strong>更强大</strong>:自动 Schema、DI 支持</li>
<li><strong>更标准</strong>:完全符合 MCP 规范</li>
<li><strong>更易维护</strong>:无需维护自定义代码</li>
</ol>
<h2 id="总结">总结</h2>
<p>通过本文,我们学习了如何在 ASP.NET Core WebApi 中集成 MCP 协议支持。使用官方 SDK,只需几行代码就能让你的 API 被 AI 客户端调用。MCP 协议的标准化特性,让 AI 应用与后端服务的集成变得前所未有的简单。</p>
<h2 id="参考资源">参考资源</h2>
<ul>
<li>MCP 官方文档</li>
<li>MCP C# SDK</li>
<li>MCP 规范</li>
<li>NuGet 包</li>
</ul>
<h2 id="源码地址">源码地址</h2>
<p>完整示例代码请访问:</p>
<hr>
<p>如果本文对你有帮助,欢迎点赞、收藏、关注!有任何问题欢迎在评论区讨论。</p>


</div>
<div id="MySignature" role="contentinfo">
    <img src="https://img2024.cnblogs.com/blog/608935/202603/608935-20260307155328237-1969575696.png"/><br><br>
来源:https://www.cnblogs.com/saodiseng2015/p/19172165
頁: [1]
查看完整版本: ASP.NET Core WebApi 集成 MCP 协议完全指南