Semantic Kernel也能充當MCP Client

背景

筆者之前,分別寫過兩篇關于Semantic Kernel(下簡稱SK)相關的博客,最近模型上下文協議(下稱MCP)大火,實際上了解過SK的小伙伴,一看到 MCP的一些具體呈現,會發現,Client 調用 Server的方式,和SK調用插件的過程很像,實際操作了一下,發現確實是可以的。

也就是說,如果我們之前的項目里用到SK做過Agent相關的模塊,如今也可以絲滑的讓其充當MCP Client的角色,去使用更多MCP生態的東西,而不需要做更多的改動。

雖然SK是為AI Agent的發展而誕生的,但好框架就是好框架,沒想到它和MCP也這么契合。

本篇,建立在《再嘗Semantic Kernel,Planning特性很香》的基礎上,再次擴展一下MCP相關的介紹。

注意:本篇不會深入介紹MCP相關的概念,架構等等前置內容,主要還是通過案例說明SK和MCP
Server之間的聯系,建議不熟悉MCP相關內容的小伙伴,先登錄MCP官網進行了解。

創建一個MCP Server

在MCP的官方介紹文檔里已經有C#的官方SDK了,這里我們參照它官方的例子,先來一個MCP Server。

Tips:官方的案例已經非常簡潔和完善了,建議沒搞過MCP的小伙伴上手試一下,雖然案例很簡單,一看就能明白,但那真正跑通的獲得感,還是得自己動手試一下才能體會到。

構建服務

這一步我覺得大家還是直接看官方文檔更清楚,我這里不在贅述

傳送門👉:https://modelcontextprotocol.io/quickstart/server#building-your-server-5

需要注意的是,我這里的Server是使用SSE的傳輸方式。

目前SSE的方式官方已經聲明會逐步被Streamable Http的形式替代,但目前還是Built-in狀態,本地調試的話還可以使用stdio的方式,這也是Claude Desktop,Cline之類客戶端工具支持的方式,這點大家按需設定即可,這部分內容可以參考這里👉:https://mcp-framework.com/docs/Transports/transports-overview。

編寫Tool

定義一個class,然后標記上MCPServer的特定屬性,這部分官網也有介紹,我就直接上代碼了

[McpServerToolType]
public static class WeatherTools
{[McpServerTool(Name = "GetWeather"), Description("獲取當前城市的天氣")]public static async Task<string> GetWeather(HttpClient client,[Description("中國的城市編碼adcode")] string adcode){if (string.IsNullOrEmpty(adcode)){return "adcode不能為空";}string gdKey = ConfigHelper.GetAppSetting("GaoDeKey");var jsonElement = await client.GetFromJsonAsync<JsonElement>($"/v3/weather/weatherInfo?key={gdKey}&city={adcode}&extensions=base");var lives = jsonElement.GetProperty("lives").EnumerateArray();if (!lives.Any()){return "當前城市天氣獲取失敗";}return string.Join("\n--\n",lives.Select(live =>{var city =  $"{live.GetProperty("province").GetString()}--{live.GetProperty("city").GetString()}";var weather = live.GetProperty("weather").GetString();var temperature = live.GetProperty("temperature").GetString();var windPower = live.GetProperty("windpower").GetString();var humidity = live.GetProperty("humidity").GetString();return $"城市:{city}\n天氣:{weather}\n溫度:{temperature}°C\n風力:{windPower}級\n濕度:{humidity}%";}));}
}

我這里,沒有使用官方案例里的天氣接口,而是改成了高德的天氣接口,因為一會兒還要演示一下SK調用MCP Server的能力,除了調用本地的Server,高德還有一個云端的MCP Server,非常好用,稍后一并介紹一下,正好就連天氣接口也改成高德的。

編寫完成后,啟動我們的Server服務。

dotnet run

驗證

Tool編寫完成后,可以先使用一些軟件或者工具類的MCP Client驗證一下,開發階段,這些工具還是非常有必要的,它的角色定位就像我們用到的數據庫管理工具,比如SSMS,Pg Admin,DBeaver等。

我這里使用的是官方的MCP Inspector,本地只要有node和npx環境即可。

另外,因為要經常測試一些Server,建議把Python和Python包管理工具uv也安裝一下。

然后,我們啟動Inspector

npx @modelcontextprotocol/inspector node build/index.js

在這里插入圖片描述

啟動之后,控制臺會監聽一個端口,然后在瀏覽器打開,然后配置好我們的Server地址,如下圖

獲取到所有的Tool之后,測試驗證一下我們剛完成的天氣接口是否生效。

