Skip to main content
Glama
zhouweico

mcp-yearning

by zhouweico

mcp-yearning

Yearning MCP Server - 让 AI 助手能够查询和管理 Yearning SQL 审核平台的工单与查询:浏览数据源与表结构、提交并审核 SQL 工单、执行只读查询等。

基于 Yearning REST / WebSocket API(/api/v2,JWT Bearer 认证);列表类与查询执行走 WebSocket,其余为 REST。

特性

  • 多协议传输stdio(默认)、ssestreamable-http,一套代码适配本地与远程场景

  • 接口认证:HTTP 传输支持 Bearer Token 保护,未授权请求返回 401

  • 原生账号密码登录:用户名/密码登录换取 JWT,401 时自动重新登录并重放请求,无需手工维护 Token

  • JWT 自动管理:登录态缓存并在 8 小时过期前(提前 0.5h)主动续登,全程无感

  • REST + WebSocket 统一封装:列表类接口(我的工单、审核列表、评论)与查询执行走 WebSocket,已封装为「连接→发一帧→收一帧→关闭」的伪 REST;查询执行额外用 msgpack 编解码

  • 信封解析:Yearning 恒返回 HTTP 200 + 信封 {payload, code:1200, text};非 1200 视为业务错误

  • Yearning 原生概念:直接以 数据源 / 库 / 表 / SQL 工单 / 审核流程 组织操作,读写一体

  • 危险操作防护:审核工单(agree)等高危操作带 destructiveHint 注解,撤回工单带 idempotentHint 注解,均需明确动作参数

  • 破坏性操作 MRTR 确认:同意工单(agree)等高危操作通过 MCP 2.0 Elicitation 机制弹出确认表单,需用户明确同意后才执行

  • MCP Resources:以 yearning:// URI 暴露用户信息、数据源列表等只读元数据,客户端可直接读取

  • Stateless HTTP:支持无状态 HTTP 模式,每次请求独立处理、无会话状态,适合 Serverless / 多副本部署

  • 灵活部署uvx 免安装运行、Docker 构建即用

前置准备

准备一个可访问的 Yearning 实例。你需要准备:

  • Yearning 地址(如 http://localhost:8000

  • 登录用户名 / 密码(常规账号或 LDAP 账号)

账号在 Yearning 内的角色决定你能看到哪些数据源、能提交/审核哪些工单;MCP Server 本身不做任何鉴权,仅原样转发请求。

快速开始

MCP 客户端(stdio,本地)

以 Claude Code 为例,在项目 .mcp.json 或全局 ~/.claude.json 中添加:

{
  "mcpServers": {
    "yearning": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mcp-yearning"],
      "env": {
        "YEARNING_URL": "http://localhost:8000",
        "YEARNING_USERNAME": "your-user",
        "YEARNING_PASSWORD": "your-password",
        "YEARNING_LOGIN_TYPE": "general",
        "YEARNING_READ_ONLY": "false"
      }
    }
  }
}

Cursor、OpenCode、Claude Desktop 等客户端的配置格式相同,核心均为 command: uvx + args: ["mcp-yearning"],按各客户端语法填入 YEARNING_* 环境变量即可。

Docker(公开镜像,免构建)

已发布公开镜像 ghcr.io/zhouweico/mcp-yearning:latest,无需本地构建。下面以 Claude Code 为例,说明如何用 docker 命令运行并配置 mcp-yearning。

方式一:stdio(由客户端拉起容器,适合本地集成)

在 Claude Code 的 .mcp.json 中直接用 docker 作为启动命令,客户端会以 stdio 管道与容器内服务通信:

{
  "mcpServers": {
    "yearning": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "-i", "--rm", "ghcr.io/zhouweico/mcp-yearning:latest"],
      "env": {
        "YEARNING_URL": "http://your-yearning:8000",
        "YEARNING_USERNAME": "your-user",
        "YEARNING_PASSWORD": "your-password"
      }
    }
  }
}

必须带 -i(保持 stdin 管道),否则容器内的 stdio 服务无法与客户端通信。

