A command-based (stdio) Model Context Protocol server for Google Firebase, providing Auth, Firestore, and Storage tools. Credentials are loaded dynamically from your project directory.
- 🗂️ Project Tools — Show the active project, list accessible projects & switch at runtime
- 💶 Billing Tool — Show the billing account, status, currency & budgets for a project
- 🔐 Auth Tools — List, get, create, update, delete users & set custom claims
- 📄 Firestore Tools — Browse collections, read/write/query/delete documents
- 📦 Storage Tools — Multiple buckets (list & switch), upload, download, copy, move & delete files, signed URLs
- ⚡ Functions Tools — List functions, read execution logs (paginated), invoke callable & scheduled functions
- 🔍 Dynamic Credentials — Automatically finds
.firebase/service-account.jsonwalking up from cwd - 📦 npx-ready — Run directly with
npx firebase-mcp-server, no global install needed
- Go to Firebase Console
- Select your project
- Project Settings → Service Accounts → Generate New Private Key
- Save the downloaded JSON file
# In your project root
mkdir -p .firebase
mv ~/Downloads/your-project-firebase-adminsdk-*.json .firebase/service-account.json
# IMPORTANT: Add to .gitignore!
echo ".firebase/" >> .gitignoreClaude Code sets cwd to your project root automatically — credentials are found with zero config:
claude mcp add firebase -- npx -y firebase-mcp-serverThat's it. As long as .firebase/service-account.json exists in your project, it works.
Add to ~/.claude/claude_desktop_config.json:
Or pass the credentials path explicitly:
{
"mcpServers": {
"firebase": {
"command": "npx",
"args": ["-y", "firebase-mcp-server", "--service-account", "/path/to/your-project/.firebase/service-account.json"]
}
}
}Add to .cursor/mcp.json in your project:
{
"mcpServers": {
"firebase": {
"command": "npx",
"args": ["-y", "firebase-mcp-server"]
}
}
}Add to ~/.windsurf/mcp.json:
{
"mcpServers": {
"firebase": {
"command": "npx",
"args": ["-y", "firebase-mcp-server"]
}
}
}firebase-mcp [options]
Options:
--service-account <path> Explicit path to service account JSON file
--project-dir <path> Directory to search .firebase/service-account.json from
--max-output-size <chars> Max inline output size before results spill to a temp file
--help Show help
The server searches for credentials in this order:
--service-account <path>— Explicit path to the JSON key file.firebase/service-account.json— Walked up from--project-dirorcwd(like.gitlookup)GOOGLE_APPLICATION_CREDENTIALS— Standard Google Cloud env varFIREBASE_SERVICE_ACCOUNT_PATH— Custom env var for explicit path- Local
gcloudsession (Application Default Credentials) — Fallback when no service account is found. Rungcloud auth application-default loginonce, and the server reuses that session. The project ID is taken fromGOOGLE_CLOUD_PROJECT, the ADC file'squota_project_id, orgcloud config get-value project.
Claude Code always starts MCP servers with cwd set to your project root. So if your project looks like this:
my-project/
├── .firebase/
│ └── service-account.json ← found automatically!
├── src/
├── package.json
└── ...
…the server finds credentials without any extra config. No cwd override needed.
For Claude Desktop, cwd is static in the config. Use --service-account for a fixed path, or set cwd in the JSON config.
# Clone and build
git clone <this-repo>
cd firebase-mcp
npm install && npm run build
# Link globally for local testing
npm link
# Test CLI
firebase-mcp --help
firebase-mcp --service-account /path/to/key.json # explicit
firebase-mcp --project-dir /path/to/your/project # search from dir
firebase-mcp # search from cwd
# Test with Claude Code (from your Firebase project dir)
cd /path/to/your-project
claude mcp add firebase -- firebase-mcp
# Or test with MCP Inspector
npx @modelcontextprotocol/inspector firebase-mcp| Tool | Description |
|---|---|
firebase_current_project |
Show the project the server is currently operating on |
firebase_list_projects |
List projects the active credentials can access |
firebase_switch_project |
Switch the active project at runtime (same credentials) |
firebase_list_projectsandfirebase_switch_projectwork best with a local gcloud session (gcloud auth application-default login) or a service account that has cross-project access.firebase_list_projectsuses the Cloud Resource Manager API, which must be enabled for the credentials.
| Tool | Description |
|---|---|
firebase_billing_status |
Billing account, status, currency & budgets (optional projectId) |
Uses the Cloud Billing API and needs no setup. It reports which billing account the project is linked to, whether billing is enabled, the account currency, and any configured budgets (best-effort).
Actual spend/cost amounts are not available through the Cloud Billing API. Google only exposes real cost breakdowns via a BigQuery billing export or the Billing → Reports page in the Cloud Console. This tool deliberately depends on neither, so it works out of the box but cannot show euros spent.
| Tool | Description |
|---|---|
firebase_auth_get_user |
Get user by UID or email |
firebase_auth_list_users |
List users (paginated, max 1000) |
firebase_auth_create_user |
Create a new user |
firebase_auth_update_user |
Update user properties |
firebase_auth_delete_user |
Delete a user |
firebase_auth_set_custom_claims |
Set custom claims (roles, permissions) |
| Tool | Description |
|---|---|
firestore_list_collections |
List top-level or sub-collections |
firestore_get_document |
Get a single document by path |
firestore_list_documents |
List documents in a collection (paginated) |
firestore_query_documents |
Query with where/orderBy/limit filters |
firestore_count_documents |
Count documents (with optional filters) |
firestore_set_document |
Create or overwrite a document |
firestore_update_document |
Update specific fields |
firestore_delete_document |
Delete a document |
| Tool | Description |
|---|---|
storage_list_buckets |
List the Cloud Storage buckets in the active project |
storage_current_bucket |
Show the bucket operations currently default to |
storage_switch_bucket |
Set the default bucket for subsequent operations (empty = reset) |
storage_list_files |
List files & folders in a bucket (with prefix filter, pagination) |
storage_get_file_metadata |
Get file metadata (size, content type, timestamps, custom metadata) |
storage_get_download_url |
Get a Firebase download URL for a file |
storage_get_signed_url |
Generate a temporary signed URL (read or write, up to 7 days) |
storage_upload |
Upload text or base64 content to a file |
storage_download |
Download a file as text or base64 (max 10MB) |
storage_delete_file |
Delete a file |
storage_copy_file |
Copy a file (same or different bucket) |
storage_move_file |
Move / rename a file |
Multiple buckets: every file tool accepts an optional
bucketargument to target a specific bucket per call.storage_switch_bucketchanges the default bucket for all subsequent calls (call it with no bucket to reset to the project default). Bucket resolution is: explicitbucketarg → active bucket → project default (<project-id>.firebasestorage.app). The active bucket resets when you switch projects.
| Tool | Description |
|---|---|
functions_list |
List Cloud Functions (Gen 2): state, trigger, runtime, URL |
functions_get_logs |
Get function execution logs from Cloud Logging (paginated, filterable) |
functions_call_callable |
Invoke an HTTPS Callable function (sends { data }, unwraps { result }) |
functions_run_scheduled |
Force an immediate run of a scheduled function via its Cloud Scheduler job |
Note: Scheduled (
onSchedule) functions cannot be invoked directly —functions_run_scheduledtriggers the underlying Cloud Scheduler job (typically namedfirebase-schedule-<functionName>-<region>). The service account needs the relevant Cloud Functions, Logging, and Cloud Scheduler IAM permissions.
Once connected, you can ask your AI assistant things like:
"List all collections in Firestore"
"Show me the first 10 users in Firebase Auth"
"Query the 'orders' collection for all orders where status == 'pending'"
"Get the document at users/abc123"
"Count how many documents are in the 'products' collection"
"Update the user with UID xyz to set displayName to 'John Doe'"
"List all files in the 'images/' folder in Storage"
"Upload this JSON to storage at 'exports/data.json'"
"Generate a signed download URL for 'reports/monthly.pdf' that expires in 24 hours"
The Firestore write tools support special field values:
// Server timestamp
{ "_type": "serverTimestamp" }
// Increment a number field
{ "_type": "increment", "value": 5 }
// Add to an array field
{ "_type": "arrayUnion", "elements": ["tag1", "tag2"] }
// Remove from an array field
{ "_type": "arrayRemove", "elements": ["tag1"] }
// Delete a field
{ "_type": "delete" }firebase-mcp/
├── src/
│ ├── index.ts # CLI entry point with arg parsing
│ ├── firebase.ts # Dynamic credential loading & Firebase init
│ ├── utils.ts # Serialization & helpers
│ └── tools/
│ ├── auth.ts # Firebase Auth tools (6)
│ ├── firestore.ts # Firestore tools (8)
│ ├── storage.ts # Firebase Storage tools (9)
│ └── functions.ts # Cloud Functions tools (4)
├── dist/ # Compiled output (after build)
├── package.json
├── tsconfig.json
└── README.md
Make sure .firebase/ is in your .gitignore:
.firebase/The service account key grants full admin access to your Firebase project. Treat it like a password.
Read operations that return more than the configured threshold (large collections, big documents, long file listings) are not truncated. Instead, the full result is written to a temporary file and the tool returns a short message telling the LLM the output was too large, along with the filePath to read:
{
"status": "output_too_large",
"message": "The output was too large to return inline. The full result has been written to the file below. Read that file to access the complete data.",
"filePath": "/tmp/firebase-mcp-XXXXXX/output.json",
"totalChars": 128034,
"threshold": 25000
}This keeps the model's context from being flooded while ensuring no data is lost — the client can read the file on demand. Temp files are written to the OS temp directory (os.tmpdir()).
The threshold (in characters) is resolved in this order:
--max-output-size <chars>CLI flagFIREBASE_MCP_MAX_OUTPUTenvironment variable- Default: 25000 characters
# via CLI flag
firebase-mcp --max-output-size 40000
# via environment variable
FIREBASE_MCP_MAX_OUTPUT=40000 firebase-mcpInvalid values (non-numeric or ≤ 0) are ignored with a warning and the default is used.
MIT
{ "mcpServers": { "firebase": { "command": "npx", "args": ["-y", "firebase-mcp-server"] } } }