Lintel
Provides read-only tools for auditing Supabase database migrations and Row Level Security (RLS) policies, including check_migrations, run_checks, diff_databases, list_checks, and explain_check. It replays base and PR migrations into throwaway Supabase databases to detect new leaks, prove anon access, and report findings.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Lintelis my new migration safe to merge?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Lintel
Catch Supabase RLS leaks in the pull request that introduces them.
Lintel replays your base branch's and your PR's migrations into two throwaway Supabase databases and checks both. It posts one PR comment listing only what the PR changed: new, fixed in this PR, unchanged. It can also prove a leak by querying as anon or as another user.
Study: How often do public Supabase repos ship a readable table?
Status: early development. The table below lists what works today. Everything else is in docs/design.md.
Built on Supabase's linter
Supabase already ships an excellent linter, splinter. You can reach it through the dashboard Advisors, supabase db advisors and the Supabase MCP server. Lintel uses it for every static finding, and adds three things it doesn't do:
PR diffs. Findings are compared against the base branch, so only what the PR introduces fails the check.
Proof. Probes run real queries as
anon(and soon as another signed-in user) and report what actually leaks, e.g. "the public anon key can read 2 rows frompublic.messagesbecause RLS is disabled."One contract, three surfaces: a CLI, an MCP server for coding agents, and a REST API (in progress).
Related MCP server: PgVouch
Try it
You need Node 22.12 or later, Docker, and the Supabase CLI. Nothing to clone or build:
cd ~/your-supabase-project
npx @amsozzer/lintel migrations check # your working tree vs mainThe first run pulls the Supabase Postgres image (about 800 MB, one time). Run npx @amsozzer/lintel setup to do that ahead of time.
New
error public.messages P001 [proven]
Proved: the public anon key can read 2 rows from `public.messages` because RLS is disabled.
error public.messages policy_exists_rls_disabled
Table `public.messages` has RLS policies but RLS is not enabled on the table. …
error public.messages rls_disabled_in_public
Table `public.messages` is public, but RLS has not been enabled.
3 new (3 error, 0 warn, 0 info) · 0 resolved · 1 unchangedFrom source instead:
git clone https://github.com/Amsozzer1/lintel && cd lintel
pnpm install && pnpm build
cd ~/your-supabase-project && node ~/lintel/dist/cli.js migrations checkUse it from a coding agent (MCP)
lintel mcp serves five read-only tools over stdio. The one agents need most is check_migrations. Ask your agent "is this migration safe to merge?" and it replays your base branch and your working tree into throwaway databases. It answers NOT SAFE: the change introduces errors, with the proven leak, before anything reaches a real database.
{
"mcpServers": {
"lintel": {
"command": "node",
"args": ["/abs/path/to/lintel/dist/cli.js", "mcp", "--config", "/abs/path/to/lintel.config.json"],
"env": { "STAGING_DATABASE_URL": "postgresql://…" }
}
}
}{ "schemas": ["public"], "profiles": { "staging": { "url": "env:STAGING_DATABASE_URL" } } }Design choices:
Tools take profile names, never connection strings, so credentials don't pass through the model's context.
Every tool is read-only.
Results mark database identifiers as untrusted data. A table can be named like an instruction.
The tool list is a versioned contract (
schemas/mcp-tools.v1.json) that CI checks for drift.
Status
Piece | State |
| ✅ |
| ✅ |
| ✅ |
GitHub Action with a fork-safe sticky comment (demo PRs: a leak caught, the fix) | ✅ |
Probe P001: proves what the | ✅ |
Probes P002 anon write, P003 cross-user read | ⏳ |
MCP server: | ✅ |
REST API (OpenAPI 3.1) | ⏳ |
lintel --help takes about 38 ms wall-clock, of which about 24 ms is Node's own startup (median of 40 runs, Apple M4, macOS 26.6, Node 24.21).
Exit codes
Code | Meaning |
0 | Clean |
1 | Findings at or above |
2 | Usage error |
3 | Can't reach the database, Docker or the Supabase CLI |
4 | Internal error |
5 | A migration failed to apply |
Limitations
Migrations only. Lintel checks the database your migrations build, not your live project. Tables, policies or grants created in the Supabase dashboard (or by SQL run outside
supabase/migrations) aren't in it. When a migration depends on one, the replay fails with exit 5 and names the missing object;supabase db resetwould fail the same way. Capture dashboard changes withsupabase db pull.Same rules as
supabase db push. Only files named<digits>_name.sqlare applied (others are listed as skipped), each in one transaction, in name order.Extensions: replays use Supabase's Postgres 17 image, so extensions it doesn't ship (e.g.
timescaledb) fail to apply.pgsodiumin old dumps: schema dumps from projects that hadpgsodiumenabled containcreate extension if not exists "pgsodium" with schema "pgsodium". On a fresh database that fails, becausewith schemaneeds the schema to exist already. Drop thewith schema "pgsodium"part: the extension always installs intopgsodium.Proof needs rows. Probes prove a leak only for tables with rows (from
seed.sql). Empty tables are reported as unverified, never as passing.lintel checklists each one:- public.notes P001 [unverified_no_rows] anon can query it, but it has no rows, so P001 can't prove whether RLS hides them. Add rows to seed.sql.
Credits
Lintel's replay databases contain the auth and storage schemas produced by the migrations of Supabase Auth v2.197.0 (MIT) and Supabase Storage v1.77.0 (Apache-2.0), dumped by scripts/gen-supabase-env.ts. Static findings come from Supabase's linter, splinter. The statement splitter is a port of the Supabase CLI's (MIT). License texts are in THIRD_PARTY_NOTICES.md.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Your Supabase account in natural language: run SQL, apply migrations, manage tables, storage, edge f
- ScribaseOAuthcom.scribase
Supabase-compatible Postgres for agents: projects, branches, SQL, auth, storage, email.
Detects database migration table locks, terraform cost leaks, and OWASP API flaws.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server that lets AI coding agents (Claude Code, Cursor, Cline) audit Supabase projects for security misconfigurations AND apply the fixes — without leaving the agent. Tools: audit_project, list_findings, preview_fix (BEGIN/ROLLBACK safety), apply_fix (with confirmation), apply_all_fixes (transactional bulk). Closes the audit-fix loop entirely in the agent — other Supabase scanners only report.52 npm1MIT
- AlicenseNot gradedqualityAmaintenanceExposes read-only tools that let AI assistants detect schema drift, analyze lock impact, verify data with checksums, and plan safe PostgreSQL migrations that are validated by deterministic checks and shadow runs.24 npmApache 2.0
- AlicenseBqualityBmaintenanceRead-only security audit for Supabase. Surfaces RLS gaps, permissive policies, exposed functions and grants, and returns scored findings with fix SQL that is never executed.6450MIT
- AlicenseAqualityCmaintenanceEnables AI coding assistants to check whether an API key is safe to expose, audit Supabase Row Level Security, generate owner-based RLS policy templates, and run a builder-specific pre-launch security checklist. Runs locally over stdio with no network calls, telemetry, or file access.5MIT