tablebridge
<!-- mcp-name: io.github.Michael-WhiteCapData/tablebridge-mcp -->
# tablebridge
**Turn a folder of CSV / Parquet / JSON files into one SQL-queryable source for your AI agent.**
[](https://github.com/Michael-WhiteCapData/tablebridge-mcp/actions/workflows/ci.yml)
[](https://pypi.org/project/tablebridge/)
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
[](LICENSE)
Small businesses don't have a data warehouse â they have a folder full of exports: `customers.csv`, last month's `orders.xlsx`, a `regions.json` someone emailed over. `tablebridge` is an [MCP](https://modelcontextprotocol.io/) server that points [DuckDB](https://duckdb.org/) at that folder, exposes **each file as a SQL table**, and lets your agent run **read-only SQL â including JOINs across files** â to answer questions over all of them at once. Scattered spreadsheets become one queryable source of truth.
It's **read-only and sandboxed**: files are loaded into an in-memory database, the data directory is the only thing it can see, and queries are validated so an agent can't write, escape to other paths, or call raw file functions.
---
## Why you'd want this
- ð **One source over many files.** JOIN `orders.csv` to `customers.csv` to `regions.json` in a single query â no ETL, no database to stand up.
- ðĶ **DuckDB-powered.** Fast analytical SQL over CSV, TSV, Parquet, JSON/NDJSON.
- ð **Safe by design.** Files are materialized into memory; queries are validated read-only; raw file-access functions and out-of-sandbox paths are rejected.
- ðĪ **Agent-friendly.** `list_sources` â `describe` â `query` is a natural flow the agent can follow on its own.
- ðŠķ **Two dependencies** (`mcp`, `duckdb`), fully typed and tested.
## Install
```bash
uvx tablebridge # run directly
# or
pip install tablebridge # then run: tablebridge
```
### Claude Code
```bash
TABLEBRIDGE_DATA_DIR=/path/to/your/data claude mcp add tablebridge -- uvx tablebridge
```
### Claude Desktop / Cursor
```jsonc
{
"mcpServers": {
"tablebridge": {
"command": "uvx",
"args": ["tablebridge"],
"env": { "TABLEBRIDGE_DATA_DIR": "/path/to/your/data" }
}
}
}
```
## Run with Docker
A [`Dockerfile`](Dockerfile) is included. The server speaks MCP over stdio. Mount the
folder you want to query at `/data` (read-only is fine) and run interactively (`-i`):
```bash
docker build -t tablebridge .
docker run --rm -i -v /path/to/your/data:/data:ro tablebridge
```
## Tools
| Tool | Description |
| --- | --- |
| `list_sources` | List the tables (one per data file) with column counts â start here |
| `describe` | A table's columns and types |
| `preview` | First N rows of a table |
| `query` | Run read-only SQL (DuckDB dialect) across the tables, JOINs included |
| `refresh` | Re-scan the data directory for added/changed files |
| `server_info` | Effective config (data dir, row cap, supported formats) |
## Example
With a folder containing `customers.csv`, `orders.csv`, and `regions.json`:
> **You:** Who are my top 3 customers by total spend, and what region are they in?
>
> **Agent:** *(calls `list_sources`, then `query`)*
> ```sql
> SELECT c.name, r.region, SUM(o.total) AS spend
> FROM customers c
> JOIN orders o ON o.customer_id = c.id
> JOIN regions r ON r.customer_id = c.id
> GROUP BY c.name, r.region
> ORDER BY spend DESC
> LIMIT 3;
> ```
## Configuration
| Variable | Default | Description |
| --- | --- | --- |
| `TABLEBRIDGE_DATA_DIR` | `.` | Directory of files to expose (the sandbox boundary) |
| `TABLEBRIDGE_MAX_ROWS` | `1000` | Max rows returned per query/preview |
| `TABLEBRIDGE_RECURSIVE` | `1` | Scan subdirectories too |
Supported formats: `.csv`, `.tsv`, `.parquet`, `.json`, `.ndjson`.
## Security model
1. **Sandboxed** to `TABLEBRIDGE_DATA_DIR` â only files under it are loaded.
2. **Materialized** into an in-memory DuckDB, then external filesystem access is disabled â queries can't reach other paths.
3. **Validated SQL** â a single read-only statement only; writes and raw file-reader functions are rejected.
## Development
```bash
git clone https://github.com/Michael-WhiteCapData/tablebridge-mcp
cd tablebridge-mcp
uv pip install -e ".[dev]"
ruff check .
pytest # uses real DuckDB over temp files
```
See [CONTRIBUTING.md](CONTRIBUTING.md).
## License
[MIT](LICENSE) ÂĐ Michael Tierney
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: describe for schema, list_sources for table listing, preview for row sampling, query for SQL execution, refresh for data reload, and server_info for configuration. No overlap.
Most tools use single imperative verbs (describe, preview, query, refresh) but list_sources uses verb_noun and server_info uses noun_noun. The pattern is mostly consistent but has minor deviations.
With 6 tools, the server covers all core functionalities needed for data exploration and querying without excess or deficiency. The scope is well-matched.
The tool set provides essential operations: listing, describing, previewing, querying, refreshing, and configuration. A minor gap could be the absence of a statistical summary tool, but the core workflow is fully covered.