Fireloom / AI agents

Let your AI agent set up the sync.

Claude Code, Codex, Cursor, Claude, ChatGPT and other AI tools can sync your Firestore database to PostgreSQL for you: connect both databases, start a real-time sync, and check on it later. You approve the agent once, in your browser.

Ask your agent

Open your coding agent in your Firebase project's folder (the one with .firebaserc) and ask:

Promptexample
Set up Fireloom to sync this project's Firestore into my Postgres database. Instructions for agents: https://fireloom.io/agents.md

The agent asks you to approve it in your browser, runs the command that gives Fireloom read-only access to Firestore (it may open a Google sign-in too), connects your database from DATABASE_URL or a connection string you give it, starts the sync and shows you the SQL to query it. Nothing to install. With the MCP server below, it's smoother still, and you can ask about your syncs any time.

Add the MCP server

Fireloom's MCP server is at https://fireloom.io/mcp (Streamable HTTP). Your AI tool signs in with OAuth: add the server, then click Allow in the browser window that opens. No API key to copy.

Claude Code

Terminal
claude mcp add --transport http --scope user fireloom https://fireloom.io/mcp

Then type /mcp in Claude Code, pick fireloom and sign in (or run claude mcp login fireloom). Claude Code loads new servers when it starts: in a session that's already running, restart it with claude --continue to keep the conversation.

Codex

Terminal
codex mcp add fireloom --url https://fireloom.io/mcp

Codex opens the sign-in right away. To sign in again later: codex mcp login fireloom.

Cursor

Add Fireloom to Cursor in one click, or add it to ~/.cursor/mcp.json:

~/.cursor/mcp.json
{ "mcpServers": { "fireloom": { "url": "https://fireloom.io/mcp" } } }

VS Code (GitHub Copilot)

Add Fireloom to VS Code, or run:

Terminal
code --add-mcp '{"name":"fireloom","type":"http","url":"https://fireloom.io/mcp"}'

Claude (claude.ai and the desktop app)

Go to Customize → Connectors → Add custom connector, enter https://fireloom.io/mcp, and click Connect. On Team and Enterprise plans an owner adds it first, under Organization settings → Connectors.

ChatGPT

Add a custom MCP server (under Plugins, + → Add custom MCP server) with the URL https://fireloom.io/mcp and OAuth, then pick Fireloom with @ in a chat.

Other tools

  • Devin Desktop (formerly Windsurf): devin mcp add -s user fireloom https://fireloom.io/mcp, then devin mcp login fireloom.
  • Antigravity CLI: add {"mcpServers": {"fireloom": {"serverUrl": "https://fireloom.io/mcp"}}} to ~/.gemini/config/mcp_config.json, then sign in from /mcp.
  • Gemini CLI: gemini mcp add --transport http fireloom https://fireloom.io/mcp, then /mcp auth fireloom.
  • Anything else that speaks MCP over HTTP with OAuth: use https://fireloom.io/mcp. Tools without OAuth can send an API key as Authorization: Bearer fl_….

Chat apps like Claude and ChatGPT can't run commands on your computer, so for the Firestore step they give you a command to run in your terminal or in Google Cloud Shell.

What the agent can do

ToolWhat it does
get_statusPlan, connections, every sync's live status, and the next step to take.
connect_firestoreA one-time command that gives Fireloom read-only access to a Firebase project.
connect_postgresTests and saves the database to sync into.
inspect_firestoreCollections, document count, and the Firestore read cost of the first load.
create_syncStarts a sync: every collection in real time, unless you say otherwise.
get_syncProgress, documents per collection, errors, and example SQL.
update_sync, resyncPause, resume, change collections or schedule; reload from a fresh snapshot.
delete_sync, delete_connectionRemove what you no longer need.
upgrade_planA checkout link for Pro or Team, for you to open.

Instructions for AI agents

If you're an AI agent and your user wants their Firestore data in PostgreSQL: with the Fireloom MCP server connected, call get_status and follow its next_step. Without it, use the HTTP API at https://fireloom.io as below. Every answer is JSON; errors are {"error": "…"} with a message you can show the user.

  1. Sign in. Start a device sign-in, show the user the verification_uri_complete link (open it in their browser if you can: open on macOS, xdg-open on Linux) and ask them to click Allow. Then poll the token endpoint every 5 seconds until it returns access_token; it answers authorization_pending until then. Send the token as Authorization: Bearer fl_… on every call. It's a secret: don't print it, and don't write it to files in the project.
  2. Connect Firestore. POST /api/sync/setup returns a one-time command. Run it in the Firebase project's folder with a timeout of at least 10 minutes (or in the background). If .firebaserc lists several projects, ask the user which one and add --project <id>; if the project has several Firestore databases, add --database <id>. It installs the Google Cloud CLI if needed, may open the browser for Google sign-in, creates a read-only service account and sends its key straight to Fireloom. It's done when it prints "Connected <project> to Fireloom."
  3. Connect Postgres. Find the connection string in the project (DATABASE_URL, POSTGRES_URL or similar in .env) or ask the user; never make one up. For Supabase, use the Session pooler string. POST /api/sync/connections, then POST /api/sync/connections/{id}/test, which answers {"ok": true} when Fireloom can connect.
  4. Start the sync. GET /api/sync/connections for the IDs, then POST /api/sync/jobs. For the first load, use the export bucket the setup command made, <project-id>-fireloom-exports; if the command ran with --no-export, use {"source": "api"} instead.
  5. Wait until it's live. GET /api/sync/jobs: each sync's stream.status goes starting → syncing or awaiting_export → live. Problems show in stream.error.
  6. Show the data. Everything is in one table, <schema>.documents (firestore.documents by default): SELECT collection, count(*) FROM firestore.documents GROUP BY 1.