至此,驗證工作完成,說明我們的MCP Server是可以正常工作的,接下來就是接入實際的業務系統,來調用這個Server提供的能力了。

在業務系統創建MCP Client

注入SK服務

這部分略過,在前面的系列文章里已經寫過了,或者大家也可以直接查看微軟的官方文檔,這里不再贅述。

編寫插件

這里呢,因為我在之前的項目里,已經開始使用SK框架了,并且完成了部分的Agent功能,都是以Plugin的方式注入到系統里的,這里的演示也就暫時以這種方式來接入,后續再根據實際情況調整。

插件的代碼如下

[KernelFunction("call_weather_api")]
[Description("通過地理編碼,獲取天氣信息")]
[return: Description("如果運行正常,返回編號所屬地址的天氣詳情")]
public async Task<string> CallWeatherApi(string adcode)
{Logger.Debug("--------天氣插件正確執行---------------");var defaultOptions = new McpClientOptions{ClientInfo = new() { Name = "SK", Version = "1.0.0" }};var defaultConfig = new SseClientTransportOptions{Endpoint = new Uri($"http://localhost:5001/sse"),Name = "Magic.Services.MCPServer",};await using var client = await McpClientFactory.CreateAsync(new SseClientTransport(defaultConfig),defaultOptions);var result = await client.CallToolAsync("GetWeather", new Dictionary<string, object?>{{ "adcode",adcode}});return JsonHelper.JsonSerialize(result);
}

調用

我這里是在Web系統里進行的演示,所以以接口形式來調用插件,代碼如下

public async Task<IActionResult> CallLocalServer(string adcode)
{_kernel.Plugins.AddFromType<LocalServer>("LocalServer", _serviceProvider);// 獲取聊天完成服務var chatCompletionService = _kernel.GetRequiredService<IChatCompletionService>();// 啟用自動函數調用OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new(){ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,//FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()};PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };ChatHistory chatHistory = [];chatHistory.AddSystemMessage($"你是一個天氣預報員,本函數的入參會給你一個中國地理位置編碼,你要調用合適的MCP Server來完成天氣預報。");chatHistory.AddUserMessage($"查詢地理編碼為【{adcode}】的地點天氣");var chatResult = await chatCompletionService.GetChatMessageContentAsync(chatHistory,openAIPromptExecutionSettings,_kernel);Console.Write($"\nAssistant : {chatResult}\n");return Json(chatResult);
}

驗證

為了方便驗證,可以先把接口的訪問等級降低,直接通過URL地址訪問,效果如下

控制臺打印的信息如下

至此,我們已經在本地創建了一個MCPServer,并通過MCP Inspector進行了驗證,同時又在原有使用SK的系統里,通過SK成功調用了這個Server提供的tool,接入復雜度可以接受,效果也非常不錯。

接下來,再試試SK能不能成功調用高德地圖的MCP Server

調用高德MCP Server

前置工作

注意,如果前面的天氣接口你是使用的高德的服務,那么相信你已經注冊了高德的key,如果沒有,這里需要去注冊一下。

編寫服務

由于調用的是第三方的MCP,我們這里可以直接在接口或者服務類里編寫調用代碼

public async Task<IActionResult> CallGaodeServer(string msg)
{// 第一步:創建 mcp 客戶端var defaultOptions = new McpClientOptions{ClientInfo = new() { Name = "地圖規劃", Version = "1.0.0" }};var defaultConfig = new SseClientTransportOptions{Endpoint = new Uri(ConfigurationHelper.GetSectionValue("GaodeMCP")),Name = "Magic.Services.MCPServer",};await using var client = await McpClientFactory.CreateAsync(new SseClientTransport(defaultConfig),defaultOptions);var tools = await client.ListToolsAsync();foreach (var tool in tools){Logger.Debug($"秀一下高德的能力之--- {tool.Name}");}#pragma warning disable SKEXP0001_kernel.Plugins.AddFromFunctions("gaodemap", tools.Select(aiFunction => aiFunction.AsKernelFunction()));#pragma warning restore SKEXP0001// 獲取聊天完成服務var chatCompletionService = _kernel.GetRequiredService<IChatCompletionService>();// 啟用自動函數調用OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new(){ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,};PromptExecutionSettings settings = new() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };ChatHistory chatHistory = [];chatHistory.AddUserMessage(msg);var chatResult = await chatCompletionService.GetChatMessageContentAsync(chatHistory,openAIPromptExecutionSettings,_kernel);Console.Write($"\nAssistant : {chatResult}\n");return Json(chatResult);
}

驗證

