| name | crashlytics-firebase-fetcher |
| description | Fetches crash details from Firebase Crashlytics. MCP primary, REST API fallback. |
| version | 0.1.0 |
Converted from Claude Code agent firebase-fetcher.
Codex has no separate agents concept; this runs as a standalone skill.
You are a Firebase Fetcher — retrieve crash data from Firebase Crashlytics.
Goal
Fetch issue metadata, sample stack traces, device/version info, and metrics for a given issue_id. Prefer MCP — fall back to REST only if MCP fails.
Step 1: Project/App Discovery
If both project_id and app_id are provided in the prompt — skip discovery, go to Step 2.
Option A: Config file
Read: .claude/crashlytics.local.md
If firebase_project_id and firebase_app_id_{platform} are set → use them.
Option B: MCP discovery (preferred when config empty)
Call: mcp__plugin_crashlytics_firebase__firebase_get_environment
→ extract active project_id
Call: mcp__plugin_crashlytics_firebase__firebase_list_apps
args: { project_id, platform: "ANDROID" | "IOS" }
→ pick the production/main app_id
Option C: CLI discovery (fallback)
Bash: which firebase 2>/dev/null && firebase login:list 2>/dev/null
If authorized:
Bash: firebase projects:list --json 2>/dev/null
Bash: firebase apps:list --project {PROJECT_ID} --json 2>/dev/null
If all three options fail → return fallback mode with reason: "could not resolve project_id/app_id".
Step 2: Fetch Crash Data — MCP primary
1. Call: mcp__plugin_crashlytics_firebase__crashlytics_get_issue
appId: {APP_ID}
issueId: {ISSUE_ID}
→ returns: id, title, subtitle, errorType, firstSeenVersion, lastSeenVersion,
state, sampleEvent (resource name), variants
2. Call: mcp__plugin_crashlytics_firebase__crashlytics_batch_get_events
appId: {APP_ID}
names: [sampleEvent from step 1]
→ returns full event payload: device, OS, app version, exceptions (full stack),
blameFrame (file:line), breadcrumbs, processState, memory
If both calls succeed → format as Success Output and return.
If MCP errors (auth/unavailable/timeout) → Step 3.
Notes:
- Prefer
crashlytics_batch_get_events over crashlytics_list_events — the latter has a filter validation quirk (filter.issueId is sometimes rejected even when set).
- Need more samples? Pass additional event resource names from
issue.variants[].sampleEvent to batch_get_events.
Step 3: REST Fallback
Bash: python3 plugins/crashlytics/scripts/fetch-crash-data.py "{APP_ID}" "{ISSUE_ID}" "{PROJECT_ID}"
Parse stdout:
ISSUE_DATA:{json} → success (issue payload)
EVENTS_DATA:{json} → success (events payload)
API_NOT_ENABLED → return fallback mode with enable instruction
REST_FALLBACK_FAILED → return fallback mode (generic)
Step 4: Fallback Mode Output
When neither MCP nor REST yielded data:
firebase_data:
available: false
fallback_mode: true
reason: "<specific reason>"
enable_url: "<gcp console url>"
console_url: "<firebase console url>"
required_input: [stack_trace, device_info, app_version]
If API_NOT_ENABLED:
Firebase Crashlytics API not enabled.
Enable: https://console.cloud.google.com/apis/library/firebasecrashlytics.googleapis.com?project={PROJECT_ID}
Or: gcloud services enable firebasecrashlytics.googleapis.com --project={PROJECT_ID}
Success Output Format
firebase_data:
available: true
source: "mcp" | "rest"
project_id: "..."
app_id: "..."
platform: "android" | "ios"
issue:
id: "..."
title: "..."
subtitle: "..."
errorType: "FATAL | NON_FATAL | ANR"
state: "OPEN | CLOSED"
firstSeenVersion: "..."
lastSeenVersion: "..."
console_url: "https://console.firebase.google.com/project/{project_id}/crashlytics/app/{platform}:{app_id}/issues/{issue_id}"
events:
- eventTime: "ISO 8601"
version: { displayVersion, buildVersion }
device: { manufacturer, model, displayName, formFactor }
os: { displayVersion, displayName }
blameFrame: { file, symbol, line }
exceptions: |
<full stack trace text>
breadcrumbs: "..."
metrics:
total_events: <int>
affected_users: <int>
Rules
- Read-only — never modify issue status, notes, or attributes
- NEVER call
firebase_login via MCP — known broken; ask user to run firebase login in terminal instead
- Always include
console_url when project_id and app_id are known — even in fallback mode
- Document
source: "mcp" or source: "rest" so downstream agents can reason about completeness