- Production environments
- Next.js applications (built-in integration)
- Applications requiring Row Level Security (RLS)
- Managed PostgreSQL with zero maintenance
Installation
Configuration
Database Setup
To use Supabase as a storage backend, you must create themcp_sessions table and configure RLS policies.
Option A: Supabase CLI (Recommended)
You can easily “eject” the required migration SQL into your own project using the built-in CLI:-
Run the initialization command:
This copies the provider migrations from
migrations/supabase/in the package to your local./supabase/migrations/folder. -
Link your project & push:
Option B: SQL Editor (Manual)
If you prefer manual setup, copy the SQL from the migration file and run it in the Supabase Dashboard SQL Editor.Why RLS ?
mcp-ts uses the service_role key for server-side Supabase storage, and that key bypasses RLS. Session access is still scoped by userId in application queries.
The migration also defines RLS policies for Supabase’s authenticated client path. If the mcp_sessions table is queried through that path, the policies use auth.uid() to ensure users can only access rows where user_id matches their Supabase user ID.
Features
- PostgreSQL persistence with JSONB support
- Row Level Security (RLS) for tenant isolation
- Automatic management of
updated_atandexpires_at - Automatic session cleanup via
pg_cron— expired pending sessions are swept every 5 minutes - Cloud-native and serverless friendly
- Application-level AES-256-GCM encryption for
tokensandheaders
Session Cleanup
When a client disconnects unexpectedly or a connection error occurs during setup, session data can become stale in the database. To prevent leftover data from accumulating,mcp-ts includes a migration that sets up automatic cleanup jobs using PostgreSQL’s pg_cron extension.
The
pg_cron extension is available on all Supabase plans (including Free). The cleanup migrations are included automatically when you run npx mcp-ts supabase-init.Session Lifecycle Management
mcp-ts implements a multi-stage automated cleanup strategy to keep your database lean while preserving long-lived automation credentials:
Stage 1: Short-term Transient Purge (Every 5 minutes)
Cleans up abandoned setup/auth records. These are sessions where status <> 'active' and the short 10-minute pending expiration has passed.
status = 'active') that have been completely untouched for 30+ days. This ensures that even active sessions don’t persist forever if they are genuinely abandoned.
How It Works
- Transient State: Pending sessions use
status: 'pending'and a restricted 10-minute pending expiration. - Promotion: Upon successful handshake or OAuth completion, the session is promoted to
status: 'active'andexpires_atis cleared. - Persistence: Active sessions are explicitly excluded from the high-frequency 5-minute sweep. This makes them safe for persistent automation and scheduled workflows.
- Eviction: If an active session is not used or refreshed for 30 consecutive days, it is considered dormant and is evicted by the daily sweep.
Customizing the Lifecycle
You can modify the cron schedules directly in your Supabase SQL editor:Disabling Management
To disable the automated lifecycle management entirely:Usage
Option 1: Automatic Detection (Recommended)
WhenSUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY are present in your environment, the global sessions proxy automatically uses the Supabase backend.
Option 2: Manual Instantiation
If you want to manage the Supabase client yourself or use multiple storage backends:Encryption at Rest
The Supabase backend automatically encrypts sensitive session fields (tokens and headers) using AES-256-GCM before writing to the database. All encryption/decryption happens transparently in your Node.js application — Supabase only ever sees cipher text.
To enable encryption, set the STORAGE_ENCRYPTION_KEY environment variable to a 32-byte hex string:

