fastmcp MCPConfig多服務器使用案例;sse、stdio、streamable-http使用

1、sse、stdio、streamable-http使用

參考:https://gofastmcp.com/deployment/running-server#the-run-method

stdio本地使用;sse、streamable-http遠程調用(
Streamable HTTP—New in version: 2.3.0)

在這里插入圖片描述
在這里插入圖片描述

調用:
stdio、sse
在這里插入圖片描述
streamable-http
在這里插入圖片描述

2、 MCPConfig多服務器使用案例

參考:
https://gofastmcp.com/clients/client

代碼

config如果只有一個服務,那call_tool函數不用前綴直接工具函數名,如果多個服務,需要添加前綴

from fastmcp import Client# Standard MCP configuration with multiple servers
config = {"mcpServers": {"trip": {"url": "http://localhost:8000/sse"},"math":{"command": "python","args": ["./api_mcp_server_math.py"],"env": {"DEBUG": "true"}}}
}async def main():async with Client(config) as client:tools = await client.list_tools()print("Available tools:")for tool in tools:   ###打印結果系統也自動加了前綴print(f"  - {tool.name}: {tool.description}")hotel_response = await client.call_tool("trip_check_hotel", {"cityname": "廣州","date": "后天"})math_response = await client.call_tool("math_add", {"a": 1, "b": 2})print("Math response:", math_response)print("Hotel response:", hotel_response)if __name__ == "__main__":import asyncioasyncio.run(main())

for tool in tools: ###打印結果系統也自動加了前綴
print(f" - {tool.name}: {tool.description}")
在這里插入圖片描述

在這里插入圖片描述

大模型自動調用工具執行

模型自動調用工具,LLM 根據用戶輸入自動選擇合適的工具;使用百煉qwen3思考模型流式輸出

#!/usr/bin/python3
# -*- coding: utf-8 -*-import json
import asyncio
from typing import List, Dict, Optionalfrom openai import OpenAI
from fastmcp import Clientclass IntegratedMCPClient:def __init__(self, config: Dict, model="qwen3-235b-a22b"):"""初始化集成的 MCP 客戶端Args:config: MCP 服務器配置字典model: 使用的模型名稱"""self.config = configself.model = model# 初始化 OpenAI 客戶端self.client = OpenAI(api_key="sk-424971",base_url="https://dashscope.ale-mode/v1")# 初始化 MCP 客戶端self.session = Client(config)self.tools = []self.server_tool_mapping = {}  # 記錄工具來自哪個服務器async def prepare_tools(self):"""準備所有可用的工具"""try:# 獲取所有工具tools = await self.session.list_tools()print(f"發現 {len(tools)} 個可用工具:")self.tools = []self.server_tool_mapping = {}for tool in tools:print(f"  - {tool.name}: {tool.description}")# 構建工具描述tool_def = {"type": "function","function": {"name": tool.name,"description": tool.description,"parameters": tool.inputSchema,}}self.tools.append(tool_def)# 記錄工具映射(如果需要區分來源)# 這里可以通過工具名前綴或其他方式來識別來源服務器if tool.name.startswith("trip_"):self.server_tool_mapping[tool.name] = "trip"elif tool.name.startswith("math_"):self.server_tool_mapping[tool.name] = "math"else:self.server_tool_mapping[tool.name] = "unknown"except Exception as e:print(f"準備工具時出錯: {e}")self.tools = []async def chat(self, messages: List[Dict]) -> Optional[object]:"""處理聊天對話,支持工具調用"""if not self.tools:await self.prepare_tools()try:# 使用流式響應,啟用思考過程response = self.client.chat.completions.create(model=self.model,messages=messages,tools=self.tools if self.tools else None,temperature=0,max_tokens=16000,stream=True,logprobs=False,stream_options={"include_usage": True},extra_body={"enable_thinking": True  # 啟用思考過程})# 收集流式響應collected_content = ""collected_tool_calls = []finish_reason = Noneprint("AI: ", end="", flush=True)for chunk in response:# 安全檢查:防止空的 choicesif not chunk.choices:continuedelta = chunk.choices[0].deltafinish_reason = chunk.choices[0].finish_reason# 打印思考過程(Qwen 特有字段)reasoning = getattr(delta, "reasoning_content", None)if reasoning:print(f"{reasoning}", end="", flush=True)# 打印常規內容if delta.content:print(delta.content, end="", flush=True)collected_content += delta.content# 收集工具調用if hasattr(delta, 'tool_calls') and delta.tool_calls:if not collected_tool_calls:collected_tool_calls = [{"id": "", "function": {"name": "", "arguments": ""}} for _ in delta.tool_calls]for i, tool_call_delta in enumerate(delta.tool_calls):if tool_call_delta.id:collected_tool_calls[i]["id"] = tool_call_delta.idif tool_call_delta.function:if tool_call_delta.function.name:collected_tool_calls[i]["function"]["name"] = tool_call_delta.function.nameif tool_call_delta.function.arguments:collected_tool_calls[i]["function"]["arguments"] += tool_call_delta.function.argumentsprint()  # 換行# 如果沒有工具調用,返回收集的內容if finish_reason != 'tool_calls' or not collected_tool_calls:class SimpleMessage:def __init__(self, content):self.content = contentreturn SimpleMessage(collected_content)# 處理工具調用print("\n[正在調用工具...]")assistant_message = {'role': 'assistant','content': collected_content,'tool_calls': [{"id": tc["id"],"type": "function","function": {"name": tc["function"]["name"],"arguments": tc["function"]["arguments"]}}for tc in collected_tool_calls]}print(f"[助手消息]: 調用了 {len(collected_tool_calls)} 個工具")messages.append(assistant_message)# 執行每個工具調用for tool_call in collected_tool_calls:try:tool_name = tool_call['function']['name']tool_args = json.loads(tool_call['function']['arguments'])server_name = self.server_tool_mapping.get(tool_name, "unknown")print(f"\n[執行工具]: {tool_name} (來自服務器: {server_name})")print(f"[工具參數]: {tool_args}")# 調用工具result = await self.session.call_tool(tool_name, tool_args)# 處理結果result_content = ""if result:if isinstance(result, list) and len(result) > 0:if hasattr(result[0], 'text'):result_content = result[0].textelse:result_content = str(result[0])else:result_content = str(result)else:result_content = "No result"# 添加工具結果到消息中messages.append({'role': 'tool','tool_call_id': tool_call['id'],'content': result_content})print(f"[工具結果]: {result_content}")except Exception as e:print(f"[工具調用錯誤]: {e}")messages.append({'role': 'tool','tool_call_id': tool_call['id'],'content': f"Error executing tool: {str(e)}"})# 使用工具結果獲取最終響應print("\n[生成最終回答...]")return await self.chat(messages)except Exception as e:print(f"聊天過程中出錯: {e}")class ErrorMessage:def __init__(self, content):self.content = contentreturn ErrorMessage(f"抱歉,處理您的請求時出現錯誤: {str(e)}")async def loop(self):"""交互式聊天循環"""print("=== 集成 MCP 客戶端啟動 ===")print("支持的命令:")print("  - quit/exit/bye: 退出程序")print("  - tools: 顯示可用工具")print("  - clear: 清除對話歷史")print("=====================================\n")conversation_history = []while True:try:async with self.session:# 如果是第一次進入,準備工具if not self.tools:await self.prepare_tools()question = input("\nUser: ").strip()# 處理特殊命令if question.lower() in ['quit', 'exit', 'bye']:print("再見!")breakelif question.lower() == 'tools':print(f"\n可用工具 ({len(self.tools)} 個):")for tool in self.tools:func = tool['function']server = self.server_tool_mapping.get(func['name'], 'unknown')print(f"  - {func['name']} (服務器: {server})")print(f"    描述: {func['description']}")continueelif question.lower() == 'clear':conversation_history = []print("對話歷史已清除")continueelif not question:continue# 添加用戶消息到歷史user_message = {"role": "user", "content": question}current_messages = conversation_history + [user_message]# 獲取響應response = await self.chat(current_messages.copy())if response and hasattr(response, 'content'):print(f"\n回答: {response.content}")# 更新對話歷史conversation_history.append(user_message)conversation_history.append({"role": "assistant", "content": response.content})# 限制歷史長度,避免上下文過長if len(conversation_history) > 20:  # 保留最近10輪對話conversation_history = conversation_history[-20:]except KeyboardInterrupt:print("\n\n程序被用戶中斷")breakexcept Exception as e:print(f"循環過程中出錯: {e}")continueasync def single_query(self, query: str) -> str:"""單次查詢接口,適用于非交互式使用"""try:async with self.session:if not self.tools:await self.prepare_tools()messages = [{"role": "user", "content": query}]response = await self.chat(messages)return response.content if response and hasattr(response, 'content') else "無響應"except Exception as e:return f"查詢失敗: {str(e)}"async def main():"""主函數"""# MCP 配置config = {"mcpServers": {"trip": {"url": "http://localhost:8000/sse"},"math": {"command": "python","args": ["./api_mcp_server_math.py"],"env": {"DEBUG": "true"}}}}print("正在初始化集成 MCP 客戶端...")mcp_client = IntegratedMCPClient(config)# 啟動交互式循環await mcp_client.loop()async def test_single_queries():"""測試單次查詢的示例"""config = {"mcpServers": {"trip": {"url": "http://localhost:8000/sse"},"math": {"command": "python", "args": ["./api_mcp_server_math.py"],"env": {"DEBUG": "true"}}}}mcp_client = IntegratedMCPClient(config)# 測試查詢test_queries = ["幫我查詢廣州后天的酒店信息","計算 15 加 27 等于多少","我想知道北京明天有什么好的酒店推薦","計算 100 乘以 50","你好,請介紹一下你的功能"]for query in test_queries:print(f"\n{'='*50}")print(f"測試查詢: {query}")print(f"{'='*50}")result = await mcp_client.single_query(query)print(f"結果: {result}")if __name__ == '__main__':# 運行交互式模式asyncio.run(main())# 或者運行測試模式# asyncio.run(test_single_queries())

