Back to blog

How to Set Up a SQLite MCP Server With OpenAI Codex

Spencer Pauly
Spencer Pauly
3 min read
How to Set Up a SQLite MCP Server With OpenAI Codex

My app uses Turso for its SQLite backend. Last week I was chasing a performance complaint and wanted to know which queries were pulling back the most rows. The SQLite query stats story is thinner than Postgres, but I figured I'd let Codex sort that out. I typed the question. Codex inspected the schema, decided what it could actually measure, wrote a query, and gave me something useful inside of a minute.

This post walks through connecting Codex to a SQLite database (including Turso/libSQL) through QueryBear.

Part of the SQLite MCP Server guide.

What you'll need

  • A SQLite database, including Turso or any libSQL endpoint
  • A QueryBear account (free to start)
  • OpenAI Codex CLI installed (npm install -g @openai/codex or the platform installer)

Why route through a gateway

Pointing Codex at your database directly means the agent can read anything your connection can read, with no filtering and no audit trail. QueryBear parses queries before they run, enforces a table allowlist, blocks specific columns, caps row counts, and logs every call. Your Turso auth token stays inside QueryBear. The SQLite MCP Server guide has the full breakdown.

Connect QueryBear to your SQLite database

  1. Open the QueryBear dashboard and click "New connection."
  2. Pick SQLite (Turso/libSQL). Paste your Turso URL (libsql://your-db.turso.io) and your auth token. QueryBear connects over HTTP using the libSQL client, so no tunneling is needed.
  3. Under "Allowed tables," pick the tables the agent can see. Under "Blocked columns," block anything sensitive.
  4. Save.

Install the QueryBear MCP server in Codex

Open ~/.codex/config.toml and add:

[mcp_servers.querybear]
url = "https://mcp.querybear.com/mcp"

Codex reads the config file on each invocation. You can also scope this to a single project by placing a .codex/config.toml at your project root.

Ask your first question

I asked: "List the most expensive queries by row count."

SQLite doesn't expose a native pg_stat_statements equivalent. Codex noted this, then pivoted to what it could actually answer: which tables are largest by row count, which makes it easy to identify where expensive full-table scans are most likely happening.

Codex generated:

SELECT
  name AS table_name,
  (SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = m.name) AS exists_flag
FROM sqlite_master m
WHERE m.type = 'table'
ORDER BY name;

Then it followed up with individual SELECT COUNT(*) calls per table to rank them. QueryBear ran each one through the parser, confirmed the tables were allowlisted, and returned results. I could see immediately which tables were large enough to warrant index attention.

SQLite's dynamic typing means Codex will sometimes get back TEXT where you'd expect INTEGER. That's a SQLite behavior, not a QueryBear or Codex issue. If a comparison looks off, tell Codex to cast explicitly: CAST(column AS INTEGER).

A Codex-specific tip

Use --resume to carry the MCP session forward between terminal invocations:

codex --resume

Schema discovery on a Turso database with many tables can take a few seconds. --resume skips that on follow-up questions, which adds up quickly during a longer investigation. If Codex surfaces a MCP error (a table not on the allowlist, a malformed query), it prints the message in plain text -- read it, adjust your allowlist or your question, and keep going.

Using a different tool?

Querying a different database?

Database Access

Give Your AI Agents
Database Access. Securely.

Connect any database. Control permissions. Audit every query. All running locally on your machine.