Agents-SDK智能體開發[4]之集成MCP入門

文章目錄

  • 說明
  • 一 Agents SDK接入MCP
    • 1.1 MCP技術回顧
    • 1.2 MCP基礎實踐流程
      • 1.2.1 天氣查詢服務器Server創建流程
      • 1.2.2 服務器依賴安裝和代碼編寫
      • 1.2.3 環境配置文件
      • 1.2.4 客戶端代碼編寫
    • 1.3 測試運行
  • 二 MCP+Agents SDK基礎調用
    • 2.1 weather_server.py
    • 2.2 client_agent.py
    • 2.3 運行測試

說明

  • 本文學自賦范社區公開課,僅供學習和交流使用,不用作任何商業用途!

一 Agents SDK接入MCP

1.1 MCP技術回顧

  • 開篇:MCP理論理解和學習
  • 啟程:MCP開發環境配置和旅游攻略案例體驗
  • https://yuanyou.blog.csdn.net/article/details/148222368

1.2 MCP基礎實踐流程

  • 先嘗試手動實現一遍MCP實踐流程,再考慮將已經部署好的server帶入Agents SDK中,作為tools進行調用。
  • 一個極簡的天氣查詢MCP基本執行流程:
    在這里插入圖片描述

1.2.1 天氣查詢服務器Server創建流程

  • 創建一個天氣查詢的服務器,通過openweather,創建一個能夠實時查詢天氣的服務器(server)。
    curl -s "https://api.openweathermap.org/data/2.5/weather?q=Beijing&units=metric&appid=xxx"
    
  • 執行結果:
    {"coord": {"lon": 116.3972,"lat": 39.9075},"weather": [{"id": 804,"main": "Clouds","description": "陰,多云","icon": "04n"}],"base": "stations","main": {"temp": 22.36,"feels_like": 22.77,"temp_min": 22.36,"temp_max": 22.36,"pressure": 1007,"humidity": 81,"sea_level": 1007,"grnd_level": 1002},"visibility": 10000,"wind": {"speed": 1.42,"deg": 26,"gust": 3.23},"clouds": {"all": 100},"dt": 1753014180,"sys": {"country": "CN","sunrise": 1752958921,"sunset": 1753011546},"timezone": 28800,"id": 1816670,"name": "Beijing","cod": 200
    }
    

1.2.2 服務器依賴安裝和代碼編寫

  1. 創建項目目錄,創建并激活虛擬環境。
    uv init mcp-weather
    cd mcp-weather
    uv venv
    .venv\Scripts\activate
    
  2. 在當前虛擬環境中添加如下依賴:
    pip install mcp httpx openai python-dotenv pypinyin openai-agents
    
  3. 創建server服務器代碼文件server.py
    import json
    import httpx
    from typing import Any
    from mcp.server.fastmcp import FastMCP# 初始化mcp服務器
    mcp=FastMCP("WeatherServer")#OpenWeather API 配置
    OPENWEATHER_API_BASE = "https://api.openweathermap.org/data/2.5/weather"
    API_KEY ="xxx"
    USER_AGENT = "weather-app/1.0"async def fetch_weather(city: str) -> dict[str, Any]|None:"""獲取天氣信息"""params={"q": city,"appid": API_KEY,"units": "metric","lang": "zh_cn"}headers={"User-Agent": USER_AGENT}async with httpx.AsyncClient() as client:response = await client.get(OPENWEATHER_API_BASE, params=params, headers=headers,timeout=1000)if response.status_code == 200:return response.json()else:return Nonedef format_weather(data: dict[str,Any] | str)->str:"""解析天氣數據字典,提取關鍵信息并格式化輸出。功能:對可能缺失的嵌套數據字段進行容錯處理,確保返回內容完整。參數:data: 天氣API返回的原始數據字典返回:格式化后的天氣信息字符串"""# 基礎位置信息(城市、國家)- 缺失時顯示"未知"city = data.get("name", "未知")  # 城市名稱(頂層字段)country = data.get("sys", {}).get("country", "未知")  # 國家代碼(嵌套在sys字段中)# 天氣核心指標 - 缺失時顯示"N/A"(Not Available)main_data = data.get("main", {})  # 提取main字段(包含溫度、濕度等)temperature = main_data.get("temp", "N/A")  # 溫度humidity = main_data.get("humidity", "N/A")  # 濕度wind_data = data.get("wind", {})  # 提取wind字段(包含風速等)wind_speed = wind_data.get("speed", "N/A")  # 風速# 天氣描述 - weather字段可能為空列表,默認返回第一個元素的描述weather_list = data.get("weather", [{}])  # 提取weather數組(默認空字典避免索引錯誤)weather_description = weather_list[0].get("description", "未知")  # 天氣狀況描述# 格式化輸出字符串(使用f-string拼接,添加emoji直觀展示)weather_info = (f"🌍 {city}, {country}\n"f"🌡? 溫度:{temperature}℃\n"f"💧 濕度:{humidity}%\n"f"💨 風速:{wind_speed} m/s\n"f"?? 天氣:{weather_description}\n")return weather_info@mcp.tool()
    async def query_weather(city: str) -> str:"""查詢天氣信息并返回結果"""weather_data = await fetch_weather(city)if weather_data:return format_weather(weather_data)else:return "無法獲取天氣信息。請檢查城市名稱是否正確。"if __name__=="__main__":mcp.run(transport='stdio')
    

