关于 csvql
csvql 是本地只读 SQL 引擎和 MCP 服务,可直接查询原位置的 CSV 文件。它面向需要受限结果、又不想把数据导入数据库的 Agent 和分析人员。
主要功能
- 01直接对 CSV 文件执行 SQL
- 02只读执行且不进行网络调用
- 03通过 --root 限制文件访问
- 04限制 MCP 结果并记录查询日志
- 05提供结构和目录列表工具
适用场景
- 01为 Agent 汇总大型 CSV 文件
- 02查询前检查结构和样例行
- 03限制 Agent 查询可访问的文件
- 04通过 SSH 在远程数据旁运行查询
MCP 相关
csvql 向 MCP 客户端提供 csv_query、csv_schema 和 csv_list。查询以 JSON 返回,限制在约 100 行或 12 KB;--root 可限制文件访问范围。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
针对 AI Agent,直接在 CSV 文件上执行只读 SQL。
数据库是你将数据加载进去的地方。csvql 则是在数据原本所在位置运行的查询工具。
csvql 可直接在 CSV 文件所在位置执行 SELECT:无需导入、无需摄取、无需服务。处理原始 CSV 的速度与 DuckDB 和 polars 大致相当,内存占用则低 3 到 11 倍。它以 MCP 服务的形式提供,因此 Agent 可以查询一个 GB 级文件并获取几行结果,而不是整个文件。它是一个静态 Zig 二进制文件,不会进行网络调用,也无法写入你的数据。
$ csvql "SELECT cab_type, COUNT(*) FROM 'trips.csv' GROUP BY cab_type"
cab_type,COUNT(*)
green,32447
yellow,967553
网站 · 快速开始 · 面向 Agent · 安装 · 性能 · SQL · 文档
为何开发
Agent 正在获得访问公司数据的权限。通常的方式是连接数据库,或将文件上传到模型。这两种方式都会移动数据。csvql 提供了第三种选择:在你自己的设备上,让它在数据旁边运行,再由 Agent 在那里查询数据。以下内容都可以在源代码中核查。
- 从设计上只读。 解析器不支持
INSERT、UPDATE、DELETE或DROP。不会写入任何输入文件。 - 不联网。 代码库中没有
std.net、std.http或套接字调用。没有遥测,也不会检查更新。运行strace -f -e trace=network会得到空跟踪记录。 - 通过标志限制访问范围。
--root /data会将进程可打开的所有文件限制在指定范围内。访问/etc/passwd和通过../遍历路径都会因PathOutsideAllowedRoot而失败。 - 限制输出量。 每次 MCP 调用返回的结果最多约 100 行 / 12 KB。即使不谨慎地执行
SELECT *,也无法塞满上下文,或通过一次次调用取出整张表。 - 内存占用平稳。 聚合操作只持有运行中的累加器,而不是整个数据集:处理 0.7 GB 文件和 8 GB 文件时均占用 74 MB。它可以在数据旁边的小型 VM 上运行。
- 便于审计。
--audit <file>会为每次查询追加一条 JSONL 记录。通过 SSH 连接时,你可以沿用现有的密钥、堡垒机和日志。
安全状况详情,包括 macOS 和 Windows 上已知的两个缺口:请参阅 SECURITY.md。
不支持的功能
- 它不是数据库。 不支持
UNION、窗口函数,也不支持LEFT/RIGHT/FULL/CROSS JOIN(仅支持内连接哈希联接)。唯一支持的子查询形式是col IN (SELECT ...)。这些情况会报错,而不是返回错误数据。如果你需要完整 SQL,请使用 DuckDB。 WHERE中的标量函数仅限DATEDIFF、DATEADD和EXTRACT。其他函数(UPPER、ROUND等)仅能用于SELECT,目前在WHERE中使用会报出容易误导的ColumnNotFound错误。- 带引号的 CSV 处理速度约慢 3 倍,因为引号会禁用扫描器依赖的 16 字节跳读。
MEDIAN会缓冲每个分组中的所有值,因此处理 20M 行时比 DuckDB 慢 5 倍(#205)。高基数GROUP BY(数百万个分组)也会更慢。- 仅支持 CSV。 JSON 和 JSONL 是输出格式,不是输入格式。
包含跟踪问题的完整列表:SQL_REFERENCE.md#known-limitations。
快速开始
# SQL mode
csvql "SELECT name, salary FROM 'data.csv' WHERE age > 30 ORDER BY salary DESC LIMIT 10"
# Simple mode: same query, positional
csvql data.csv "name,salary" "age>30" 10 "salary:desc"
# Pipes
cat data.csv | csvql "SELECT name, age FROM '-' WHERE age > 25"
csvql "SELECT * FROM 'data.csv' WHERE status = 'active'" > output.csv
# Other formats
csvql "SELECT name, age FROM 'data.tsv'" -d $'\t'
csvql "SELECT name, age FROM 'data.csv' LIMIT 3" --json # or --jsonl, --markdown
# What is in this file?
csvql --schema data.csv
标志:-d/--delimiter、--json、--jsonl、--markdown、--no-header、--no-input-header(无表头文件会使用 c1..cN)、-o/--output、--threads、--strict、--schema、--root、--audit、--mcp。详情请运行 csvql --help。简易模式:SIMPLE_QUERY_LANGUAGE.md。
面向 Agent(MCP)
设置
csvql install # registers csvql in Claude Code and Claude Desktop; --print to dry-run
如果存在 Claude Code CLI,它会运行 claude mcp add,并将 mcpServers.csvql 条目合并到 Claude Desktop 配置中,同时保留其他服务。之后重启 Claude。
其他方式:在 Releases 页面获取适用于 Claude Desktop 的一键安装 csvql-<platform>.mcpb 包(设置 → 扩展),或手动添加配置:
{ "mcpServers": { "csvql": { "command": "/usr/local/bin/csvql", "args": ["--mcp", "--root", "/data"] } } }
VS Code(Copilot)在 .vscode/mcp.json 的 servers 下使用相同的 command/args,并设置 "type": "stdio"。
工具
| 工具 | 返回内容 |
|---|---|
csv_query(sql) | JSON 格式的结果,上限约为 100 行 / 12 KB |
csv_schema(file) | 列名和几行示例数据 |
csv_list(directory?) | 目录中的 CSV 文件 |
Agent 使用普通 SQL 查询单引号括起的路径:
SELECT customer, SUM(revenue) AS total FROM 'sales.csv' GROUP BY customer ORDER BY total DESC LIMIT 10
SELECT STRFTIME('%Y-%m', order_date) AS month, COUNT(*) FROM 'orders.csv' GROUP BY month ORDER BY 1
SELECT o.id, c.name FROM 'orders.csv' o JOIN 'customers.csv' c ON o.customer_id = c.id WHERE c.region = 'West'
远程和本地部署
在数据所在的服务器上运行 csvql,并通过 SSH 连接。通过网络传输的只有 SQL 和少量结果。无需开放端口、反向代理或新凭据:
// client MCP config; csvql runs on the remote server
{ "command": "ssh", "args": ["analyst@dataserver", "csvql", "--mcp", "--root", "/data"] }
如果 Agent 或其他用户能够访问 csvql,务必设置 --root。同时使用权限受限的 OS 用户和只读挂载。检查清单:SECURITY.md#hardening-for-on-prem-and-remote-access。
Token 成本
通过 MCP 查询出租车数据集的 5 个问题,成本约为 640 个 token,其中包含工具架构;成本不会随文件大小变化。粘贴 417 MB 的文件则约需 2.3 亿个 token。这只是可行性方面的对比,并非节省量。如果 Agent 已有 shell 并运行 duckdb -csv,其 token 用量会略低于通过 MCP 使用 csvql,因为 MCP 返回 JSON。对 Agent 而言,csvql 的优势在于 --root、只读执行、输出上限和内存占用,而非 token 数量。请自行测量:bench/bench_tokens.py。
安装
Homebrew(macOS / Linux):
brew install melihbirim/csvql/csvql
预编译二进制文件,从 GitHub Releases 获取:
# macOS (Apple Silicon)
curl -L https://github.com/melihbirim/csvql/releases/latest/download/csvql-macos-aarch64.tar.gz | tar xz
sudo mv csvql-macos-aarch64 /usr/local/bin/csvql
# macOS (Intel)
curl -L https://github.com/melihbirim/csvql/releases/latest/download/csvql-macos-x86_64.tar.gz | tar xz
sudo mv csvql-macos-x86_64 /usr/local/bin/csvql
# Linux (x86_64)
curl -L https://github.com/melihbirim/csvql/releases/latest/download/csvql-linux-x86_64.tar.gz | tar xz
sudo mv csvql-linux-x86_64 /usr/local/bin/csvql
Windows(x86_64):从同一页面下载 csvql-windows-x86_64.zip,并将 csvql-windows-x86_64.exe 放入 PATH。
库,使用相同的引擎,无需子进程:
pip install csvql-query # Python: csvql.query(), .query_df(), .query_csv() → docs/PYTHON.md
npm install csvql-query # Node.js: require('csvql-query'), plus a `csvql-query` CLI → docs/NODE.md
从源代码构建,需要 Zig 0.15.2:
git clone https://github.com/melihbirim/csvql.git && cd csvql
zig build -Doptimize=ReleaseFast
sudo cp zig-out/bin/csvql /usr/local/bin/
bash 和 zsh 的 Shell 补全文件位于 completions/。它们可补全 csvql --help 中的标志、install 子命令和文件路径。
# bash: add to ~/.bashrc (on macOS, Terminal opens login shells, so use ~/.bash_profile)
source /path/to/csvql/completions/csvql.bash
# zsh: put _csvql in a directory on your fpath
mkdir -p ~/.zsh/completions
cp completions/_csvql ~/.zsh/completions/_csvql
# then in ~/.zshrc, before compinit runs:
# fpath=(~/.zsh/completions $fpath)
# autoload -Uz compinit && compinit
性能
对原始 CSV 执行相同的 GROUP BY department 查询,每个引擎单独运行一个进程,测试环境为配备 16 GB 内存的 Apple M2 Pro。峰值内存和耗时:
| 文件 | csvql | DuckDB | polars 2.0 |
|---|---|---|---|
| 0.69 GB | 74 MB / 0.2s | 254 MB / 0.8s | 1151 MB / 0.6s |
| 1.89 GB | 74 MB / 0.4s | 253 MB / 1.2s | 2107 MB / 1.1s |
| 3.80 GB | 75 MB / 0.7s | 275 MB / 2.1s | 2666 MB / 9.8s |
| 8.14 GB | 74 MB / 2.4s | 367 MB / 5.5s | 1754 MB / 26.7s |
内存占用基本不变,因为聚合操作持有的是累加器,而不是整个数据集。这适用于聚合操作,但不适用于必须保留行数据的 ORDER BY。速度与另外两个引擎相当:在扫描、筛选和小文件方面,csvql 快 2 到 5 倍;对原始 CSV 执行联接时优势明显;COUNT(*) 和 top-N 与 polars 相当;而在 MEDIAN 和包含数百万个分组的 GROUP BY 上则落后于 DuckDB。对于 Agent 的时间尺度来说,这些都无关紧要。内存占用才重要,因为它决定了 csvql 能在哪种机器上运行。
每个数字都有可复现的脚本。完整表格包括带引号的 CSV、宽表文件、联接、子查询和性能较差的情况:BENCHMARKS.md。
SQL
SELECT / FROM / WHERE / GROUP BY / HAVING / ORDER BY / LIMIT / OFFSET、内部 JOIN(链式)、col IN (SELECT ...)、LIKE / ILIKE / BETWEEN / IS NULL / AND / OR / NOT、DISTINCT、CASE WHEN。聚合函数:COUNT、SUM、AVG、MIN、MAX、VARIANCE、STDDEV、MEDIAN、QUANTILE、MODE、GROUP_CONCAT、COUNT(DISTINCT)。SELECT 中的标量函数:字符串(UPPER、LOWER、TRIM、LENGTH、REVERSE、CONCAT、LTRIM、RTRIM、LEFT、RIGHT、REPEAT、POSITION、INSTR、SUBSTR、REPLACE、SPLIT_PART、LPAD、RPAD)、数学(ABS、SIGN、CEIL、FLOOR、MOD、ROUND、TRUNC、SQRT、POWER、LN、LOG、EXP、GREATEST、LEAST)、CAST、COALESCE、NULLIF、IFNULL、日期(STRFTIME、DATE_PART、EXTRACT、DATEDIFF、DATEADD、CURRENT_DATE、NOW()、CURRENT_TIMESTAMP)。
csvql "SELECT department, COUNT(*), AVG(salary) FROM 'data.csv' WHERE salary > 50000 GROUP BY department HAVING COUNT(*) > 10 ORDER BY department"
csvql "SELECT e.name, d.dept_name FROM 'employees.csv' e JOIN 'departments.csv' d ON e.dept_id = d.id WHERE d.dept_name = 'Engineering'"
csvql "SELECT id FROM 'orders.csv' WHERE customer_id IN (SELECT id FROM 'customers.csv' WHERE region = 'EU')"
完整语法和限制:SQL_REFERENCE.md。与 DuckDB 进行差分测试的内容:CORRECTNESS.md。
文档
| 文档 | 描述 |
|---|---|
| SQL_REFERENCE.md | 完整 SQL 语法、可运行示例、与 DuckDB 的差异、限制 |
| SECURITY.md | 安全态势、网络和磁盘写入保障、加固措施 |
| CORRECTNESS.md | 与 DuckDB 的测试内容和方式、已知差距、错误行为 |
| BENCHMARKS.md | 与 DuckDB、polars、pandas、DataFusion 的完整性能分析 |
| ARCHITECTURE.md | 引擎设计、优化技术 |
| SIMPLE_QUERY_LANGUAGE.md | 简易模式语法参考 |
| docs/PYTHON.md · docs/NODE.md · docs/LIBRARY.md | Python、Node.js 和 Zig 库 API |
| CONTRIBUTING.md | 贡献指南 |
计划中
已发布的功能请参阅发布说明。适合初次贡献者的问题均明确了涉及文件和完成标准。
许可证
MIT,详见 LICENSE.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。