Source: https://fireloom.io/agents

> Let an AI agent sync Firestore to PostgreSQL for you. Fireloom's MCP server works with Claude Code, Codex, Cursor, Claude and ChatGPT; other agents use the HTTP API.

# 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:

Prompt (example)

```
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](cursor://anysphere.cursor-deeplink/mcp/install?name=fireloom&config=eyJ1cmwiOiJodHRwczovL2ZpcmVsb29tLmlvL21jcCJ9) 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](vscode:mcp/install?%7B%22name%22%3A%22fireloom%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Ffireloom.io%2Fmcp%22%7D), 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](https://shell.cloud.google.com/?show=terminal).

### What the agent can do

| Tool | What it does |
| --- | --- |
| `get_status` | Plan, connections, every sync's live status, and the next step to take. |
| `connect_firestore` | A one-time command that gives Fireloom read-only access to a Firebase project. |
| `connect_postgres` | Tests and saves the database to sync into. |
| `inspect_firestore` | Collections, document count, and the Firestore read cost of the first load. |
| `create_sync` | Starts a sync: every collection in real time, unless you say otherwise. |
| `get_sync` | Progress, documents per collection, errors, and example SQL. |
| `update_sync`, `resync` | Pause, resume, change collections or schedule; reload from a fresh snapshot. |
| `delete_sync`, `delete_connection` | Remove what you no longer need. |
| `upgrade_plan` | A 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`.

Shell (HTTP 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](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.

| Request | What it does |
| --- | --- |
| `GET /api/sync/plan` | The plan, its limits and usage. |
| `POST /api/sync/setup` | A 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/connections` | Connections, without their secrets. |
| `POST /api/sync/connections` | Add 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}/estimate` | Counts the documents a sync would load: `{"collections": []}` → `{"documents"}`. |
| `DELETE /api/sync/connections/{id}` | Delete a connection no sync uses. |
| `GET /api/sync/jobs` | Syncs, with live status in `stream`. |
| `POST /api/sync/jobs` | Start 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}/run` | Run a scheduled sync now, or reload a real-time one. |
| `GET /api/sync/jobs/{id}/runs` | Recent 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](https://fireloom.io/app?signup=1)