1.2.3 環境配置文件

  • 創建.env文件
BASE_URL="https://api.siliconflow.cn/v1/chat/completions"
MODEL=deepseek-ai/DeepSeek-V3
OPENAI_API_KEY="sk-xxx"

1.2.4 客戶端代碼編寫

  • 創建一個可以和server進行通信的客戶端,需要注意的是,該客戶端需要包含大模型調用的基礎信息。我們需要編寫一個client.py腳本。
    import asyncio
    import os
    import json
    import sys
    from typing import Optional
    from  contextlib import AsyncExitStack
    from openai.types.chat import ChatCompletionToolParam
    from openai import OpenAI
    from dotenv import load_dotenvfrom mcp import ClientSession,StdioServerParameters
    from mcp.client.stdio import stdio_clientfrom pypinyin import lazy_pinyin, Style# 加載env文件,確保配置正確
    load_dotenv()class MCPClient:def __init__(self):"""初始化MCP客戶端"""self.write = Noneself.stdio = Noneself.exit_stack = AsyncExitStack()self.base_url=os.getenv("BASE_URL")self.model = os.getenv("MODEL")self.openai_api_key = os.getenv("OPENAI_API_KEY")if not self.openai_api_key:raise ValueError("OPENAI_API_KEY未設置")self.client=OpenAI(api_key=self.openai_api_key, base_url=self.base_url)self.session: Optional[ClientSession] = Noneself.exit_stack=AsyncExitStack()async def connect_to_server(self, server_script_path:str):"""連接MCP服務器并列出可用工具"""is_python=server_script_path.endswith(".py")is_js=server_script_path.endswith(".js")if not (is_python or is_js):raise ValueError("服務器腳本必須以.py或.js結尾")command="python" if is_python else "node"server_params=StdioServerParameters(command=command,args=[server_script_path],env=None)# 啟動MCP服務器并建立通信stdio_transport=await self.exit_stack.enter_async_context(stdio_client(server_params))self.stdio,self.write=stdio_transportself.session= await self.exit_stack.enter_async_context(ClientSession(self.stdio,self.write))await self.session.initialize()# 列出MCP服務器上的工具response=await self.session.list_tools()tools=response.toolsprint("\n已連接到服務器,支持以下工具:",[tool.name for tool in tools])async def process_query(self, query:str)-> str:"""使用大模型處理查詢并調用可用的MCP工具(Function Calling)"""messages=[{"role": "user","content": query}]response=await self.session.list_tools()available_tools = [ChatCompletionToolParam(type="function",function={"name": tool.name,"description": tool.description,"parameters": tool.inputSchema})for tool in response.tools]response= self.client.chat.completions.create(model=self.model,messages=messages,tools=available_tools)# 處理返回的內容content=response.choices[0]# 檢查是否使用了工具if content.finish_reason == "tool_calls":# 何時需要使用工具就解析工具tool_call = content.message.tool_calls[0]tool_name=tool_call.function.nametool_args=json.loads(tool_call.function.arguments)# 如果調用的是 query_weather 工具,處理城市名稱if tool_name == "query_weather" and "city" in tool_args:city = tool_args["city"]# 簡單判斷是否為中文城市名if any('\u4e00' <= c <= '\u9fff' for c in city):# 轉換為拼音,首字母大寫pinyin_city = ''.join([word.capitalize() for word in lazy_pinyin(city)])tool_args["city"] = pinyin_city# 執行工具result=await self.session.call_tool(tool_name, tool_args)print(f"\n\n[Calling Tool: {tool_name} with args: {tool_args}]")# 將工具調用和結果添加到消息歷史中messages.append(content.message.model_dump())messages.append({"role": "tool","content": result.content[0].text,"tool_call_id": tool_call.id})# 將上面的結果再返回給大模型用于最終的效果response=self.client.chat.completions.create(model=self.model,messages=messages)return response.choices[0].message.content# 如果調用工具直接返回結果return content.message.contentasync def chat_loop(self):"""運行交互式聊天循環"""print("\nMCP客戶端已啟動!輸入'quit'退出")while True:try:query=input("\n you:").strip()if query.lower() == "quit":breakresponse=await self.process_query(query)print(f"\n ai: {response}")except Exception as e:print(f"\n Error: {e}")async def cleanup(self):"""清理資源"""await self.exit_stack.aclose()async def main():if len(sys.argv)<2:print("Usage: python client.py <server_address>")sys.exit(1)client=MCPClient()try:await client.connect_to_server(sys.argv[1])await client.chat_loop()finally:await client.cleanup()if __name__ == "__main__":asyncio.run(main())
    

