@jgomez_tcw/lovable-mcp
v0.3.0
Published
MCP server for lovable.dev — install with zero credentials; Claude collects them at first use via lovable_login. Drives the dashboard, AI agent, linked GitHub repo, Supabase, and deployed-env secrets. ~58 tools, stdio transport.
Maintainers
Readme
lovable-mcp
An MCP server that lets Claude collaborate with a Lovable.dev project end-to-end:
| Surface | What the tools cover |
| ----------------------- | --------------------------------------------------------------------------------------------- |
| Lovable dashboard | List workspaces / projects, search, read project metadata, permissions, source-code tree. |
| GitHub source code | Read / write files in the project's linked repo. Push to the repo updates Lovable's source. |
| Supabase database | Generic select / insert / update / delete / RPC against the project's Supabase backend. |
| Deployed env secrets| Read values of process.env.* from the deployed app via the mcp-probe route. |
Install
cd project
npm install
npm run setup # interactive wizard — collects every env var, validates,
# and writes .env (mode 0600). See "Setup wizard" below.
npm run buildOr, if you prefer to skip the wizard, copy .env.example to .env and fill
in by hand.
Setup wizard
npm run setup (or npx lovable-mcp-setup once built) walks every value the
server reads and writes them to .env:
- Lovable platform constants (
LOVABLE_API_BASE,LOVABLE_FIREBASE_API_KEY,LOVABLE_FIREBASE_PROJECT_ID) are recovered live fromlovable.dev's JS bundle — no defaults are hardcoded in this repo. If Lovable migrates their Firebase tenant the nextnpm run setuppicks up the new values automatically. If the discovery fetch fails (offline, proxy) the wizard falls back to manual entry with no defaults. - Lovable auth — pick refresh token (preferred) or email + password. Either path is validated against Firebase before being written; if it works, the wizard prints the email it authenticated as.
- Optional sections — workspace/project defaults, GitHub PAT + repo, Supabase URL + keys, and the mcp-probe token. Skip any you don't need; the corresponding tools will surface a friendly "not configured" error.
The wizard is re-runnable: existing values are pre-filled and shown as defaults, so just hitting Enter through every prompt is a no-op.
Note: the wizard masks secret input with
*s when stdin is a TTY. If you pipe input in non-interactively, masking is disabled but the rest still works.
Run with Claude Code / Desktop
Add to ~/.claude/mcp.json (Claude Code) or the Claude Desktop config:
{
"mcpServers": {
"lovable": {
"command": "node",
"args": ["/absolute/path/to/lovable-mcp/project/dist/index.js"],
"env": {
"LOVABLE_REFRESH_TOKEN": "...",
"GITHUB_TOKEN": "...",
"SUPABASE_URL": "https://<your-supabase-ref>.supabase.co",
"SUPABASE_ANON_KEY": "..."
}
}
}
}For development, npm run inspector opens the MCP Inspector against the
running server.
Auth: how the Lovable bearer token is obtained
- If
LOVABLE_REFRESH_TOKENis set, the MCP callsPOST https://securetoken.googleapis.com/v1/token?key=<api_key>withgrant_type=refresh_tokento mint an ID token, and refreshes ~60s before expiry. - Otherwise, if
LOVABLE_EMAIL/LOVABLE_PASSWORDare set, the MCP callssignInWithPasswordat startup and stores the resulting refresh token in memory for the lifetime of the process.
To extract a refresh token without committing your password:
# In the browser devtools while signed in to lovable.dev:
JSON.parse(localStorage.getItem(
Object.keys(localStorage).find(k => k.startsWith('firebase:authUser:'))
)).stsTokenManager.refreshTokenTool catalogue
Tool naming convention: <surface>_<verb>_<object>. All tools take JSON args
validated with zod. Errors are returned as MCP errors (the tool throws); Claude
will see them.
lovable.* — dashboard, chat, passthrough
| Tool | Args | Returns / does |
| ----------------------------- | ------------------------------------------ | ---------------------------- |
| lovable_whoami | (none) | Current user (uid, email) |
| lovable_get_permissions | { workspace_id? } | Caller permission strings |
| lovable_search_projects | { workspace_id?, sort_by?, ..., user_id? } | Workspace projects search |
| lovable_get_project | { project_id? } | /projects/{id}/details |
| lovable_get_project_cloud_config | { project_id? } | /projects/{id}/cloud/config (Supabase wiring) |
| lovable_get_source_tree | { project_id? } | /projects/{id}/source-code — full file contents (heavy) |
| lovable_get_git_files | { project_id?, ref? } | File list at a git ref |
| lovable_list_secrets | { workspace_id? } | Names + status (no values) |
| lovable_get_profile | { username_or_uid } | Public profile |
| lovable_get_workspace | { workspace_id? } | Workspace details |
| lovable_get_credit_balance | { workspace_id? } | Remaining credits |
| lovable_list_shared_projects / lovable_list_starred_projects / lovable_list_workspace_invitations | paginated | User-scoped reads |
| lovable_send_chat_message | { project_id?, message, chat_only?, view?, view_description?, thread_id? } | WRITE. Sends a message to the AI agent; returns generated user_message_id + ai_message_id |
| lovable_read_chat_message | { project_id?, message_id } | Reads a trajectory message directly from Firestore; poll while status === "in_progress" |
| lovable_get_project_edits | { project_id?, limit?, before?, bookmarked? } | Recent file edits made by the AI agent |
| lovable_get_project_logs | { project_id?, type?, env?, start?, end? } | Runtime logs (server / edge_function / postgres). Defaults to last 1h. |
| lovable_supabase_management_api | { project_id?, supabase_ref?, env?, method?, sub_path, body? } | Escape hatch. Generic passthrough to /cloud/db-proxy/v1/projects/{ref}/... for any Supabase Mgmt API endpoint we haven't modeled explicitly. |
github.* — repo R/W (drives Lovable source)
| Tool | Args |
| -------------------------- | ------------------------------------------------------- |
| github_get_file | { path, ref? } |
| github_list_directory | { path, ref? } |
| github_put_file | { path, content, message, branch?, sha? } |
| github_delete_file | { path, message, sha, branch? } |
| github_search_code | { q, per_page? } |
| github_get_tree | { ref?, recursive? } |
| github_commit_files | { files: [{ path, content }], message, branch? } |
db.* — Direct PostgREST (RLS-bound, anon-key path)
Use this when you want RLS enforced or you're calling the MCP without a
Lovable session. Default schema is public, default key is SUPABASE_ANON_KEY.
Pass use_service_role: true to opt in to the bypass-RLS key (only works if
SUPABASE_SERVICE_ROLE_KEY is set — usually it isn't; prefer db_proxy.*).
| Tool | Args |
| -------------------------- | --------------------------------------------------------------------------------- |
| db_list_tables | (none) — parses OpenAPI from /rest/v1/ |
| db_describe_table | { table, schema? } |
| db_select | { table, schema?, columns?, filters?, order?, limit?, offset?, range?, use_service_role? } |
| db_insert | { table, schema?, rows, return_representation?, use_service_role? } |
| db_update | { table, schema?, filters, values, return_representation?, use_service_role? } |
| db_delete | { table, schema?, filters, return_representation?, use_service_role? } |
| db_rpc | { function, args?, schema?, use_service_role? } |
| db_auth_admin_list_users | { page?, per_page? } — service-role required |
db_proxy.* — Lovable Cloud db-proxy (admin path, no service-role needed)
The preferred path for admin DB work. Authenticated by the Lovable Firebase
token already held by the MCP; no service-role key required. Runs SQL
read-only by default; mutations require write: true.
| Tool | Args |
| ----------------------------------- | -------------------------------------------------------------------- |
| db_proxy_cloud_config | { project_id? } — Supabase ref + publishable key (dev + prod) |
| db_proxy_get_project | { project_id?, supabase_ref?, env? } |
| db_proxy_get_api_keys | { ... } — anon + service_role JWTs |
| db_proxy_query | { sql, write?, env?, ... } — read-only by default |
| db_proxy_introspect_tables | { schema?, ... } — table-level: rls, size, row estimate, comment |
| db_proxy_introspect_columns | { schema?, ... } — information_schema.columns dump |
| db_proxy_introspect_relationships | { schema?, ... } — foreign keys (handles composite FKs); src+tgt schema/table/columns, ON UPDATE / ON DELETE rules |
| db_proxy_introspect_full | { schema?, ... } — one-shot nested dump: per-table columns + PK + FKs (outgoing & incoming) + indexes + RLS policies |
| db_proxy_list_migrations | { ... } |
| db_proxy_apply_migration | { name, sql, ... } |
| db_proxy_list_secrets | { ... } — Supabase project env vars |
| db_proxy_upsert_secrets | { secrets: [{name,value}], ... } |
| db_proxy_list_functions | { ... } |
| db_proxy_list_buckets | { ... } |
| db_proxy_get_postgrest_config | { ... } |
| db_proxy_get_auth_config | { ... } |
secrets.* — deployed env probe
| Tool | Args |
| ---------------------------- | ------------------------------------- |
| secrets_read | (none) — returns currently-allowlisted secrets |
| secrets_set_allowlist | { names: string[], message? } — PRs an update to src/routes/lovable/mcp-probe.ts |
Project layout
project/
├── package.json
├── tsconfig.json
├── .env.example
├── README.md
└── src/
├── index.ts # stdio MCP server bootstrap
├── config.ts # env loading + validation
├── clients/
│ ├── firebase.ts # Firebase ID-token manager (refresh-token + signInWithPassword)
│ ├── lovable.ts # api.lovable.dev HTTP client
│ ├── github.ts # GitHub REST client
│ ├── supabase.ts # PostgREST + Storage + Auth wrappers (anon + service-role)
│ └── probe.ts # mcp-probe caller
└── tools/
├── lovable.ts # lovable.* — dashboard reads
├── chat.ts # lovable_send_chat_message / read_chat_message / get_project_edits
├── passthrough.ts # lovable_supabase_management_api / get_project_logs
├── github.ts # github.* tool registrations
├── db.ts # db.* tool registrations (direct PostgREST)
├── dbProxy.ts # db_proxy.* tool registrations (Lovable cloud db-proxy)
└── secrets.ts # secrets.* tool registrationsRoadmap
- Streaming chat tool (
lovable_chat) that posts to/projects/{id}/chat. - Code-edit tools (
lovable_edit_code) that talk to/projects/{id}/edit-codeinstead of going through GitHub — useful for "preview" edits without a commit. - Auto-OpenAPI parse for typed Supabase sub-tools (one tool per table).
- Realtime subscription bridge over MCP notifications (low priority).
