firebase-tools 15.0.0 → 15.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/appUtils.js CHANGED
@@ -27,21 +27,20 @@ async function getPlatformsFromFolder(dirPath) {
27
27
  }
28
28
  exports.getPlatformsFromFolder = getPlatformsFromFolder;
29
29
  async function detectApps(dirPath) {
30
- const packageJsonFiles = await detectFiles(dirPath, "package.json");
31
- const pubSpecYamlFiles = await detectFiles(dirPath, "pubspec.yaml");
32
- const srcMainFolders = await detectFiles(dirPath, "src/main/");
33
- const xCodeProjects = await detectFiles(dirPath, "*.xcodeproj/");
34
- const adminAndWebApps = (await Promise.all(packageJsonFiles.map((p) => packageJsonToAdminOrWebApp(dirPath, p)))).flat();
35
- const flutterAppPromises = await Promise.all(pubSpecYamlFiles.map((f) => processFlutterDir(dirPath, f)));
36
- const flutterApps = flutterAppPromises.flat();
37
- const androidAppPromises = await Promise.all(srcMainFolders.map((f) => processAndroidDir(dirPath, f)));
38
- const androidApps = androidAppPromises
39
- .flat()
40
- .filter((a) => !flutterApps.some((f) => isPathInside(f.directory, a.directory)));
41
- const iosAppPromises = await Promise.all(xCodeProjects.map((f) => processIosDir(dirPath, f)));
42
- const iosApps = iosAppPromises
43
- .flat()
44
- .filter((a) => !flutterApps.some((f) => isPathInside(f.directory, a.directory)));
30
+ const [packageJsonFiles, pubSpecYamlFiles, srcMainFolders, xCodeProjects] = await Promise.all([
31
+ detectFiles(dirPath, "package.json"),
32
+ detectFiles(dirPath, "pubspec.yaml"),
33
+ detectFiles(dirPath, "src/main/"),
34
+ detectFiles(dirPath, "*.xcodeproj/"),
35
+ ]);
36
+ const [adminAndWebApps, flutterApps, androidAppsRaw, iosAppsRaw] = await Promise.all([
37
+ Promise.all(packageJsonFiles.map((p) => packageJsonToAdminOrWebApp(dirPath, p))).then((r) => r.flat()),
38
+ Promise.all(pubSpecYamlFiles.map((f) => processFlutterDir(dirPath, f))).then((r) => r.flat()),
39
+ Promise.all(srcMainFolders.map((f) => processAndroidDir(dirPath, f))).then((r) => r.flat()),
40
+ Promise.all(xCodeProjects.map((f) => processIosDir(dirPath, f))).then((r) => r.flat()),
41
+ ]);
42
+ const androidApps = androidAppsRaw.filter((a) => !flutterApps.some((f) => isPathInside(f.directory, a.directory)));
43
+ const iosApps = iosAppsRaw.filter((a) => !flutterApps.some((f) => isPathInside(f.directory, a.directory)));
45
44
  return [...flutterApps, ...androidApps, ...iosApps, ...adminAndWebApps];
46
45
  }
47
46
  exports.detectApps = detectApps;
package/lib/bin/mcp.js CHANGED
@@ -2,14 +2,14 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.mcp = void 0;
5
+ const path_1 = require("path");
6
+ const util_1 = require("util");
5
7
  const logger_1 = require("../logger");
6
8
  const index_1 = require("../mcp/index");
7
- const util_1 = require("util");
9
+ const index_js_1 = require("../mcp/prompts/index.js");
10
+ const index_js_2 = require("../mcp/resources/index.js");
11
+ const index_js_3 = require("../mcp/tools/index.js");
8
12
  const types_1 = require("../mcp/types");
9
- const index_js_1 = require("../mcp/tools/index.js");
10
- const index_js_2 = require("../mcp/prompts/index.js");
11
- const index_js_3 = require("../mcp/resources/index.js");
12
- const path_1 = require("path");
13
13
  const STARTUP_MESSAGE = `
14
14
  This is a running process of the Firebase MCP server. This command should only be executed by an MCP client. An example MCP client configuration might be:
15
15
 
@@ -22,28 +22,60 @@ This is a running process of the Firebase MCP server. This command should only b
22
22
  }
23
23
  }
24
24
  `;