1.3 測試運行

  1. 進入項目目錄,激活虛擬環境

    cd ./mcp-weather
    source .venv/bin/activate
    
  2. 運行MCP客戶端和服務器

    uv run client.py server.py
    
    (mcp-weather) D:\Code\mcp-study\mcp-weather>uv run client.py server.py已連接到服務器,支持以下工具: ['query_weather']MCP客戶端已啟動!輸入'quit'退出you:請問北京今天天氣如何?[Calling Tool: query_weather with args: {'city': 'BeiJing'}]ai: 北京今天的天氣情況如下:🌍 **北京,中國**
    🌡? **溫度**:22.85℃
    💧 **濕度**:74%
    💨 **風速**:2.14 m/s
    ?? **天氣狀況**:陰天,多云請根據實際需要增減衣物,出行注意安全!
    

二 MCP+Agents SDK基礎調用

  • Agents SDK可以將某個對應的Agent封裝為client與外部定義好的server進行通信。客戶端為client_agent.py、服務端weather_server.py
    在這里插入圖片描述

2.1 weather_server.py

import json
import httpx
from typing import Any
from mcp.server.fastmcp import FastMCP# 初始化mcp服務器
mcp=FastMCP("WeatherServer")#OpenWeather API 配置
OPENWEATHER_API_BASE = "https://api.openweathermap.org/data/2.5/weather"
API_KEY ="xxx"
USER_AGENT = "weather-app/1.0"async def fetch_weather(city: str) -> dict[str, Any]|None:"""獲取天氣信息"""params={"q": city,"appid": API_KEY,"units": "metric","lang": "zh_cn"}headers={"User-Agent": USER_AGENT}async with httpx.AsyncClient() as client:response = await client.get(OPENWEATHER_API_BASE, params=params, headers=headers,timeout=1000)if response.status_code == 200:return response.json()else:print(f"Error fetching weather data: {response.status_code}, {response.text}")  # 增加日志輸return Nonedef format_weather(data: dict[str,Any] | str)->str:"""解析天氣數據字典,提取關鍵信息并格式化輸出。功能:對可能缺失的嵌套數據字段進行容錯處理,確保返回內容完整。參數:data: 天氣API返回的原始數據字典返回:格式化后的天氣信息字符串"""# 基礎位置信息(城市、國家)- 缺失時顯示"未知"city = data.get("name", "未知")  # 城市名稱(頂層字段)country = data.get("sys", {}).get("country", "未知")  # 國家代碼(嵌套在sys字段中)# 天氣核心指標 - 缺失時顯示"N/A"(Not Available)main_data = data.get("main", {})  # 提取main字段(包含溫度、濕度等)temperature = main_data.get("temp", "N/A")  # 溫度humidity = main_data.get("humidity", "N/A")  # 濕度wind_data = data.get("wind", {})  # 提取wind字段(包含風速等)wind_speed = wind_data.get("speed", "N/A")  # 風速# 天氣描述 - weather字段可能為空列表,默認返回第一個元素的描述weather_list = data.get("weather", [{}])  # 提取weather數組(默認空字典避免索引錯誤)weather_description = weather_list[0].get("description", "未知")  # 天氣狀況描述# 格式化輸出字符串(使用f-string拼接,添加emoji直觀展示)weather_info = (f"🌍 {city}, {country}\n"f"🌡? 溫度:{temperature}℃\n"f"💧 濕度:{humidity}%\n"f"💨 風速:{wind_speed} m/s\n"f"?? 天氣:{weather_description}\n")return weather_info@mcp.tool()
async def query_weather(city: str) -> str:"""查詢天氣信息并返回結果"""weather_data = await fetch_weather(city)if weather_data:return format_weather(weather_data)else:return "無法獲取天氣信息。請檢查城市名稱是否正確。"if __name__=="__main__":mcp.run(transport='stdio')

