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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…