方式二:HTTP + 认证(容器独立运行,客户端远程连接,适合多客户端共享)

先启动容器:

docker run -d -p 8080:8080 \
  -e MCP_TRANSPORT=streamable-http \
  -e MCP_AUTH_TOKEN=your-strong-token \
  -e YEARNING_URL=http://your-yearning:8000 \
  -e YEARNING_USERNAME=your-user \
  -e YEARNING_PASSWORD=your-password \
  ghcr.io/zhouweico/mcp-yearning:latest

再在 Claude Code 的 .mcp.json 中通过 HTTP 连接:

{
  "mcpServers": {
    "yearning": {
      "type": "streamable-http",
      "url": "http://localhost:8080/mcp",
      "headers": {
        "Authorization": "Bearer your-strong-token"
      }
    }
  }
}

可用工具

只读工具(14 个)

按业务域分组排列:元数据 → SQL 工单 → 查询与评论。

工具

分组

说明

对应 API

yearning_user_info

元数据

当前用户信息、可查询数据源

GET /api/v2/fetch/userinfo

yearning_list_sources

元数据

列出有权限的数据源

GET /api/v2/fetch/source

yearning_list_databases

元数据

数据源下的库列表

GET /api/v2/fetch/base

yearning_list_tables

元数据

库下的表列表

GET /api/v2/fetch/table

yearning_table_fields

元数据

表结构(字段 + 索引)

GET /api/v2/fetch/fields

yearning_sql_check

SQL 工单

提交前 SQL 审核检测(order_type: ddl / dml)

PUT /api/v2/fetch/test

yearning_my_orders

SQL 工单

我的工单列表(分页/状态/关键字过滤)

WS /api/v2/common/list

yearning_order_detail

SQL 工单

工单详情(SQL 明细 + 完整 SQL)

GET /api/v2/fetch/detail + /fetch/sql

yearning_order_timeline

SQL 工单

工单审核时间线与流程步骤

GET /api/v2/fetch/timeline + /fetch/steps

yearning_rollback_sql

SQL 工单

获取工单回滚 SQL

GET /api/v2/fetch/roll

yearning_audit_orders

SQL 工单

待我审核的工单列表

WS /api/v2/audit/order/list

yearning_query_status

查询与评论

查询审核开关 + 我的查询工单状态

GET /api/v2/fetch/is_query + /fetch/query_status

yearning_run_query

查询与评论

执行只读 SELECT 查询(不修改数据;Yearning 留存查询审计记录)

WS /api/v2/query/results(msgpack)

yearning_order_comments

查询与评论

读取工单评论

WS /api/v2/fetch/comment

写工具(5 个)

按工单生命周期排列:提交 → 撤回 → 审核 → 查询申请 → 评论。

工具

分组

说明

对应 API

yearning_submit_order

SQL 工单

提交 SQL 工单(DDL/DML)

POST /api/v2/common/post

yearning_undo_order

SQL 工单

撤回自己未执行的工单

GET /api/v2/fetch/undo

yearning_audit_order

SQL 工单

审核工单:agree/reject/undo(agree 即批准变更落地,高危)

POST /api/v2/audit/order/state

yearning_submit_query_order

查询与评论

提交数据查询申请

POST /api/v2/query/post

yearning_post_comment

查询与评论

发表工单评论

POST /api/v2/fetch/comment

未提供的操作:管理端(admin)能力(用户 / 数据源 / 规则管理)与 AI 辅助(text2sql / advisor)为后续 Phase,未包含在本期;此类操作请通过 Yearning 控制台人工执行。

只读 / 写的区别:上表「只读工具」在 YEARNING_READ_ONLY=true仍然可用;「写工具」在该模式下会被完全排除——不出现在 tools/list 中,Agent 既看不到也无法调用(注册期排除,非运行期拦截)。这样生产环境开启只读后,Agent 只能查询、绝无意外变更工单的风险。

审核/撤回为危险操作yearning_audit_order(agree)会批准一条 DDL/DML 变更在数据源执行,yearning_undo_order 会撤回工单;调用时务必明确动作参数,避免对话中的误操作直接落到生产。