2.2 client_agent.py

import asyncio
import time
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel,Agent, Runner, gen_trace_id, trace, set_default_openai_client
from agents.mcp import MCPServer, MCPServerStdio
from agents.model_settings import ModelSettings
from agents import set_tracing_disabled  # or from your framework's module
OPENAI_API_KEY="hk-xxx"
OPENAI_API_BASE="https://api.openai-hk.com/v1"
MODEL="deepseek-v3"# 創建一個Agent對象并調用DeepSeek模型
external_client = AsyncOpenAI(base_url = OPENAI_API_BASE,api_key= OPENAI_API_KEY,
)set_default_openai_client(external_client)
set_tracing_disabled(True)
deepseek_model=OpenAIChatCompletionsModel(model=MODEL,openai_client=external_client)async def run(mcp_server: MCPServer):agent = Agent(name="Assistant",instructions="你是一名助人為樂的助手",mcp_servers=[mcp_server],model=deepseek_model)message = "請幫我查詢Beijing天氣如何?"print(f"Running: {message}")result = await Runner.run(starting_agent=agent, input=message)print(result.final_output)async def mcp_run():async with MCPServerStdio(name="Weather Server",cache_tools_list=True,params = {"command": "uv","args": ["run", "weather_server.py"]} ) as server:await run(server)if __name__ == "__main__":asyncio.run(mcp_run())

2.3 運行測試

(mcp-weather) D:\Code\mcp-study\mcp-weather>uv run client_agent.py
Running: 請幫我查詢Beijing天氣如何?
北京當前的天氣情況如下:- **溫度**34.66- **濕度**54%
- **風速**2.78 m/s
- **天氣狀況**:晴天氣晴朗,但溫度較高,請注意防曬和補水!

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

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

相關文章

Camera相機人臉識別系列專題分析之十九:MTK ISP6S平臺FDNode傳遞三方FFD到APP流程解析