25
+ const HELP_TEXT = `Usage: firebase mcp [options]
26
+
27
+ Description:
28
+ Starts the Model Context Protocol (MCP) server for the Firebase CLI. This server provides a
29
+ standardized way for AI agents and IDEs to interact with your Firebase project.
30
+
31
+ Tool Discovery & Loading:
32
+ The server automatically determines which tools to expose based on your project context.
33
+
34
+ 1. Auto-Detection (Default):
35
+ - Scans 'firebase.json' for configured services (e.g., Hosting, Firestore).
36
+ - Checks enabled Google Cloud APIs for the active project.
37
+ - Inspects project files for specific SDKs (e.g., Crashlytics in Android/iOS).
38
+
39
+ 2. Manual Overrides:
40
+ - Use '--only' to restrict tool discovery to specific feature sets (e.g., core, firestore).
41
+ - Use '--tools' to disable auto-detection entirely and load specific tools by name.
42
+
43
+ Options:
44
+ --dir <path> Project root directory (defaults to current working directory).
45
+ --only <features> Comma-separated list of features to enable (e.g. core, firestore).
46
+ If specified, auto-detection is disabled for other features.
47
+ --tools <tools> Comma-separated list of specific tools to enable. Disables
48
+ auto-detection entirely.
49
+ -h, --help Show this help message.
50
+ `;
25
51
  async function mcp() {
26
52
  const { values } = (0, util_1.parseArgs)({
27
53
  options: {
28
54
  only: { type: "string", default: "" },
55
+ tools: { type: "string", default: "" },
29
56
  dir: { type: "string" },
30
57
  "generate-tool-list": { type: "boolean", default: false },
31
58
  "generate-prompt-list": { type: "boolean", default: false },
32
59
  "generate-resource-list": { type: "boolean", default: false },
60
+ help: { type: "boolean", default: false, short: "h" },
33
61
  },
34
62
  allowPositionals: true,
35
63
  });
36
64
  let earlyExit = false;
65
+ if (values.help) {
66
+ console.log(HELP_TEXT);
67
+ earlyExit = true;
68
+ }
37
69
  if (values["generate-tool-list"]) {
38
- console.log((0, index_js_1.markdownDocsOfTools)());
70
+ console.log((0, index_js_3.markdownDocsOfTools)());
39
71
  earlyExit = true;
40
72
  }
41
73
  if (values["generate-prompt-list"]) {
42
- console.log((0, index_js_2.markdownDocsOfPrompts)());
74
+ console.log((0, index_js_1.markdownDocsOfPrompts)());
43
75
  earlyExit = true;
44
76
  }
45
77
  if (values["generate-resource-list"]) {
46
- console.log((0, index_js_3.markdownDocsOfResources)());
78
+ console.log((0, index_js_2.markdownDocsOfResources)());
47
79
  earlyExit = true;
48
80
  }
49
81
  if (earlyExit)
@@ -52,9 +84,15 @@ async function mcp() {
52
84
  (0, logger_1.useFileLogger)();
53
85
  const activeFeatures = (values.only || "")
54
86
  .split(",")
87
+ .map((f) => f.trim())
55
88
  .filter((f) => types_1.SERVER_FEATURES.includes(f));
89
+ const enabledTools = (values.tools || "")
90
+ .split(",")
91
+ .map((t) => t.trim())
92
+ .filter((t) => t.length > 0);
56
93
  const server = new index_1.FirebaseMcpServer({
57
94
  activeFeatures,
95
+ enabledTools,
58
96
  projectRoot: values.dir ? (0, path_1.resolve)(values.dir) : undefined,
59
97
  });
60
98
  await server.start();
@@ -54,36 +54,36 @@
54
54
  },
55
55
  "dataconnect": {
56
56
  "darwin": {
57
- "version": "3.0.0",
58
- "expectedSize": 30155616,
59
- "expectedChecksum": "cda7603cc22f37e06c372dcfca55b612",
60
- "expectedChecksumSHA256": "bd57becce3712cf535d91fe97dfbdeee333a8bf2eb9c050a183643a3d7c4fa5f",
61
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.0.0",
62
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.0"
57
+ "version": "3.0.1",
58
+ "expectedSize": 30212960,
59
+ "expectedChecksum": "5a556a6e52d8e4707be9e65555cf6fc0",
60
+ "expectedChecksumSHA256": "04507e034d26a9e1053a246508351881473c82daf86357a28472e112f50e0128",
61
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.0.1",
62
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1"
63
63
  },
64
64
  "darwin_arm64": {
65
- "version": "3.0.0",
66
- "expectedSize": 29630050,
67
- "expectedChecksum": "34c68e4dff99a933b71bee73c35307be",
68
- "expectedChecksumSHA256": "ff29f821f4a242d93c13c22dbd7b5d6c65ea16bbad78b2b36d075f943345b7c7",
69
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.0.0",
70
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.0"
65
+ "version": "3.0.1",
66
+ "expectedSize": 29680322,
67
+ "expectedChecksum": "31b21517979ce3acc408c432023a97e5",
68
+ "expectedChecksumSHA256": "36e2db3abf7a024436ba045805153a5f7ae2845f34658c187c38aeff329c6626",
69
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.0.1",
70
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1"
71
71
  },
72
72
  "win32": {
73
- "version": "3.0.0",
74
- "expectedSize": 30653440,
75
- "expectedChecksum": "6087cb5b1dea5154fd168dd131006e85",
76
- "expectedChecksumSHA256": "0efa54faf43f1eb3bba200e0a1c369f3fec8d2a929911a223d06322ef94afdec",
77
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.0.0",
78
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.0.exe"
73
+ "version": "3.0.1",
74
+ "expectedSize": 30712832,
75
+ "expectedChecksum": "953603294bf7112a5100936db813f928",
76
+ "expectedChecksumSHA256": "4a71d6ce535302a28215e08cc3b645818cf8d8204f4bb2512455d3b7d3c17df1",
77
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.0.1",
78
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1.exe"
79
79
  },
80
80
  "linux": {
81
- "version": "3.0.0",
82
- "expectedSize": 30077112,
83
- "expectedChecksum": "1e8b62069c07fbb2139521b7ff631865",
84
- "expectedChecksumSHA256": "19d0a384d80ba1128ca4a64814d76b67e4da012020fec5b5dd329ece8fc37471",
85
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.0.0",
86
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.0"
81
+ "version": "3.0.1",
82
+ "expectedSize": 30138552,
83
+ "expectedChecksum": "48d5f03c2edea8d4c6b200dccc9bf8a8",
84
+ "expectedChecksumSHA256": "cdf2d37f69b4372c0757afcc6c6ed4d7c6162fe7d29d9191e20e1411e116a665",
85
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.0.1",
86
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1"
87
87
  }
88
88
  }
89
89
  }
