sse mcp flask 开放mcp服务到内网

python 复制代码
# e:\code\my_python_server\sse\sse_server.py
from mcp import ClientSession
from mcp.client.sse import sse_client
import asyncio
from flask import Flask, request, jsonify

app = Flask(__name__)

async def read_excel_data(filepath, sheet_name=None):
    """通过 SSE 连接到 MCP 服务器并读取 Excel 数据"""
    url = "http://localhost:8017/sse"
    
    async with sse_client(url) as (read, write):
        async with ClientSession(read, write) as session:
            # 初始化连接
            await session.initialize()
            print("已连接到 MCP 服务器")
            
            # 处理 sheet_name 参数
            # 如果没有提供 sheet_name,则使用默认值 "Sheet1"
            if sheet_name is None:
                sheet_name = "Sheet1"
            
            # 读取数据
            result = await session.call_tool(
                "read_data_from_excel",
                arguments={
                    "filepath": filepath,
                    "sheet_name": sheet_name,
                    "start_cell": "A1",
                    "preview_only": True
                }
            )
            print("已读取数据:", result)
            # 将结果转换为可序列化的格式
            return convert_result_to_serializable(result)

def convert_result_to_serializable(result):
    """将 CallToolResult 转换为可序列化的字典格式,并避免重复内容"""
    if hasattr(result, '__dict__'):
        # 如果结果对象有 __dict__ 属性,尝试转换其属性
        serializable = {}
        for key, value in result.__dict__.items():
            if isinstance(value, (str, int, float, bool, type(None))):
                serializable[key] = value
            elif isinstance(value, (list, tuple)):
                serializable[key] = [convert_result_to_serializable(item) if hasattr(item, '__dict__') else item for item in value]
            elif isinstance(value, dict):
                serializable[key] = {k: convert_result_to_serializable(v) if hasattr(v, '__dict__') else v for k, v in value.items()}
            else:
                # 对于其他对象,转换为字符串表示
                serializable[key] = str(value)
        
        # 特殊处理 content 和 structuredContent 字段,避免重复数据
        if 'content' in serializable and 'structuredContent' in serializable:
            # 如果 structuredContent 中的 result 与 content 的 text 相同,则移除其中一个
            if (isinstance(serializable['content'], list) and 
                len(serializable['content']) > 0 and
                isinstance(serializable['content'][0], dict) and
                'text' in serializable['content'][0] and
                isinstance(serializable['structuredContent'], dict) and
                'result' in serializable['structuredContent']):
                
                # 比较内容是否重复
                if serializable['content'][0]['text'] == serializable['structuredContent']['result']:
                    # 移除重复的 structuredContent,只保留 content
                    del serializable['structuredContent']
        
        return serializable
    else:
        return str(result)

async def list_available_tools():
    """通过 SSE 连接到 MCP 服务器并列出所有可用工具"""
    url = "http://localhost:8017/sse"
    
    async with sse_client(url) as (read, write):
        async with ClientSession(read, write) as session:
            # 初始化连接
            await session.initialize()
            print("已连接到 MCP 服务器")
            
            # 列出所有可用工具
            tools = await session.list_tools()
            return [{"name": tool.name, "description": tool.description} for tool in tools.tools]

@app.route('/read_excel', methods=['GET'])
def read_excel_endpoint():
    """Flask 路由,接受 filepath 和可选的 sheet_name 参数并返回读取结果"""
    filepath = request.args.get('filepath')
    sheet_name = request.args.get('sheet_name')
    
    if not filepath:
        return jsonify({"error": "缺少 filepath 参数"}), 400
    
    try:
        # 在异步环境中运行
        result = asyncio.run(read_excel_data(filepath, sheet_name))
        return jsonify({"result": result})
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/list_tools', methods=['GET'])
def list_tools_endpoint():
    """Flask 路由,列出所有可用的 MCP 工具"""
    try:
        # 在异步环境中运行
        tools = asyncio.run(list_available_tools())
        return jsonify({"tools": tools})
    except Exception as e:
        return jsonify({"error": str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
相关推荐
DLYSB_5 小时前
存储运维实战:基于 Ceph Event 监听与 Python 适配器的分布式存储健康度物理声光响应架构
运维·ceph·python·报警灯
陈随易5 小时前
FFmpeg 9.0 发布,代号 Lei,音视频处理再升级
前端·后端·程序员
阿童木写作5 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
阿童木写作7 小时前
Python实现Temu图片批量翻译自动化教程
运维·人工智能·python·自动化
就是一只白8 小时前
复制地理信息python版本
python
凌虚8 小时前
面向 MySQL 用户的 PostgreSQL 快速上手指南
数据库·后端·架构
看浪的路人8 小时前
第1讲:Agent 到底是什么?和 Chatbot 有什么区别
python·ai
瓦学妹9 小时前
什么是网络索引?它是如何工作的?
大数据·网络·python·网络爬虫
IT_陈寒9 小时前
Vite静态资源引用这个坑我踩得有点疼
前端·人工智能·后端
天天爱吃肉82189 小时前
商用车多体动力学实战笔记|第6篇:动力传动系统(发动机、变速箱、分动器、TCS、LSD限滑差速)
大数据·人工智能·笔记·python·嵌入式硬件·汽车