duckseek
This server lets you inspect and query tabular data (Excel/Access/Parquet) using natural language, with SQL verification and read-only execution.
duckseek_status: Check environment readiness (which of the six required LLM/embedding env vars are missing, names only) and data/index state.
duckseek_list_tables: List registered tables grouped by source, with row counts from stored profiles (null if not yet profiled).
duckseek_ask: Ask a natural-language question over registered tables; returns a markdown answer, the executed SQL, row count, elapsed time, source tables, and whether embedding retrieval degraded to BM25-only. Ambiguous questions return a clarification request. All execution is read-only and restricted to a single SELECT.
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., "@duckseekWhat were the top 5 most popular pickup locations for yellow taxis in March 2026?"
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.
DuckSeek
一句话简介:DuckSeek(Python 包名 nl2data)是一个开源(Apache-2.0)的 CLI
工具,让你用自然语言直接查询大体量(十万至千万行级)Excel / Access / Parquet
数据——答案永远附带实际执行的 SQL,可人工核验。支持处理多表,表格行数上限取决于
硬件性能。已附带 SKILL 和 MCP 接口——一个很有扩展潜力和想象力的接口。
架构
文件(.xlsx/.xlsm/.mdb/.accdb/.parquet)
│ ingest(零拷贝 Parquet 注册 / 转换落盘)
▼
data/parquet/<source>/<table>.parquet ──► data/warehouse.duckdb(表以 VIEW 注册)
│ │
│ profile(聚合 SQL 画像) │ cards(M-Schema 表卡片)
▼ ▼
data/catalog/profiles/*.json ──────► data/catalog/cards(_md)/*.json(md)
│ │
│ ▼
│ index(LanceDB 向量 + BM25,术语直通)
│ │
└──────────────────► retrieve(Top-K 表卡片,token 预算贪心)
▼
generate(LLM → SQL,诚实反问)
▼
guard(sqlglot 静态护栏)
▼
run(只读沙箱执行 + 结果压缩)
▼
interpret(第二次 LLM 解读)
▼
答案 + SQL + 行数/耗时/token + 明细位置原始数据文件不进入 LLM 上下文:模型仅看到 schema 卡片与(必要时压缩的)查询 结果——大结果集(>20 行)只给统计画像与样本,小结果集(≤20 行)以内联样本透传。
Related MCP server: agentic-ops-builder
快速开始(约 30 分钟)
环境要求:Python ≥ 3.11、uv、六个环境变量 (LLM 与 embedding 各一套,均为 OpenAI 兼容 API;DeepSeek / Qwen / Kimi / GLM 等均可;同一厂商提供两者时,EMB_BASE_URL 可与 LLM_BASE_URL 相同):
export LLM_BASE_URL="https://your-llm-provider/v1"
export LLM_API_KEY="sk-..."
export LLM_MODEL="your-chat-model"
export EMB_BASE_URL="https://your-emb-provider/v1"
export EMB_API_KEY="sk-..."
export EMB_MODEL="your-embedding-model"git clone https://github.com/Zhu-Guang-Scion/Duckseek.git && cd Duckseek
uv sync # 创建 .venv 并安装依赖(锁定于 uv.lock)
# 1) 接入数据(三种来源任选;零拷贝注册或转换落盘;表名 = 文件名,clean_name 规则)
uv run nl2data ingest excel path/to/订单.xlsx # 多 sheet → 每 sheet 一表
uv run nl2data ingest access path/to/legacy.mdb # 需 mdbtools(Linux/macOS/WSL)
uv run nl2data ingest parquet samples/nyc-taxi/yellow_tripdata.parquet --name yellow_tripdata
# 2) 画像 → 3) 卡片 → 4) 检索索引(幂等,可重复执行)
uv run nl2data profile --all
uv run nl2data cards build --all
uv run nl2data index build
# 5) 提问(答案附实际执行的 SQL)
uv run nl2data ask "2026年3月黄色出租车的总订单量是多少?"
# 交互模式(/retry [补充] /show sql /export csv <路径> /export xlsx [目录] /tables /exit):
uv run nl2data ask导出产物(可选,M6):需要留档或在 Excel 继续加工时,同一次导出产出双文件——
result.xlsx(数据表 + 元数据表 + LLM 判定的 Excel 原生图表,可在 Excel 中继续
编辑)与 manifest.json(自描述机器清单,供其他程序/agent 读取):
# CLI:单发附加 --export xlsx(产物落在 data/exports/<时间戳>_<hash>/)
uv run nl2data ask "各个行政区的黄车订单量是多少?" --export xlsx
# MCP:duckseek_ask 可选参数 export="xlsx",返回载荷附 artifacts 路径键导出为 opt-in(不传参数零额外调用);行数超上限会截断且必有披露(xlsx meta
表醒目行 + manifest 的 truncated/total_rows/exported_rows);图表判定失败只降级
不阻断(manifest 记录 chart_error 原因)。产物目录不自动清理,手动删除即可。
数据形态要求:每个 sheet 需为单一表头的规整矩形表(表头行自动探测,前几行的 标题行/空行自动跳过);多级表头、合并单元格表头与一表多块的报表式 sheet 暂不支持, 需先手工整理。
仓库自带 samples/nyc-taxi/ 三张 NYC 出租车样本表(yellow / green / taxi_zones,
即上例与评测集所用数据);其中 yellow 行程表 67.9MB,处于 GitHub 单文件
50–100MB 警告带(未超 100MB 硬限制),克隆即得、无需另行下载。中文列名自动
转拼音安全名(订单ID → ding_dan_id),原名完整保留在 catalog.yaml 双向映射中。
配置与词典:路径与阈值在 config.yaml(NL2DATA_CONFIG 可覆盖位置),密钥
只走环境变量、绝不落盘;业务黑话进 data/catalog/glossary.yaml(术语 → 表/列/
口径,表级 filter 仅本表生效,metric_filter+applies_to 随指标全局生效,
校验 uv run nl2data glossary check);表级说明进 docs/table_notes.md。
MCP + Skill 接入(AI 宿主)
任意 MCP 宿主(Claude Code / Cursor / zcode 等)可显式调用 DuckSeek:
uv run nl2data mcp serve 启动 stdio 服务器,注册片段与各宿主配置位置见
skills/duckseek/README.md;宿主 LLM 的调用契约
(工作流 / 纪律 / 故障速查)见 skills/duckseek/SKILL.md。
{
"mcpServers": {
"duckseek": {
"command": "uv",
"args": ["--directory", "<本仓库绝对路径>", "run", "nl2data", "mcp", "serve"],
"env": {
"LLM_BASE_URL": "<LLM 网关地址>",
"LLM_API_KEY": "<LLM 密钥>",
"LLM_MODEL": "<模型名>",
"EMB_BASE_URL": "<embedding 网关地址>",
"EMB_API_KEY": "<embedding 密钥>",
"EMB_MODEL": "<embedding 模型名>"
}
}
}
}注意:env 块必须显式携带六个变量——MCP 客户端 stdio 启动默认只透传安全白名单
环境变量;密钥轮换后需重启会话(环境变量启动时读取)。
评测体系(敢迭代)
三层判定,一条命令回归:
uv run nl2data eval e2e [--save-baseline] # golden 20 条 × N=3 多数决
uv run nl2data eval recall # 仅召回层
uv run nl2data audit 10 # 最近问答审计L1 召回:retrieve 是否召回期望表(Recall@3);
L2 SQL:全链是否执行成功(反问=失败;护栏拒/执行错=错误;SQL 文本不比对);
L3 结果:与 golden 参考值语义等价(行多重集合、列超集投影、数值容差 + ×100 单位等价标注;不做行式/列式形状等价)。
golden 集(eval/recall_golden.yaml,20 条真实问答三元组)与冻结基线
(eval/baseline_e2e.json,git 跟踪:L1=1.000 / L2=0.95 / L3=0.75)构成回归
锚点:改提示词/换模型后重跑,与基线 diff 即逐 case 风险清单。已知摆动说明:四个
边界/风格类 case(#7 多列形状 / #11 时间列归因 / #16 反问边界 / #19 百分比舍入)
在 N=3 多数决下仍可能双向翻转,thinking 关闭条件下 L3 ∈ [0.75, 0.80] 属正常带;
比对器已知边界(风格类差异不计为回归缺陷)见 docs/milestone-4-notes.md。
安全模型摘要
宁可误拒,不可漏放;拒绝必须给出可读原因。
护栏层:九条规则全走 sqlglot 解析树(注释/大小写/嵌套免疫)——语句白名单 (仅 SELECT/WITH)、表白名单、表函数一票否决、列存在性、LIMIT 注入 500/封顶 10000;
沙箱层:只接受护栏签发的
ValidatedSQL类型 + DuckDBread_only=True+ 守护线程超时——伪造入参在类型层即被拒;红队制度:累计 100+ 对抗样本(提示注入/SQL 注入/文件读取/CTE 藏写等), 全部拦截后固化进测试套件;
密钥纪律:API key 不写入任何文件/日志/异常消息/工具参数与返回值 (专项测试断言)。
命名说明
面 | 名称 |
产品 / 分发版 | DuckSeek |
Python 包与 CLI 命令 | nl2data( |
MCP 服务器与三工具 | duckseek / duckseek_status / duckseek_list_tables / duckseek_ask |
Skill | skills/duckseek/(name: duckseek) |
包级重命名(nl2data → duckseek,CLI 同步更名并给出迁移说明)列在路线图阶段三; 此前宿主面与命令行名并存属预期,SKILL.md 内已注明对应关系。
路线图
阶段二(准确率工程):多候选 SQL + 选择器、实体索引、Python 分析沙箱、查询缓存;
阶段三(团队开源):Web UI、多用户只读与审计、docker-compose、包级更名 duckseek(含 CLI 迁移说明)、中英双 README;
里程碑历史与当前状态见 goals.md §4(M1-M5 全部完成)。
文档地图
goals.md —— 工程内部事实源(目标、锁定决策、契约、里程碑记录)
docs/architecture.md —— 架构与设计决策全文(本 README 母体)
docs/milestone-{1..5}-notes.md —— 各里程碑验收留档
skills/duckseek/ —— Skill 三件套(SKILL.md / 注册指南 / 凭证模板)
docs/table_notes.md —— 表级说明(注入卡片)
eval/recall_golden.yaml —— golden 评测集
许可证
Apache-2.0,见 LICENSE。
Available Tools
3 toolsduckseek_askA
Answer a natural-language question over the registered tables.
Runs retrieve → SQL generation → read-only guard → sandboxed
execution. Returns answer (compact markdown of the result),
sql (the executed statement, for verification), row_count,
elapsed_ms, source_tables and embedding_degraded (true
when this call's retrieval fell back to BM25-only — tell the user
and suggest providing EMB_* for best recall); interpret the answer
yourself. Ambiguous questions return needs_clarification with a
follow-up question to ask the user. Read-only; the SQL is
verified to be a single SELECT before it runs.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description fully discloses the read-only guard, sandboxed execution, single-SELECT verification, and the embedding_degraded return flag with instructions to inform the user. It also explains the needs_clarification response for ambiguous questions, leaving little behavioral ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, then pipeline, outputs, and edge cases. It is dense but each sentence adds essential information; a slight trim would push it to a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, behavioral safety, return fields, edge cases, and remedial instructions despite having output schema and no annotations. It is complete enough for an agent to call and interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only defines 'question' as a required string with 0% description coverage. The description supplies meaning by specifying it is a natural-language question over the registered tables and by describing how ambiguous inputs are handled.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Answer a natural-language question over the registered tables,' which names a specific action and resource. This clearly distinguishes it from sibling tools 'duckseek_status' and 'duckseek_list_tables.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description plainly frames when to use the tool—when there is a natural-language question about the registered tables—and details its processing pipeline. It does not explicitly name alternatives or exclusion conditions, but the context is evident from the tool name and siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
duckseek_list_tablesA
List registered tables grouped by source, with row counts.
Row counts come from stored profiles; rows: null means the table
has not been profiled yet. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of behavioral disclosure. It explicitly states the operation is read-only, explains that row counts come from stored profiles, and defines the meaning of 'rows: null'. These details add meaningful context beyond the input schema, which is empty.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: the primary purpose is front-loaded in the first sentence, and the only additional detail is a useful clarification about row counts. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless listing tool with an output schema, the description covers the purpose, grouping, row-count semantics, and read-only nature. Nothing an agent needs to select and invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description adds no parameter semantics, but none are needed; the schema fully covers the (empty) parameter set.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List registered tables grouped by source, with row counts.' This clearly distinguishes the tool from siblings (duckseek_status and duckseek_ask), which appear to cover status reporting and question answering rather than table enumeration.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is strongly implied by the imperative 'List registered tables,' and the zero-parameter signature makes invocation straightforward. However, the description does not explicitly state when to prefer this tool over duckseek_status or duckseek_ask, nor does it provide any exclusion or condition-based guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
duckseek_statusA
Environment + data readiness for DuckSeek.
Reports which of the six env vars (LLM_BASE_URL/LLM_API_KEY/LLM_MODEL, EMB_BASE_URL/EMB_API_KEY/EMB_MODEL) are missing — names only, never values — plus registered sources/tables and retrieval-index state. Call this first; if variables are missing, ask the user to provide them into the server environment.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral disclosure. It is transparent about what is reported, explicitly states that only names are reported ('never values'), and conveys this is a read-only diagnostic operation through the verb 'Reports.' It also sets expectations for the data-readiness state covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and information-dense. It front-loads the core purpose, enumerates the specific env vars, adds the key privacy guarantee, and ends with an actionable instruction — no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool with an output schema, the description is complete. It informs the agent of the exact env vars, the data-state items, the privacy constraint, and the appropriate next step, leaving no meaningful gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the input schema is already complete and the description cannot add much. The baseline of 4 applies here; the description confirms this is a call with no inputs and focuses entirely on what it returns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear statement of purpose: 'Environment + data readiness for DuckSeek.' It then specifies the exact resource being reported (missing env vars, registered sources/tables, retrieval-index state), which distinguishes it from siblings like duckseek_list_tables and duckseek_ask.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs the agent to 'Call this first', establishing clear positional precedence over sibling tools. It also provides a concrete follow-up action when variables are missing: 'ask the user to provide them into the server environment.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
duckseek_ask - First observed
duckseek_list_tables - First observed
duckseek_status
TDQS
Scored across 3 tools
duckseek_status and duckseek_list_tables both surface registered tables and index state, creating mild overlap, but status is clearly a readiness check while list_tables is metadata-only. duckseek_ask is fully distinct as the query entry point.
All tools share the duckseek_ prefix and snake_case convention, but the structure is mixed: status is a noun, list_tables is verb_noun, and ask is verb-only. The pattern is still predictable and readable.
Three tools cover the complete workflow: check readiness, inspect available tables, and ask a natural-language question. Each tool earns its place and the small count fits the server's narrow read-only querying purpose.
The core lifecycle of status discovery, table inspection, querying, and clarification is present, with good guardrails like read-only SQL verification and BM25 fallback reporting. The main gap is that list_tables exposes row counts but not schemas or columns, so agents must infer schema details through duckseek_ask.
Maintenance
Related MCP Connectors
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
- BasedashOAuthcom.basedash
Governed BI MCP. Ask questions of live company data and list workspace sources via OAuth.
Ask questions in plain language, get answers from your business database. No SQL required.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables querying your spreadsheet using natural language questions; provides read-only tools for schema, sample data, and structured query execution with auditable computation traces.MIT
- FlicenseNot gradedqualityBmaintenanceEnables natural-language Q&A, human-approved actions, and dashboard generation over a data ontology via MCP.-
- AlicenseNot gradedqualityBmaintenanceEnables governed, agent-agnostic data exploration by allowing users to ask natural language questions through MCP-compatible agents, executing safe, permission-scoped queries against data sources and returning interactive charts.15 npmApache 2.0
- FlicenseNot gradedqualityCmaintenanceEnables querying CSV or Excel data using natural language through MCP tools, running pandas operations on an uploaded dataset.-