Skip to main content
Glama
SQLite Explorer MCP

SQLite Explorer MCP

sqlite-mcp-explorer

A sandboxed text-to-SQL stack for AI agents: a read-only SQL server over MCP, a natural-language interface, and a benchmark that scores any text-to-SQL model on syntax validity, schema adherence and execution accuracy. Giving an agent a database is risky; the sandbox is built so a bad, hallucinated or hostile query cannot change data or run away.

demo

Safety model

Several independent layers, so one failure does not open the door:

  1. Read-only connection: the file is opened with mode=ro; SQLite itself refuses writes.

  2. Authorizer allow-list: only SELECT, column reads, functions and recursive CTEs are permitted. DROP, DELETE, UPDATE, INSERT, CREATE, ALTER, PRAGMA, ATTACH, VACUUM and load_extension are denied.

  3. One statement per call, so SELECT 1; DELETE ... is rejected.

  4. Bounded cost: results are capped at 200 rows (the response says if it was truncated), and a query is aborted after 2 seconds.

The tests exercise each layer, including attack queries, and check that data is unchanged afterwards.

Related MCP server: MCP SQLite Server (Read-Only)

Text-to-SQL and benchmark

Ask in plain English; a generator writes SQL, and that SQL runs through the same sandbox as everything else. Plug in any OpenAI-compatible model (OpenAI, Ollama, vLLM, LM Studio):

TEXT2SQL_MODEL="openai:llama3@http://localhost:11434/v1" sqlite-explorer-web

Gemini works through Google's OpenAI-compatible endpoint; keep the key under its own name:

GEMINI_API_KEY=... TEXT2SQL_API_KEY_ENV=GEMINI_API_KEY \
TEXT2SQL_MODEL="openai:gemini-3.1-flash-lite@https://generativelanguage.googleapis.com/v1beta/openai" \
sqlite-explorer-web
GEMINI_API_KEY=... sqlite-explorer-bench --api-key-env GEMINI_API_KEY \
  --generator "openai:gemini-3.1-flash-lite@https://generativelanguage.googleapis.com/v1beta/openai"

Use a current model name from the provider's docs (Gemini 2.5 models are already retired for new users). The generator retries 429/5xx responses, but gives up at once on a daily quota.

Live result (gemini-3.1-flash-lite, free tier, run 2026-10-22, one run): 53 questions, 100% produced SQL, 100% syntax validity, 100% schema adherence, 100% execution accuracy; latency p50 13.1 s, p95 52.2 s. A first run scored 98% (52/53): q50 ("average product price in each category") failed because the reference rounds to 2 decimals and the question did not say so. The question now says "rounded to 2 decimals". This is a small, easy benchmark, so 100% shows the pipeline works end to end rather than ranking models.

Benchmark any generator on 53 questions across 10 categories (counts, aggregates, joins, group-by, subqueries, top-N, dates). Reference answers are executed SQL, not text:

sqlite-explorer-bench --generator template                          # baseline, no LLM
sqlite-explorer-bench --generator "openai:llama3@http://localhost:11434/v1" --out run.json
sqlite-explorer-bench --generator ... --min-accuracy 0.8            # exit 1 below 80%, for CI

Metric

Meaning

Syntax validity

The SQL parses

Schema adherence

Every table and column exists (hallucinations fail here)

Execution accuracy

The result set matches the reference query's (order ignored unless the reference has ORDER BY)

Unsafe SQL (for example a generated DROP TABLE) is flagged and never executed.

The bundled template generator is a regex baseline, not an LLM. It scores about 45% (simple counts and filters pass; every join, group-by and subquery fails), which gives a real model something to beat. Its produced SQL rate shows how often it declined to answer.

Demo (no API key)

pip install -e ".[dev]"
sqlite-explorer-web                # http://127.0.0.1:8000

It opens a synthetic shop database (customers, products, orders, order items) generated from a fixed seed; it contains no real data. The page has buttons that attempt DROP TABLE, a two-statement query and an infinite recursive query, so you can watch each get rejected.

Use your own database:

SQLITE_DB=/path/to/app.db sqlite-explorer-web

MCP tools

{ "mcpServers": { "sqlite": { "command": "sqlite-explorer-mcp",
                              "env": { "SQLITE_DB": "/path/to/app.db" } } } }

Tool

Does

list_tables()

Tables and views

describe_table(table)

Columns, types, keys, foreign keys, row count

get_schema_ddl()

CREATE TABLE statements; read first, then write SQL against them

run_query(sql)

One read-only SELECT; errors if rejected or timed out

Tests

python -m pytest
ruff check src tests

Verified vs not verified

  • Verified: the sandbox and benchmark logic (51 tests, including attack queries and a perfect "oracle" generator that scores 100%); the OpenAI-compatible generator against a mocked transport; and the benchmark CLI end to end against a local fake OpenAI-compatible server.

  • Verified live: the benchmark against Gemini gemini-3.1-flash-lite (result above).

  • Not verified: runs against a live Ollama/vLLM/OpenAI model, and the web UI with a live model.

Limitations

  • The benchmark's reference answers are tied to the seeded sample database; use --cases with your own questions for another database.

  • Vector / hybrid search is not included.

  • SQLite only.

  • A read-only query can still read anything in the file. Point it at a database (or a copy) that contains only data the agent may see.

  • The 2-second limit stops runaway queries, but it is a per-query guard, not a rate limiter.

  • No authentication on the web console; keep it on localhost.

Available Tools

4 tools
describe_tableB

Columns, types, primary keys, foreign keys and row count of a table.

Inputs: table (required). Returns: object

get_schema_ddlA

CREATE TABLE statements for the whole database. Read this first, then write a SELECT for run_query: every table and column you use must appear here.

Inputs: no named parameters. Returns: result

list_tablesB

Names of the tables and views in the database.

Inputs: no named parameters. Returns: result

run_queryA

Run ONE read-only SELECT statement. Writes, PRAGMA, ATTACH and multiple statements are rejected. Results are capped at 200 rows (check truncated) and queries time out after 2s.

Inputs: sql (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 4 tools

    Disambiguation4/5

    The tools have mostly distinct purposes: listing tables, describing one table, fetching full DDL, and running a query. There is some conceptual overlap between describe_table and get_schema_ddl, but the descriptions make the intended scope of each clear.

    Naming Consistency5/5

    All tool names use snake_case with a clear verb_noun pattern: list_tables, describe_table, get_schema_ddl, run_query. The convention is predictable throughout.

    Tool Count5/5

    Four tools are well-scoped for a read-only SQLite exploration server. Each tool has a clear role and there is no unnecessary surface area.

    Completeness5/5

    The read-only exploration domain is fully covered: list tables/views, inspect a table, retrieve full schema, and execute SELECT queries. No obvious operational gap exists given the intentionally read-only scope.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Exposes a SQLite database to AI assistants with structured, read-safe access. Includes five tools for schema exploration, querying, and sampling data.
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to safely query and explore SQLite databases through read-only, guard-protected tools that block writes, sensitive table access, and runaway queries.
      1
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to inspect database schemas and run strictly read-only SQL queries with guardrails against destructive statements, multi-statement chaining, and unbounded scans. Supports SQLite natively and PostgreSQL optionally.
      4
      37 PyPI
      MIT