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)
相关推荐
一人の梅雨4 小时前
1688 店铺商品全量采集与智能分析:从接口调用到供应链数据挖掘
开发语言·python·php
间彧4 小时前
Java单例模式:饿汉式与懒汉式实现详解
后端
道可到4 小时前
百度面试真题 Java 面试通关笔记 04 |JMM 与 Happens-Before并发正确性的基石(面试可复述版)
java·后端·面试
Terio_my5 小时前
Python制作12306查票工具:从零构建铁路购票信息查询系统
开发语言·python·microsoft
Ray665 小时前
guide-rpc-framework笔记
后端
37手游后端团队5 小时前
Claude Code Review:让AI审核更懂你的代码
人工智能·后端·ai编程
万粉变现经纪人5 小时前
如何解决 pip install -r requirements.txt 约束文件 constraints.txt 仅允许固定版本(未锁定报错)问题
开发语言·python·r语言·django·beautifulsoup·pandas·pip
站大爷IP5 小时前
Python定时任务实战:APScheduler从入门到精通
python
长安不见5 小时前
解锁网络性能优化利器HTTP/2C
后端