MRTR 确认yearning_audit_order(agree)为破坏性操作,执行前会通过 MCP 2.0 Elicitation 弹出确认表单,需用户明确同意后才执行。若客户端不支持 Elicitation(如 stdio 模式),则降级为直接执行。

配置

环境变量

MCP 传输与认证

变量

说明

默认值

MCP_TRANSPORT

传输协议:stdio / sse / streamable-http

stdio

MCP_HOST

HTTP 传输监听地址(stdio 忽略),默认仅本地回环;对外暴露需显式设置并务必配置 MCP_AUTH_TOKEN

127.0.0.1

MCP_PORT

HTTP 传输监听端口(stdio 忽略)

8080

MCP_AUTH_TOKEN

设置后启用 Bearer Token 认证,保护 HTTP 接口

-(不鉴权)

MCP_STATELESS_HTTP

启用无状态 HTTP 模式,适合 Serverless 部署(详见下方说明)

false

MCP_LOG_LEVEL

日志级别:debug/info/warning/error

info

Yearning 连接

变量

说明

默认值

YEARNING_URL

Yearning 地址

http://localhost:8000

YEARNING_USERNAME

登录用户名(必填)

-

YEARNING_PASSWORD

登录密码(必填)

-

YEARNING_LOGIN_TYPE

登录类型:general / ldap

general

YEARNING_TIMEOUT

请求超时(秒)

30

YEARNING_READ_ONLY

只读模式,排除全部写工具(适合生产环境)

false

YEARNING_INSECURE

跳过 TLS 证书验证,用于自签名证书环境(详见下方说明)

false

认证凭证只需用户名/密码:客户端首次请求时自动调用 POST /api/v2/login(或 ldap)换取 JWT 并缓存;收到 401 时先尝试重新登录、失败则重放原请求(最多一次),全程无需人工干预。

注意区分两类凭证:MCP_AUTH_TOKEN 保护本 MCP Server 的 HTTP 接口;YEARNING_USERNAME / YEARNING_PASSWORD 用于登录 Yearning,两者互不相关。

Yearning 概念说明

Yearning 的 SQL 审核组织层级为:数据源(source)> 库(database)> 表(table)> SQL 工单(order)> 审核流程(audit)

  • 提交一条 SQL 变更需先经 yearning_sql_check 检测,再用 yearning_submit_order 提单;工单按配置的审核流流转,审核人用 yearning_audit_order 放行/驳回。

  • 线上查询走 yearning_run_query(仅 SELECT),需具备查询权限;部分环境开启查询审核后,查询也需先 yearning_submit_query_order 申请。

  • 工单状态:0 已驳回 / 1 已同意待执行 / 2 待审核 / 3 已完成 / 4 已终止 / 5 执行中 / 6 已撤回。

只读模式

设置 YEARNING_READ_ONLY=true 可排除全部写工具,仅允许查询,适合生产环境使用:

{
  "env": {
    "YEARNING_READ_ONLY": "true"
  }
}

TLS 证书验证

本服务基于 httpx2 发起 HTTPS 请求,默认会验证 TLS 证书(行为与 httpx 一致)。

  • 在使用自签名证书或内部 CA 的环境中,HTTPS 请求会因证书校验失败而报错。此时可设置环境变量 YEARNING_INSECURE=true 跳过 TLS 证书验证。

  • 该选项适用于开发、测试等使用自签名证书的环境。

{
  "env": {
    "YEARNING_INSECURE": "true"
  }
}

安全警告:禁用 TLS 证书验证是不安全的,会使得 HTTPS 连接容易受到中间人攻击。请勿在生产环境中使用,生产环境应使用受信任的 CA 签发的有效证书。

多协议传输

通过 MCP_TRANSPORT 选择传输协议:

  • stdio(默认):标准输入输出,适合 Claude Code、Cursor 等本地 AI 客户端集成。

  • sse:Server-Sent Events,HTTP 传输,端点 http://<host>:<port>/sse

  • streamable-http:Streamable HTTP,端点 http://<host>:<port>/mcp

streamable-http 启动示例:

