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.
- π Auth Tools β List, get, create, update, delete users & set custom claims
- π Firestore Tools β Browse collections, read/write/query/delete documents
- π¦ Storage Tools β List, upload, download, copy, move & delete files, generate signed URLs
- π 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
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_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_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 |
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)
βββ 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"] } } }