在上一篇文章.NET 創建MCP使用大模型對話-CSDN博客中,我們簡述了如何使用mcp client使用StdIo模式調用本地mcp server。本次實例將會展示如何使用mcp client模式調用遠程mcp server。
一:創建mcp server
我們創建一個天氣服務。
?新建WebApi項目,選擇.NET9框架,名稱叫做MCPWebAPI。
添加ModelContextProtocol引用,注意當前是preview版本,需要勾選包含發行版才能搜到。
添加ModelContextProtocol.AspNetCore引用,?注意當前是preview版本。
1:在默認生成的Program.cs文件中,注入AddMcpServer和啟用Mcp路由,如下圖:
using ModelContextProtocol.AspNetCore;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();
builder.Services.AddOpenApi();//注冊MCPServer,并從當前程序集加載Tool <新增代碼>
builder.Services.AddMcpServer().WithToolsFromAssembly();var app = builder.Build();if (app.Environment.IsDevelopment())
{app.MapOpenApi();
}app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();//注冊MCPServer的路由 <新增代碼>
app.MapMcp();app.Run();
2:新增天氣Tool。代碼和上篇文章一直,不再贅述。
using ModelContextProtocol.Server;
using System.ComponentModel;namespace MCPWebAPI.Tools
{[McpServerToolType]public class WeatherTool{[McpServerTool(Name = "Get City Weather"), Description("獲取指定城市的天氣,返回temperature溫度和weather天氣情況組成的json信息。")]public static string GetCurrentWeather([Description("城市名稱")] string city){//隨機溫度var temperature = new Random().Next(-20, 50);//天氣組var weatherList = new string[] { "晴", "多云", "大雨", "小雨", "大雪" };//隨機天氣var weather = weatherList[new Random(Guid.NewGuid().GetHashCode()).Next(0, weatherList.Length - 1)];//模仿json格式返回return "{\"temperature\":" + temperature + ",\"weather\":\"" + weather + "\"}";}}
}
3:運行程序,不報錯即為成功。
[可選]調試工具:
首先,啟動WebApi項目 ,本地端口:5251
在控制臺運行 npx @modelcontextprotocol/inspector 命令
按提示打開http://127.0.0.1:6274/網頁,選擇sse模式,填寫WebApi項目啟動地址+/sse后綴:http://localhost:5251/sse,點擊鏈接即可。
注:如遇報錯 ReferenceError: fetch is not defined ,請升級你的node.js版本,確保高于V18.0。
二:創建 mcp client
流程和上個文章差不多,新建控制臺項目,選擇.NET9框架,名稱叫做MCPClient。
添加ModelContextProtocol引用。
1. 注冊Client
McpClientOptions options = new()
{ClientInfo = new() { Name = "Weather Client", Version = "1.0.0" }
};//1:注冊MCPServer,以項目中引用為例。//上一篇以stdio方式運行MCPServer
/*var config = new McpServerConfig
{Id = "weather",Name = "Weather MCP Server",TransportType = TransportTypes.StdIo,TransportOptions = new Dictionary<string, string>{//運行MCPServer["command"] = "dotnet",["arguments"] = "run --project ../../../../MCPServer --no-build",}
};*///本次以SSE遠程方式連接MCPWebAPI
var config = new McpServerConfig
{Id = "weather",Name = "Weather MCP Server",TransportType = TransportTypes.Sse,Location = "http://127.0.0.1:5251/sse",
};
最大的區別就是使用TransportTypes.Sse模式通訊,并增加Location調用地址。
其他代碼不變。列出Client所有代碼:
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Client;
using ModelContextProtocol.Configuration;
using ModelContextProtocol.Protocol.Transport;
using OpenAI;Console.WriteLine($"程序啟動中,請稍后");McpClientOptions options = new()
{ClientInfo = new() { Name = "Weather Client", Version = "1.0.0" }
};//1:注冊MCPServer,以項目中引用為例。//SSE遠程方式連接MCPWebAPI
var config = new McpServerConfig
{Id = "weather",Name = "Weather MCP Server",TransportType = TransportTypes.Sse,Location = "http://127.0.0.1:5251/sse",
};using var factory =LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Trace));//2:創建MCPClient
await using var mcpClient = await McpClientFactory.CreateAsync(config, options);//3:發現MCPServer中的Tool
var mcpTools = await mcpClient.ListToolsAsync();
foreach (var tool in mcpTools)
{Console.WriteLine($"{tool.Name} ({tool.Description})");
}Console.WriteLine("---------- Tools");
Console.WriteLine();//4:注冊大模型//注冊方式1,使用本地模型。以本地使用Ollama啟動的千問32b模型為例
//var openClient = new OllamaChatClient(new Uri("http://localhost:11434/"), "qwq:32b");//注冊方式2,使用遠程模型。以阿里云百煉平臺為例
var oclinet = new OpenAIClient(new System.ClientModel.ApiKeyCredential("密鑰"), new OpenAIClientOptions
{Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1")
});
//模型名稱
var openClient = new OpenAIChatClient(oclinet, "qwen-max");//測試模型,使用流式輸出。
var res = openClient.GetStreamingResponseAsync("你好");
await foreach (var message in res)
{Console.Write(message);
}
Console.WriteLine();Console.WriteLine("-------------llm test");
Console.WriteLine();//5:創建Chat客戶端
var client = new ChatClientBuilder(openClient)//添加日志.UseLogging(factory)//向聊天客戶端添加函數調用.UseFunctionInvocation().Build();//6:執行對話
var msg = "";while (true)
{Console.WriteLine();Console.WriteLine("這里是天氣服務,你想咨詢哪里的天氣?");msg = Console.ReadLine();if (msg == "exit"){Console.WriteLine("程序退出");return;}IList<ChatMessage> messages =[//為ai設定身份new(ChatRole.System, """你是一個天氣助理,在輸出天氣時,請以家長口吻叮囑用戶添衣、帶傘等。"""),new(ChatRole.User, msg)];//區別于GetStreamingResponseAsync,此處示例非流式輸出//注意,某些大模型要求流水輸出,只能使用GetStreamingResponseAsync方式。var response =await client.GetResponseAsync(messages,new ChatOptions { Tools = [.. mcpTools] });Console.WriteLine(response);}
代碼倉庫:https://github.com/zhanglilong23/mcpdemo.git