SQL 执行 MCP 工具开发(一)

效果展示

调用MCP执行SQL时会自动弹出消息框,倒计时结束前未审批会自动拒绝该SQL的执行,此外可以通过备注介入,给AI合理的建议。

构建 MCP 服务

导入的包

python 复制代码
import json
import os
import subprocess
import time
from functools import wraps
from pathlib import Path

from mcp.server import FastMCP

MIN_WINDOW_SIZE = (500, 300)
MAX_WINDOW_SIZE = (800, 550)
DATA_SAVE_PATH = "E:/Workspace/MCP/tools/execute_sql/data"
WAILS_EXE_PATH = "E:/Workspace/MCP/tools/execute_sql/build/bin/execute-sql.exe"
mcp = FastMCP("ExecuteSQLReview", host="127.0.0.1", port=50050)

if __name__ == "__main__":
    mcp.run(transport="streamable-http")

stdio 无法正常弹窗,请使用 streamable-http 模式。

装饰器

python 复制代码
def mcp_tool(enable=True, max_length=2000):
    def decorator(func):
        original_func = func

        @wraps(func)
        def wrapper(*args, **kwargs):
            if not enable:
                return original_func(*args, **kwargs)
            raw_response = original_func(*args, **kwargs)
            if len(str(raw_response)) > max_length:
                file_name = DATA_SAVE_PATH + f"/result-{time.time()}.json"
                with open(file_name, "w", encoding="utf-8") as f:
                    f.write(json.dumps(raw_response, ensure_ascii=False, indent=4))
                return {
                    "code": 200,
                    "msg": f"响应结果过长,请调用文件工具查看",
                    "file_path": os.path.abspath(file_name)
                }
            return raw_response

        if enable:
            return mcp.tool()(wrapper)
        else:
            return wrapper

    return decorator

装饰器的作用有两方面,一是方便快速启用停用MCP工具,二是保存SQL执行结果,因为执行SQL返回的结果往往较多,因此这里新增了返回长度判断,如果过长则自动保存至文件中并提示AI使用文本工具查看。

计算窗口尺寸

python 复制代码
def calc_window_size(content, min_window_size=MIN_WINDOW_SIZE, max_window_size=MAX_WINDOW_SIZE):
    if not content:
        return min_window_size
    # 计算行数和最大行长度
    lines = content.split('/n')
    line_count = len(lines)
    max_char_count = max(len(line) for line in lines) if lines else 0
    # 每个字符的预估宽度
    CHAR_WIDTH = 13
    # 每行的预估高度
    LINE_HEIGHT = 28
    # 基础边距
    BASE_PADDING = 20
    # 计算尺寸(考虑边距)
    window_width = max_char_count * CHAR_WIDTH + BASE_PADDING * 2
    window_height = line_count * LINE_HEIGHT + BASE_PADDING * 2

    # 边界处理
    def clamp(value, min_val, max_val):
        return max(min_val, min(value, max_val))

    width = clamp(window_width, min_window_size[0], max_window_size[0])
    height = clamp(window_height, min_window_size[1], max_window_size[1])
    return width, height

执行SQL

python 复制代码
@mcp_tool(enable=True)
def execute_sql_review(sql: str, tags: list[dict]) -> dict:
    """
    执行SQL语句
    sql: 执行的SQL语句
    tags: 标签列表, 执行SQL标签, 查询, 更新, 删除.... 例: [{"name": "更新语句", "color": "#ffcb6b"}]
    """
    data = {
        "sql": sql,
        "options": [
            {"name": "通过", "value": "accept"},
            {"name": "拒绝", "value": "reject", "is_default": True},
        ],
        "tags": tags,
        "auto_close": 50
    }
    data_save_path = DATA_SAVE_PATH + f"/data-{time.time()}.json"
    result_save_path = DATA_SAVE_PATH + f"/result-{time.time()}.json"
    with open(data_save_path, "w", encoding="utf-8") as f:
        f.write(json.dumps(data, ensure_ascii=False, indent=4))
    width, height = calc_window_size(sql)
    cmd = [
        str(Path(WAILS_EXE_PATH).resolve()),
        "-data_path", str(Path(data_save_path).resolve()),
        "-result_path", str(Path(result_save_path).resolve()),
        "-title", "ExecuteSQLReview",
        "-width", str(width),
        "-height", str(height),
        "-min_width", str(MIN_WINDOW_SIZE[0]),
        "-min_height", str(MIN_WINDOW_SIZE[1]),
        "-on_top", "true",
        "-disable_resize", "true",
        "-frameless", "false",
        "-close_confirm", "false"
    ]
    # 运行
    subprocess.run(
        cmd, capture_output=False, text=True, encoding='utf-8', errors='ignore', shell=False
    )
    # 获取执行结果
    with open(result_save_path, "r", encoding="utf-8") as f:
        result = json.load(f)
    # 判断执行结果
    if result["select"] == "reject":
        return result
    # 模拟执行SQL并返回
    return {
        "run_ti": 566,
        "run_result": [{"name": "a", "age": 15}, {"name": "b", "age": 16}]
    }

这里执行SQL的逻辑可以自定义实现。

MCP 配置

相关推荐
belldeep2 小时前
python:Flask 3, mistune 2, 实现在线编辑 Markdown 文档的 Web 服务程序
python·flask·markdown·mistune·pygments
清风与日月2 小时前
OpenCV 图像显示高级技巧和常见问题
人工智能·opencv·计算机视觉
摘星编程2 小时前
突破界限!多模态AI如何重塑人机交互的未来?
人工智能·人机交互
apcipot_rain2 小时前
python 多进程多线程 学习笔记
笔记·python·学习
勇气要爆发2 小时前
2026年想学AI,面对 Dify、Coze、n8n、LangChain 该学哪个?
人工智能·langchain·dify·coze·n8n
love530love2 小时前
ZeroClaw Reflex UI完整搭建流程——ZeroClaw Gateway + LM Studio + Reflex 本地 AI 管理面板
人工智能·windows·gateway·lm studio·reflex·openclaw·zeroclaw
CelestialYuxin2 小时前
FAMOSE:ReAct智能体驱动的自动化特征工程新框架
人工智能
qq_454245032 小时前
开源GraphMindStudio工作流引擎:自动化与AI智能体的理想核心
运维·人工智能·开源·c#·自动化
一个努力编程人2 小时前
NLP领域————GPT算法
人工智能·gpt·自然语言处理