【關注我,后續持續新增專題博文,謝謝!!!】 上一篇我們講了: 這一篇我們開始講: Camera相機人臉識別系列專題分析之十九:MTK平臺FDNode傳遞三方FFD到APP流程解析 目錄 一、背景 二、:OcamMeta傳遞FFD到APP 2.1:OcamMeta 2.2 :OcamMeta::process更新FFD 2.…

【實時Linux實戰系列】構建實時監測與報警系統

在實時系統中&#xff0c;監測與報警系統是確保系統正常運行和及時響應異常情況的關鍵組件。實時監測與報警系統能夠實時收集系統數據&#xff0c;分析關鍵事件&#xff0c;并在檢測到異常時發出警報。這種系統廣泛應用于工業自動化、醫療設備監控、網絡安全等領域。掌握實時監…

PHP入門及數據類型

PHP數據類型 PHP標記 //HTML風格 <?phpecho "hello world"; ?> //簡短風格 <?echo "hello world"; ?>數據類型 PHP 最初源于 Perl 語言&#xff0c;與 Perl 類似&#xff0c;PHP 對數據類型采取較為寬松的態度。PHP 規定&#xff0c;變量數…

沸點 | 嬴圖參加世界人工智能大會

2025 WAIC于 7 月 26 日至 28 日在上海舉行。大會展覽面積突破 7 萬平方米&#xff0c;800 余家企業參展。嬴圖作為圖數據庫領域的領先企業&#xff0c;攜前沿技術與創新應用精彩亮相。?大會期間&#xff0c;嬴圖創始人兼CEO孫宇熙與來自全球的頂尖學者、企業代表共同探討人工…

2. 字符設備驅動

一、設備號 1.1. 什么是設備號 設備號是用來標記一類設備以及區分這類設備中具體個體的一組號碼。 設備號由主設備號和次設備號組成。主設備號的作用為標記一類設備、用于標識設備驅動程序,而次設備號的作用是為了區分這類設備中的具體個體設備及用于標識同一驅動程序下的具…

uboot armv8 啟動流程之 linker script

section 詳細說明.text按如下順序&#xff0c;中斷向量表vectors, 啟動入口代碼start.o,普通text, glue &#xff08;arm thumb2 相互調用時自動生成的代碼&#xff09;*(.vectors)CPUDIR/start.o (.text*)*(.text*)*(.glue*)__image_copy_start 標記為text 段入口&#xff0c;…

xxljob總結

XXL-Job 支持多種任務類型&#xff0c;以下是常見任務類型的示例 Demo&#xff0c;包含核心配置和代碼片段&#xff0c;幫助快速理解用法&#xff1a;一、Bean模式任務&#xff08;最常用&#xff09;通過注解 XxlJob 定義任務方法&#xff0c;直接在 Spring 容器中管理&…

Python包安全工程實踐:構建安全可靠的Python生態系統

在現代計算環境中&#xff0c;性能往往是Python包成功的關鍵因素。本文將深入探討Python包的性能優化技術&#xff0c;包括并發編程模型、性能分析工具、內存優化策略以及原生代碼集成等高級主題&#xff0c;幫助你構建高性能的Python組件。1. 性能分析基礎1.1 性能分析工具矩陣…

kubernetes基礎知識

個人博客站—運維鹿: http://www.kervin24.top CSDN博客—做個超努力的小奚&#xff1a; https://blog.csdn.net/qq_52914969?typeblog一、kubernetes介紹Kubernetes本質是一組服務器集群&#xff0c;它可以在集群的每個節點上運行特定的程序&#xff0c;來對節點中的容器進行…

winntsetup安裝驅動和光驅安裝F6功能一樣----NT5.2.3790源代碼分析

D:\drv>dir驅動器 D 中的卷是 新加卷卷的序列號是 443D-D64BD:\drv 的目錄2025-08-03 23:57 <DIR> . 2025-08-03 23:57 <DIR> .. 2008-05-27 10:01 119,068 yk51x86.cat 2008-05-20 10:01 969,380 yk51x86.inf…

