Skip to main content
Glama
Pinggu17

sqlite-ro-mcp

by Pinggu17
README.md
# sqlite-ro-mcp

A read-only SQLite [MCP](https://modelcontextprotocol.io) server in one auditable Python file.

Most "read-only" SQLite MCP servers are write-capable servers with a switch:
an env var, or even a tool argument the model itself can flip. This server
takes a different position: **the write path does not exist.**

## Defense in depth

1. **No mutating tool is defined.** There is nothing to toggle.
2. **Every statement is validated** - head whitelist (`SELECT` / `WITH` /
   `EXPLAIN`) plus a write-keyword scan on comment- and literal-stripped SQL,
   so `WITH cte AS (...) INSERT ...` and keyword-in-string tricks are caught.
3. **Connections are opened `mode=ro`.** Even if a validation bug slipped
   through, SQLite itself refuses the write.

Layer 3 matters: SQLite accepts statements like `WITH ... INSERT`, which a
naive first-word check happily approves. Validation bugs are a *when*, not an
*if* - the connection flag is the guarantee, the validator is just the first
line. The test suite proves this directly: one test bypasses the validator
entirely (calls the connection layer straight) and confirms SQLite itself
still refuses the write.

The whole server is a single file of a few hundred lines with one dependency
(the official `mcp` SDK). You can audit the entire attack surface in a few
minutes.

## Install

```bash
pipx install sqlite-ro-mcp        # or: pip install sqlite-ro-mcp
```

Or run from a checkout: `pip install -e .`

## Use with Claude Code

```bash
claude mcp add sqlite-ro -- sqlite-ro-mcp --db sales=path/to/sales.db --db logs=path/to/logs.db
```

Multiple databases are exposed by **named alias allowlist** - only the files
you name are reachable (no directory scanning).

## Tools

| tool | description |
|---|---|
| `list_databases` | aliases and file paths this server exposes |
| `list_tables(db)` | tables and views |
| `describe_table(db, table)` | columns, types, nullability, primary key |
| `read_query(db, sql, params?)` | single SELECT / WITH / EXPLAIN, `?` binding, 500-row cap, 30s timeout |

## Options

```text
usage: sqlite-ro-mcp [-h] --db [NAME=]PATH [--timeout TIMEOUT] [--instructions INSTRUCTIONS]

Read-only SQLite MCP server

options:
  -h, --help            show this help message and exit
  --db [NAME=]PATH      SQLite file to expose; repeatable
  --timeout TIMEOUT     per-query timeout in seconds (default 30)
  --instructions INSTRUCTIONS
                        override the instructions text advertised to clients
```

## Non-goals

Writes of any kind, remote databases, authentication. If you need a
write-capable server, use one that is honest about being one.

## Authorship

Built with Claude Code. Requirements, the no-write-path design constraint,
and review are by the author; implementation is AI-assisted and covered by
the test suite in `tests/`.

## License

MIT