$npx -y skills add butterbase-ai/butterbase-skills --skill contributingUse when contributing to the Butterbase codebase, adding new MCP tools, creating API routes, writing migrations, or understanding the monorepo architecture
| 1 | ## 1. Overview |
| 2 | |
| 3 | Contributor guide for the Butterbase monorepo. Covers architecture, how to add MCP tools, API routes, database migrations, and coding conventions. |
| 4 | |
| 5 | --- |
| 6 | |
| 7 | ## 2. Monorepo Map |
| 8 | |
| 9 | | Directory | Package | Purpose | |
| 10 | |-----------|---------|---------| |
| 11 | | `packages/cli` | `@butterbase/cli` (v0.1.3) | Published CLI tool (Commander.js). Commands: init, apps, schema, functions, storage, deploy, data, env, keys, realtime, status, open | |
| 12 | | `packages/sdk` | `@butterbase/sdk` (v1.2.1) | Published TypeScript SDK. Modules: auth, storage, functions, AI, billing, realtime, admin | |
| 13 | | `packages/shared` | `@butterbase/shared` | Internal shared types, constants, schema DSL, error types | |
| 14 | | `packages/plugin` | `@butterbase/plugin` | Claude Code plugin (this package — skills for AI agents) | |
| 15 | | `services/control-api` | `@butterbase/control-api` | Fastify API server — the brain. Routes, plugins, services. Port 4000 | |
| 16 | | `services/mcp-server` | `@butterbase/mcp-server` | MCP server with ~28 tools (consolidated `manage_*` action-based tools + a few standalone ones like `init_app`, `deploy_function`, `select_rows`). Runs via stdio or HTTP (served by control-api at `/mcp`) | |
| 17 | | `services/deno-runtime` | — | Serverless function executor. Deno-based worker isolation. Port 7133 | |
| 18 | | `services/cron-scheduler` | `@butterbase/cron-scheduler` | Cron job runner using node-cron + cron-parser | |
| 19 | | `services/dashboard` | — | React management UI (Vite + Radix UI) | |
| 20 | | `services/dashboard-api` | — | Dashboard backend proxy. Port 4100 | |
| 21 | | `services/docs` | `@butterbase/docs` | Astro/Starlight documentation site | |
| 22 | | `services/storage-indexer` | — | Cloudflare Worker for S3 event indexing | |
| 23 | | `db/control-plane` | — | SQL migrations (sequential numbering, `001_` upward). Control plane database schema | |
| 24 | | `db/data-plane` | — | Per-app database initialization scripts | |
| 25 | |
| 26 | --- |
| 27 | |
| 28 | ## 3. Adding a New MCP Tool (4 Steps) |
| 29 | |
| 30 | ### Step 1: Create tool file at `services/mcp-server/src/tools/my-new-tool.ts` |
| 31 | |
| 32 | Decide whether the new capability is a standalone tool (single, self-contained operation like `init_app`) or another action on an existing umbrella tool (`manage_schema`, `manage_function`, etc). Most new operations should be added as actions on an existing `manage_*` tool — this keeps the surface area small for AI agents. |
| 33 | |
| 34 | For a brand-new standalone tool, follow the pattern from `init-app.ts`: |
| 35 | |
| 36 | ```typescript |
| 37 | import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; |
| 38 | import { z } from 'zod'; |
| 39 | import { apiPost } from '../api-client.js'; |
| 40 | |
| 41 | interface MyResponse { |
| 42 | // response shape |
| 43 | } |
| 44 | |
| 45 | export function registerMyNewTool(server: McpServer) { |
| 46 | server.tool( |
| 47 | 'my_new_tool', // snake_case name |
| 48 | `Tool description. // Multi-line description with examples |
| 49 | |
| 50 | Example: |
| 51 | Input: { ... } |
| 52 | Output: { ... } |
| 53 | |
| 54 | Common errors: |
| 55 | - ERROR_CODE: Description`, |
| 56 | { |
| 57 | // Zod schema for parameters |
| 58 | app_id: z.string().describe('The app ID'), |
| 59 | param: z.string().describe('Parameter description'), |
| 60 | }, |
| 61 | async ({ app_id, param }) => { |
| 62 | const result = await apiPost<MyResponse>(`/v1/${app_id}/my-endpoint`, { param }); |
| 63 | return { |
| 64 | content: [{ |
| 65 | type: 'text' as const, |
| 66 | text: JSON.stringify(result, null, 2), |
| 67 | }], |
| 68 | }; |
| 69 | } |
| 70 | ); |
| 71 | } |
| 72 | ``` |
| 73 | |
| 74 | API client functions available: `apiGet`, `apiPost`, `apiPatch`, `apiDelete` (from `../api-client.js`). |
| 75 | |
| 76 | ### Step 2: Register in `services/mcp-server/src/create-server.ts` |
| 77 | |
| 78 | ```typescript |
| 79 | import { registerMyNewTool } from './tools/my-new-tool.js'; |
| 80 | // ... |
| 81 | registerMyNewTool(server); |
| 82 | ``` |
| 83 | |
| 84 | ### Step 3: Create the backing API route in `services/control-api/src/routes/` |
| 85 | |
| 86 | - Fastify route handler matching the endpoint your tool calls |
| 87 | - Register in `services/control-api/src/index.ts` |
| 88 | |
| 89 | ### Step 4: Update documentation in `services/mcp-server/src/docs/user-documentation.ts` |
| 90 | |
| 91 | - Add tool to the relevant section's table in the `SECTIONS` object |
| 92 | |
| 93 | --- |
| 94 | |
| 95 | ## 4. Adding a Database Migration |
| 96 | |
| 97 | - **IMPORTANT**: Use `scripts/migrate.ts` or `scripts/backfill-migrations.ts`, NEVER raw `psql` |
| 98 | - Migration files: `db/control-plane/NNN_description.sql` (sequential numbering, starting at `001_initial_schema.sql`) |
| 99 | - Pick the next free three-digit prefix; never edit a committed migration |
| 100 | - Run migrations: `npx tsx scripts/migrate.ts` |
| 101 | |
| 102 | --- |
| 103 | |
| 104 | ## 5. Coding Conventions |
| 105 | |
| 106 | | Convention | Example | |
| 107 | |-----------|---------| |
| 108 | | MCP tool names | `snake_case`. Two flavours: standalone (`init_app`, `deploy_function`, `select_rows`) and `manage_*` umbrella tools that take an `action` enum (`manage_schema`, `manage_rls`, `manage_function`, `manage_frontend`, etc.) | |
| 109 | | App IDs | `app_` prefix: `app_abc123` | |
| 110 | | Service keys | `bb_sk_` prefix: `bb_sk_a1b2c3...` | |
| 111 | | Environment variables | `BUTTERBASE_` prefix: `BUTTERBASE_API_KEY` | |
| 112 | | Response |