yearning2-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@yearning2-mcp给 user 表加个索引,提个工单"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
yearning2-mcp
把 Yearning 2.x(SQL 审核平台)接入 MCP,让 Claude / Cursor / WorkBuddy 这类 AI 客户端 能直接查平台数据、提工单、执行只读查询。
零第三方依赖 —— 只用 Python 标准库。
pip install不会拖进 requests / pydantic 那一套能力分三层,边界在服务端硬拦 —— 只读 / 提交 / 拦截,不靠提示词约束、也没有
--force后门不碰审批 —— 审批类接口一律拒绝。工单只提交,执行与否由人决定
提到线上之前先过闸门 —— 数据源授权、审核人合法、SQL 类型自洽、两步确认,四道都过才发请求
适配 2.x —— 登录走根路径
/ldap·/login,业务接口在/api/v2/*
⚠️ 只适用于 Yearning 2.x
如果你用的是 Yearning 3.x,本项目不适用 —— 3.x 的查询走 WebSocket + msgpack, 登录接口与静态资源打包方式都不一样,2.x 的接口形态在这上面跑不通。
怎么判断自己用的是哪个版本:打开 Yearning 首页看静态资源路径。形如
/front/assets/js/chunk-*.js(webpack 打包)的是 2.x;app.<hash>.js 那种打包风格的是 3.x。
Related MCP server: MCP MySQL Server
快速开始
1. 安装
pip install yearning2-mcp # 或
uvx yearning2-mcp # 不安装,直接跑2. 配置凭据
推荐:写一份配置文件,别把密码塞进客户端的配置里(那通常是明文、还会被同步到别处)。
mkdir -p ~/.yearning
cat > ~/.yearning/config.json <<'JSON'
{
"endpoint": "http://yearning.example.com:8000",
"username": "your-account",
"password": "your-password",
"login_mode": "ldap"
}
JSON3. 接进 MCP 客户端
Claude Desktop 的 claude_desktop_config.json、Cursor 的 mcp.json、WorkBuddy 的
~/.workbuddy/mcp.json 都是同一个结构:
{
"mcpServers": {
"yearning2": {
"command": "yearning2-mcp"
}
}
}用 uvx 的话把 command 换成 "uvx"、args 加 ["yearning2-mcp"]。
不想写配置文件,也可以用环境变量(优先级高于配置文件):
{
"mcpServers": {
"yearning2": {
"command": "yearning2-mcp",
"env": {
"YEARNING_ENDPOINT": "http://yearning.example.com:8000",
"YEARNING_USERNAME": "your-account",
"YEARNING_PASSWORD": "your-password"
}
}
}
}4. 先自检,再信任
yearning2-mcp --check-config # 看解析到的配置对不对(不会打印密码)
yearning2-mcp --selftest # 连通性 / 登录 / 权限 / 拦截规则,一次跑完两个都过了,再回到 MCP 客户端里把这个 server 信任 / 启用。多数客户端需要重启一次才加载新 server。
工具清单
14 个工具,按用途分三组。
只读(8 个,只发 GET)
工具 | 作用 |
| 连通性、登录方式、账号、角色、真实姓名、各环境实测可提工单的数据源数量。排查问题先调这个 |
| 某环境某类型下我实际可用的数据源清单 + 可选审核人。提工单前必调 |
| 用户数 / 工单总数 / 查询总数 / 数据源数 |
| 环境(IDC)列表 |
| 各数据源查询次数分布(前 30 个) |
| 首页公告板配置 |
| 工单执行明细分页,可按环境 / 数据源 / 时间过滤 |
| 受控的只读 GET 透传,用于读上面没覆盖的只读接口 |
查询(3 个,走「先提工单、批准后查询」的官方流程)
工具 | 作用 | 需要确认 |
| 申请某个环境的查询权限(进审核流程) | ✅ 两步 |
| 看查询工单状态: | — |
| 执行只读 SQL( | — |
工单(3 个)
工具 | 作用 | 需要确认 |
| 提交 DDL / DML 工单(进审核流程,不会立即执行) | ✅ 两步 |
| 我提交过的工单列表,可按状态 / 关键字 / 日期区间筛 | — |
| 撤销我自己的待审工单 / 结束我自己的查询权限 | ✅ 两步 |
接好之后不需要记工具名,直接说人话就行:
你说 | 会调 |
「Yearning 能连上吗」/「我有什么权限」 |
|
「我在 prod 能提哪些库的工单」 |
|
「Yearning 上有多少工单和用户」 |
|
「列一下 Yearning 有哪些环境」 |
|
「哪个库被查得最多」 |
|
「查工单,第 2 页每页 20 条」 |
|
「把 user 表加个索引,提个工单」 |
|
「帮我查一下 xxx 库的订单表有多少行」 |
|
「我刚提的那个工单批了吗」 |
|
「我今天的工单」 |
|
「我有哪些执行失败的工单」 |
|
「撤了刚才那个工单」 |
|
安全模型
拦截与闸门写在 src/yearning2_mcp/safety.py 与 writes.py,是执行层而不是提示词。
调用方(包括模型本身)绕不过去,除非改这两个文件 —— 属刻意行为,改完请同步改本文档与 SECURITY.md。
三层能力
层 | 入口 | 说明 |
只读 READ |
| 只发 GET。写操作型 GET( |
提交 WRITE | 6 个专用工具 | 不接受任意路径:方法+路径写死在 |
拦截 BLOCKED | 无入口 | 审批类( |
四道闸门(提工单 / 执行查询时)
数据源授权 —— 用
GET /api/v2/fetch/source?idc=&tp=取真实授权清单,数据源必须命中。 命中的是清单里的原始字符串(线上存在" db-readonly"这种带前导空格的脏记录, 比对时 strip、发出去时原样)。审核人合法 ——
assigned必须来自服务端给的可选审核人清单。留空且清单非空时,直接把可选值列出来。SQL 与工单类型自洽 ——
ddl工单必须全是 DDL 语句,dml工单必须全是 DML。SELECT提工单会被拒(该走查询工单),DDL/DML 混写按 DML 归类。两步确认 —— 提工单、撤单、结束查询权限这四类动作默认只返回预览, 要带
confirm=true再调一次才真发请求。yearning_run_query不在其中: 它是只读且可重复执行的,每次都要求确认会让探索式查询没法用 —— 它的保护来自 「SQL 只读性校验」+「数据源必须属于已批准查询工单的环境」这两条。
执行查询额外补的洞
POST /api/v2/query/results 只看「有没有生效中的查询工单」,不校验数据源属于哪个环境。
批准了 A 环境照样能查 B 环境的库。yearning_run_query 因此先读查询工单的环境,
再要求数据源落在该环境的 query 授权清单里。
只读 SQL 的三条判定规则
writes.ensure_read_only() 不靠大黑词表(那会把 SELECT event, set_at FROM logs 误杀),
而是三条精确规则:
每条语句的首词必须是只读起始词(
SELECT/WITH/SHOW/DESC/DESCRIBE/EXPLAIN/TABLE/VALUES/HELP)WITH/EXPLAIN这类复合前缀,整条语句里不得再出现写动词不得出现文件读写词(
OUTFILE/DUMPFILE/LOAD_FILE)、危险函数(SLEEP/BENCHMARK/GET_LOCK) 与锁语义(FOR UPDATE/FOR SHARE/LOCK IN)
判定前先做单趟状态机去噪声:注释、字符串字面量、反引号标识符里的内容都不参与判断 ——
否则 SELECT '--' AS x 会被当成注释截断。语句数上限 50 条。
边界强制在哪里
三层边界都在 safety.py / writes.py 的执行层强制,不是提示词约束:
拒绝判定发生在任何 HTTP 请求发出之前;写动作只能从 WRITE_ACTIONS 白名单出去,
方法 + 路径写死,调用方只能填业务参数、无法自定义目标路径。
配置参考
查找顺序(命中即停)
--config指定的文件环境变量
YEARNING_CONFIG指向的文件(两者都是显式指定:文件不存在会直接报错,不会静默回落)~/.yearning/config.json./yearning.config.json
环境变量(始终优先于文件)
变量 | 说明 |
| 地址,如 |
| 登录账号 |
| 登录密码 |
|
|
| 配置文件路径 |
| 会话缓存路径,默认 |
| 日志路径,默认 |
运行期文件
路径 | 内容 |
| JWT + 真实姓名等会话缓存(POSIX 下权限 600)。按 endpoint 隔离,换实例不复用 |
| 运行日志,排障看这个。超过 2MB 自动轮转 |
命令行
yearning2-mcp # 启动 stdio MCP 服务(MCP 客户端默认这么调)
yearning2-mcp --check-config # 打印解析到的配置,不回显密码
yearning2-mcp --selftest # 对真实实例自检:TCP / 登录 / 身份 / 权限 / 只读接口 / 拦截规则
yearning2-mcp --selftest --report report.txt
yearning2-mcp --print-tools # 以 JSON 打印工具清单
yearning2-mcp --version--selftest 的退出码:0 全部通过,1 连接或登录失败,2 配置有问题。
从源码跑
本项目用 src/ 布局,所以要先装一次才能以模块方式启动:
git clone https://github.com/guanjwen/yearning2-mcp.git
cd yearning2-mcp
pip install -e . # 或 pip install .
yearning2-mcp --print-tools # 确认工具清单生成正常
yearning2-mcp --selftest # 对真实实例自检兼容性
项 | 情况 |
Yearning | 2.3.x(路由表取自上游 |
认证 | LDAP 已实测;本地账号走 |
只读能力 | 全部接口已在真实部署上实测 |
提工单 | 已实测到预览与全部闸门(含 4 条负向用例:越权数据源、非法审核人、类型不匹配、缺 confirm)。真实提交会真的产生线上工单,没有在别人的生产环境上做;提交与预览复用同一份请求体构造 |
执行查询 | 已实测闸门与拒绝路径;查询通道本身需要一条已批准的查询工单才能走通 |
审批 / 管理 | 不提供,也不打算提供 |
Python | 3.9 ~ 3.14(3.13 / 3.14 已实测;CI 覆盖全矩阵) |
平台 | Windows / Linux / macOS(纯标准库,无平台相关代码) |
第三方依赖 | 无 |
常见问题
现象 | 原因 / 处理 |
工具报「无法连接」 | 内网地址,先连上 VPN。客户端会自动绕开系统代理( |
工具报「登录失败」 | 账号密码错,或 LDAP 不可达。用 |
返回字符串 | 子路径写错了。这是 Yearning 对错误子路径的兜底响应,不是报错 |
报「环境没有添加流程」 | 该环境没配审批流程, |
| 你的账号在该环境该类型下没有授权。 |
| 先去 |
查询状态第一次显示已生效、再查变成已结束 | 上游行为: |
提工单返回「预览」而不是「已提交」 | 这是设计如此。确认无误后带 |
MCP 客户端里看不到工具 | 确认配置是合法 JSON;多数客户端需要重启才加载新 server |
改了服务端代码不生效 | MCP server 是长驻子进程,不会热重载。改完要重启 MCP 客户端 |
平台侧的安全问题(非本项目缺陷)
在真实环境中实测时发现的三个问题,都属于 Yearning 服务端,本项目只能在自己这一侧补闸门。 注意:绕过本 MCP 直接调这些接口,一样能命中。
GET /api/v2/fetch/perform以普通账号身份即可调用,响应体里带着执行人的 PBKDF2 密码哈希。 哈希不可逆,但 12 万轮 PBKDF2 对弱口令可以离线爆破,属未授权敏感信息泄露。 建议在FetchPerformList的返回结构里去掉password字段,或把该接口收进相应权限组。 本项目已主动把该接口拦掉,不让它经 MCP 进入对话记录。提工单接口(
SQLReferToOrder/ReferQueryOrder)在服务端一行权限校验都没有。ddl_source/dml_source的过滤只发生在GET /api/v2/fetch/source里 —— 也就是前端下拉框。直接POST /api/v2/common/order可以给任意数据源提工单。 本项目补上了这道闸门(闸门 1),但服务端该补的还是要补。/api/v2/query/results只看「有没有生效中的查询工单」,不校验数据源属于哪个环境。 批准了 A 环境,就能拿它查 B 环境的库。本项目在yearning_run_query里补了环境归属校验, 同样,服务端该补的还是要补。
贡献
见 CONTRIBUTING.md。核心约定两条:保持零依赖、 写操作必须走白名单 + 闸门,且不引入任何审批类能力。
许可
MIT。
本项目是独立实现的 HTTP 客户端,不包含 Yearning 的任何代码。 上游 cookieY/Yearning 采用 AGPL-3.0,两者互不影响。
致谢
cookieY/Yearning —— 接口形态与路由规则来自其 2.3.5 版源码
Model Context Protocol —— 协议规范
This server cannot be deployed
Maintenance
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Runtime permission, approval, and audit layer for AI agent tool execution.
- dataOAuthco.thinair
PostgreSQL, MySQL, and SQL Server in one session. 26 read-only MCP tools for AI agents.
Guard AI agents' PostgreSQL/MySQL access via MCP: SQL audit, auth, masking, write approval
13
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI models to interact with MySQL databases through a standardized interface, supporting queries, data manipulation, table inspection, and query performance analysis with secure prepared statements.47 npm22MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to safely query MySQL databases with read-only access by default, supporting table listing, structure inspection, and SQL queries with optional write operation control.16 npmMIT
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to securely interact with MySQL databases through tools for query execution, schema inspection, and transaction management. It features built-in safety controls like row limits and query validation to ensure safe and standardized database access.3,689 npm-
- AlicenseAqualityCmaintenanceEnables AI assistants to inspect and query a MySQL database through safe, structured tools, including schema discovery and read-only queries.9130 npmMIT