The backend/AI & agents

40 MCP tools · scoped keys · enforced by Postgres

A key permission is not a policy.

Give an agent real tools over your data — read, write, migrate, deploy — through an MCP server it connects to in one config block.

Then take the safety on trust out of it. What the agent may touch is a scoped key, and what the database will return is row-level security. Two gates, neither of them a prompt.

Model Context Protocol

Your project, as tools an assistant can call

@rebasepro/mcp speaks the Model Context Protocol, so anything that speaks MCP can drive your backend: query and edit data, push schema changes, open a database branch, trigger a cron job, tail the dev server.

Your collection definitions and the generated Drizzle schema are exposed as MCP resources too, so the assistant reads your actual data model rather than guessing at it from the code it happens to have open.

There is nothing to build and no adapter to write. It is one block in a config file.

.cursor/mcp.json
// .cursor/mcp.json — or Claude Desktop, Windsurf, Copilot…
{
  "mcpServers": {
    "rebase": {
      "command": "npx",
      "args": ["@rebasepro/mcp"],
      "env": {
        "REBASE_BASE_URL": "https://api.example.com",
        "REBASE_API_TOKEN": "rk_live_…"
      }
    }
  }
}

The tool surface

40 tools, and these are their real names

Not a category diagram — the actual list the server registers. An agent that can call these can build and operate an application without a human in the request path.

Data5
  • list_documents
  • get_document
  • create_document
  • update_document
  • delete_document
Users & roles6
  • list_users
  • create_user
  • update_user
  • delete_user
  • list_roles
  • rebase_auth_reset_password
Schema & database7
  • rebase_schema_generate
  • rebase_schema_introspect
  • rebase_db_push
  • rebase_db_generate
  • rebase_db_migrate
  • rebase_generate_sdk
  • rebase_doctor
Branching4
  • rebase_db_branch_create
  • rebase_db_branch_list
  • rebase_db_branch_info
  • rebase_db_branch_delete
Storage3
  • storage_list_objects
  • storage_get_metadata
  • storage_delete_object
Cron5
  • cron_list_jobs
  • cron_get_job
  • cron_trigger_job
  • cron_get_job_logs
  • cron_toggle_job
Functions1
  • invoke_function
Dev server3
  • rebase_dev_start
  • rebase_dev_logs
  • rebase_dev_stop
Projects6
  • rebase_project_list
  • rebase_project_current
  • rebase_project_switch
  • rebase_project_add
  • rebase_project_remove
  • rebase_project_status

Least-privilege agents

Authorization the agent cannot forget

Everyone in this category will tell you their agent integration is safe. The question worth asking is what enforces it — because if the answer is the tool layer, then a bug in the tool layer is a breach. Here the tool layer is the first of two gates, and the second one is the database.

Revoke a scope below and watch the same four calls come back refused.

support-agent

The key you hand the agent. Revoke something and watch the session below.

scopes

RLS roles

Scopes decide which calls the key may make; roles decide which rows those calls see. As service alone, Postgres grants it nothing unless a policy names it.

MCP session2 of 4 refused
query_collection{ "collection": "products", "limit": 20 }
API key scopePostgres RLS

200 20 rows · id, title, price, stock

update_document{ "collection": "orders", "id": "8f21", "data": { "status": "refunded" } }
API key scopePostgres RLS

200 1 row updated · orders/8f21

delete_document{ "collection": "orders", "id": "8f21" }
API key scopePostgres RLS

403 SCOPE_MISSING · data:delete:orders

Refused twice: the key has no such scope, and no delete policy on orders names "service", so 0 rows match.

get_document{ "collection": "customers", "id": "c7" }
API key scopePostgres RLS

404 NOT_FOUND · customers/c7

The key holds the scope. Postgres does not agree — customers lets each customer read their own row, and "service" is nobody's.

The two gates are independent, which is the part worth sitting with: grant data:delete:orders above and the call still deletes nothing, because a scope is not a policy — and it comes back 403 rather than reporting a delete that never happened. No prompt, jailbreak or bug in the tool layer widens what the database will return.

A key, not a god-mode credential

A key holds scopes, one per collection and operation — data:read:orders, data:write:orders — and delete is its own scope, separable from write, which is the one you actually want to withhold from an agent.

Which rows it sees is a separate setting: its roles. With none beyond service, Postgres grants the key nothing at all unless one of your policies names that role.

The key itself is shown once. What the server keeps is a SHA-256 hash, so a dump of the keys table does not hand anyone a working key — and a key that leaks is revoked by deleting the row, not by rotating a shared secret. Each one carries its own rate limit and its own expiry.

How the policies are generated
POST /api/admin/api-keys
// The key behind that token. Scopes say which calls it may make —
// delete is its own scope — and roles say which rows those calls see.
{
  "name": "support-agent",
  "scopes": [
    "data:read:products",
    "data:read:orders",
    "data:write:orders"
  ],
  "roles": [],
  "expires_at": "2026-12-31"
}

Agent infrastructure

Everything an agent needs to operate

Vector search, scoped keys, streaming functions, realtime and scheduled tasks — the operational surface agents build on, in one window instead of a wall of cards.

agent · what it can reach

A surface an agent can hold

No controllers, no serializers, no migrations to hand-write, and nothing for a model to invent between the schema and the route. The whole contract fits in one context window, and the compiler checks whatever it writes back.

config/collections/orders.ts
export const orders: PostgresCollectionConfig = {
table: "orders",
properties: { total, status, customer },
securityRules: [{ operation: "select", … }],
};
→ REST · typed SDK · RLS policies · admin views
no controllers to reviewfits in one context windowcompiler-checked

MCP is a standard, so the list of things that can drive your backend is not ours to control — it is whatever speaks it.

Claude CodeClaude DesktopCursorWindsurfGitHub CopilotCodexGemini CLIZed

Point an agent at it

Scaffold a project, add the config block, and hand your assistant a key that can read one collection. It is a faster way to find out whether any of this is true than reading the rest of this page.

>pnpm dlx @rebasepro/cli init