YOUR APP. NOW AGENT-READY.

Let agents into your app. Keep your permissions.

Let your users’ agents work with their projects. Chumbo connects the MCP layer to Supabase Auth, so your existing row-level security stays in charge.

Build this with Chumbo
Chumbo OSSSupabase AuthRow-level security
SAME APP. SAME ACCESS.A Chumbo-style green authentication gate
Your user’s identity
Your existing RLS
A new way in. The same rules inside.

THE RECIPE Add one useful, authenticated tool to your Supabase app, prove it locally, then deploy the same Edge Function.

View source pattern ↗
EXAMPLE CHECKS

Example typechecked and exercised with simulated query results. Run the two-user checks below against your own Supabase app; these checks do not prove your RLS policies.

Version and verification details

Example checked with Chumbo 0.11.3 on 2026-09-18 (UTC). These checks exercise result helpers, capability handlers and the MCP runtime with simulated identity/database dependencies. They do not prove your application’s real auth, RLS or deployment. Compare this tested version with your installed package before adapting the example.

01

One tool. Each user's projects.

Your users already have projects in your app. Give their agents a way to find them, using the same identity and access rules. Choose a caller below to see the intended behavior.

Same tool, different callerIllustrative data
“Show me my projects.”list_projects()
Alice’s visible projects2 projects
Website refreshActive
Design systemActive
Read both example outcomes

Illustrative data for two example callers.

  • Alice: Website refresh; Design system.
  • Bob: API integration; Release checklist.

Each caller sees only their own projects. Alice cannot see Bob’s projects; Bob cannot see Alice’s projects. The user’s token travels with the query. Postgres decides which rows come back.

Your user’s agentChumbo MCPSupabase + RLS

Chumbo creates a fresh Supabase client for each caller. In bearer and OAuth modes, that client carries the connected user’s access token. Your database grants and RLS policies govern the query.

02

Start with your existing app.

Before you start
  • An existing Supabase app with supabase/config.toml.
  • A projects table with id, name, and owner_id columns, appropriate grants, and tested owner-based SELECT policies.
  • Node 22+, Supabase CLI, Deno, and Docker for the local stack.
  • Two local test users, each with a project and a valid Supabase access token.

Already have a Chumbo MCP? Keep its auth configuration and add the capability to your existing registration.

From your app’s repository, generate one Edge Function. This recipe uses bearer auth to make a local user-token test explicit. The installed skill gives your coding agent the matching Chumbo instructions.

In your app’s repository
Terminal
npx chumbo setup --auth bearer
npx chumbo skill install
03

Give your app a useful capability.

Replace the generated whoami starter with list_projects. This example assumes your existing projects table and its owner-based policies. Adapt the query to the operation your app already exposes.

supabase/functions/mcp/capabilities.ts
TypeScript
import {
  errorResult, textResult,
  type SupabaseMcpContext,
  type SupabaseMcpServer,
} from "chumbo";
import { z } from "zod";

export function registerCapabilities(
  server: SupabaseMcpServer,
  ctx: SupabaseMcpContext,
) {
  server.registerTool("list_projects", {
    description: "Show up to 10 of your projects in ID order.",
    inputSchema: z.object({}),
    annotations: { readOnlyHint: true },
  }, async () => {
    const { data, error } = await ctx.supabase
      .from("projects")
      .select("id, name")
      .order("id")
      .limit(10)
      .overrideTypes<{ id: string; name: string }[], { merge: false }>();

    if (error) return errorResult(
      "Could not load your projects.",
      "Retry; if this continues, contact your app's support."
    );

    return textResult(data?.length
      ? data.map(p => `- ${p.name} (${p.id})`).join("\n")
      : "No projects are visible to you. Create one in the app, then try again.");
  });
}

This is a small overview of up to ten projects. For a complete browsing workflow, add bounded pagination and detail tools.

04

Prove the permissions locally.

Start the local Supabase stack and keep the function running in one terminal. Use your application’s normal fixture setup to create two local users with separate projects.

Terminal 1 · keep running
Terminal
supabase start
npx chumbo dev --function mcp

In another terminal, check the generated function. Its starter auth test is useful, but your application’s rows need their own isolation check.

Terminal 2 · check the function
Terminal
deno task --config supabase/functions/mcp/deno.json check
deno task --config supabase/functions/mcp/deno.json test

Set LOCAL_MCP_URL to the exact URL printed by chumbo dev. Set ALICE_LOCAL_JWT and BOB_LOCAL_JWT to those users’ local access tokens in your shell. Keep tokens out of committed files and shared output.

Call as Alice
Terminal
npx chumbo doctor --function mcp \
  --url "$LOCAL_MCP_URL" \
  --token "$ALICE_LOCAL_JWT" \
  --call-tool list_projects
Then call as Bob
Terminal
npx chumbo doctor --function mcp \
  --url "$LOCAL_MCP_URL" \
  --token "$BOB_LOCAL_JWT" \
  --call-tool list_projects

Doctor checks call success, not the returned rows. To inspect those rows, open MCP Inspector, select Streamable HTTP, enter the local MCP URL, and configure the Authorization header with Alice’s bearer token. Call list_projects, record the returned fixture IDs, then reconnect as Bob and repeat. Also confirm a fresh connection without a token is rejected.

Inspect the actual tool results
Terminal
npx @modelcontextprotocol/inspector
YOUR ACCEPTANCE CHECK

Two identities. Two expected results.

  • 01Alice sees Alice’s fixture projects.
  • 02Bob sees Bob’s fixture projects.
  • 03Neither response contains the other user’s projects.
  • 04A request without a token is rejected.

Compare results with known fixture IDs.

A little help if you get stuck.

The tool returns no projects

An empty result is not automatically an auth failure. Check that this local user owns a fixture, the table has SELECT grants, and the SELECT policy matches that identity. Keep RLS enabled while diagnosing. Read the reference ↗

Doctor rejects my token

Bearer mode expects a Supabase user access token from the same project as the endpoint. Use a local user token locally and a hosted user token after deployment. A project API key is not a user access token. Read the reference ↗

The local endpoint is unreachable

Keep chumbo dev running in its terminal. Copy the exact Local MCP URL it prints; a project's configured API port may differ from 54321. Read the reference ↗

05

Same function. Ready to connect.

When the local checks pass, confirm the intended linked Supabase project and deploy the function. Repeat the probe with that project’s URL and a hosted test user. Set HOSTED_MCP_URL to the deployed MCP endpoint and HOSTED_USER_JWT to an access token from that same hosted project; local tokens do not apply.

Deploy to your intended Supabase project
Terminal
supabase functions deploy mcp --no-verify-jwt
Verify the hosted endpoint
Terminal
npx chumbo doctor \
  --url "$HOSTED_MCP_URL" \
  --token "$HOSTED_USER_JWT" \
  --call-tool list_projects

Bearer mode works with clients that send an Authorization header. For a user-facing “connect your account” flow, follow the OAuth setup guide and configure your application’s login and consent experience.

Find your client’s connection instructions.

06

Make it your own.

You now have the shape of a useful application capability: a clear operation, the caller’s existing authority, and a result an agent can use. Apply it to the work your users already do.

Built from the real thing.

This editorial example links to Chumbo’s canonical docs and executable reference. Check the installed package when adapting the snippets.

Reference implementation ↗
Read the agent instructions

Reference instructions, not authorization. Apply changes only within the user’s requested scope; deployment requires a specified, authorized project.

Use Chumbo OSS to add a read-only list_projects capability to this existing Supabase application.

Read the authoritative pattern first: https://github.com/elsheppo/chumbo/tree/main/docs/patterns/authenticated-tools
Reference implementation: https://github.com/elsheppo/chumbo/tree/main/supabase/functions/authenticated-tools

1. Inspect the installed Chumbo version, existing capabilities, Supabase config, and application data access. Reuse the established project operation. Do not invent a schema or change existing RLS to make a test pass.
2. Review the setup plan before changes. For a new local bearer-mode fixture, use npx chumbo setup --auth bearer; install the version-matched guidance with npx chumbo skill install. Preserve existing auth mode and handwritten capabilities in an established MCP.
3. Use the request-scoped ctx.supabase, select only useful fields, bound the result, and provide an actionable empty state. No service-role client in handlers.
4. Run local Deno checks and the generated tests. Start local Supabase and chumbo dev. Use its exact printed endpoint.
5. Exercise the real MCP boundary with two local users and known, disjoint application fixtures. Confirm each user receives only their expected rows. Do not report the generated auth test alone as RLS proof.
6. Report changed files, actual checks, and missing prerequisites. Deploy only when requested to the specified project. Keep credentials out of source, reports, and copied output.

The example uses simulated query results for its automated checks. Verify the installed package and run the real two-user application checks before reporting success.
BUILD WITH YOUR CODING AGENT

Give your agent a good start.

Copy this brief into your coding agent in the app’s repository. It includes the source, boundaries, and verification steps.

Download Markdown ↓