csvql
Click on "Install 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., "@csvqlRun a SQL query on sales.csv to get total sales per product"
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.
The analytical CSV query engine for AI agents.
Run SQL analytics — GROUP BY, aggregates, joins, time-series — on CSV files in place: no database, no import, no ingest. csvql ships as an MCP server, so an LLM can query a gigabyte file for a few hundred tokens instead of pasting it (impossible) into context. A single static binary written in Zig. Your data never leaves your machine.
A database is something you load your data into. csvql is a query you run on the data where it already lives.
Read-only and on-prem by design. csvql only runs SELECT — it has no INSERT/UPDATE/DELETE/DROP and physically cannot modify your data. It makes zero network calls, needs no cloud, and runs fully air-gapped. Our next north star: the safe way to give AI agents query access to corporate data — run csvql next to the data on your own servers (read-only, nothing leaves the box) instead of shipping files out to an LLM.
Token economics: query files instead of pasting them
Pasting a 417 MB CSV into an LLM costs 230 million tokens — it fits no context window. Over MCP, the agent queries the file in place and gets back only the answer:
Question an agent asks | Tokens used |
"How many trips per cab type?" | 43 |
"Which year was busiest?" | 49 |
"Average fare by passenger count?" | 123 |
Same answers, ~1,000–500,000× fewer tokens — flat, regardless of file size. One command wires it into Claude: csvql install. Measure it yourself: bench/bench_tokens.py.
$ csvql "SELECT cab_type, COUNT(*) FROM 'trips.csv' GROUP BY cab_type"
cab_type,COUNT(*)
green,32447
yellow,967553
0.05s — no import, queried straight off the fileWebsite · Quick Start · Installation · Performance · SQL Reference · Docs
Quick Start
csvql auto-detects SQL or simple mode from your input:
# SQL mode
csvql "SELECT name, salary FROM 'data.csv' WHERE age > 30 ORDER BY salary DESC LIMIT 10"
# Simple mode — same query, shorter syntax
csvql data.csv "name,salary" "age>30" 10 "salary:desc"
# Just browse a file
csvql data.csvUnix Pipes
cat data.csv | csvql "SELECT name, age FROM '-' WHERE age > 25"
csvql "SELECT * FROM 'data.csv' WHERE status = 'active'" > output.csv
csvql "SELECT email FROM 'users.csv'" | wc -lFlags
Flag | Short | Description |
| Suppress header row in output | |
| Treat the first row as data; auto-name columns | |
| Write results to a file instead of stdout | |
|
| Field delimiter (default |
| Output as a JSON array ( | |
| Output as JSONL / NDJSON (one JSON object per line) | |
| Worker threads for parallel execution; | |
| Error on a WHERE numeric comparison against a non-numeric value instead of silently skipping that row (see CORRECTNESS.md) | |
|
| Show version |
|
| Show help |
| Start as an MCP server (stdio JSON-RPC transport) | |
| Confine file access to a directory (repeatable via commas) | |
| Append a JSONL audit record per query (timestamp, SQL) |
# TSV file
csvql "SELECT name, salary FROM 'data.tsv'" -d $'\t'
# Pipe into another tool that expects no header
csvql "SELECT name, age FROM 'data.csv'" --no-header | awk -F, '{print $2}'
# TSV input, no header in output
cat data.tsv | csvql "SELECT * FROM '-'" -d $'\t' --no-headerRelated MCP server: mcp-csv-database
Installation
Homebrew (macOS / Linux)
brew install melihbirim/csvql/csvqlOr in two steps if you plan to install multiple tools from this tap:
brew tap melihbirim/csvql
brew install csvql
melihbirim/csvqlis the tap (the formula repository), and the trailing/csvqlis the formula name inside it.
Prebuilt Binaries
Download from 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/csvqlBuild from Source
Requires Zig 0.13.0+ (tested with 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/Performance
2M rows, 56 MB CSV, Apple M2 Pro — aggregates on the raw CSV (best-of-5):
Query | csvql | DuckDB | Speedup |
| 0.012s | 0.136s | 11.3x |
| 0.020s | 0.146s | 7.3x |
| 0.088s | 7.832s | 89x |
NYC Taxi, 20M rows, 8 GB CSV — raw CSV, no ingest, both engines: ~3.2x faster, ~6x less memory, and 0 bytes of extra storage (DuckDB's fast path needs a 2.1 GB native store first). At this scale csvql reads raw CSV about as fast as cat — the read itself is the bound, not parsing.
Full breakdown (LIKE, multi-table JOIN, subqueries, memory/storage, methodology): BENCHMARKS.md. Reproduce any number yourself: bench/bench_all.sh.
SQL Reference
SELECT/FROM/WHERE/GROUP BY/HAVING/ORDER BY/LIMIT/OFFSET, JOIN, subquery IN/NOT IN, LIKE/ILIKE/BETWEEN/IS NULL/AND/OR/NOT, aggregates (COUNT/SUM/AVG/MIN/MAX/VARIANCE/STDDEV/MEDIAN/GROUP_CONCAT), CASE WHEN, and scalar functions (UPPER/LOWER/TRIM/CONCAT/SUBSTR/REPLACE/SPLIT_PART/ROUND/CAST/COALESCE/STRFTIME/DATEDIFF/DATEADD/and more).
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')"Full syntax table, runnable examples for every feature, known differences from DuckDB, and current limitations: SQL_REFERENCE.md.
Positional "simple mode" is also available for quick one-off filters without writing SQL: csvql data.csv "name,salary" "age>30" 10 "salary:desc" — see SIMPLE_QUERY_LANGUAGE.md.
MCP Server
csvql ships as a Model Context Protocol server, letting AI assistants (Claude, Copilot, etc.) query your CSV files directly.
csvql --mcpWhy query instead of paste?
A 1 MB CSV costs ~560,000 tokens to paste into an LLM — it doesn't even fit a 200K-token context window. Pasting a real dataset is impossible past a few hundred KB, and expensive long before that. With csvql --mcp the agent queries the file instead and gets back only the rows it asked for:
CSV size | Paste into context | Query via | Savings |
1 MB | 559K tokens ❌ (overflows) | ~540 tokens | 1,000x |
10 MB | 5.6M tokens ❌ | ~550 tokens | 10,000x |
100 MB | 55M tokens ❌ | ~565 tokens | 98,000x |
417 MB | 230M tokens ❌ | ~560 tokens | ~410,000x |
The query cost is flat — it's the SQL plus a few result rows, independent of file size — so a 417 MB file costs the same ~560 tokens as a 1 MB one. Five real questions, answered against DuckDB's NYC-taxi data; token counts via tiktoken (exact cl100k). Reproduce: bench/bench_tokens.py. Your data never leaves your machine.
Exposed Tools
Tool | Description |
| Execute any supported SQL query, returns results as JSON |
| Column names and sample rows for a CSV file |
| List CSV files in a directory |
Supported Queries via MCP
csv_query accepts the full SQL dialect supported by csvql. You can ask your AI assistant things like:
Natural language prompt | SQL sent to |
"Show me the top 10 customers by revenue" |
|
"How many orders per month in 2025?" |
|
"How long does delivery take on average?" |
|
"Flag orders where picking exceeded SLA" |
|
"Add 2-day estimated delivery to shipments" |
|
"Which employees have no department?" |
|
"List all cities, deduplicated, sorted" |
|
"Average salary by department, only > 80k avg" |
|
"Join orders with customers, filter by region" |
|
"Salaries in range 50k–70k" |
|
"Employees not in London or Paris" |
|
Full WHERE clause support: =, !=, >, >=, <, <=, LIKE, BETWEEN, IN, IS NULL, IS NOT NULL, NOT, AND, OR
Full SELECT support: column projections, AS aliases, DISTINCT, COUNT/SUM/AVG/MIN/MAX/VARIANCE/STDDEV/MEDIAN/GROUP_CONCAT, GROUP BY, HAVING, ORDER BY (by name, alias, or position), LIMIT, STRFTIME(), DATE_PART(), JOIN, UPPER/LOWER/TRIM/LENGTH/SUBSTR/REPLACE/SPLIT_PART/GREATEST/LEAST, ABS/SIGN/CEIL/FLOOR/MOD/ROUND, COALESCE, CAST, DATEDIFF, DATEADD, EXTRACT
Setup
One command (recommended) — registers csvql in Claude Code and Claude Desktop, no manual config:
csvql install # add --print to dry-run firstIt runs claude mcp add for Claude Code (if the CLI is present) and merges an mcpServers.csvql entry into the Claude Desktop config, preserving your other servers. Restart Claude afterward.
Claude Desktop (one-click) — grab the csvql-<platform>.mcpb for your OS from Releases and open it in Claude Desktop (Settings → Extensions). No terminal. Build it yourself with scripts/build-mcpb.sh.
VS Code (Copilot) — create .vscode/mcp.json in your workspace:
{
"servers": {
"csvql": {
"type": "stdio",
"command": "/usr/local/bin/csvql",
"args": ["--mcp"]
}
}
}Claude Desktop — add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"csvql": {
"command": "/usr/local/bin/csvql",
"args": ["--mcp"]
}
}
}Once connected, you can ask your AI assistant to query CSV files directly:
"What are the top 5 product categories by revenue this year?"
Remote & on-prem: query data where it lives
Big files are hard to download — so run csvql on the server next to the data and connect over SSH. Only the SQL query and the small result cross the wire; the data never leaves the box. No open port, no reverse proxy — it rides your existing SSH keys and audit trail:
// client MCP config — csvql runs on the remote server
{ "command": "ssh", "args": ["analyst@dataserver", "csvql", "--mcp", "--root", "/data"] }--root sandboxes file access. With --root /data, queries can only read files under /data — SELECT * FROM '/etc/passwd' and ../ traversal are rejected. Always set --root when exposing csvql to an agent or another user. Pair it with a restricted OS user and a read-only mount for defense in depth.
Read-only by construction: csvql only runs SELECT — it has no INSERT/UPDATE/DELETE/DROP and cannot modify your data. It makes zero outbound network calls and runs fully air-gapped. Full posture and hardening guidance in SECURITY.md.
Language Libraries
csvql ships as a native library for Python and Node.js — same SIMD engine, same performance, no subprocess.
pip install csvql-query # Python: csvql.query(), .query_df(), .query_csv()
zig build node -Doptimize=ReleaseFast # Node.js: require('csvql-query')Full API, options (delimiter/comment/skip-empty-lines), memory comparisons against csv-parse/papaparse, and a runnable ETL example: docs/NODE.md · docs/PYTHON.md.
Documentation
Document | Description |
Full SQL syntax, runnable examples, DuckDB differences, limitations | |
Detailed performance analysis vs DuckDB, ClickHouse | |
What's tested against DuckDB, how, known gaps, error behaviour | |
Engine design, optimization techniques | |
Security posture, network/disk-write guarantees, hardening | |
Simple mode syntax reference | |
Node.js library: full API, options, ETL example | |
Python library: full API | |
Using the CSV parser as a Zig library | |
Contribution guidelines |
Roadmap
Feature | Issue | Status |
| ✅ shipped (v0.5.0) | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
MCP server ( | ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped | |
| ✅ shipped (v1.7.0) | |
| ✅ shipped (v1.7.0) | |
MCP token guardrails + | ✅ shipped (v1.7.0) | |
| ✅ shipped (v1.7.0) | |
| ✅ shipped (v1.7.0) | |
| ✅ shipped (v1.8.0) | |
| ✅ shipped (v1.8.0) | |
| ✅ shipped (v1.9.0) | |
HTTP/SSE MCP transport (shared service) | planned | |
| ✅ shipped | |
| help wanted | |
Shell completions (bash/zsh) | help wanted |
Contributing
Contributions welcome — bug reports, performance improvements, features, docs. See CONTRIBUTING.md.
New here? The good first issues are scoped with file pointers and clear done-when criteria — a great place to start (new SQL functions, output formats, and more).
License
MIT — see LICENSE.md.
Built with Zig · 9x faster than DuckDB · MCP Server · GitHub
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Query, join, profile, clean and convert CSV/JSON/Parquet with server-side DuckDB over MCP.
- OleanderOAuthdev.oleander
The all-in-one data stack for agents. Upload files, run SQL, evolve tables, and render charts.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Related MCP Servers
- AlicenseAqualityNot gradedmaintenanceAn MCP server that enables AI assistants to load, query, and analyze local CSV files using tools for filtering, aggregation, and grouping. It provides capabilities to describe schemas, calculate statistics, and sample data directly from CSV files.6-
- AlicenseBqualityDmaintenanceLoads CSV files into a temporary SQLite database and provides comprehensive data analysis tools via MCP, enabling AI assistants to query, analyze, and export data using natural language.14MIT
- AlicenseBqualityCmaintenanceEnables SQL querying over CSV and Excel files using DuckDB, providing tools to load files, inspect schemas, and run read-only queries via MCP.5MIT
- FlicenseNot gradedqualityCmaintenanceEnables natural language data analysis on uploaded CSV files by converting them to SQLite and exposing read-only database tools via MCP. Integrates with Ollama LLM to translate user questions into safe SQL queries.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/melihbirim/csvql'
If you have feedback or need assistance with the MCP directory API, please join our Discord server