ShellHTTP API
# 1. Sign in: show the user verification_uri_complete, then poll curl -s -X POST https://fireloom.io/oauth/device -d client_name="Claude Code" curl -s -X POST https://fireloom.io/oauth/token \ -d grant_type=urn:ietf:params:oauth:grant-type:device_code -d device_code=DEVICE_CODE # 2. Firestore: get the one-time setup command, then run it curl -s -X POST https://fireloom.io/api/sync/setup -H "Authorization: Bearer $TOKEN" # 3. Postgres curl -s -X POST https://fireloom.io/api/sync/connections -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Postgres", "kind": "postgres", "secret": "postgres://…", "config": {"schema": "firestore"}}' curl -s -X POST https://fireloom.io/api/sync/connections/POSTGRES_ID/test -H "Authorization: Bearer $TOKEN" # 4. The sync: every collection, in real time curl -s -X POST https://fireloom.io/api/sync/jobs -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "my-app → Postgres", "source": "FIRESTORE_ID", "destination": "POSTGRES_ID", "mode": "realtime", "collections": [], "initial_load": {"source": "auto_export", "bucket": "PROJECT_ID-fireloom-exports"}}' # 5. Status curl -s https://fireloom.io/api/sync/jobs -H "Authorization: Bearer $TOKEN"

Fireloom never writes to Firestore, and in Postgres it only touches the tables it created. On the Free plan an account has one sync; when a call says the plan is full, the user can upgrade at https://fireloom.io/#pricing.

HTTP API reference

Base URL https://fireloom.io. Send Authorization: Bearer fl_… and, with a body, Content-Type: application/json. Up to 600 requests a minute.

RequestWhat it does
GET /api/sync/planThe plan, its limits and usage.
POST /api/sync/setupA one-time Firestore setup command (valid for an hour) and its id.
GET /api/sync/setup/{id}connection_id once the setup command has run.
GET /api/sync/connectionsConnections, without their secrets.
POST /api/sync/connectionsAdd one: {"name", "kind": "postgres", "secret": "<connection string>", "config": {"schema"}}, or "kind": "firestore" with a service account key as the secret.
POST /api/sync/connections/{id}/test{"ok", "error"}; for Firestore also its top-level collections.
POST /api/sync/connections/{id}/estimateCounts the documents a sync would load: {"collections": []} → {"documents"}.
DELETE /api/sync/connections/{id}Delete a connection no sync uses.
GET /api/sync/jobsSyncs, with live status in stream.
POST /api/sync/jobsStart one: name, source, destination, collections (empty for all), mode (realtime or scheduled with interval_minutes), initial_load, table_prefix.
PATCH /api/sync/jobs/{id}Change enabled, name, collections, interval_minutes or reconcile_hours.
POST /api/sync/jobs/{id}/runRun a scheduled sync now, or reload a real-time one.
GET /api/sync/jobs/{id}/runsRecent full passes and their results.
DELETE /api/sync/jobs/{id}Delete a sync. Its table stays in Postgres.

OAuth discovery for MCP clients is at https://fireloom.io/.well-known/oauth-authorization-server. Clients can identify themselves with a Client ID Metadata Document or register dynamically, and must use PKCE (S256).

API keys for scripts

For CI or your own scripts, create a key in the dashboard under Account → AI agents and API keys. It works like an agent's token: Authorization: Bearer fl_…, for the HTTP API or the MCP server.

Security

  • You approve every agent in your browser, signed in to Fireloom. Account lists each agent and key with when it was last used, and revoking one takes effect at once.
  • Agents can manage connections and syncs. They can't read stored keys or connection strings, manage API keys or delete your account.
  • Fireloom's access to Firestore is read-only (plus an export-only role for the first load). In Postgres it only writes to tables it created.
  • A connection string you give an agent passes through your AI tool. A dedicated Postgres role that only owns Fireloom's schema keeps that low-risk.

Prefer to click?

The dashboard does the same in about five minutes. Free up to 100,000 documents per Firebase project.

Start syncing free