The backend an agent cannot wreck
scribase-mcp gives Claude Code, Cursor, and any MCP client 44 tools over your Scribase projects. Reads run immediately; every write waits for an explicit confirm, and schema changes must pass an RLS isolation test first.
- Server
- scribase-mcp
- Transport
- stdio, or streamable HTTP at /mcp
- Control plane
- https://api.scribase.com
- Auth
- Personal access token or org API key, audited per call
Mutations need confirm
Every tool that changes something refuses without confirm: true and returns the exact request it would send, so a human approves that specific change.
RLS is proven before it ships
schema.apply only takes a token from policy.test, which proves the isolation matrix and then breaks each guarantee on purpose to show the proof can fail.
Changes land on a preview first
Preview branches are TTL-swept copies of production with sanitized data. Merges are foreign-key safe and preceded by a backup.
Install once, then add it to your editor
Create a scoped agent token in the console under Account, Tokens. Give it only the organizations the agent should see.
# Remote: nothing to install. Use the URL below with a personal
# access token (scb_pat_) or organization API key (sbk_).
# Local instead: build the server from the Scribase repository (Rust 1.85+)
cargo install --path crates/mcp
# Over stdio your editor starts it; `scribase-mcp serve --http :8787`
# serves the same tools remotely (needs SCRIBASE_API_URL).
# Schema tools run on a scratch Postgres the server starts itself
# (initdb, pg_ctl and psql on PATH), or on the cluster in PGHOST if set.
# Control-plane tools use SCRIBASE_API_URL and SCRIBASE_ACCESS_TOKEN.claude mcp add --transport http scribase https://api.scribase.com/mcp \
--header "Authorization: Bearer $SCRIBASE_ACCESS_TOKEN"{
"mcpServers": {
"scribase": {
"url": "https://api.scribase.com/mcp",
"headers": {
"Authorization": "Bearer ${env:SCRIBASE_ACCESS_TOKEN}"
}
}
}
}44 tools, grouped by what they touch
Schema and policy
Run on a scratch branch owned by the session. schema.apply only accepts a token that policy.test (or policy.simulate) issued for the exact same schema, so an unproven policy cannot be applied.
| schema.propose | Parse and plan a schema change without applying it. | read |
| policy.simulate | Apply to a scratch branch and run the cross-user isolation matrix. Issues an apply token on pass. | read |
| policy.test | The Aegis mutation harness: prove isolation, then break each guarantee on throwaway branches and require every break to be caught. Issues an apply token on pass. | read |
| schema.apply | Apply a schema that policy.test already proved, using its token. | needs confirm |
| sql.explain | EXPLAIN a statement against the session branch. | read |
Branches and previews
Preview environments are TTL-swept branches of production with sanitized data.
| environment.create | Create an environment, including a preview with a TTL. | needs confirm |
| environment.list | List environments in a project. | read |
| environment.get | Read one environment and its phase. | read |
| environment.delete | Delete an environment. | needs confirm |
| environment.suspend | Suspend an environment. | needs confirm |
| environment.resume | Resume a suspended environment. | needs confirm |
| branch.register | Register an environment as a branch of a base. | needs confirm |
| branch.list | List branches and their lineage. | read |
| branch.diff | Schema diff between a base and a head environment. | read |
| branch.merge | Merge a head branch into its base, foreign-key safe. | needs confirm |
| branch.link_pull_request | Link a branch to a GitHub, GitLab, or Bitbucket pull request. | needs confirm |
| operation.get | Poll an asynchronous operation to a terminal state. | read |
Data and runtime
Read-only views of a live environment.
| database.tables | List tables with row estimates and RLS state. | read |
| database.query | Run a read-only SQL query. | read |
| auth.users | List auth users (no secrets). | read |
| storage.buckets | List storage buckets. | read |
| functions.list | List deployed functions. | read |
| logs.tail | Tail recent logs. | read |
| metrics.get | Read environment metrics. | read |
| insights.get | Security and performance advisors. | read |
| usage.get | Usage against the plan caps. | read |
Migrations, backups, and portability
Every write is gated behind confirm and audited.
| migrate.run | Plan and lint migrations; apply only with apply and confirm. | needs confirm |
| backup.list | List backups. | read |
| backup.get | Read one backup and its verification evidence. | read |
| backup.create | Take a backup. | needs confirm |
| backup.restore | Restore a backup into a target environment. | needs confirm |
| import.supabase | Dry-run or start a project import in the background. | needs confirm |
| import.status | Follow a background import: phase, counts, errors, report. | read |
| export.run | Produce a portable export bundle. | read |
Organization and access
Membership and key management.
| org.list | List organizations the token can see. | read |
| org.get | Read an organization. | read |
| org.put | Create or update an organization. | needs confirm |
| member.put | Set a member role. | needs confirm |
| project.list | List projects. | read |
| project.get | Read a project. | read |
| project.put | Create or update a project. | needs confirm |
| apikey.list | List API keys (never their values). | read |
| apikey.revoke | Revoke an API key. | needs confirm |
| audit.list | Read the audit log. | read |
Preview branch, RLS tests, human confirm, merge
Drop this skill into a project and Claude Code follows the safe-change flow every time it touches your schema: it rehearses on a preview, proves isolation, shows you the diff, and waits for your approval before merging.
mkdir -p .claude/skills/scribase-safe-change
curl -fsSL https://scribase.com/mcp/skill -o .claude/skills/scribase-safe-change/SKILL.mdOr download SKILL.md directly. It works with the CLI alone, and uses the MCP tools when the server is connected.
Moving an existing app first? See the migration guide.
---
name: scribase-safe-change
description: Ship a schema or row-level-security change to a Scribase project safely. Creates a preview branch, applies the migration there, proves RLS isolation with policy.test (the Aegis mutation harness), shows the diff, waits for explicit human confirmation, then merges and cleans up. Use whenever you add or change tables, columns, indexes, functions, or policies on Scribase.
---
# Scribase safe change: preview, test, confirm, merge
Never change production schema directly. Every change goes through this flow,
in order. If any step fails, stop and report; do not skip ahead.
Inputs you need: `ORG`, `PROJECT`, the project `REGION`, a short change
name `CHANGE` (for example `add-invoices`), and the migration files under
`migrations/`.
Credentials come from the environment only (`SCRIBASE_API_URL`,
`SCRIBASE_ACCESS_TOKEN`). Never print them.
## 1. Create a preview branch
A preview is a copy of production with sanitized data and a TTL, so a forgotten
preview deletes itself.
```bash
PREVIEW="preview-$CHANGE"
scribase env create "$ORG" "$PROJECT" "$PREVIEW" preview sanitized "$REGION" "$PREVIEW" 24
scribase operation get "$ORG" "$OPERATION_ID" # repeat until state is succeeded
scribase branch register "$ORG" "$PROJECT" "$PREVIEW" --base production
```
With the MCP server: `environment.create` (kind `preview`, data mode
`sanitized`, TTL 24), then `operation.get` until it succeeds, then
`branch.register`. Both mutations need `confirm: true`; creating a
preview is safe to confirm yourself because it cannot touch production.
## 2. Apply the migration to the preview only
```bash
scribase migrate "$ORG" "$PROJECT" "$PREVIEW" --dir migrations # plan + lint
scribase migrate "$ORG" "$PROJECT" "$PREVIEW" --dir migrations --apply # apply to the preview
```
If the linter blocks a change (a lock-heavy ALTER, a dropped column still in
use), fix the migration. Do not force it.
## 3. Prove row level security
Every table that holds user data must have RLS enabled and policies that keep
user A out of user B's rows.
- MCP: call `policy.test` with the full schema source. It applies the
schema to a scratch branch, runs the cross-user isolation matrix, then
breaks each guarantee on purpose (FORCE removed, USING (true), a dropped
WITH CHECK) on throwaway branches and requires every break to be caught.
A pass returns an apply token; a failure lists every leak or missed mutant.
- CLI: run Aegis against the preview. `--mutate` breaks each policy on
purpose and checks the tests notice, which proves the tests can fail.
```bash
aegis compile aegis.yaml
aegis test
aegis test --mutate
scribase insights "$ORG" "$PROJECT" "$PREVIEW" # advisors: missing RLS, unindexed FKs
```
A single leak or a surviving mutation is a failure. Fix the policies and
return to step 2.
## 4. Show the change and wait for a human
```bash
scribase branch diff "$ORG" "$PROJECT" production "$PREVIEW"
scribase branch merge "$ORG" "$PROJECT" production "$PREVIEW" --dry-run
```
Present, in one message: the schema diff, the merge dry run, the RLS results
(simulate verdict, Aegis pass and mutation score), and any insights findings.
Then stop and ask for explicit approval to merge into production. Do not
treat silence, an earlier approval, or approval of a different change as
consent. With MCP, `branch.merge` without `confirm` returns the exact
request; show it and wait.
## 5. Merge after approval
```bash
scribase backup create "$ORG" "$PROJECT" production "pre-$CHANGE" # restore point
scribase branch merge "$ORG" "$PROJECT" production "$PREVIEW"
```
With MCP: `backup.create` then `branch.merge` with `confirm: true`, only
after the human approved in step 4. Poll any returned operation with
`operation.get` until it reaches a terminal state. A 202 is not success.
## 6. Clean up and report
```bash
scribase env delete "$ORG" "$PROJECT" "$PREVIEW" "$PREVIEW-delete"
```
Report: the migration files applied, the RLS evidence, the backup id taken
before the merge, and the operation ids. If anything failed after the merge,
say so first and offer `scribase restore start` from the pre-merge backup.