@@ -51,7 +51,7 @@ function instanceConsoleLink(projectId, instanceId) {
51
51
  return `https://console.cloud.google.com/sql/instances/${instanceId}/overview?project=${projectId}`;
52
52
  }
53
53
  exports.instanceConsoleLink = instanceConsoleLink;
54
- exports.DEFAULT_DATABASE_VERSION = "POSTGRES_15";
54
+ exports.DEFAULT_DATABASE_VERSION = "POSTGRES_17";
55
55
  async function createInstance(args) {
56
56
  const databaseFlags = [{ name: "cloudsql.iam_authentication", value: "on" }];
57
57
  if (args.enableGoogleMlIntegration) {
package/lib/mcp/index.js CHANGED
@@ -4,26 +4,27 @@ exports.FirebaseMcpServer = void 0;
4
4
  const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
5
5
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
6
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
7
- const util_1 = require("./util");
8
- const types_1 = require("./types");
9
- const index_1 = require("./tools/index");
10
- const index_2 = require("./prompts/index");
11
- const configstore_1 = require("../configstore");
7
+ const crossSpawn = require("cross-spawn");
8
+ const node_fs_1 = require("node:fs");
12
9
  const command_1 = require("../command");
13
- const requireAuth_1 = require("../requireAuth");
14
- const projectUtils_1 = require("../projectUtils");
15
- const errors_1 = require("./errors");
16
- const track_1 = require("../track");
17
10
  const config_1 = require("../config");
18
- const rc_1 = require("../rc");
11
+ const configstore_1 = require("../configstore");
19
12
  const hubClient_1 = require("../emulator/hubClient");
20
- const node_fs_1 = require("node:fs");
21
- const logging_transport_1 = require("./logging-transport");
22
13
  const env_1 = require("../env");
14
+ const projectUtils_1 = require("../projectUtils");
15
+ const rc_1 = require("../rc");
16
+ const requireAuth_1 = require("../requireAuth");
23
17
  const timeout_1 = require("../timeout");
18
+ const track_1 = require("../track");
19
+ const errors_1 = require("./errors");
20
+ const logging_transport_1 = require("./logging-transport");
21
+ const index_1 = require("./prompts/index");
24
22
  const resources_1 = require("./resources");
25
- const crossSpawn = require("cross-spawn");
23
+ const index_2 = require("./tools/index");
24
+ const types_1 = require("./types");
25
+ const util_1 = require("./util");
26
26
  const availability_1 = require("./util/availability");
27
+ const cloudbilling_1 = require("../gcp/cloudbilling");
27
28
  const SERVER_VERSION = "0.3.0";
28
29
  const cmd = new command_1.Command("mcp");
29
30
  const orderedLogLevels = [
@@ -55,6 +56,7 @@ class FirebaseMcpServer {
55
56
  this.currentLogLevel = process.env.FIREBASE_MCP_DEBUG_LOG ? "debug" : undefined;
56
57
  this.activeFeatures = options.activeFeatures;
57
58
  this.startupRoot = options.projectRoot || process.env.PROJECT_ROOT;
59
+ this.enabledTools = options.enabledTools;
58
60
  this.server = new index_js_1.Server({ name: "firebase", version: SERVER_VERSION });
59
61
  this.server.registerCapabilities({
60
62
  tools: { listChanged: true },
@@ -135,7 +137,8 @@ class FirebaseMcpServer {
135
137
  this.logger.debug("detecting active features of Firebase MCP server...");
136
138
  const projectId = (await this.getProjectId()) || "";
137
139
  const accountEmail = await this.getAuthenticatedUser();
138
- const ctx = this._createMcpContext(projectId, accountEmail);
140
+ const isBillingEnabled = projectId ? await (0, cloudbilling_1.checkBillingEnabled)(projectId) : false;
141
+ const ctx = this._createMcpContext(projectId, accountEmail, isBillingEnabled);
139
142
  const detected = await Promise.all(types_1.SERVER_FEATURES.map(async (f) => {
140
143
  const availabilityCheck = (0, availability_1.getDefaultFeatureAvailabilityCheck)(f);
141
144
  if (await availabilityCheck(ctx))
@@ -172,8 +175,9 @@ class FirebaseMcpServer {
172
175
  const features = ((_a = this.activeFeatures) === null || _a === void 0 ? void 0 : _a.length) ? this.activeFeatures : this.detectedFeatures;
173
176
  const projectId = (await this.getProjectId()) || "";
174
177
  const accountEmail = await this.getAuthenticatedUser();
175
- const ctx = this._createMcpContext(projectId, accountEmail);
176
- return (0, index_1.availableTools)(ctx, features);
178
+ const isBillingEnabled = projectId ? await (0, cloudbilling_1.checkBillingEnabled)(projectId) : false;
179
+ const ctx = this._createMcpContext(projectId, accountEmail, isBillingEnabled);
180
+ return (0, index_2.availableTools)(ctx, features, this.enabledTools);
177
181
  }
178
182
  async getTool(name) {
179
183
  const tools = await this.getAvailableTools();
@@ -184,8 +188,9 @@ class FirebaseMcpServer {
184
188
  const features = ((_a = this.activeFeatures) === null || _a === void 0 ? void 0 : _a.length) ? this.activeFeatures : this.detectedFeatures;
185
189
  const projectId = (await this.getProjectId()) || "";
186
190
  const accountEmail = await this.getAuthenticatedUser();
187
- const ctx = this._createMcpContext(projectId, accountEmail);
188
- return (0, index_2.availablePrompts)(ctx, features);
191
+ const isBillingEnabled = projectId ? await (0, cloudbilling_1.checkBillingEnabled)(projectId) : false;
192
+ const ctx = this._createMcpContext(projectId, accountEmail, isBillingEnabled);
193
+ return (0, index_1.availablePrompts)(ctx, features);
189
194
  }
190
195
  async getPrompt(name) {
191
196
  const prompts = await this.getAvailablePrompts();
@@ -218,7 +223,7 @@ class FirebaseMcpServer {
218
223
  return null;
219
224
  }
220
225
  }
221
- _createMcpContext(projectId, accountEmail) {
226
+ _createMcpContext(projectId, accountEmail, isBillingEnabled) {
222
227
  const options = { projectDir: this.cachedProjectDir, cwd: this.cachedProjectDir };
223
228
  return {
224
229
  projectId: projectId,
@@ -227,6 +232,7 @@ class FirebaseMcpServer {
227
232
  rc: (0, rc_1.loadRC)(options),
228
233
  accountEmail,
229
234
  firebaseCliCommand: this._getFirebaseCliCommand(),
235
+ isBillingEnabled,
230
236
  };
231
237
  }
232
238
  _getFirebaseCliCommand() {
@@ -282,7 +288,8 @@ class FirebaseMcpServer {
282
288
  if (err)
283
289
  return err;
284
290
  }
285
- const toolsCtx = this._createMcpContext(projectId, accountEmail);
291
+ const isBillingEnabled = projectId ? await (0, cloudbilling_1.checkBillingEnabled)(projectId) : false;
292
+ const toolsCtx = this._createMcpContext(projectId, accountEmail, isBillingEnabled);
286
293
  try {
287
294
  const res = await tool.fn(toolArgs, toolsCtx);
288
295
  await this.trackGA4("mcp_tool_call", {
@@ -332,7 +339,8 @@ class FirebaseMcpServer {
332
339
  projectId = projectId || "";
333
340
  const skipAutoAuthForStudio = (0, env_1.isFirebaseStudio)();
334
341
  const accountEmail = await this.getAuthenticatedUser(skipAutoAuthForStudio);
335
- const promptsCtx = this._createMcpContext(projectId, accountEmail);
342
+ const isBillingEnabled = projectId ? await (0, cloudbilling_1.checkBillingEnabled)(projectId) : false;
343
+ const promptsCtx = this._createMcpContext(projectId, accountEmail, isBillingEnabled);
336
344
  try {
337
345
  const messages = await prompt.fn(promptArgs, promptsCtx);
338
346
  await this.trackGA4("mcp_get_prompt", {
@@ -366,7 +374,8 @@ class FirebaseMcpServer {
366
374
  projectId = projectId || "";
367
375
  const skipAutoAuthForStudio = (0, env_1.isFirebaseStudio)();
368
376
  const accountEmail = await this.getAuthenticatedUser(skipAutoAuthForStudio);
369
- const resourceCtx = this._createMcpContext(projectId, accountEmail);
377
+ const isBillingEnabled = projectId ? await (0, cloudbilling_1.checkBillingEnabled)(projectId) : false;
378
+ const resourceCtx = this._createMcpContext(projectId, accountEmail, isBillingEnabled);
370
379
  const resolved = await (0, resources_1.resolveResource)(req.params.uri, resourceCtx);
371
380
  if (!resolved) {
372
381
  throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Resource '${req.params.uri}' could not be found.`);
@@ -15,6 +15,7 @@ function hydrateTemplate(config) {
15
15
  : "<NONE>";
16
16
  const projectConfigPath = config.projectConfigPath || "<NO CONFIG PRESENT>";
17
17
  const geminiTosAccepted = config.geminiTosAccepted ? "Accepted" : "<NOT ACCEPTED>";
18
+ const billingEnabled = config.projectId ? (config.isBillingEnabled ? "Yes" : "No") : "N/A";
18
19
  const authenticatedUser = config.authenticatedUser || "<NONE>";
19
20
  const detectedApps = Object.entries(config.detectedAppIds).length > 0
20
21
  ? `\n\n${(0, js_yaml_1.dump)(config.detectedAppIds).trim()}\n`
@@ -30,6 +31,7 @@ Project Directory: ${config.projectDir}
30
31
  Project Config Path: ${projectConfigPath}
31
32
  Active Project ID: ${activeProject}
32
33
  Gemini in Firebase Terms of Service: ${geminiTosAccepted}
34
+ Billing Enabled: ${billingEnabled}
33
35
  Authenticated User: ${authenticatedUser}
34
36
  Detected App IDs: ${detectedApps}
35
37
  Available Project Aliases (format: '[alias]: [projectId]'): ${availableProjects}${hasOtherAccounts ? `\nAvailable Accounts: \n\n${availableAccounts}` : ""}
@@ -63,7 +65,7 @@ exports.get_environment = (0, tool_1.tool)("core", {
63
65
  requiresAuth: false,
64
66
  requiresProject: false,
65
67
  },
66
- }, async (_, { projectId, host, accountEmail, rc, config }) => {
68
+ }, async (_, { projectId, host, accountEmail, rc, config, isBillingEnabled }) => {
67
69
  const aliases = projectId ? (0, projectUtils_1.getAliases)({ rc }, projectId) : [];
68
70
  const geminiTosAccepted = !!configstore_1.configstore.get("gemini");
69
71
  const projectFileExists = config.projectFileExists("firebase.json");
@@ -84,6 +86,7 @@ exports.get_environment = (0, tool_1.tool)("core", {
84
86
  projectDir: host.cachedProjectDir,
85
87
  projectConfigPath: projectFileExists ? config.path("firebase.json") : undefined,
86
88
  geminiTosAccepted,
89
+ isBillingEnabled,
87
90
  authenticatedUser: accountEmail || undefined,
88
91
  projectAliasMap: rc.projects,
89
92
  allAccounts,
@@ -1,20 +1,59 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.markdownDocsOfTools = exports.availableTools = void 0;
4
- const index_1 = require("./auth/index");
5
- const index_2 = require("./dataconnect/index");
6
- const index_3 = require("./firestore/index");
4
+ const index_1 = require("./apphosting/index");
5
+ const index_2 = require("./apptesting/index");
6
+ const index_3 = require("./auth/index");
7
7
  const index_4 = require("./core/index");
8
- const index_5 = require("./storage/index");
9
- const index_6 = require("./messaging/index");
10
- const index_7 = require("./remoteconfig/index");
11
- const index_8 = require("./crashlytics/index");
12
- const index_9 = require("./apphosting/index");
13
- const index_10 = require("./apptesting/index");
14
- const index_11 = require("./realtime_database/index");
15
- const index_12 = require("./functions/index");
16
- async function availableTools(ctx, activeFeatures) {
17
- const allTools = getAllTools(activeFeatures);
8
+ const index_5 = require("./crashlytics/index");
9
+ const index_6 = require("./dataconnect/index");
10
+ const index_7 = require("./firestore/index");
11
+ const index_8 = require("./functions/index");
12
+ const index_9 = require("./messaging/index");
13
+ const index_10 = require("./realtime_database/index");
14
+ const index_11 = require("./remoteconfig/index");
15
+ const index_12 = require("./storage/index");
16
+ function addFeaturePrefix(feature, tools) {
17
+ return tools.map((tool) => (Object.assign(Object.assign({}, tool), { mcp: Object.assign(Object.assign({}, tool.mcp), { name: `${feature}_${tool.mcp.name}`, _meta: Object.assign(Object.assign({}, tool.mcp._meta), { feature }) }) })));
18
+ }
19
+ const tools = {
20
+ apphosting: addFeaturePrefix("apphosting", index_1.appHostingTools),
21
+ apptesting: addFeaturePrefix("apptesting", index_2.apptestingTools),
22
+ auth: addFeaturePrefix("auth", index_3.authTools),
23
+ core: addFeaturePrefix("firebase", index_4.coreTools),
24
+ crashlytics: addFeaturePrefix("crashlytics", index_5.crashlyticsTools),
25
+ database: addFeaturePrefix("realtimedatabase", index_10.realtimeDatabaseTools),
26
+ dataconnect: addFeaturePrefix("dataconnect", index_6.dataconnectTools),
27
+ firestore: addFeaturePrefix("firestore", index_7.firestoreTools),
28
+ functions: addFeaturePrefix("functions", index_8.functionsTools),
29
+ messaging: addFeaturePrefix("messaging", index_9.messagingTools),
30
+ remoteconfig: addFeaturePrefix("remoteconfig", index_11.remoteConfigTools),
31
+ storage: addFeaturePrefix("storage", index_12.storageTools),
32
+ };
33
+ const allToolsMap = new Map(Object.values(tools)
34
+ .flat()
35
+ .sort((a, b) => a.mcp.name.localeCompare(b.mcp.name))
36
+ .map((t) => [t.mcp.name, t]));
37
+ function getToolsByName(names) {
38
+ const selectedTools = new Set();
39
+ for (const toolName of names) {
40
+ const tool = allToolsMap.get(toolName);
41
+ if (tool) {
42
+ selectedTools.add(tool);
43
+ }
44
+ }
45
+ return Array.from(selectedTools);
46
+ }
47
+ function getToolsByFeature(serverFeatures) {
48
+ const features = new Set((serverFeatures === null || serverFeatures === void 0 ? void 0 : serverFeatures.length) ? serverFeatures : Object.keys(tools));
49
+ features.add("core");
50
+ return Array.from(features).flatMap((feature) => tools[feature] || []);
51
+ }
52
+ async function availableTools(ctx, activeFeatures, enabledTools) {
53
+ if (enabledTools === null || enabledTools === void 0 ? void 0 : enabledTools.length) {
54
+ return getToolsByName(enabledTools);
55
+ }
56
+ const allTools = getToolsByFeature(activeFeatures);
18
57
  const availabilities = await Promise.all(allTools.map((t) => {
19
58
  if (t.isAvailable) {
20
59
  return t.isAvailable(ctx);
@@ -24,39 +63,9 @@ async function availableTools(ctx, activeFeatures) {
24
63
  return allTools.filter((_, i) => availabilities[i]);
25
64
  }
26
65
  exports.availableTools = availableTools;
27
- function getAllTools(activeFeatures) {
28
- const toolDefs = [];
29
- if (!(activeFeatures === null || activeFeatures === void 0 ? void 0 : activeFeatures.length)) {
30
- activeFeatures = Object.keys(tools);
31
- }
32
- if (!activeFeatures.includes("core")) {
33
- activeFeatures.unshift("core");
34
- }
35
- for (const key of activeFeatures) {
36
- toolDefs.push(...tools[key]);
37
- }
38
- return toolDefs;
39
- }
40
- const tools = {
41
- core: addFeaturePrefix("firebase", index_4.coreTools),
42
- firestore: addFeaturePrefix("firestore", index_3.firestoreTools),
43
- auth: addFeaturePrefix("auth", index_1.authTools),
44
- dataconnect: addFeaturePrefix("dataconnect", index_2.dataconnectTools),
45
- storage: addFeaturePrefix("storage", index_5.storageTools),
46
- messaging: addFeaturePrefix("messaging", index_6.messagingTools),
47
- functions: addFeaturePrefix("functions", index_12.functionsTools),
48
- remoteconfig: addFeaturePrefix("remoteconfig", index_7.remoteConfigTools),
49
- crashlytics: addFeaturePrefix("crashlytics", index_8.crashlyticsTools),
50
- apptesting: addFeaturePrefix("apptesting", index_10.apptestingTools),
51
- apphosting: addFeaturePrefix("apphosting", index_9.appHostingTools),
52
- database: addFeaturePrefix("realtimedatabase", index_11.realtimeDatabaseTools),
53
- };
54
- function addFeaturePrefix(feature, tools) {
55
- return tools.map((tool) => (Object.assign(Object.assign({}, tool), { mcp: Object.assign(Object.assign({}, tool.mcp), { name: `${feature}_${tool.mcp.name}`, _meta: Object.assign(Object.assign({}, tool.mcp._meta), { feature }) }) })));
56
- }
57
66
  function markdownDocsOfTools() {
58
67
  var _a, _b, _c;
59
- const allTools = getAllTools([]);
68
+ const allTools = getToolsByFeature([]);
60
69
  let doc = `
61
70
  | Tool Name | Feature Group | Description |
62
71
  | --------- | ------------- | ----------- |`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "15.0.0",
3
+ "version": "15.1.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "mcpName": "io.github.firebase/firebase-mcp",