MCP_TRANSPORT=streamable-http \
MCP_HOST=0.0.0.0 MCP_PORT=8080 \
MCP_AUTH_TOKEN=your-strong-token \
mcp-yearning

接口认证

设置 MCP_AUTH_TOKEN 后,所有 HTTP 请求必须携带正确 Token,否则返回 401

Authorization: Bearer <MCP_AUTH_TOKEN>

也兼容 X-Auth-Token / X-MCP-Token 请求头。健康检查端点 GET /health 免鉴权,返回 {"status":"ok"},用于容器探活。

stdio 传输为本地进程通信,不涉及网络,无需也不会进行 Token 认证。未设置 MCP_AUTH_TOKEN 时 HTTP 接口不鉴权,生产环境请务必配置。

注意区分两类凭证:MCP_AUTH_TOKEN 保护本 MCP Server 的 HTTP 接口;YEARNING_USERNAME / YEARNING_PASSWORD 用于登录 Yearning,两者互不相关。

MCP Resources

本服务以 MCP 2.0 Resources 暴露只读元数据,客户端可直接通过 URI 读取,无需调用工具:

Resource URI

说明

yearning://user-info

当前登录用户信息(含可查询数据源)

yearning://sources

数据源列表

Resources 仅暴露只读数据,不涉及任何写操作。

Stateless HTTP 模式

设置 MCP_STATELESS_HTTP=true 可启用无状态 HTTP 模式,每次请求独立处理、不保留会话状态,适合 Serverless 平台(如 AWS Lambda、阿里云函数计算)或多副本无状态部署:

MCP_TRANSPORT=streamable-http \
MCP_STATELESS_HTTP=true \
MCP_PORT=8080 \
mcp-yearning

Stateless 模式下不支持流式响应(SSE stream),每个 HTTP 请求独立完成工具调用后返回。适合短时、无状态的工具调用场景。

容器化部署

本地构建(Docker)

# 构建镜像
docker build -t mcp-yearning:latest .

# 以 streamable-http 运行并启用认证
docker run -d --name mcp-yearning -p 8080:8080 \
  -e MCP_TRANSPORT=streamable-http \
  -e MCP_AUTH_TOKEN=your-strong-token \
  -e YEARNING_URL=http://your-yearning:8000 \
  -e YEARNING_USERNAME=your-user \
  -e YEARNING_PASSWORD=your-password \
  mcp-yearning:latest

Docker Compose

复制 .env.example.env 并按需修改,然后:

cp .env.example .env
docker compose up -d

docker-compose.yml 已内置 build(基于本地 Dockerfile 构建并标记为 mcp-yearning:latest)和健康检查(探测 /health),以非 root 用户运行,适合本地开发部署。

使用场景示例

配置好后,你可以这样和 AI 对话(每条示例后括注主要涉及的工具):

数据源与表结构探查

连上 Yearning,告诉我我有哪些数据源可用

yearning_user_info + yearning_list_sources

看看 order_db 这个数据源下有哪些库,再列出 user 表有哪些字段和索引

yearning_list_databasesyearning_list_tablesyearning_table_fields

提交并跟踪 SQL 变更

把这条建表语句在 dev 环境提个工单,先帮我做个 SQL 检测看看有没有问题:
CREATE TABLE t_demo (id INT PRIMARY KEY, name VARCHAR(64));

yearning_sql_checkyearning_submit_order

我刚提的工单到哪一步了?把审核时间线和当前步骤给我

yearning_my_ordersyearning_order_timeline

这个工单如果执行出错,回滚 SQL 是什么

yearning_rollback_sql

审核人视角

列出待我审核的工单

yearning_audit_orders

工单 ORD-2026-0001 没问题,帮我通过

yearning_audit_ordertp=agree

线上只读查询

在 order_db 的 user 库里查一下最近 7 天注册的账号,前 100 条

yearning_run_query

这个环境的查询为什么被拦了?看看查询审核开关和我的查询工单状态

yearning_query_status

协作与审计

把 ORD-2026-0001 这个工单的评论都拉出来看看

