ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Yuxi MySQL 报表技能(mysql-reporter):从 SQL 查询到可视化图表的完整实战指南

Yuxi MySQL 报表技能(mysql-reporter):从 SQL 查询到可视化图表的完整实战指南 Yuxi MySQL 报表技能mysql-reporter从 SQL 查询到可视化图表的完整实战指南【免费下载链接】Yuxi可私有部署的多租户知识智能体平台统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi本篇技术指南以 Yuxi 内置技能mysql-reporter位于 backend/package/yuxi/agents/skills/buildin/mysql-reporter/SKILL.md为核心系统讲解如何让 Agent 通过沙盒终端脚本安全地查询 MySQL 数据库、探查表结构与字段语义、执行只读 SQL并借助 Charts MCP 生成可视化报表。读完本文你将掌握该技能的完整操作流程、环境变量配置边界、安全校验机制SQL 注入拦截、超时控制、结果截断以及它与 Yuxi Skill 运行时依赖解析、授权投影的集成原理能够直接在私有部署的多租户知识智能体平台上复现并扩展查询数据库 → 生成业务报表的能力。技能定位Yuxi 内置技能体系中的数据库报表模块Yuxi 是一个可私有部署的多租户知识智能体平台其 Agent 能力通过 Skill技能机制进行编排。内置技能统一在 backend/package/yuxi/agents/skills/buildin/init.py 中注册mysql-reporter是其中之一其注册信息如下BuiltinSkillSpec( slugmysql-reporter, source_dir_SKILLS_ROOT / mysql-reporter, description基于 MySQL 数据库生成查询报表和可视化图表适合分析业务指标、统计趋势并用 Charts MCP 展示结果。, version2026.06.05, mcp_dependencies(mcp-server-chart,), ),从这份声明可以看出两个关键事实该技能依赖 MCP 服务mcp-server-chart即文档中提到的 Charts MCP用于把查询结果渲染为图表技能的元数据slug、description、version来自 SKILL.md 的 frontmatter而 Yuxi 的 Skill 解析器会校验 frontmatter 中的name、slug、description字段见 backend/package/yuxi/agents/skills/service.py 中_parse_skill_markdown的校验逻辑。技能目录结构如下buildin/mysql-reporter/ ├── SKILL.md # 技能定义流程、约束、允许的工具 └── scripts/ ├── _mysql_common.py # 共享连接工具配置加载 连接创建 ├── list_tables.py # 列出库中所有表 ├── describe_table.py # 描述指定表结构 └── query.py # 执行只读 SQL 查询一、技能工作原理终端脚本 图表工具的组合式报表根据 SKILL.md 的定位描述MySQL 报表技能的目标是根据用户的指令通过终端脚本访问 MySQL 数据库并结合图表绘制工具构建 SQL 查询报告。典型使用场景包括统计销售数据、分析用户行为、生成业务报表、查询业务指标等。当用户在对话中提出这类需求时技能就会被激活。它不直接暴露任意 MySQL 客户端给 Agent而是通过scripts/下三个受控的 CLI 脚本提供受限的数据库访问能力从机制上约束 Agent 只能执行白名单内的只读操作详见下文安全机制部分。二、标准操作流程7 步技能文档给出了 Agent 执行报表任务的完整流程每步都对应具体的 CLI 操作理解用户指令明确报表的需求和目标指标口径、时间范围、分组维度、输出形式进入技能目录通过 terminal 执行cd /home/gem/skills/mysql-reporter该路径是沙盒中技能投影后的目录在 Yuxi 的 Skill 运行时中用户授权技能会被投影到只读的虚拟技能路径见 backend/package/yuxi/agents/skills/runtime.py 中build_runtime_skills对VIRTUAL_SKILLS_PATH/{slug}/SKILL.md的映射查看可用表执行uv run scripts/list_tables.py如果脚本提示缺少 MySQL 配置按环境变量缺失处理一节回复用户而不是自行猜测查看表结构必要时执行uv run scripts/describe_table.py --table 表名执行查询生成正确且高效的只读 SQL通过uv run scripts/query.py --sql SQL语句 --timeout 60获取结果生成图表使用 Charts MCP即mcp-server-chart将结果可视化为图表嵌入报表将图表以 markdown 图片格式描述嵌入最终报表。三个脚本均使用 uv 的脚本依赖声明运行PEP 723 内联依赖元数据见各脚本文件头部的# /// script注释块依赖pymysql1.1.0因此无需手动安装依赖即可执行。三、环境变量Agent 沙盒专属配置技能文档强调了一个容易踩坑的关键约束脚本只读取 Agent 沙盒中的环境变量不读取后端.env或 Docker Compose 变量。这意味着 MySQL 连接配置必须在**个人设置中的「沙盒环境变量」**里配置而不是在部署配置文件里。这一点在 scripts/_mysql_common.py 的load_mysql_config()中有直接体现——它只从os.getenv读取变量必填默认值说明MYSQL_HOST是无MySQL 主机地址MYSQL_USER是无连接用户名MYSQL_PASSWORD是无连接密码敏感严禁输出到报表MYSQL_DATABASE是无目标数据库名MYSQL_PORT否3306端口号MYSQL_DATABASE_DESCRIPTION否默认 MySQL 数据库数据库业务说明用于辅助 Agent 理解表和指标含义配置加载逻辑源码级细节config: dict[str, Any] { host: os.getenv(MYSQL_HOST), user: os.getenv(MYSQL_USER), password: os.getenv(MYSQL_PASSWORD), database: os.getenv(MYSQL_DATABASE), port: int(os.getenv(MYSQL_PORT) or 3306), charset: utf8mb4, description: os.getenv(MYSQL_DATABASE_DESCRIPTION) or 默认 MySQL 数据库, }四个必填项任一缺失时会抛出MySQLConnectionError错误信息形如MySQL configuration missing required key: host, please check your environment variables.。缺失配置时的正确处置技能文档明确要求不要继续猜测连接信息或编造报表明确告诉用户需要在个人设置 → 沙盒环境变量中配置缺失的MYSQL_*变量提醒用户保存后仅对新建沙盒生效需要重新发起任务或新建会话后再执行。关于沙盒环境变量仅对新建沙盒生效的语义可以从 Yuxi 的沙盒工作区机制推断Agent 沙盒是独立的运行时环境环境变量随沙盒创建时注入已有沙盒不会热更新配置因此技能文档要求重新发起任务或新建会话以获得全新的沙盒实例。四、三个 CLI 脚本的源码级解析4.1 共享连接层_mysql_common.py这是三个脚本共同的依赖模块单元测试 backend/test/unit/agents/skills/test_mysql_reporter_scripts.py 中test_mysql_reporter_scripts_share_common_connection_helpers验证了三个脚本引用的load_mysql_config与create_connection正是来自该模块负责配置加载见上文从环境变量读取并校验必填项连接创建create_connection()内置 3 次重试采用指数退避time.sleep(2 ** attempt)即 1s、2s连接参数包括connect_timeout10、read_timeout60、write_timeout30、autocommitTrue、游标使用DictCursor返回字典形式的行便于按列名取值。4.2list_tables.py列出全部表命令uv run scripts/list_tables.py内部执行SHOW TABLES将结果逐行列出若配置了MYSQL_DATABASE_DESCRIPTION会在输出顶部附上数据库说明: {description}帮助 Agent 理解业务上下文如销售库空库时返回数据库中没有找到任何表出错时向 stderr 输出获取表名失败: {异常}并返回退出码 1。4.3describe_table.py描述表结构命令uv run scripts/describe_table.py --table 表名--table为必填参数输出格式为制表符分隔的表格字段名 / 类型 / NULL / 键 / 默认值 / 额外 / 备注通过查询information_schema.COLUMNS补充字段注释COLUMN_COMMENT并执行SHOW INDEX FROM汇总索引信息如PRIMARY: id, user_id这两步失败时静默降级不影响主结构输出安全校验MySQLSecurityChecker.validate_table_name()要求表名匹配^[a-zA-Z_][a-zA-Z0-9_]*$字母/下划线开头仅含字母数字下划线非法表名直接抛出ValueError(表名包含非法字符请检查表名)杜绝表名注入。单元测试test_mysql_reporter_describe_table_name_security_validates_known_cases覆盖了users、_audit_log通过1users、user-name、users;drop被拒绝的场景。4.4query.py执行只读 SQL 查询命令格式uv run scripts/query.py --sql SQL语句 --timeout 60--sql必填要执行的 SQL--timeout可选默认 60 秒合法范围为1600 秒validate_timeout校验超时抛出QueryTimeoutError。查询超时机制查询在单线程线程池ThreadPoolExecutor(max_workers1)中执行主线程通过future.result(timeouttimeout)等待。超时后取消 future、关闭连接并抛出QueryTimeoutError从而避免信号处理带来的生成器问题源码注释明确说明了这一设计动机。结果格式化与截断查询结果以 markdown 表格输出含表头分隔线默认最多展示 50 行总字符数超过 10,000 时按行截断并给出警告⚠️ 警告: 查询结果过大只显示了前 N 行共 M 行。建议使用更精确的查询条件或使用 LIMIT 子句来减少返回的数据量。单列宽度最大 50 字符防止超长字段破坏排版。智能错误提示build_query_error()会根据异常特征给出针对性建议超时 → 建议减少数据量WHERE 过滤、使用 LIMIT、或增大--timeout最大 600 秒table ... doesnt exist→ 建议运行scripts/list_tables.py查看可用表名column ... doesnt exist→ 建议运行scripts/describe_table.py查看表结构SQL 中出现%被当作参数占位符时 → 提示将百分号写成双百分号%%或改用参数化查询。五、安全机制只读校验与注入防护源码级证据query.py中的MySQLSecurityChecker.validate_sql()实现了多层防护这是该技能安全设计的核心注释剥离先移除--行注释与/* ... */块注释避免用注释绕过白名单判断语句白名单SQL 必须以SELECT、SHOW、DESCRIBE、EXPLAIN之一开头ALLOWED_OPERATIONS危险关键字黑名单DROP、DELETE、UPDATE、INSERT、CREATE、ALTER、TRUNCATE、REPLACE、LOAD、GRANT、REVOKE、SET、COMMIT、ROLLBACK、UNLOCK、KILL、SHUTDOWN全部禁止多语句拦截剥离结尾分号后若语句内部仍含;判定非法阻止SELECT ...; DROP TABLE ...这类拼接攻击注入特征检测正则匹配or 11、union select、exec(、xp_cmdshell、sleep(、benchmark(、waitfor delay等模式以及; 危险关键字组合。单元测试test_mysql_reporter_query_security_validates_sql_and_timeout给出了完整用例矩阵例如输入判定SELECT * FROM users✅ 通过show tables/DESCRIBE users/EXPLAIN SELECT ...✅ 通过SELECT 1;单个结尾分号✅ 通过DELETE FROM users❌ 拒绝SELECT * FROM users WHERE id 1 OR 11❌ 拒绝SELECT * FROM users UNION SELECT password FROM admin❌ 拒绝SELECT * FROM users; DROP TABLE users❌ 拒绝/* 多行注释 */ SELECT 1✅ 通过注释被剥离后白名单命中超时参数的校验同样严格必须为int且在 1600 之间None、0、601、字符串60均被拒绝。六、关键约束Agent 必须遵守的行为红线技能文档明确列出了 Agent 在执行报表任务时的约束这些约束从产品层面对齐了上文的代码级安全机制SQL 正确且高效避免全表扫描应善用索引可先通过describe_table.py查看索引信息与LIMIT必须走本技能脚本MySQL 操作一律通过scripts/下的 CLI 脚本执行不要调用平台内置的 MySQL tools内置 MySQL 工具可能不具备同样的只读白名单与审计能力敏感信息保护不得在报表或错误说明中输出MYSQL_PASSWORD等敏感环境变量的值只能说明缺少哪些变量名图表必须显式嵌入Charts MCP 的返回结果默认不会渲染最终报表必须以描述的 markdown 图片格式嵌入只输出结论最终回复只包含与报表相关的结论不要返回原始 SQL 查询语句。七、允许的工具清单技能运行时只向 Agent 暴露以下工具集与 SKILL.md 的允许的工具一节一致terminal执行scripts/list_tables.py、scripts/describe_table.py、scripts/query.py三个受控脚本Charts MCPmcp-server-chart生成可视化图表网络检索工具仅在必要时补充背景信息。工具的白名单化正是 Yuxi Skill 依赖机制的落地技能在BuiltinSkillSpec中声明mcp_dependencies(mcp-server-chart,)运行时再通过resolve_skill_gated_tools/build_dependency_bundle见 backend/package/yuxi/agents/skills/runtime.py把声明的 MCP 与工具按需挂载到当前 Agent Run未授权的工具不会出现在该技能上下文中。八、与 Yuxi Skill 运行时的集成方式要理解该技能如何生效可以看 Yuxi Skill 运行时的三个环节注册与安装内置技能由BUILTIN_SKILLS列表统一注册slug 为mysql-reporter版本2026.06.05用户侧启用后技能数据写入 Skill 表见 backend/package/yuxi/agents/skills/repository.py内置技能默认以global读范围共享BUILTIN_SKILL_SHARE_CONFIG {access_level: global, ...}授权投影用户可访问的技能会被同步为只读投影目录sync_user_accessible_skills见 backend/package/yuxi/agents/skills/service.py即技能文档中cd /home/gem/skills/mysql-reporter所指向的沙盒内路径的来源投影过程中会拒绝符号链接并做哈希比对保证沙盒内看到的技能内容是可信快照运行时快照每次 Agent Run 启动时resolve_runtime_skills_for_context解析出effective_skills含依赖闭包展开与runtime_skills元数据并把根级SKILL.md的内容注入上下文Agent 据此理解技能的操作流程与约束见 backend/package/yuxi/agents/skills/runtime.py。因此mysql-reporter/SKILL.md不仅是一份给人看的说明更是运行时注入给模型的行为规范——流程、环境变量处理、关键约束都会被模型作为执行依据。九、实战演练从一条用户指令到一张报表结合以上内容一个完整的典型调用链如下以统计最近 7 天各地区的销售额为例用户 → 帮我统计最近 7 天各地区的销售额画成柱状图 │ ├─ 1. 理解需求指标销售额维度地区时间近7天输出柱状图 ├─ 2. cd /home/gem/skills/mysql-reporter ├─ 3. uv run scripts/list_tables.py # 确认有 orders、regions 等表 ├─ 4. uv run scripts/describe_table.py --table orders # 确认字段名与注释 ├─ 5. uv run scripts/query.py --sql SELECT r.name, SUM(o.amount) AS sales FROM orders o JOIN regions r ON o.region_id r.id WHERE o.created_at DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY r.name ORDER BY sales DESC --timeout 60 ├─ 6. 调用 Charts MCP 生成柱状图得到图片 URL └─ 7. 在报表中嵌入 各地区近7天销售额只输出业务结论执行第 3 步时若出现MySQL configuration missing required key: xxxAgent 应停止后续步骤按环境变量缺失处理要求用户去个人设置补配沙盒环境变量并说明需重新发起任务。十、可验证的测试与文档依据技能定义backend/package/yuxi/agents/skills/buildin/mysql-reporter/SKILL.md脚本实现backend/package/yuxi/agents/skills/buildin/mysql-reporter/scripts/_mysql_common.py、list_tables.py、describe_table.py、query.py技能注册backend/package/yuxi/agents/skills/buildin/__init__.py单元测试backend/test/unit/agents/skills/test_mysql_reporter_scripts.py覆盖共享连接工具、缺失配置报错、SQL/表名/超时校验矩阵、投影后 CLI 行为运行时与授权backend/package/yuxi/agents/skills/runtime.py、backend/package/yuxi/agents/skills/service.py、backend/package/yuxi/agents/skills/repository.py相关能力文档docs/agents/skills-management.mdSkill 管理与授权、docs/agents/mcp-integration.mdCharts MCP 接入总结mysql-reporter技能展示了 Yuxi 平台上受限数据库访问 可视化报表的标准范式通过终端脚本提供只读白名单仅SELECT/SHOW/DESCRIBE/EXPLAIN、注入拦截多语句、危险关键字、注入特征多重校验、资源保护1600 秒超时、10,000 字符与 50 行结果截断三层面管控再叠加沙盒环境变量注入与敏感信息不落盘原则让 Agent 既能自主完成从查表、看结构、写 SQL 到出图报表的完整链路又不会触碰数据写权限与凭据安全底线。对于需要在私有化环境中做业务指标统计、销售分析、用户行为洞察的团队直接启用该内置技能并按文档配置沙盒环境变量即可让 Agent 立刻具备可靠的 MySQL 报表生产能力。【免费下载链接】Yuxi可私有部署的多租户知识智能体平台统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表