Web 開發 11

今天完成了workshop2&#xff0c;進度有點慢&#xff0c;但是記錄一下極為愚蠢的一輪輪問答和思考~&#xff01;&#xff08;還是有點成就感的&#xff09;ps&#xff1a;【】內為我的提問1 導入語句&#xff08;ES6 模塊導入語法&#xff09;【import CatHappiness from "…

寫作路上的迷茫與突破

曾經&#xff0c;我也是那個在寫作面前躊躇不前的人。每次提筆&#xff0c;滿心都是“我寫不好”“我沒什么可寫的”“我達不到別人的高度”……這些念頭像藤蔓一樣&#xff0c;緊緊纏繞著我&#xff0c;讓我寸步難行。我看著群里的小伙伴們一個個妙筆生花&#xff0c;自己卻只…

23 Active Directory攻擊與防護策略解析

引言 Active Directory&#xff08;AD&#xff09;是企業IT環境中用戶認證、訪問控制和身份管理的核心。因其掌握整個網絡的"鑰匙"&#xff0c;AD常成為攻擊者的首要目標。 從憑證轉儲到隱蔽偵察&#xff0c;攻擊者通過多種手段控制AD。無論您是網絡安全分析師、紅…

【內容規范】關于標題中【】標記的使用說明

【內容規范】關于標題中【】標記的使用說明 在信息爆炸的時代&#xff0c;如何讓內容更易識別、更具條理性&#xff0c;成為內容創作者和平臺運營者共同關注的問題。標題中【】標記的使用&#xff0c;正是在這種需求下形成的一種實用規范。 這種規范的核心作用在于建立統一的內…

centos 9 安裝docker教程

拉取相關依賴 dnf -y install dnf-plugins-core設置阿里云鏡像庫 dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo安裝docker dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plu…

關閉Jetbrains Mono字體連寫、連字功能

所謂的關閉Jetbrains Mono字體連寫&#xff0c;其實就是更換為Jetbrains Mono NL字體二者的區別就是符號間距的大小不同&#xff0c;也就是有無連字功能。 下圖以Visutal Studio為例&#xff1a;

漫花軟件集合分享

漫花軟件集合分享的各種apk 1、磁盤漫畫【推薦】 2、你搜 3、皮皮喵 4、潑辣漫畫 5、趣漫畫 6、異次元&圖源 7、漫 8、再漫畫X 9、章魚漫畫 10、芝士漫畫&圖源 通過網盤分享的文件&#xff1a;漫畫軟件 鏈接: https://pan.baidu.com/s/1dlGl50MNzzVOdTP38_…

DB-GPT 0.7.3 版本更新:支持Qwen3 Embedding和Reranker模型、支持知識庫自定義檢索策略等

V0.7.3版本主要新增、增強了以下核心特性 &#x1f340; 支持Qwen3 Embedding和Reranker模型 &#x1f340; 支持知識庫自定義檢索策略&#xff1a;語義檢索、全文檢索、樹形檢索、混合檢索等 &#x1f340; 新增GaussDB數據源支持 &#x1f340; 支持GLM-4.1V多模態模型 …

Django常見模型字段

AutoField:數據庫中的自動增長類型&#xff0c;相當于ID自動增長的IntegerField類型字段&#xff0c;對應mysql的Int類型 BooleanField:真/假的布爾類型字段&#xff0c;對應mysql的Tinyint類型 CharField:字符類型字段&#xff0c;對應mysql的varChar類型 DateField:日期字段&…

前端列表封面圖如何自不同圖片比例不變形

設置圖片寬度100%時&#xff0c;若不設置高度&#xff0c;可能導致高度不足導致空白區域。如何實現圖片高度自適應填充&#xff0c;避免空白區域&#xff1f;解決方式&#xff1a;加上height&#xff1a;100%&#xff1b;object-fit:cover&#xff1b;就可以始終剪切鋪滿&#…