驗證工作,還是和前面一樣,暫時在瀏覽器里直接訪問即可。

控制臺打印的信息更友好一點

結束語

好了,至此,我們成功在原有的系統上,使用SK框架充當MCP Client的角色,完成了本地MCP Server的調用和第三方MCP Server的調用目標。

最后,再推薦幾個介紹MCP的參考站點

  • 中文官網:https://mcp-docs.cn/
  • MCP.so:https://mcp.so/zh
  • 癡者工良的博客:https://www.cnblogs.com/whuanle/p/18837493
  • Semantic Kernel的學習文檔:https://learn.microsoft.com/zh-cn/semantic-kernel/
  • 本人 之前寫的兩篇介紹SK的博客,本文的代碼部分缺失很多初始化的代碼,均在這兩篇當中https://juejin.cn/post/7460393309552164902,https://juejin.cn/post/7463301527991762955

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77112.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77112.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77112.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

識別圖片內容OCR并重命名文件

在工作場景中&#xff0c;經常出現通過拍攝設備獲取圖片后&#xff0c;未及時進行有效命名的情況。這些圖片中往往包含關鍵信息&#xff08;如合同編號、產品型號、日期等&#xff09;&#xff0c;需要人工識別并命名&#xff0c;存在以下痛點&#xff1a; 效率低下&#xff1…

【防火墻 pfsense】3 portal

&#xff08;1&#xff09;應該考慮的問題&#xff1a; ->HTTPS 連接的干擾問題&#xff1a;HTTPS 是一種旨在防止惡意第三方截取和篡改流量的協議。但強制門戶的工作原理是截取并改變終端用戶與網絡之間的連接。這對于 HTTP 流量來說不是問題&#xff0c;但使用 HTTPS 加密…

銀發科技:AI健康小屋如何破解老齡化困局

隨著全球人口老齡化程度的不斷加深&#xff0c;如何保障老年人的健康、提升他們的生活質量&#xff0c;成為了社會各界關注的焦點。 在這場應對老齡化挑戰的戰役中&#xff0c;智紳科技順勢而生&#xff0c;七彩喜智慧養老系統構筑居家養老安全網。 而AI健康小屋作為一項創新…

TCP協議理解

文章目錄 TCP協議理解理論基礎TCP首部結構圖示字段逐項解析 TCP是面向連接&#xff08;Connection-Oriented&#xff09;面向連接的核心表現TCP 面向連接的核心特性TCP 與UDP對比 TCP是一個可靠的(reliable)序號與確認機制&#xff08;Sequencing & Acknowledgment&#xf…

什么是機器視覺3D碰撞檢測?機器視覺3D碰撞檢測是機器視覺3D智能系統中安全運行的核心技術之一

