AI agents need access to your database.
And they need a live map of what’s in it.
Database MCP gives them both, read-only.
Twira gives your AI agent direct, read-only access to your live database. Full structural map, every table, column, foreign key, index, RLS policy, migration history, discovered live, never reconstructed from code. Plus read-only queries against the real thing. The agent sees everything, changes nothing. Writes stay in your hands.
You see your database. Your agent doesn’t. Twira gives the agent eyes, read-only by design.
Read-only by design
Enforced at the SQL validator + the connector layer. Writes stay with you, via your migrations, scripts, ops.
mapEvery table, column, FK, index, view, function, trigger, discovered live.
queryRead-only SELECTs. Sample. Profile. EXPLAIN.
securityRow-level security policies. Migration history.
healthPer-table stats.
code refsEvery place your code touches a table, 17 ORM patterns.
You ask
“Find users with orders over £100.”
Twira instantly
- queries the orders table live, finds the FK to users(id)
- sees amount is numeric(10,2), not int, quotes the value correctly
- spots an RLS policy filtering by tenant_id
- generates a query that respects all three
- attaches the connection identity (read-only user, bypass_rls=false)
Agent writes correct SQL, verified against live truth.
How the agent uses this
Agent calls `db` via MCP. 20 actions in total, all Pro. `env` parameter selects which connection from your `Twira.json` (default `dev`). Read-only enforced at both the SQL validator and the connector layer.
When you reach for it
- The agent is about to write a SQL query and needs the real schema, not a guess, calling describe on a table returns columns, constraints, and COMMENT ON text in one response.
- Refactoring a column, calling refs with the table.column name finds every place in code that reads or writes it (works whether your code uses raw SQL or any of 17 supported ORMs).
- PII audit, calling find-column with a name pattern returns every (schema, table, column) where the name matches, across the entire database.
- Investigating why a row is missing, calling rls on a table shows which row-level security policies are filtering your view, with the actual USING and WITH CHECK expressions.
- Pre-flight before a migration, calling migrations auto-detects what framework you are running (Flyway, Rails, Alembic, Diesel, Knex, Prisma, Goose, or Sqitch) and lists every version applied.
- Investigating a slow endpoint, calling slow-queries surfaces the top offenders from pg_stat_statements with calls, total time, mean time, and cache-hit ratio.
- Understanding a column before refactoring it, calling profile on a column returns cardinality, null percentage, and the most-common values.
- Confirming what the agent has access to right now, every response carries the connection identity envelope showing role, superuser status, and RLS posture.
See it work
$ # Agent calls via MCP, there is no `twira db` CLI
db action=refs table="users.email" env=devTechnical depth, for engineers who want it
In your editor
In your terminal, `psql` connects you to the database in seconds. DataGrip, TablePlus, Postico, DBeaver, every developer keeps a SQL client open alongside their IDE. You browse tables, run queries, check indexes, look at migration history. The database is a few keystrokes away.
What Database MCP does
Database MCP is two tools in one connection. **The structural map**, every table, column, foreign key, index, view, function, trigger, RLS policy, and migration history, discovered **live** from the database, not reconstructed from your code. **The live query**, read-only SELECTs, table samples, column profiles, EXPLAIN plans. 20 actions across 6 engines. Configure the connection once in `Twira.json`; the agent calls anything from there. No index to maintain. No cache to invalidate. Every response carries a `connection` envelope (provider, current user, role, RLS bypass flag) so the agent knows which auth context produced the answer. Read-only is enforced at both the SQL validator and the connector layer.
How it actually works
Database MCP is the bridge between your code and the database your code actually talks to. The agent stops guessing the schema and starts asking, through the same MCP interface it uses to query the codebase. Six engines are supported: PostgreSQL (the deepest surface), MySQL, SQL Server, MongoDB, DuckDB, and local SQLite. Each engine supports the subset of actions that makes sense for it.
Database MCP ships 20 actions across four working groups, all Pro-tier. Data queries: query (read-only SELECT), sample (peek at N rows with optional column projection), and profile (column-level statistics, distinct count, null percentage, top-N most-common values). Schema discovery: describe (columns, constraints, COMMENT ON text), tables, keys (FK relationships outgoing or backwards), indexes, views (regular plus materialised), functions, triggers, sequences, enums, extensions, and find-column (locate every (schema, table, column) by name pattern, PII tracing in one call). Health and tuning: stats (per-table size, row count, dead tuples, vacuum/analyse state, seq vs index scan counts), explain (query plan as JSON, optional ANALYZE for actual row counts and timings), and slow-queries (top-N from pg_stat_statements). Security and evolution: rls (row-level security policies with the actual USING and WITH CHECK expressions) and migrations (auto-detects your migration framework, Flyway, Rails, Alembic, Diesel, Knex, Prisma, Goose, or Sqitch, and returns the applied history).
The refs action is the foundational one. Cross-reference any table or column name to every place in your code that touches it. The data comes from the indexed sql_references table the indexer already built, so a question like "where is users.email read or written?" becomes a single MCP call, not a grep across thousands of files. Coverage spans raw SQL in any language plus 17 ORM patterns: Prisma, TypeORM, Sequelize, Drizzle, Knex, Mongoose, Django, SQLAlchemy, Peewee, ActiveRecord, Eloquent, Doctrine, GORM, Diesel, SQLx, JPA/Hibernate, and EF Core. The answer is correct whether you write raw queries or use an ORM that buries them.
Not every action runs on every engine. PostgreSQL gets the full set. SQLite, MySQL, and SQL Server support the broadly portable subset (tables, describe, keys, indexes, views, explain, query, sample). Postgres-only actions include profile, functions, triggers, sequences, enums, extensions, stats, slow-queries, rls, and migrations. MongoDB gets the data and schema-discovery actions adapted to its model. Unsupported combinations return a structured "Not supported: <action> on provider <name>" error, never a silent failure.
Every response carries a connection-identity envelope: provider, database name, server, current_user, session_user, current_role, is_superuser, bypass_rls, and read_only. This sounds like plumbing; it is actually the answer to "why did this query return what it returned?", when an RLS policy filters out rows, when a role grants accidental access, when a query returns nothing because the connection is pointed at the wrong env, the envelope tells you immediately.
Connections are per-environment. Configure dev, staging, prod, or anything else under the database block in Twira.json and toggle between them with the env parameter (default "dev"). Credentials live in your .env file, referenced from the connection string. Nothing about the connection details, credentials, or query results ever leaves your machine, Database MCP runs locally against the database you point it at, the same as if you were running psql yourself.
Read-only enforcement runs at two layers. The SQL validator accepts SELECT, WITH, EXPLAIN, SHOW, and PRAGMA. INSERT, UPDATE, DELETE, ALTER, DROP, CREATE, and TRUNCATE are rejected before they reach the connector. The connector itself opens read-only sessions where the engine supports it. The design intent is clear: the agent should never accidentally write to your database. Writes belong to a different category of action, a developer-authored script someone ran on purpose, or a reviewed migration that lands through your migration framework (the same one Database MCP's migrations action introspects). EXPLAIN ANALYZE is permitted because it runs the same SELECT body the validator already accepted, useful for actual row counts and timings, never destructive.
Setup is two steps. First, the code-side of Database MCP (the refs action) reads from the index, running twira index once on install builds the sql_references cross-reference table. Second, database connections themselves are configured in Twira.json when you first need them. From there, the agent calls any of the 20 actions through MCP. Database MCP is MCP-only by design, there is no twira db CLI subcommand. Connections, query results, and credentials stay on your machine.
What it isn’t
- Read-only. Every action is enforced as read-only at both the SQL validator and the connector layer. The agent cannot write, update, or delete. To change the database, you still write the migration yourself.
- All 20 actions are Pro-tier.
- Not every action is supported on every engine. PostgreSQL has the deepest surface; SQLite, MySQL, SQL Server, MongoDB have subsets. Unsupported actions return a structured "Not supported on provider X" error, no silent failures.
- Connections come from Twira.json, not from environment variables passed at call time. The agent specifies `env: "dev" | "sandbox" | "prod"`, the actual credentials stay on your machine in config you control.
One install. Your agent will know the difference in the first session.
$ curl -fsSL twira.com/install.sh | sh