muhandis-rls-check
This MCP server helps audit Supabase RLS by providing the read-only query and explaining its pasted result without accessing your data.
rls_check_query: returns a read-only SQL query listing public tables/views with RLS state, anon/authenticated grants, columns, and policies.rls_check_explain: explains the query result table by table, worst first, identifying exposed, check-it, locked, and safe cases.Findings are in Arabic for founders with English labels and links to Arabic fix lessons.
Works offline on the pasted result; needs no key, password, database connection, or row data.
Suitable for SQL Editor or Supabase MCP
execute_sql, then passing the single JSON result cell to the explain tool.
Analyzes the Row Level Security (RLS) configuration of a Supabase project from the result of a read-only SQL query (RLS state, policies, grants, column names). It explains table by table which tables are exposed to the anon key, which let signed-in users read other users' data, which are locked, and which are safe. The query can be run manually in the Supabase SQL Editor or by an agent through the official Supabase MCP.
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., "@muhandis-rls-checkGet the RLS check query, then explain which of my Supabase tables are exposed"
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.
RLS check for Supabase: who can read your customers' data?
A read-only query you run in your own Supabase SQL Editor, and an analyser that explains the result table by table:
which tables anyone with the public (anon) key can read or change;
which tables let any signed-in user read other users' rows;
which tables are locked, and which are safe.
The findings are written in Arabic for non-technical founders, with English labels (exposed, check it,
locked, safe), and each one links to an Arabic lesson on the fix.
It reads no data. The query reads table descriptions only: RLS state, policies, grants and column names. Never a row.
It needs no key or password and opens no connection to your database. You run the query yourself, or an agent runs it through the official Supabase MCP.
It is the same check as the browser tool at muhandis.online/tools/rls-check:
lib/rls-check.jsis the site's analyser, copied byte for byte.
Usage
1. In the browser (easiest)
Open the check page, copy the query, run it in Supabase and paste the result. Everything happens in your browser; nothing is sent anywhere.
2. From the command line
npx muhandis-rls-check query > query.sql # the query: run it in your SQL Editor
npx muhandis-rls-check result.json # paste the result cell into a file; this explains it
npx muhandis-rls-check result.json --json # the same explanation as JSONIt exits with 1 when a table is exposed, so it can be a CI step.
3. For an AI assistant (MCP)
Add it to Claude, Cursor or any MCP client. The assistant runs the query (through the official Supabase MCP, for example) and this server explains the result. The server itself holds no connection details.
{
"mcpServers": {
"muhandis-rls-check": { "command": "npx", "args": ["-y", "muhandis-rls-check", "mcp"] }
}
}Tools: rls_check_query returns the query, rls_check_explain explains a result.
4. As a Claude skill
The same check as a Claude skill: Claude gives you the query, then runs the pasted result
through skills/rls-check/scripts/rls_check.py, a Python copy of the analyser that the tests hold to the same output
as lib/rls-check.js. It needs no key and makes no network call.
Claude app: download
rls-check.zipfrom the latest release, then Customize > Skills, upload it and turn it on. Code execution must be enabled.Claude Code:
/plugin marketplace add Muhandis-online/rls-check
/plugin install rls-check@muhandisRelated MCP server: schema-guard-mcp
What it checks
Label | Arabic | Meaning |
| مكشوف | RLS is off and the visitor role has a grant; or a policy whose condition is |
| تأكد منه | Data everyone can read that has no personal columns, such as a product list; or inserts without sign-in, such as a contact form |
| مقفول | RLS on with no policies, or no grants: the app cannot reach it |
| سليم | Policies tied to the row's owner through |
Personal columns are recognised by name (email, phone, user_id, iban, national, iqama and similar).
Limits
This checks the rules you can see; it does not replace a test. After it, sign in with two accounts and confirm each one sees only its own rows. Supabase's own Security Advisor flags related issues (RLS disabled, security-definer views, permissive policies); this tool adds an explanation in Arabic for the product's owner, and a link to how to fix each finding.
Found an exposed table and want an engineer to fix it with you? muhandis.online/services/fix
Made by Muhandis, a software company for businesses in Saudi Arabia and the GCC. MIT licence.
Available Tools
2 toolsrls_check_explainRLS check: explain the resultARead-only
Explains the output of rls_check_query table by table, worst first: which tables anyone with the public (anon) key can read or change, which any signed-in user can read across users, which are locked, which are safe. Findings are in Arabic for founders (labels also given in English) and link to Arabic lessons on muhandis.online. Works offline on the pasted result.
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes | The JSON result cell of rls_check_query, as text (it starts with {"tool":"muhandis-rls-check"...) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful behavioral detail: findings are ordered worst first, grouped by risk class, written in Arabic with English labels, and linked to Arabic lessons.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded, first stating what is explained and then adding ordering, language, linking, and offline behavior. Every clause carries relevant information, though it could be slightly tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only explanation tool with no output schema, the description gives enough detail about what the findings contain, how they are ordered, what languages are used, and that it works offline. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the single result parameter is already documented as the JSON result cell from rls_check_query. The description reinforces that it operates on a pasted result, but adds no new syntax or format details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb/resource: it explains the output of rls_check_query table by table. It also distinguishes the tool from the sibling query tool by emphasizing explanation of a pasted result, not execution of a check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly indicates the tool is used on the result from rls_check_query and that it works offline on the pasted result. It does not explicitly state exclusions or when not to use it, but the context is strong and unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rls_check_queryRLS check: the read-only queryARead-only
Returns a read-only SQL query that lists every table and view in the public schema of a Supabase (Postgres) project with its RLS state, grants to anon/authenticated, column names and policies. It reads no row of data. Run it in the project (SQL Editor, or a Supabase MCP execute_sql tool), then pass the single JSON result cell to rls_check_explain.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, and the description adds non-obvious behavior the annotations cannot express: this tool emits a query rather than executing it, touches zero rows, and returns a single JSON result cell that must be handed off. That is exactly the extra context the bar asks for when annotations exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each load-bearing: what it returns, what it does not touch, and how to run and hand off the result. The scope detail is front-loaded before the operational instructions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still characterizes the return value (a SQL query text, whose execution yields a single JSON cell) and the downstream consumer. Nothing an agent needs to call this correctly — where to run it, what comes back, where it goes next — is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema is an empty object with zero parameters, so there is nothing for the description to disambiguate and no risk of a caller mis-passing arguments. Baseline 4 applies; no parameter meaning is added or needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and artifact ('Returns a read-only SQL query') plus the exact payload it enumerates: every table and view in the public schema with RLS state, anon/authenticated grants, columns, and policies. It is unambiguously distinct from its only sibling, which consumes the output rather than producing it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete execution contexts ('SQL Editor, or a Supabase MCP execute_sql tool') and the explicit next step ('pass the single JSON result cell to rls_check_explain'), which routes the agent through the sibling pair. It also pre-empts a likely misreading by stating it reads no row of data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.1.1- First observed
rls_check_explain - First observed
rls_check_query
TDQS
Scored across 2 tools
The two tools have clearly distinct roles: one generates a read-only SQL query, the other explains the resulting JSON output. The descriptions explicitly describe a sequential handoff, leaving no realistic chance of misselection.
Both names follow the same rls_check_<action> snake_case pattern, with query and explain as clear action suffixes. The convention is fully consistent across the set.
Two tools is on the thin side generally, but for this narrowly scoped two-step RLS audit workflow each tool earns its place. There is no obvious extra operation that would justify adding more tools.
The pair covers the full lifecycle: generate the diagnostic query, run it externally, then explain the pasted result. The query tool states it reads no row data and the explain tool works offline, so there are no apparent dead ends for the stated purpose.
Maintenance
Related MCP Connectors
Check Supabase SQL for who can read and write each table: RLS gaps, open policies, grants, fix SQL.
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
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceThis is an MCP server for PostgREST. It allows LLMs perform database queries and operations on Postgres databases via PostgREST. This server works with both Supabase projects (which use PostgREST) and standalone PostgREST servers.2,041 npm2,990Apache 2.0
- AlicenseAqualityDmaintenanceAudits PostgreSQL/Supabase schemas for security issues like missing RLS, permissive policies, and sensitive data exposure during AI conversations.3MIT
- AlicenseNot gradedqualityBmaintenanceEnables safe, read-only SQL exploration and debugging on Supabase Edge Functions, respecting user JWTs. It inspects schemas, explains query plans, proposes RLS policies, and runs guarded queries without destructive operations.MIT
- 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.451MIT