yearning_order_comments

在 ORD-2026-0001 工单下留言:已确认索引已存在,可放行

yearning_post_comment

审核 / 撤回等危险操作需明确动作参数;yearning_audit_order(agree) 会批准变更在生产数据源执行,请确认无误后再调用。管理端(admin)能力与 AI 辅助工具为后续 Phase,未包含在本期。

已知限制

以下为当前实现与 Yearning 接口交互中的已知边界,使用前请留意:

  • WebSocket 工具共 4 个yearning_my_ordersyearning_audit_ordersyearning_order_comments(JSON)与 yearning_run_query(msgpack)。它们依赖将裸 JWT 放入 Sec-WebSocket-Protocol 头完成鉴权;若 Yearning 前置了不透传该请求头、或会校验 subprotocol 合法性的反向代理 / 网关,WebSocket 鉴权会失败。直连 Yearning 不受影响。

  • 每次调用新建一条 WebSocket 连接,无复用:列表类接口被高频调用时存在握手开销(TCP + WS + JWT 解析每回重来)。功能无误,但高并发场景延迟偏高。

  • 查询审核开启时 yearning_run_query 需先审批:若 Yearning 开启了查询审核(数据源需先有 status=2 的已批准查询工单),未审批前执行查询不会返回结果;本服务会识别该情况并明确提示「请先经 yearning_submit_query_order 提交查询申请并审批」,而非返回空结果误导。

  • 权限 / token 类失败已转译为友好错误:无对应数据源权限、token 失效、查询审核未批准、或传入参数不合法时,Yearning 会不回帧直接关闭连接。本服务的 WebSocket 封装已增加接收超时,并把底层连接中断转成 YearningApiError(说明可能原因),不再向调用方抛出底层栈信息。

  • yearning_run_query 请求字段与 Yearning 结构体绑定:查询请求以 msgpack 编码,键名(type / sql / schema)对应 Yearning QueryDeal.Ref 的 Go 字段;若 Yearning 改动了该结构体或引入 msgpack tag,需同步更新 clients/ws.py 的打包逻辑。

  • yearning_sql_check 仅接受 DDL / DML:Yearning 的检测接口会拒绝 SELECT 等非工单 SQL(返回「请提交DML语句」)。这是平台设计而非缺陷——SELECT 不走工单流程,请直接使用 yearning_run_query

  • 登录类型仅支持 general / ldap:受 Yearning 平台限制,OIDC 等第三方 SSO 为浏览器跳转流程,无头客户端无法用账号密码完成,当前未实现(详见配置说明)。

  • 部分只读接口使用 GET + JSON body:Yearning 的 /fetch/* 等接口(对应 yearning_list_*yearning_order_detail 等工具)通过 GET 请求携带 JSON body 传参(服务端 c.Bind 只读 body,不读 query string)。这不符合常见 HTTP 语义,若前置的反向代理 / 网关 / CDN 会丢弃 GET 请求的 body,这些工具会静默返回空结果(信封仍为 code==1200)。透传 body 的代理(如默认配置的 Nginx)不受影响,已在真实部署环境实测正常;如遇列表恒为空,请优先排查代理是否吞掉了 GET body。

开发

pip install -e ".[dev]"
pytest          # respx mock 测试,无需真实 Yearning 环境
ruff check src tests

实现注记

  • 列表类接口(我的工单、审核列表、评论)为 WebSocket(/common/list/audit/order/list/fetch/comment),客户端封装为「连接→发一帧→收一帧→关闭」的伪 REST

  • 查询执行(/query/results)走 WebSocket 且用 msgpack 编解码:请求为 msgpack.packb({"type": 0, "sql": sql, "schema": schema}),响应含 results / query_time / error / status

  • HTTP 请求统一 Authorization: Bearer <JWT>;WebSocket 将 JWT 放入 Sec-WebSocket-Protocol(裸 token,无 Bearer 前缀)

  • 响应信封恒为 HTTP 200,结构 {payload, code, text};成功 code==1200,非 1200 视为业务错误;未知 tp 返回裸字符串 "Illegal"

License

MIT