Local policy wrapper for Supabase MCP with Keychain-backed tokens, project allowlists, write locks, and audit logs.
supabase-mcp-guard
English | 简体中文
Local policy wrapper for Supabase MCP.
It keeps your Supabase access token out of MCP config files and command-line arguments, adds local policy checks before requests hit the official @supabase/mcp-server-supabase, and makes production write access an explicit action instead of a default capability.
This project does not replace Supabase MCP. It sits in front of it.
Why this exists
Supabase MCP is powerful, but AI coding clients usually treat MCP servers as highly trusted local tools. In practice that creates a few common problems:
- Supabase access tokens end up in plain text config files.
- Tokens are passed through command-line arguments.
- Production and development projects share one broad access token.
- Write-capable tools are available by default.
- AI agents can accidentally run migrations or write SQL against production.
supabase-mcp-guard reduces that risk locally with a stricter execution model.
What it does
- Reads the Supabase access token from a configurable secret provider.
- Keeps the token out of command-line arguments.
- Supports project allowlists.
- Blocks selected high-risk tools permanently.
- Keeps write protection enabled by default.
- Allows short unlock windows for write operations.
- Treats
execute_sqlspecially: read-only SQL can pass while write/DDL SQL is blocked unless unlocked. - Writes a local audit log for tool calls and blocked operations.
Current platform support
- macOS
macos-keychainenvcommandpowershell-secretmanagementif you already use PowerShell on macOS
- Windows
powershell-secretmanagementwindows-credential-managerenvcommand
- Linux
envcommandpowershell-secretmanagementif PowerShell is installed
The first-class installers included in this repo are:
- macOS: scripts/install_macos.sh
- Windows: scripts/install_windows.ps1
Supported MCP clients
This project uses stdio transport, so it can be wired into many MCP-capable clients.
Documented in this repo:
- Codex
- Claude Code
- Cursor
- VS Code
Install
Clone the repo
git clone https://github.com/askmeishi/supabase-mcp-guard.git
cd supabase-mcp-guard
Install dependencies
npm install
Install from npm
npm install -g supabase-mcp-guard
If you install from npm globally, you can run the wrapper directly without cloning the repo:
supabase-mcp-guard --self-test
This checks that the binary starts correctly and shows whether a config file is already present.
macOS installer
./scripts/install_macos.sh --client=codex
What it does:
- prompts for a new Supabase access token
- stores it in macOS Keychain
- writes config to
~/.config/supabase-mcp-guard/config.json - installs the wrapper to
/usr/local/bin/supabase-mcp-guard - optionally patches
~/.codex/config.toml
Windows installer
Open PowerShell and run:
Set-ExecutionPolicy -Scope Process Bypass
.\scripts\install_windows.ps1
What it does:
- prompts for a new Supabase access token
- installs PowerShell
SecretManagementandSecretStoremodules if missing - stores the token in
SecretStore - writes config to
%APPDATA%\supabase-mcp-guard\config.json - installs the wrapper under
%LOCALAPPDATA%\Programs\supabase-mcp-guard - adds the local wrapper directory to the user
PATH
If you installed from npm instead of cloning this repo, you can still use the wrapper directly and create your config manually from config.example.json.
Secret providers
macos-keychain
Use macOS Keychain:
{
"secretProvider": {
"type": "macos-keychain",
"service": "supabase-mcp-guard",
"account": "primary"
}
}
powershell-secretmanagement
Use PowerShell SecretManagement and a named secret:
{
"secretProvider": {
"type": "powershell-secretmanagement",
"name": "supabase-mcp-guard",
"vault": "SecretStore"
}
}
windows-credential-manager
Use a Windows Credential Manager target:
{
"secretProvider": {
"type": "windows-credential-manager",
"target": "supabase-mcp-guard"
}
}
This provider expects a PowerShell environment where the CredentialManager module and Get-StoredCredential are available.
env
Read the token from an environment variable:
{
"secretProvider": {
"type": "env",
"name": "SUPABASE_ACCESS_TOKEN"
}
}
command
Read the token from an arbitrary local command:
{
"secretProvider": {
"type": "command",
"command": "op",
"args": ["read", "op://vault/item/token"]
}
}
This is the most flexible option for unsupported platforms or custom secret stores.
Config
Example config: config.example.json
Typical config:
{
"secretProvider": {
"type": "macos-keychain",
"service": "supabase-mcp-guard",
"account": "primary"
},
"projectRef": null,
"readOnly": false,
"features": null,
"apiUrl": null,
"logFile": "~/.local/state/supabase-mcp-guard/audit.log",
"stateFile": "~/.local/state/supabase-mcp-guard/write_lock.json",
"defaultUnlockMinutes": 10,
"allowedProjectIds": ["your-project-ref"],
"alwaysBlockedTools": ["create_project", "pause_project", "restore_project"]
}
Notes:
allowedProjectIds: if set, requests for other project IDs are blocked.projectRef: optional upstream fixed project binding.readOnly: if true, all write-sensitive upstream tools are blocked even during unlock windows.alwaysBlockedTools: tools that are always denied.
Client snippets
The CLI can print snippets directly:
supabase-mcp-guard print-snippet --client codex
supabase-mcp-guard print-snippet --client claude-code
supabase-mcp-guard print-snippet --client cursor
supabase-mcp-guard print-snippet --client vscode
Codex
[mcp_servers.supabase]
command = "supabase-mcp-guard"
startup_timeout_sec = 30
Claude Code
Use a stdio MCP server entry in your Claude Code MCP JSON:
{
"mcpServers": {
"supabase": {
"type": "stdio",
"command": "supabase-mcp-guard",
"args": []
}
}
}
Cursor
Use a stdio MCP server entry in your Cursor MCP JSON:
{
"mcpServers": {
"supabase": {
"type": "stdio",
"command": "supabase-mcp-guard",
"args": []
}
}
}
VS Code
Use a stdio MCP server entry in your VS Code MCP config:
{
"servers": {
"supabase": {
"type": "stdio",
"command": "supabase-mcp-guard",
"args": []
}
}
}
Usage
Start as MCP stdio server:
supabase-mcp-guard
Check current lock state:
supabase-mcp-guard status
Temporarily unlock writes:
supabase-mcp-guard unlock --minutes 10
Lock again:
supabase-mcp-guard lock
Self-test:
supabase-mcp-guard --self-test
Security model
The guard enforces a local policy layer before forwarding requests upstream:
execute_sql- read-only SQL is allowed
- write/DDL SQL is blocked unless unlocked
- tools marked by upstream as write-capable
- blocked unless unlocked
- tools in
alwaysBlockedTools- always blocked
- project IDs outside
allowedProjectIds- always blocked
This helps reduce accidental misuse, but it is not a substitute for correct database-side security:
- do not expose sensitive schemas
- use proper grants
- use RLS where appropriate
- keep
SECURITY DEFINERandsearch_pathunder control
Audit log
The wrapper writes a local audit log to the configured logFile.
Examples:
- macOS/Linux default:
~/.local/state/supabase-mcp-guard/audit.log - Windows default:
%LOCALAPPDATA%\supabase-mcp-guard\audit.log
Blocked requests and completed upstream tool calls are both recorded.
Threat model
This project is designed for the common local AI-assistant risk model:
- you trust your own machine
- you do not want secrets sitting in plaintext config
- you want a last-mile local policy check before production writes
It does not protect against:
- a fully compromised machine
- malicious code already running with your user privileges
- overbroad permissions granted directly inside Supabase
Publishing
This repository is set up for both local package validation and tagged releases.
Local verification before release:
npm run check
npm pack --dry-run
Release flow:
- bump
package.jsonversion - commit and push to
main - create and push a version tag such as
v0.1.1 - GitHub Actions
Releasepublishes to npm and creates a GitHub Release
Required secret:
NPM_TOKENin the GitHub repository secrets
Roadmap
- Linux first-class installer
- client-specific helper commands beyond config snippets
- finer-grained SQL policy rules
- environment-specific policies
- notification hooks for blocked high-risk actions
References
For the latest client-specific MCP setup details, check the official client docs:
The JSON snippets above are intended for stdio-based MCP clients and may need minor path adjustments depending on how you install the wrapper.
License
MIT