Skip to content

[MCP] Crashlytics auto-detection can fail in Flutter projects and hide Crashlytics tools #10211

@lukemmtt

Description

@lukemmtt

Summary

I ran into a Firebase MCP discovery problem in a Flutter app that already has Crashlytics configured.

When the server starts in its default auto-detect mode, Crashlytics tools are not exposed. After digging into it locally, the reason appears to be an internal exception during feature detection, as opposed to something missing in my Crashlytics config.

The same install exposes the Crashlytics tools immediately if I force features with --only, so this looks like an MCP auto-detection bug.

Environment

  • firebase-tools 15.11.0
  • macOS arm64
  • Flutter app with firebase_crashlytics in pubspec.yaml
  • lib/firebase_options.dart generated by FlutterFire
  • Android project also applies the Crashlytics Gradle plugin

Steps to reproduce

  1. Use a Flutter app that has Firebase configured and firebase_crashlytics installed.
  2. Start Firebase MCP in the app root without forcing features:
    firebase mcp --dir /path/to/flutter_app
  3. Have an MCP client list tools.

I also reproduced this directly in-process with the installed server:

const { FirebaseMcpServer } = require("firebase-tools/lib/mcp/index.js");

(async () => {
  const server = new FirebaseMcpServer({ projectRoot: "/path/to/flutter_app" });
  await new Promise(r => setTimeout(r, 500));
  await server.mcpListTools();
})();

Expected behavior

Crashlytics tools should be exposed automatically for a Flutter project that already has Crashlytics configured.

Actual behavior

Tool listing fails during auto-detection with:

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
    at Object.join (node:path:1339:7)
    at /opt/homebrew/lib/node_modules/firebase-tools/lib/appUtils.js:172:53
    at Array.map (<anonymous>)
    at detectAppIdsForPlatform (/opt/homebrew/lib/node_modules/firebase-tools/lib/appUtils.js:171:52)
    at async processFlutterDir (/opt/homebrew/lib/node_modules/firebase-tools/lib/appUtils.js:92:27)
    at async Promise.all (index 0)
    at async Promise.all (index 1)
    at async detectApps (/opt/homebrew/lib/node_modules/firebase-tools/lib/appUtils.js:42:72)
    at async getPlatformsFromFolder (/opt/homebrew/lib/node_modules/firebase-tools/lib/appUtils.js:32:18)
    at async isCrashlyticsInstalled (/opt/homebrew/lib/node_modules/firebase-tools/lib/mcp/util/crashlytics/availability.js:14:23)

Workaround

If I start MCP with forced features, Crashlytics tools show up immediately:

firebase mcp --dir /path/to/flutter_app --only core,auth,crashlytics,firestore,functions,messaging,database,remoteconfig,storage

With forced features, the server exposes the expected Crashlytics tools, including:

  • crashlytics_get_issue
  • crashlytics_get_report
  • crashlytics_list_events
  • crashlytics_batch_get_events

Suspected cause

This looks like an ordering problem in MCP startup.

mcpListTools() calls detectActiveFeatures() and detectProjectRoot() in parallel:

await Promise.all([this.detectActiveFeatures(), this.detectProjectRoot()]);

But detectActiveFeatures() builds its context from this.cachedProjectDir, and _createMcpContext() uses that cached dir immediately.

So it looks possible for Crashlytics availability detection to run before the project root has been cached, which then leads to path.join(dirPath, file) getting undefined inside detectAppIdsForPlatform().

Related issues

This feels related in spirit to earlier MCP Crashlytics discovery issues, but not identical:

I can provide more detail if it would be helpful, but the in-process reproduction above seems to capture the failure pretty directly.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions