WorkBuddy 调用润乾 NLQ MCP 实现数据查询分析实践

NLQ MCP DEMO for TPCHSKILL说明

MCP说明

NLQ MCP DEMO for TPCH(下简称NLQ MCPMCP)是基于TPCH数据源的数据查询MCP,它可以接收来自AI智能体生成的规范NLQ代码,执行并返回查询结果。

NLQ执行代码用汉语书写,普通业务人员也能看懂,从而可以确认AI生成的查询动作是否正确,避免AI幻觉曲解用户目标导致的错误。

这个DEMOTPCH数据集为基础,读者可以了解NLQ的实施过程后改造其中的SKILL以适应其它数据主题并部署到其它地址上。

NLQ MCP 服务地址:http://d.raqsoft.com.cn:6888/mcp

MCP 提供三个工具:

工具名

说明

getLoginUrl

获取OAuth 登录地址

login

access_token 绑定会话身份

execute

提交 NLQ命令并执行查询

nlq SKILL用于辅助WorkBuddy生成查询分析数据的命令,用户输入的自然语言需求,将被拆分为「查询/计算」与「呈现」两部分;前者转换为规范的NLQ代码,发送给MCP 执行查询;结果集返回后由 WorkBuddy 渲染。

SKILL的名称可以根据需要设定,最好足够简明,便于在实际使用中明确选择。

SKILL的安装

使用压缩包安装技能

从润乾NLQ查询演示页面(http://query.raqsoft.com.cn:6999/nlq4tpch.html)下载SKILL文件nlqdemoskill.zip解压,内容如下:

..

nlq路径中则为技能相关文件:

..

即可用这个压缩包在WorkBuddy中安装技能。

WorkBuddy 侧边栏中选择专家·技能·连接器」技能,在右上角选择添加技能上传技能

..

在导入技能窗口的左下角,点击选择ZIP文件

..

如果zip文件中的nlq技能当前不存在,WorkBuddy将从技能文件中识别出技能介绍,可以继续安装:

..

安装成功后,在列表中,即可看到导入的技能:

..

复制文件安装SKILL

也可以选择不使用压缩文件,而是直接把SKILL文件夹复制到WorkBuddy的路径中,再由WorkBuddy识别安装。

A.项目级安装(推荐团队共用)

nlq目录完整复制到项目根目录下的 .workbuddy/skills/ 中:

项目根/

└── .workbuddy/

└── skills/

└── nlq/

├── SKILL.md

├── references/

└── scripts/

WorkBuddy 左侧「项目」选择当前项目 「技能」或「配置」中确认 nlq 已出现在技能列表。

若未自动发现,尝试重新加载项目或重启 WorkBuddy

B.用户全局安装(个人多项目复用)

全局技能在所有项目中可用,但项目级同名技能会覆盖全局版本。

将目录复制到 ~/.workbuddy/skills/nlq/Windows`%USERPROFILE%.workbuddy\skills\nlq`)。

全局技能在所有项目中可用,但项目级同名技能会覆盖全局版本。

SKILL文件体系

技能目录建议按以下结构组织(与 WorkBuddy Skill 规范一致):

nlq

├── SKILL.md # 主技能文件(触发词、流程、规则)

├── references/

│ ├── grammar-spec.md # 语法规则、查询范式、NLQ 语法、不支持类型

│ └── field-dictionary.md # 表结构、字段名、维词、常数词、聚合指标词典

└── scripts/

└── nlq_login.py # nlq OAuth 登录脚本(自动生成)

文件

作用

SKILL.md

定义技能的完整处理流程、输出格式、失败重试策略、MCP 调用方式

references/grammar-spec.md

查询范式、NLQ功能词列表、语法约束、不支持的查询类型及示例

references/field-dictionary.md

当前数据源的表名、字段名、维词、常数词、聚合指标;注意:实测数据源 schema 可能与通用词典不同,需以 execute 返回的列名为准

scripts/nlq_login.py

OAuth 登录辅助脚本;自动打开浏览器等待授权,成功后保存

NLQ MCP连接配置

配置步骤

WorkBuddy 侧边栏点击专家·技能·连接器」连接器

..

②在右上角点击自定义连接器」配置MCP

..

编辑 mcp.json(项目级或用户级),添加MCP服务配置,名称用NLQ-MCP。示例:

{

"mcpServers": {

"NLQ-MCP": {

"url": "http://d.raqsoft.com.cn:6888/mcp",

"disabled": false

"description": "NLQ 查询执行服务"

}

}

}

保存后,在我的MCP找到NLQ-MCP,点击「信任/启用」,状态变为绿色即连接成功。

..

..

技能中通过内置脚本自动登录MCP

首次调用 execute ,或者登录过期时,需完成 OAuth 登录并获取 session_id

在技能的SKILL.md定义的登录脚本路径默认为<技能目录>/scripts/nlq_login.py

execute 返回未登录/鉴权失败错误时,Agent 会自动运行:

python <技能目录>/scripts/nlq_login.py <结果文件路径>

脚本行为:

自动打开系统浏览器,跳转到 OAuth 授权页面;

等待用户授权(最多 5 分钟);

授权成功后,交换 token(使用 x-www-form-urlencoded 表单,非 JSON);

session_id 写入指定的结果文件;

后续请求通过 Mcp-Session-Id 头携带会话身份。

同一会话内可复用已保存的 session_id;会话失效时重新运行脚本。

在首次调用技能时,如果MCP未连接,或者登录已过期,将弹出浏览器窗口:

..

这里只是演示登录功能,并未做实际的用户口令检查,随便填上用户名和密码即可过关。

登录后,返回WorkBuddy可以继续执行技能:

..

手动登录(备用

若自动脚本不可用,可手动调用 MCP 工具:

调用 nlq_getLoginUrl 获取授权 URL

在浏览器中打开该 URL,完成授权,获取 access_token

调用 nlq_login 绑定会话;

之后即可正常调用 execute

如果在查询中出现问题,可以根据遇到的具体情况修改相关文件:

问题描述

修改建议

数据库变更

更新 references/field-dictionary.md,修改相关内容

NLQ语法变更

更新 references/grammar-spec.md,补充新功能词和示例

MCP名称变更

修改SKILL.md中有关MCP连接的内容,默认MCP名称是NLQ-MCP

MCP登录异常

检查 scripts/nlq_login.py 的处理

技能行为异常

检查 SKILL.md 中的重试逻辑和判定规则

SKILL调用

WorkBuddy中使用技能查询

技能安装成功后,在WorkBuddy中输入查询信息,它会自动选择使用技能,如果只有一个自然语言的查询技能,可以直接输入:查询客户信息以及它们的订单数,按照订单数降序排序,列出前10 名,保留同名次的。

如果存在多个类似的技能,可以在查询语句前指定技能名称,输入:/nlq 查询客户信息以及它们的订单数,按照订单数降序排序,列出前10 名,保留同名次的

..

..

在返回结果中会列出执行命令列表(上图红框中),这些NLQ语句是AI生成并传送给MCP查询数据的,可以用于了解实际执行的计算过程。如果AI的理解和用户的目标有差异,就能及时发现,并在WorkBuddy中输入修改意见来纠正。

查询结果被整理为HTML,可在右侧结果窗口中查看:

..

正常流程

用户输入自然语言查询

智能体处理流程:

┌───────────────────┐

意图拆分(第 0 步)

│ · 查询/计算 后续步骤

│ · 呈现需求 暂存

└───────────────────┘

┌───────────────────┐

转换 NLQ │ ← 参考 grammar-spec.md + field-dictionary.md

输出§A格式

└───────────────────┘

┌───────────────────┐

调用 NLQMCP execute │ ← 传入 §A 代码(去掉「实现代码:」前缀)

检查登录状态 │ ← 未登录则运行 nlq_login.py

└───────────────────┘

┌───────────────────┐

判断返回形态

形态1: JSON 结果集 │ → 进入呈现叠加(§D.3

形态2: 错误信息 │ → 进入重试/失败处理(§C

└───────────────────┘

┌───────────────────┐

呈现叠加

│ · 仅表格 → Markdown

│ · 表格+图表 → HTML

│ · 仅图表 → show_widget

└───────────────────┘

输出给用户

失败重试路径

失败类型

处理方式

上限

转换自查失败(触发 A

重新转换 调用 execute

3

NLQMCP返回错误信息(触发 B

附加错误信息 重新转换 调用 execute

3

NLQMCP临时不可用(触发 C

短暂等待 重新调用 execute

3

输入歧义/不合理

不重试,输出§B要求改写


语法/词典不支持

不重试,输出§B要求改写


3 次都失败

输出§E错误汇总 + 分析 终止


查询示例

单表查询

明细查询

名称包含“中国”的客户信息,按账户余额降序排序

说明:单表的明细数据,模糊匹配字段过滤,结果需要排序。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “客户名称 包含 ‘中国’ 客户”

排序 客户账户余额 降序

..

计算2025年订单明细的折扣后金额、税额和含税总价

说明:单表的明细数据,按字段值区间过滤,需要增加计算列。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “发货日期 202511日 至 20251231日 订单明细”

计算列 订购金额*(1-折扣率) 命名 折扣后金额, 折扣后金额*税率 命名 应缴税额, 折扣后金额+应缴税额 命名 含税总价

..

汇总查询


计算月度订单总额、订单数量的环比增长率

说明:分组汇总,并环比计算增长率。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “年 月 订单金额 总和,订单 数”

排序 升序, 升序

计算列 订单金额总和 增长率 命名 总额环比, 订单数 增长率 命名 数量环比..

各零件类型的大/小库存与高成本库存零件数

说明:查询复杂聚合指标。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “零件类型 大库存零件数,小库存零件数,高成本库存零件数”

..

各行业 20% 客户均额与大余额客户数

说明:查询复杂聚合指标,包括带参数的指标。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “行业 前20客户均额,大余额客户数”

排序 20客户均额 降序

..

复杂查询


查询2025年订单金额高于平均订单金额的订单

说明:根据单表的汇总结果来执行过滤。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “2025年 订单”

计算列 订单金额 平均 命名 平均金额

筛选 订单金额>平均金额..

订单额极差大于1万元的客户信息

说明:订单额极差是复杂聚合指标,需要计算同一客户的最大订单额和最小订单额的差。计算后再根据结果执行过滤。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “订单额极差大于10000,客户”

排序 订单额极差 降序(NLQ-MCP 排序)

..

多表关联查询

多表汇总查询

查询客户信息以及它们的订单数,按照订单数降序排序,列出前10名,保留同名次的

说明:主子表汇总查询,并根据汇总结果排序以及过滤。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “客户,订单 数”

排名 订单数 降序 10 命名 名次

..

上海实业数据科技有限公司生产的商品2025年每个月的订单总额和累积占比

说明:通过多表关联关系分步查询数据,再汇总计算。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “制造商名称 上海实业数据科技有限公司 零件”

② 查询 “零件 2 发货日期 202511日 至 20251231日 年月,订购金额 总和”

排序 年月 升序

计算列 订购金额总和 占比 命名 月占比, 月占比 累计 命名 累积占比

..

各国客户的资金存量和消费规模

说明:多表的按维汇总。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “国家 客户 客户账户余额 总和, 订单 订单金额 总和”

..

多表关联的复杂查询

亚洲客户2025年每个月的大额订单数

说明:通过关联表过滤数据,并计算复杂聚合指标。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “地区 亚洲 2025年 年月,大额订单数,订单 数”..

技能执行后的后续分析

取得数据后绘图

列出2025年,订单数精确前20名客户的订单数和总订单金额,并绘制柱线图

说明:主表和多个子表的汇总查询,并按汇总结果排序及过滤。这里绘制统计图由WorkBuddy根据返回数据来生成。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “客户,2025年 订单 数,订单金额 总和”

排名 订单数 降序 20 命名 名次

..

针对统计结果进一步分析

各个供应商的大额明细数与大量明细数

说明:分组汇总,计算复杂聚合指标。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “供应商 大额明细数,大量明细数”

排序 大额明细数 降序

..

这个数据能得到什么结论吗?

说明:查询与nlq技能无关,由WorkBuddy自行回答。

实际查询结果:

..能,而且这份数据的形态比排名本身更有信息量。先更正一点:第一版散点图我用了近似示意点,上方已用 1,000 家真实数据重画,结论以真实版为准。以下是基于真实数据的分析(对已取回结果的呈现层统计,服务器原始数值未改动):

结论 1:大额能力与大量能力高度绑定(r = 0.901),几乎不存在“专项型”供应商

回归线 y = 0.73x + 7.2,拟合度很高;散点紧密贴着趋势线分布;

极端类型一家都没有:大额明细数 50 但大量 <20 的供应商为 0 家;反过来也为 0 家;双高型(大额 ≥50 且大量 ≥40)多达 725 家;

这推翻了我上一轮的初步说法(“贵和量大是两类不同供应结构”)——数据说明恰恰相反:接大单多的供应商接大批量的也多,两者是同一种“规模承接能力”的两个侧面。选商时不需要按“大单型/批量型”分别建库。

结论 2:供应商能力高度均匀,没有真正的头部

大额明细数范围 11100,均值 58.0 与中位数 59 几乎重合,p10=40 / p90=77,分布对称无长尾;

集中度极低:大额明细数总和的 Top10 占比仅 1.6%Top50 也只有 7.4%

业务含义:头部(中华环保 100/81)与榜尾(11/7)虽然差近 10 倍,但整个盘子是平缓坡而非金字塔——靠“换更大的供应商”来提升承接能力的空间很小,差异化要在价格、质量、地区等其他维度找。

结论 3(数据质量提示):这种“完美均匀”的形态不太像真实供应链

真实世界的供应商能力通常呈右偏长尾(少数巨头 + 大量小厂),而这里是均匀分布、两端对称——结合此前零件零售价集中在 ¥901910 等特征,这份数据源大概率是按均匀分布生成的模拟数据。结论 12 在本数据集内成立,但如果要把这套分析方法迁移到真实业务,预期分布形态会不同(真实场景 r 会低一些、集中度会高很多)。

基于已有的结果,分析一下各种订单适合哪种供应商吧,分类时用数据

说明:查询与nlq技能无关,由WorkBuddy根据前面的分析和查询结果总结。

实际查询结果:

..

..

解析查询结果

交叉统计各订单优先级与订单状态下的订单数和金额

说明:分组汇总后,结果显示为交叉表,并进一步分析。

实际查询结果:

执行命令(提交至 NLQ-MCP):

① 查询 “订单优先级 订单状态 订单 数,订单金额 总和”

..

继续输入:分析一下结果

说明:查询与nlq技能无关,由WorkBuddy自行回答。

实际查询结果:

P 状态订单显著少(每档仅 110–152 笔),是典型的少量待处理/挂起尾巴;其中 2-HIGH × P 金额占比最高(¥1,358 万),最值得关注清理;

F O 两类体量相当(各约 2,300–2,500 笔、¥1.65–1.81 亿),说明整体订单约一半仍处于未完成状态;

优先级之间的分布非常均匀——订单数和金额并未随优先级升高而倾斜,说明优先级标记与实际订单价值关联不大(1-URGENT 5-LOW 的金额几乎同量级)。