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 +14 -15
- package/lib/bin/mcp.js +46 -8
- package/lib/emulator/downloadableEmulatorInfo.json +24 -24
- package/lib/gcp/cloudsql/cloudsqladmin.js +1 -1
- package/lib/mcp/index.js +31 -22
- package/lib/mcp/tools/core/get_environment.js +4 -1
- package/lib/mcp/tools/index.js +53 -44
- package/package.json +1 -1
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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const flutterApps =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.flat()
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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.
|
|
58
|
-
"expectedSize":
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.0.
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.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.
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.0.
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.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.
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.0.
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.
|
|
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.
|
|
82
|
-
"expectedSize":
|
|
83
|
-
"expectedChecksum": "
|
|
84
|
-
"expectedChecksumSHA256": "
|
|
85
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.0.
|
|
86
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.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 = "
|
|
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
|
|
8
|
-
const
|
|
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
|
|
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
|
|
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
|
|
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
|
|
176
|
-
|
|
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
|
|
188
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|
package/lib/mcp/tools/index.js
CHANGED
|
@@ -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("./
|
|
5
|
-
const index_2 = require("./
|
|
6
|
-
const index_3 = require("./
|
|
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("./
|
|
9
|
-
const index_6 = require("./
|
|
10
|
-
const index_7 = require("./
|
|
11
|
-
const index_8 = require("./
|
|
12
|
-
const index_9 = require("./
|
|
13
|
-
const index_10 = require("./
|
|
14
|
-
const index_11 = require("./
|
|
15
|
-
const index_12 = require("./
|
|
16
|
-
|
|
17
|
-
|
|
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 =
|
|
68
|
+
const allTools = getToolsByFeature([]);
|
|
60
69
|
let doc = `
|
|
61
70
|
| Tool Name | Feature Group | Description |
|
|
62
71
|
| --------- | ------------- | ----------- |`;
|