在這里插入圖片描述

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

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

相關文章

網站服務器被DDOS攻擊打不開,是要換高防服務器還是加CDN能防護住?

高防云服務器、高防 IP 和高防 CDN 作為常見應對網絡攻擊的重要利器,它們各自有著獨特的特點和應用場景,從技術架構看,高防云服務器是資源型防護,深度整合計算與防御資源;高防IP是流量型防護,以代理模式實現…

深入解析原型模式:從理論到實踐的全方位指南

深入解析原型模式:從理論到實踐的全方位指南 引言:為什么需要原型模式? 在軟件開發過程中,對象創建是一個頻繁且關鍵的操作。傳統方式(如直接使用new關鍵字)在某些場景下會顯得效率低下且不夠靈活。想象這…

HuggingFace鏡像配置失效問題深度解析:Python模塊導入機制的陷阱

前言 在使用HuggingFace的transformers和datasets庫時,國內用戶經常會遇到網絡連接問題。雖然設置了鏡像源環境變量,但仍然報錯無法連接到huggingface.co。本文將深入分析這個問題的根因,并從Python模塊導入機制的角度解釋為什么環境變量設置…

leetcode146-LRU緩存

leetcode 146 思路 什么是LRU緩存? LRU(Least Recently Used)緩存是一種常見的緩存淘汰策略,核心思想是:當緩存容量滿時,優先淘汰最久未使用的數據。LeetCode 146 題要求實現一個支持get和put操作的 LR…

MQTT:構建高效物聯網通信的輕量級協議

MQTT – 輕量級物聯網消息推送協議 MQTT(Message Queuing Telemetry Transport)是機器對機器(M2M)/物聯網(IoT)連接協議。它被設計為一個極其輕量級的發布/訂閱消息傳輸協議。對于需要較小代碼占用空間和/或網絡帶寬非常寶貴的遠程連接非常有用&#xf…

AI自動生成復雜架構圖,流程圖,思維導圖

AI自動生成復雜架構圖,流程圖,思維導圖方案 1. 背景 在我們自己去繪制架構圖,流程圖,思維導圖的時候,我們通常需要花費大量的時間去繪制。 目前的一些直接生圖的模型也只能生成簡單的流程圖,不能生成復雜…

129. 求根節點到葉節點數字之和 --- DFS +回溯(js)

129. 求根節點到葉節點數字之和 --- DFS 回溯(js) 題目描述解題思路完整代碼 題目描述 129. 求根節點到葉節點數字之和 解題思路 和 257. 二叉樹的所有路徑(js) 是一樣的思路。 不一樣的地方就是遇到葉子節點的時候把路徑拼接…

SpringBoot電腦商城項目--修改默認收貨地址

1. 修改默認收貨地址-持久層 1.1 規劃sql語句 檢測當前用戶向設置為默認收貨地址的這條數據是否存在 SELECT * FROM t_address WHERE aid#{aid} 在修改用戶的收獲默認地址之前,先將所有的收貨地址設置為非默認 UPDATE t_address SET is_default0 WHERE uid#{uid} …

LabVIEW FPGA 資源擴展

針對NI CompactRIO 9045 控制器 Kintex-7 70T FPGA 資源不足問題,通過 NI 9151 R 系列可重配置 I/O 模塊擴展外部 FPGA 處理能力,在保留原有機箱架構下實現實時任務分流,解決Slice、LUT 等資源緊張問題,提升系統并行處理能力。 ?…

【漏洞復現】Apache Kafka Connect 任意文件讀取漏洞(CVE-2025-27817)

文章目錄 前言一、Apache Kafka 簡介二、漏洞描述三、影響版本四、FOFA查詢語句五、漏洞原理分析六、漏洞復現七、修復建議前言 由于Apache Kafka客戶端未對用戶輸入進行嚴格驗證和限制,未經身份驗證的攻擊者可通過構造惡意配置讀取環境變量或磁盤任意內容,或向非預期位置發…

day13-軟件包管理

1.每日復盤與今日內容 1.1復盤 yum源/apt源配置文件,核心下載地址.二進制部署服務.編譯安裝軟件. 2.軟件包管理-實戰部分 2.1 yum源/apt源配置 源下載軟件的地址配置多種源 1??系統也有默認的源,里面也包含很多常用的軟件. 2??安裝nginx、yum源 3??安…

榕壹云快遞寄件系統:聚合快遞、智能追蹤、二次開發,一站式物流解決方案

在電商物流高速發展的今天,快遞寄件需求呈現爆炸式增長。傳統分散的寄件方式效率低下,用戶迫切需要一個整合多家快遞公司的便捷平臺。榕壹云公司開發的快遞寄件系統應運而生,通過聚合多家快遞資源、優化操作流程、提供豐富的功能模塊&#xf…

一款功能強大的專業CSV編輯工具

Rons Data Edit是一款為Windows操作系統設計的現代CSV文件編輯器,它結合了優雅、強大和易用性,它可以打開任何格式的分隔文本文件(如CSV、TSV等),并允許用戶完全控制文件的內容和結構。 功能特點 支持明暗主題,可以在預定義的20多…

什么是軟件架構?和系統設計有何區別?

一、軟件架構的定義與核心要素 1.1 基本概念 軟件架構(Software Architecture)是指系統的高層結構,包含: 組件(Components)及其相互關系指導設計的架構原則和決策滿足質量屬性(Quality Attributes)的技術方案引用權威定義:IEEE 1471標準將架構描述為"系統的基本組織,…

九尾狐編程語言新算法“超維時空演算體”

一、核心架構設計 1.量子﹣生物混合計算基座 ◇底層采用量子糾纏拓撲網絡,處理超越經 典計算復雜度的問題(如 NP - Hard 優化).中層嵌入類腦脈沖神經網絡,模擬人腦跨領域聯想能力,…

RoboVerse--為機器人學習打造的大一統世界--UC Berkeley...--2025.4.26

ROBOVERSE 包含一個可擴展的仿真平臺、大規模的合成數據集,以及統一的基準測試。 該仿真平臺通過統一協議,支持新任務和演示的無縫接入,保證了靈活性和可擴展性。該數據集包含 1,000 多個多樣化任務及超過 1,000 萬個狀態轉換,構…

Fiddler抓包工具實戰指南:結合Charles、Postman優化Web與移動調試流程

在Web開發與移動端調試的工作流程中,網絡請求的可視化、分析和控制能力對開發效率有著決定性影響。特別是在處理復雜接口聯調、性能瓶頸排查,甚至安全漏洞分析時,一款可靠的抓包工具幾乎成為了每一位開發者的“標配”。 Fiddler作為長期深受…

6/19作業

思維導圖 單選題 樹 1. 向一棵平衡二叉樹中插入一個結點后,一定會改變其平衡性。 ( ) A 正確 B 錯誤 正確答案:B 你的答案:A 官方解析: 向平衡二叉樹中插入節點并不一定會改變其平衡性。平衡二叉樹(如AVL樹…

angular 圖斑點擊,列表選中并滾動到中間位置

如圖所示&#xff1a; html代碼&#xff1a; 1. #listContainer 2. [attr.data-id]"center.id" <div class"resTableCss" #listContainer><div *ngFor"let center of tbList" [attr.data-id]"center.id" class"res-it…

Java線程同步的簡單理解

為什么需要線程同步 對于以下代碼&#xff1a;兩個線程對同一個變量分別進行100000次加一和減一操作&#xff0c;但是每次運行的輸出基本都是不同的&#xff08;注意線程的join操作保證了兩個線程都運行完之后才執行System.out.println&#xff09; import org.junit.Test;pu…