做数据库运维的朋友应该都有过这种体验:半夜被一条“MySQL 主库线程数过高”的告警叫醒,睡眼惺忪爬起来,登录跳板机,一条条执行 SHOW PROCESSLIST、查慢日志、跑 EXPLAIN,最后定位到某个慢 SQL 再通知业务方优化。整个过程说不上难,但就是重复、琐碎,而且特别依赖“知道下一步该查什么”的经验积累。
前段时间我在研究 MCP(Model Context Protocol,模型上下文协议),脑子里突然冒出一个念头:如果把 MySQL 的日常巡检和诊断动作全部抽象成标准工具,让 AI 助手通过 MCP 协议直接调用,是不是就能把这套排查链路自动化?说干就干,我花了两周时间,基于开源 MCP 服务端搭了一个 MySQL 智能运维平台,前端对接常见的交互式 AI 客户端,用自然语言就能完成大部分日常巡检和初步诊断。这篇博客就把整个思路、架构、核心代码和踩过的坑完整记录下来,希望对同样折腾 MCP + 运维自动化的朋友有帮助。
1. 为什么是 MCP + MySQL 这个组合
1.1 传统 MySQL 运维的流水线困局
先说个普遍痛点。生产环境 MySQL 出故障,大多数时候不是“不会处理”,而是“排查链路太长”。业务方反馈慢,你要先看连接数有没有打满,再看有没有锁等待,然后翻慢日志,定位具体 SQL,跑 EXPLAIN,分析索引情况,最后才能判断问题出在哪。
我粗略统计过,一次典型故障里,真正动手修复的时间可能只有几分钟,但前面的检查动作往往要花上半小时甚至更久。关键在于,这些检查动作高度重复:连接数、锁状态、慢日志、索引、表结构,翻来覆去就是那十几条标准 SQL。传统做法是写一批固定脚本,定时采样、出问题时人工翻报表,但脚本能解决“数据有没有”的问题,解决不了“该查什么、怎么解读”的问题。因为故障场景千变万化,固定脚本永远覆盖不全,判断逻辑还得靠人肉完成。
1.2 MCP 补上了“AI 摸到数据库”的最后一公里
MCP 是 Anthropic 提出并开源的一套标准化协议,核心思路很简单:把 AI 模型和外部工具之间的调用关系标准化。服务端以标准接口暴露工具、资源和提示词,客户端接入后,AI 模型就能自主决定何时调用、以什么参数调用这些能力。
这类的价值我用一个类比说过很多次:就像打印机驱动。早年每台打印机要装专属驱动,换了品牌就抓瞎;后来有了标准打印协议,插上就能用。MCP 之于 AI 应用,做的就是这件事。AI 模型不需要了解 MySQL 协议细节,也不需要关心服务端是 Python 还是 Go 写的,它只需要知道“这边有几个工具,分别能干什么”,就能自主编排诊断流程。
具体到 MySQL 运维,这个组合的价值就体现出来了:AI 模型天然擅长“根据现象判断下一步查什么”这类推理,而 MySQL 诊断同样高度依赖一套标准查询命令。两者通过 MCP 对接之后,AI 不再是纸上谈兵的聊天机器人,而是真正能读取数据库状态、执行只读分析的操作者。
1.3 适用场景与边界划分
虽然这个组合很诱人,但我不建议把所有运维工作都交给 AI。我在设计工具集时,把场景分成了三类:
- 适合交给 AI 的:日常巡检、慢查询分析、连接数查看、锁状态诊断、索引使用情况分析、EXPLAIN 结果解读、表结构查看等只读类操作。
- 需要谨慎对待的:需要写操作的变更类动作,比如建索引、改配置、清理数据。这类操作建议只暴露“评估”能力,不暴露“执行”能力。
- 坚决不碰的:DROP TABLE、TRUNCATE、大量 UPDATE/DELETE、账号权限修改等高危动作,在服务端层面直接做白名单拦截。
这个边界会在服务端代码里强制约束,而不是指望 AI 自觉。后面讲实现的时候,你会看到我是如何在工具层就杜绝写操作的。
2. 平台整体架构与核心设计
2.1 MCP 服务端到底长什么样、怎么工作
先看 MCP 协议层的基本模型,它包含四个核心概念:
- Tools(工具):AI 可调用的具体函数,例如“执行只读 SQL”“查看当前连接列表”。模型根据系统提示和用户问题决定是否调用。
- Resources(资源):可暴露给模型的静态或动态数据,例如服务器配置信息、监控报表。资源通常用于给模型补充上下文。
- Prompts(提示词):预置的指令模板,帮助模型按特定套路执行任务,例如“慢查询分析模板”。
- Transport(传输层):客户端与服务端之间的通信方式,最常见的是标准输入输出(stdio)和 SSE/HTTP。
我的平台主要依赖 Tools 层,因为诊断动作本质上是“模型发起调用、工具执行并返回结果”的循环。
调用流程可以简单理解成:用户用自然语言提问 → AI 模型判断需要调用某个工具 → 通过 MCP 客户端发起工具调用请求 → 服务端连接 MySQL 执行查询 → 返回格式化结果 → 模型基于结果继续推理和回答。整个过程中,模型是决策者,服务端是执行者。
2.2 数据流与分层设计
我在设计时把它分成三层,职责清晰:
- 接入层:MCP 服务端入口,负责处理协议握手、工具注册、请求分发。这一层不写任何业务逻辑。
- 工具层:定义每一个运维动作,比如“查看慢日志”“分析索引”。工具函数做参数校验、调用数据层、格式化返回结果。
- 数据层:负责 MySQL 连接管理、SQL 安全过滤、查询超时控制。数据层是安全底线所在。
这种分层的好处是:将来想加一个新工具,只需要在工具层写一个函数并注册,不需要改动其他逻辑。我把所有工具做到同一个服务进程里,方便部署和管理;如果工具量太大,也可以拆成多个 MCP 服务按需挂载。
2.3 技术选型的理由
我选择了 Python + 官方 MCP SDK + PyMySQL 这套组合,理由有三条:
- 生态成熟:MCP 官方 Python SDK 维护最活跃,FastMCP 装饰器模式写起来极快,适合快速验证。
- 数据库连接方便:PyMySQL 是纯 Python 实现,安装简单,不需要编译原生依赖,在大多数 Linux 服务器上都能直接跑。
- 和 AI 工具链天然契合:Python 生态里的类型注解、数据格式化、日志工具都能直接复用,后面想扩展解析能力也容易。
如果你想用 Node.js 或 Go,MCP 社区也有对应 SDK,但我在对比后认为 Python 版本对“工具注册 + 参数校验”的支持最完善,尤其是 FastMCP 的 Pydantic 参数校验,能帮我们省掉大量防御性代码。
3. 从零落地开源服务端:核心环节拆解
3.1 项目初始化与依赖清单
我建议先建一个干净的虚拟环境,避免污染系统 Python。依赖非常简单:
mkdir mysql-mcp-ops && cd mysql-mcp-ops python3 -m venv .venv source .venv/bin/activate pip install "mcp[cli]" pymysql cryptography python-dotenv这里解释一下每个依赖的用途:
mcp[cli]:MCP 官方 Python SDK,附带了调试命令行工具 mcp,方便本地跑 Dev 模式验证工具是否正常注册。pymysql:纯 Python 的 MySQL 驱动,不需要编译。cryptography:PyMySQL 连接 MySQL 8+ 时做认证插件(caching_sha2_password)必需。python-dotenv:从 .env 文件读取数据库连接配置,避免把密码写死在代码里。
项目结构保持扁平:
mysql-mcp-ops/ ├── .env # 数据库连接等敏感配置 ├── server.py # MCP 服务端入口 ├── db.py # 数据库连接与安全过滤 ├── tools/ # 工具集目录 │ ├── __init__.py # 注册工具到服务端 │ ├── inspect.py # 连接信息、状态变量 │ ├── slow_query.py # 慢查询分析 │ ├── schema.py # 表结构、索引查看 │ └── processlist.py # 当前连接与锁信息 └── requirements.txt3.2 数据库连接管理与安全设计
这是整个平台最核心、也最不能含糊的部分。我的思路是:服务端数据库连接使用专用只读账号,该账号在 MySQL 侧只授予 SELECT、SHOW VIEW、PROCESS 等只读权限,从数据库层面杜绝写操作。
# db.py import os import pymysql from pymysql.cursors import DictCursor from dotenv import load_dotenv load_dotenv() DB_CONFIG = { "host": os.getenv("MYSQL_HOST", "127.0.0.1"), "port": int(os.getenv("MYSQL_PORT", "3306")), "user": os.getenv("MYSQL_USER", "ops_reader"), "password": os.getenv("MYSQL_PASSWORD", ""), "charset": "utf8mb4", "cursorclass": DictCursor, "connect_timeout": 5, "read_timeout": 10, "write_timeout": 5, } def get_connection(): return pymysql.connect(**DB_CONFIG)这里有几个细节值得注意:
read_timeout设置为 10 秒,避免慢 SQL 拖垮整个工具服务。万一某个查询超过 10 秒没返回,连接会主动断开并报错。charset必须用utf8mb4,因为很多业务表里会有 emoji 或生僻字,用旧版 utf8 会导致转码异常。- 每次调用工具都新建连接、用后即关。虽然连接池更高效,但运维工具调用频率不高,简单连接反而避免连接泄漏问题。
然后在数据库侧创建只读账号,这一步建议由 DBA 执行:
CREATE USER 'ops_reader'@'%' IDENTIFIED BY 'YourStrongPassword'; GRANT SELECT, SHOW VIEW, PROCESS ON *.* TO 'ops_reader'@'%'; GRANT SELECT ON performance_schema.* TO 'ops_reader'@'%'; FLUSH PRIVILEGES;注意PROCESS权限是查看 SHOW PROCESSLIST 所必需的,但如果你的安全策略较严,也可以不授,只靠information_schema.PROCESSLIST做部分查看。performance_schema用于读取部分诊断数据,按需授权。
3.3 核心工具函数的实现
工具层是我花时间最多的地方。我最终保留了 6 个工具,覆盖了日常巡检和故障排查的大部分场景。逐个看核心实现。
第一个工具:执行只读查询。这是最基础但也是最危险的工具,所以安全校验必须做足:
# tools/inspect.py import re import json from mcp.server.fastmcp import FastMCP from db import get_connection # SQL 白名单校验:只允许以这些关键字开头的语句 ALLOWED_PREFIX = ( "select", "show", "explain", "describe", "desc", "with", "show full", "show create", ) BLOCK_PATTERNS = [ r"\b(insert|update|delete|drop|truncate|alter|create|grant|revoke)\b", r"\b(mysql\.user|mysql\.db)\b", ] def _check_read_only_sql(sql: str): sql_stripped = sql.strip().lower().rstrip(";") if not sql_stripped.startswith(ALLOWED_PREFIX): raise ValueError(f"仅支持 SELECT/SHOW/EXPLAIN/DESCRIBE 语句") for pattern in BLOCK_PATTERNS: if re.search(pattern, sql_stripped, re.IGNORECASE): raise ValueError("检测到禁止的关键字或系统表访问") return sql_stripped def register_inspect_tools(mcp: FastMCP): @mcp.tool() def exec_query(sql: str, limit: int = 50) -> str: """在 MySQL 上执行只读查询并返回结果。limit 控制最大返回行数,默认 50,最大 200。""" sql = _check_read_only_sql(sql) if limit > 200: limit = 200 try: conn = get_connection() with conn.cursor() as cur: cur.execute(sql) # 如果用户没写 LIMIT,自动追加 if "limit" not in sql.lower(): sql_with_limit = sql.rstrip(";") + f" LIMIT {limit}" cur.execute(sql_with_limit) rows = cur.fetchmany(size=limit) # 转成 JSON 方便模型阅读 result = json.dumps(rows, default=str, ensure_ascii=False) return f"查询成功,返回 {len(rows)} 行:\n{result}" finally: if 'conn' in locals() and conn: conn.close()这段代码有三个关键防御点:关键字黑名单拦截、LLM 可能会“忘写” LIMIT 自动补、结果序列化成 JSON 让模型更容易解读。这里有个很实际的问题:模型生成的 SQL 不一定老实,有时会生成select * from 超大表这种危险查询,所以我强制补 LIMIT,同时上限 200 行,双保险。
第二个工具:查看当前连接和锁状态。这是故障排查高频动作:
# tools/processlist.py from mcp.server.fastmcp import FastMCP from db import get_connection import json def register_processlist_tools(mcp: FastMCP): @mcp.tool() def show_processlist() -> str: """查看当前 MySQL 所有活跃连接,包括用户、来源 IP、状态、正在执行的 SQL。用于排查连接数过高和锁问题。""" conn = get_connection() try: with conn.cursor() as cur: cur.execute("SHOW FULL PROCESSLIST") rows = cur.fetchall() return f"当前活跃连接数:{len(rows)}\n" + json.dumps(rows, default=str, ensure_ascii=False) finally: conn.close() @mcp.tool() def show_innodb_status() -> str: """查看 InnoDB 引擎状态,主要用于分析死锁、锁等待和事务信息。""" conn = get_connection() try: with conn.cursor() as cur: cur.execute("SHOW ENGINE INNODB STATUS") row = cur.fetchone() # 原始输出很长,截取 Status 字段 status_text = row.get("Status", "") if row else "" return status_text[:3000] finally: conn.close()SHOW FULL PROCESSLIST有个坑:某条连接正在执行长 SQL 时,Info字段可能是 NULL,因为 MySQL 返回的是正在执行的语句,语句太长还会被截断。所以我在返回时做了default=str,避免 NULL 导致 JSON 序列化失败。
第三个工具:慢查询分析。这个最复杂,因为不同 MySQL 版本的慢日志存储方式不一样:
# tools/slow_query.py from mcp.server.fastmcp import FastMCP from db import get_connection import json def register_slow_query_tools(mcp: FastMCP): @mcp.tool() def show_slow_log(limit: int = 20) -> str: """查看最近产生的慢查询记录,返回 SQL 文本、耗时、锁等待时间、扫描行数等关键指标。""" conn = get_connection() try: with conn.cursor() as cur: # MySQL 8.0+ 且开启慢查询日志到表时使用 mysql.slow_log try: cur.execute( "SELECT start_time, query_time, lock_time, rows_examined, rows_sent, sql_text " "FROM mysql.slow_log ORDER BY start_time DESC LIMIT %s", (limit,) ) rows = cur.fetchall() return f"最近 {len(rows)} 条慢查询:\n" + json.dumps(rows, default=str, ensure_ascii=False) except Exception: # 如果没授权访问 slow_log 表,退化为 information_schema 信息 cur.execute( "SELECT VARIABLE_VALUE FROM information_schema.GLOBAL_STATUS " "WHERE VARIABLE_NAME LIKE 'Slow_queries'" ) row = cur.fetchone() return f"累计慢查询数:{row.get('VARIABLE_VALUE', 'N/A')}。提示:如需查看具体慢 SQL,请开启慢日志或授予对应权限。" finally: conn.close()这里我做了降级处理,不同环境权限不一样,服务端不应该因为访问失败就罢工。我在代码里 catch 住异常后,退化成返回慢查询总量的全局状态,至少给 AI 提供部分信息,让它知道系统里可能有多少慢查询需要关注。
第四个工具:查看表结构和索引。这是我实际使用频率最高的工具,因为 AI 分析 SQL 性能时,经常需要确认某个字段是否有索引:
# tools/schema.py from mcp.server.fastmcp import FastMCP from db import get_connection import json def register_schema_tools(mcp: FastMCP): @mcp.tool() def show_table_schema(table_name: str, database_name: str = None) -> str: """查看指定表的建表语句,包含所有字段定义和索引信息。用于分析 SQL 是否走了正确索引。""" conn = get_connection() try: with conn.cursor() as cur: schema_sql = "SHOW CREATE TABLE" if database_name: schema_sql += f" `{database_name}`.`{table_name}`" else: schema_sql += f" `{table_name}`" cur.execute(schema_sql) row = cur.fetchone() if not row: return f"未找到表 {table_name},请检查表名或库名是否正确。" # 结果是一个 dict,第二个字段是 Create Table create_stmt = list(row.values())[1] if len(row) > 1 else str(row) return create_stmt finally: conn.close()这个工具的妙处在于,模板字符串里对库名和表名都加了反引号,能有效避免 SQL 注入。虽然我们只读,但表名拼进 SQL 时如果不加过滤,模型可能生成奇怪的输入,反引号方案成本最低、效果最好。
3.4 注册所有工具并启动服务端
最后在入口文件里把所有工具注册好,然后用 FastMCP 启动:
# server.py from mcp.server.fastmcp import FastMCP from tools.inspect import register_inspect_tools from tools.processlist import register_processlist_tools from tools.slow_query import register_slow_query_tools from tools.schema import register_schema_tools import os mcp = FastMCP( "mysql-ops-server", instructions="你是 MySQL 智能运维助手。根据用户问题调用工具进行诊断,所有操作必须走只读工具,严禁尝试写操作。", ) # 注册工具集 register_inspect_tools(mcp) register_processlist_tools(mcp) register_slow_query_tools(mcp) register_schema_tools(mcp) if __name__ == "__main__": # 默认走 stdio 传输,适合对接本地客户端 mcp.run(transport="stdio")启动之后,可以用 SDK 自带的调试命令验证工具是否注册成功:
mcp dev server.py这个命令会启动一个开发调试界面,你能看到所有注册的工具列表、参数定义,还能手动模拟调用。我强烈建议在接 AI 客户端之前,先用这个工具把所有函数手动调一遍,确认返回格式符合预期,不然很有可能客户端那边报半天错,结果是服务端工具本身出了问题。
4. 对接交互式 AI 助手,让运维对话化
4.1 客户端选择与配置流程
服务端就绪后,接下来就是接入交互式 AI 客户端,让用户通过自然语言操作。我测试了两种主流客户端:桌面版 Claude 和命令行 Codex,以及一种自己用 MCP SDK 写的极简客户端。原理都一样,只需要在客户端配置里加上我们服务端的启动命令。
以 Claude Desktop 为例,配置文件在claude_desktop_config.json里加一段:
{ "mcpServers": { "mysql-ops": { "command": "python", "args": ["/绝对路径/mysql-mcp-ops/server.py"], "env": { "MYSQL_HOST": "127.0.0.1", "MYSQL_PORT": "3306", "MYSQL_USER": "ops_reader", "MYSQL_PASSWORD": "YourStrongPassword" } } } }如果你的服务端跑在远程机器上,就不能用 stdio 了,需要改成 SSE 模式:
# server.py 中改成 mcp.run(transport="sse", host="0.0.0.0", port=8000)客户端配置随之改为:
{ "mcpServers": { "mysql-ops": { "url": "http://你的服务器:8000/sse" } } }但我要提醒一下:远程模式意味着 AI 客户端可以跨网络连接你的数据库运维服务端,安全风险显著提升,必须在服务端加鉴权层(比如 API Key),否则不建议直接暴露到公网。
4.2 实战演示:用自然语言完成一次慢查询分析
配置好之后,我做的第一件事就是模拟一次真实故障排查。我在测试库造了几十万条数据,故意在某个表里删掉一个关键索引,然后执行一条很慢的查询,把这个查询塞进慢日志。接着用 AI 客户端问:
“帮我看看最近有没有慢查询,分析一下原因,并给出优化建议。”
AI 会这样工作:它先调用show_slow_log工具,拿到最近慢查询列表,发现有一条SELECT * FROM orders WHERE user_id = 123 AND amount > 100耗时 4.2 秒;然后它调用show_table_schema查看orders表结构,确认user_id字段没有索引;再调用exec_query跑一条EXPLAIN SELECT ...,看到全表扫描的标记;最后综合这些信息给出优化建议:为user_id和amount建立联合索引。
整个过程我一行 SQL 都没手写。AI 自己决定调用什么工具、传什么参数、如何解读结果。这就是 MCP 的威力所在:模型是决策者,服务端是执行者,两者之间通过标准协议高效协作。
4.3 权限与审计,运维的最后底线
接入 AI 助手后,权限控制反而更重要了。我在整个项目里贯彻了“三层防守”的思路:
- 数据库层:使用只读账号,从根上杜绝写操作。这一步最有效,因为就算服务端代码出了漏洞,数据库权限也能兜底。
- 应用层:SQL 关键字白名单 + 黑名单校验,防止模型生成危险语句。前面代码里的
_check_read_only_sql就是干这个的。 - 使用层:AI 客户端的对话记录天然可审计,建议开启会话日志。一旦出了事故,可以回溯到是哪次调用、什么参数导致了问题。
另外,我还给服务端加了一个简单的请求日志功能,每次工具调用都会记录时间、工具名、参数、返回行数:
# 在工具函数里统一加装饰器 import logging, time, functools def audit_log(func): @functools.wraps(func) def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) logging.info( f"[AUDIT] tool={func.__name__} params={kwargs} elapse={time.time()-start:.2f}s result_len={len(str(result))}" ) return result return wrapper建议生产环境把审计日志接入统一日志平台,方便事后排查和告警联动。
5. 实操踩坑记:常见问题与排查技巧
5.1 MCP 服务端启动失败或客户端连不上
这是新手最容易遇到的第一道坎。我遇到的情况主要有三种:
- Python 解释器路径不对:客户端配置里
command写的是python,但你的虚拟环境 Python 不在 PATH 里。解决方案是在配置里写绝对路径,比如/root/mysql-mcp-ops/.venv/bin/python。 - 依赖没装进同一个环境:如果你在虚拟环境里装了依赖,但客户端用的是系统 Python 启动服务端,会直接报 ModuleNotFoundError。建议启动前先用
which python确认路径。 - SSE 端口被防火墙挡住:远程模式下客户端连不上,第一反应
curl http://你的服务器:8000/sse看看通不通,不通就先查防火墙和安全组。
排查技巧:不要瞎猜,先在命令行手动跑一次python server.py看有没有报错,这能排除 80% 的环境问题。
5.2 模型生成的 SQL 不理想,或者结果解析失败
模型虽然聪明,但生成的 SQL 偶尔还是让我哭笑不得。比如它会在SHOW CREATE TABLE语句里多加一个分号,或者在EXPLAIN后面跟一整条 INSERT 语句。我发现最有效的防御不是反复 prompt 纠正,而是在代码里做模糊容忍:
# 统一清理掉末尾分号、多余空白 sql = sql.strip().rstrip(";").strip() # 如果同时出现多个分号,只保留第一段 if ";" in sql: sql = sql.split(";")[0].strip()另外,MySQL 返回的Decimal、datetime类型不能被标准 JSON 序列化,必须加default=str。我在第一版代码里忽略了这个问题,导致 AI 客户端报 “JSON serialization error”,排查了半天才发现是日期字段没处理。
5.3 返回数据量过大导致会话上下文爆炸
AI 客户端的上下文窗口是有限的。如果你执行一条SELECT * FROM 大表,虽然服务端只返回 200 行,但这 200 行可能包含非常长的文本字段、二进制字段,直接把上下文塞爆。我的解决方案是在工具层做两层截断:
- 服务端限制行数上限不超过 200。
- 单次返回内容超过 3000 字符时,自动做截断并加提示:“结果过长已截断,前 N 字符。”
这样能保证 AI 客户端始终有足够上下文处理最核心的信息,而不是被一堆无关字段淹没。
5.4 安全方面的踩坑:权限被低估了
我在测试时曾偷懒用 root 账号连接服务端,结果 AI 在一次推理中“自作主张”生成了一条ALTER TABLE语句。虽然我们的 SQL 白名单拦截了它,但这件事给我提了个醒:永远不要依赖 AI 的自觉,永远在工具层强制校验,永远使用最小权限账号。这条金标准现在写在项目 README 的最前面。
另一个容易被忽略的点是:PROCESS权限虽然只是查看进程列表,但它能看到其他用户正在执行的 SQL 文本,如果生产库有敏感查询,这个权限可能涉及合规问题。建议根据实际安全策略评估是否授予。
6. 后续扩展思路与个人体会
做到这一步,平台已经能覆盖日常巡检和初步诊断了。但我觉得它还有很大的扩展空间,列几个我认为值得继续做的方向:
- 扩展数据源:MCP 服务端不止可以接 MySQL,还可以接 Redis(查看 key 分布、慢日志)、PG(长事务、死锁)、Elasticsearch(慢查询、集群状态),做成一个统一的“数据库智能助手”。
- 对接告警平台:把 MCP 服务端挂在告警回调里,让 AI 在收到告警时自动做初步诊断,并输出分析报告和安全建议。
- 增加运维知识库:把内部的 SQL 规范、索引规范、故障复盘文档通过 MCP Resources 暴露给模型,让回答更贴合团队实践。
- Webhook 联动:AI 分析完后,可以再通过另一个工具对接工单系统,自动创建优化任务,形成闭环。
最后说一点个人体会。我最初做这个项目,只是想省掉半夜爬起来手敲 SQL 的麻烦。做完之后最大的感受是:MCP 给运维自动化的想象力不在哪一条具体的 SQL,而是它把“AI 编排工具”这件事真正标准化了。以前我们写自动化脚本,是在对抗不确定的工具接口;现在只需要暴露能力,剩下的判断和编排可以交给 AI。当然,前提是安全边界做扎实。
如果你也在研究 MCP 和数据库运维的结合,建议先从只读巡检这类低风险场景开始跑通全链路,踩过一轮坑之后再考虑扩大工具集。这套链路跑通之后,你会明显感觉到,深夜看告警这件事,终于不再那么孤独了。