機器視覺3D碰撞檢測是一種結合計算機視覺和三維空間分析的技術,旨在檢測三維場景中物體之間是否發生碰撞(即物理接觸或交疊)。它通過分析物體的形狀、位置、運動軌跡等信息,預測或實時判斷物體間的碰撞可能性。以下是其核心要點: 基本原理 三維感知:利用深度相機(如RGB-…

nacos設置權重進行負載均衡不生效

nacos設置權重進行負載均衡不生效&#xff0c;必須在啟動類下加上這個bean Beanpublic IRule nacosRule(){return new NacosRule();}如下圖所示

創建 Node.js Playwright 項目:從零開始搭建自動化測試環境

一、環境準備 在開始創建 Playwright 項目之前&#xff0c;確保你的電腦上已經安裝了以下工具&#xff1a; Node.js&#xff1a;Playwright 依賴于 Node.js 環境&#xff0c;確保你已經安裝了最新版本的 Node.js。可以通過以下命令檢查是否安裝成功&#xff1a; node -v npm -…

日語學習-日語知識點小記-構建基礎-JLPT-N4階段(11): てあります。

日語學習-日語知識點小記-構建基礎-JLPT-N4階段&#xff08;11&#xff09;&#xff1a; てあります。 1、前言&#xff08;1&#xff09;情況說明&#xff08;2&#xff09;工程師的信仰 2、知識點&#xff08;1&#xff09;てあります。&#xff08;&#xff12;&#xff09;…

【金倉數據庫征文】- 深耕國產數據庫優化,筑牢用戶體驗新高度

目錄 引言 一、性能優化&#xff1a;突破數據處理極限&#xff0c;提升運行效率 1.1 智能查詢優化器&#xff1a;精準優化數據檢索路徑 1.2 并行處理技術&#xff1a;充分釋放多核計算潛力 1.3 智能緩存機制&#xff1a;加速數據訪問速度 二、穩定性提升&#xff1a;筑牢…

Java代理講解

代理 代理模式是一種結構型設計模式&#xff0c;它允許我們通過添加一個代理對象來控制對另一個對象的訪問。代理對象和實際對象具有相同的接口&#xff0c;使得客戶端在不知情的情況下可以使用代理對象進行操作。代理對象在與客戶端進行交互時&#xff0c;可以控制對實際對象…

利用deepseek快速生成甘特圖

一、什么是甘特圖 甘特圖&#xff08;Gantt Chart&#xff09;是一種直觀的項目管理工具&#xff0c;廣泛應用于多個領域&#xff0c;主要用于??時間規劃、任務分配和進度跟蹤??。 直觀性??&#xff1a;時間軸清晰展示任務重疊或延遲。 ??靈活性??&#xff1a;支持…

從零開始學習SLAM|技術路線

概念 視覺SLAM&#xff08;Simultaneous Localization and Mapping&#xff09;系統中&#xff0c;整個過程通常分為 前端 和 后端 兩個主要部分。前端處理的是從傳感器數據&#xff08;如相機圖像、激光雷達等&#xff09;中提取和處理信息&#xff0c;用于實時定位和建圖&am…

LeetCode 解題思路 44(Hot 100)

解題思路&#xff1a; dp 數組的含義&#xff1a; 以 nums[i] 為結尾的最長遞增子序列的長度。遞推公式&#xff1a; dp[i] Math.max(dp[i], dp[j] 1)。dp 數組初始化&#xff1a; dp[i] 1。遍歷順序&#xff1a; 從小到大去遍歷&#xff0c;從 i 1 開始&#xff0c;直到 …

精益數據分析(22/126):解鎖創業增長密碼與長漏斗分析

精益數據分析&#xff08;22/126&#xff09;&#xff1a;解鎖創業增長密碼與長漏斗分析 在創業與數據分析的探索旅程中&#xff0c;我們都在不斷尋求新的知識和方法&#xff0c;以提升創業的成功率。我一直期望能和大家共同學習、共同進步&#xff0c;今天就讓我們繼續深入研…

大模型應用開發之LLM入門

一、大模型概述 1、大模型概念 LLM是指用有大量參數的大型預訓練語言模型&#xff0c;在解決各種自然語言處理任務方面表現出強大的能力&#xff0c;甚至可以展現出一些小規模語言模型所不具備的特殊能力 2、語言模型language model 語言建模旨在對詞序列的生成概率進行建模…

Vue 計算屬性 VS 偵聽器:從原理到性能的深度對比

在 Vue 開發中&#xff0c;computed&#xff08;計算屬性&#xff09;和watch&#xff08;偵聽器&#xff09;是響應式系統的兩大核心工具。 它們看似都能處理數據變化&#xff0c;實則設計理念和應用場景大相徑庭。 一、核心區別&#xff1a;數據驅動的兩種范式 1. 觸發機制…

特斯拉宣布啟動自動駕駛網約車測試,無人出租車服務進入最后準備階段

特斯拉公司于4月24日正式宣布&#xff0c;已在美國得克薩斯州奧斯汀和加利福尼亞州舊金山灣區啟動自動駕駛網約車服務的員工內部測試。這項測試將為今年夏季計劃推出的完全無人駕駛出租車服務進行最后的驗證和準備。 此次測試使用約200輛經過特殊改裝的Model 3車型&#xff0c;…

基于springboot的在線教育系統

一、系統架構 前端&#xff1a;vue | element-ui | html | jquery | css | ajax 后端&#xff1a;springboot | mybatis 環境&#xff1a;jdk1.8 | mysql | maven | nodejs | idea 二、代碼及數據 三、功能介紹 01. web端-首頁1 02. web端-首頁2 03. w…

文檔編輯:reStructuredText全面使用指南 — 第四部分 高級主題

文檔編輯&#xff1a;reStructuredText全面使用指南 — 第四部分 高級主題 reStructuredText&#xff08;簡稱RST或ReST&#xff09;是一種輕量級的標記語言&#xff0c;用于編寫結構化的文檔。它由Python社區開發&#xff0c;并廣泛應用于技術文檔、書籍、博客文章等。reStruc…

git Http改用戶下載

用原先別人賬號,無權下更新 http方式設置自己賬號 例如 git fetch --all 提示沒有權限從 http://192.168.1.2/gitlab/項目路徑.git下載 git remote set-url origin http://your-username192.168.1.2/gitlab/項目路徑.git your-username修改成自己的git賬號 需要輸入一個Tok…