firebase-tools 14.11.1 → 14.11.2
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/apptesting/ensureProjectConfigured.js +4 -3
- package/lib/commands/ext-export.js +1 -1
- package/lib/commands/login.js +2 -2
- package/lib/deploy/functions/params.js +4 -0
- package/lib/mcp/errors.js +7 -1
- package/lib/mcp/index.js +46 -45
- package/lib/mcp/tools/apphosting/fetch_logs.js +22 -22
- package/lib/mcp/tools/apphosting/list_backends.js +10 -10
- package/lib/mcp/tools/auth/disable_user.js +7 -7
- package/lib/mcp/tools/auth/get_user.js +6 -6
- package/lib/mcp/tools/auth/index.js +10 -10
- package/lib/mcp/tools/auth/list_users.js +6 -6
- package/lib/mcp/tools/auth/set_claims.js +7 -7
- package/lib/mcp/tools/auth/set_sms_region_policy.js +6 -6
- package/lib/mcp/tools/core/consult_assistant.js +6 -6
- package/lib/mcp/tools/core/create_android_sha.js +9 -9
- package/lib/mcp/tools/core/create_app.js +7 -7
- package/lib/mcp/tools/core/create_project.js +13 -13
- package/lib/mcp/tools/core/get_admin_sdk_config.js +7 -7
- package/lib/mcp/tools/core/get_environment.js +8 -8
- package/lib/mcp/tools/core/get_project.js +5 -5
- package/lib/mcp/tools/core/get_sdk_config.js +9 -9
- package/lib/mcp/tools/core/index.js +24 -24
- package/lib/mcp/tools/core/init.js +8 -8
- package/lib/mcp/tools/core/list_apps.js +6 -6
- package/lib/mcp/tools/core/list_projects.js +6 -6
- package/lib/mcp/tools/core/update_environment.js +10 -10
- package/lib/mcp/tools/crashlytics/index.js +2 -2
- package/lib/mcp/tools/crashlytics/list_top_issues.js +6 -6
- package/lib/mcp/tools/dataconnect/emulator.js +6 -6
- package/lib/mcp/tools/dataconnect/execute_graphql.js +10 -10
- package/lib/mcp/tools/dataconnect/execute_graphql_read.js +10 -10
- package/lib/mcp/tools/dataconnect/execute_mutation.js +13 -13
- package/lib/mcp/tools/dataconnect/execute_query.js +13 -13
- package/lib/mcp/tools/dataconnect/generate_operation.js +8 -8
- package/lib/mcp/tools/dataconnect/generate_schema.js +6 -6
- package/lib/mcp/tools/dataconnect/get_connector.js +8 -8
- package/lib/mcp/tools/dataconnect/get_schema.js +8 -8
- package/lib/mcp/tools/dataconnect/index.js +18 -18
- package/lib/mcp/tools/dataconnect/list_services.js +5 -5
- package/lib/mcp/tools/firestore/delete_document.js +13 -13
- package/lib/mcp/tools/firestore/get_documents.js +13 -13
- package/lib/mcp/tools/firestore/list_collections.js +9 -9
- package/lib/mcp/tools/firestore/query_collection.js +13 -13
- package/lib/mcp/tools/index.js +18 -18
- package/lib/mcp/tools/messaging/index.js +2 -2
- package/lib/mcp/tools/messaging/send_message.js +7 -7
- package/lib/mcp/tools/remoteconfig/get_template.js +5 -5
- package/lib/mcp/tools/remoteconfig/index.js +4 -4
- package/lib/mcp/tools/remoteconfig/publish_template.js +7 -7
- package/lib/mcp/tools/remoteconfig/rollback_template.js +6 -6
- package/lib/mcp/tools/rules/get_rules.js +8 -8
- package/lib/mcp/tools/rules/validate_rules.js +10 -10
- package/lib/mcp/tools/storage/get_download_url.js +8 -8
- package/lib/mcp/tools/storage/get_rules.js +8 -8
- package/package.json +1 -1
- package/templates/init/dataconnect/mutations.gql +1 -1
- package/templates/init/dataconnect/queries.gql +3 -3
|
@@ -11,9 +11,10 @@ const prompt_1 = require("../prompt");
|
|
|
11
11
|
const TEST_RUNNER_ROLE = "roles/firebaseapptesting.testRunner";
|
|
12
12
|
const TEST_RUNNER_SERVICE_ACCOUNT_NAME = "firebaseapptesting-test-runner";
|
|
13
13
|
async function ensureProjectConfigured(projectId) {
|
|
14
|
-
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.appTestingOrigin)(), "
|
|
15
|
-
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.
|
|
16
|
-
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.
|
|
14
|
+
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.appTestingOrigin)(), "Firebase App Testing", false);
|
|
15
|
+
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudRunApiOrigin)(), "Cloud Run", false);
|
|
16
|
+
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.storageOrigin)(), "Cloud Storage", false);
|
|
17
|
+
await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.artifactRegistryDomain)(), "Artifact Registry", false);
|
|
17
18
|
const serviceAccount = runnerServiceAccount(projectId);
|
|
18
19
|
const serviceAccountExistsAndIsRunner = await (0, resourceManager_1.serviceAccountHasRoles)(projectId, serviceAccount, [TEST_RUNNER_ROLE], true);
|
|
19
20
|
if (!serviceAccountExistsAndIsRunner) {
|
|
@@ -45,7 +45,7 @@ exports.command = new command_1.Command("ext:export")
|
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
const manifestSpecs = withRefSubbed.map((spec) => {
|
|
48
|
-
const paramCopy = Object.assign({}, spec.params);
|
|
48
|
+
const paramCopy = Object.assign(Object.assign({}, spec.params), spec.systemParams);
|
|
49
49
|
if (spec.eventarcChannel) {
|
|
50
50
|
paramCopy.EVENTARC_CHANNEL = spec.eventarcChannel;
|
|
51
51
|
}
|
package/lib/commands/login.js
CHANGED
|
@@ -22,7 +22,7 @@ exports.command = new command_1.Command("login")
|
|
|
22
22
|
}
|
|
23
23
|
const user = options.user;
|
|
24
24
|
const tokens = options.tokens;
|
|
25
|
-
if (user && tokens && !options.reauth) {
|
|
25
|
+
if (user && (tokens === null || tokens === void 0 ? void 0 : tokens.refresh_token) && !options.reauth) {
|
|
26
26
|
logger_1.logger.info("Already logged in as", clc.bold(user.email));
|
|
27
27
|
return user;
|
|
28
28
|
}
|
|
@@ -37,7 +37,7 @@ exports.command = new command_1.Command("login")
|
|
|
37
37
|
configstore_1.configstore.set("usage", collectUsage);
|
|
38
38
|
if (geminiUsage || collectUsage) {
|
|
39
39
|
logger_1.logger.info();
|
|
40
|
-
utils.logBullet("To change your
|
|
40
|
+
utils.logBullet("To change your preferences at any time, run `firebase logout` and `firebase login` again.");
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
const useLocalhost = (0, utils_1.isCloudEnvironment)() ? false : options.localhost;
|
|
@@ -108,6 +108,10 @@ class ParamValue {
|
|
|
108
108
|
return ["true", "y", "yes", "1"].includes(this.rawValue);
|
|
109
109
|
}
|
|
110
110
|
asList() {
|
|
111
|
+
if (this.rawValue.includes("[")) {
|
|
112
|
+
const unquoted = this.rawValue.replace(/'/g, '"');
|
|
113
|
+
return JSON.parse(unquoted);
|
|
114
|
+
}
|
|
111
115
|
return this.rawValue.split(this.delimiter);
|
|
112
116
|
}
|
|
113
117
|
asNumber() {
|
package/lib/mcp/errors.js
CHANGED
|
@@ -3,8 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.mcpGeminiError = exports.mcpAuthError = exports.NO_PROJECT_ERROR = void 0;
|
|
4
4
|
const util_1 = require("./util");
|
|
5
5
|
exports.NO_PROJECT_ERROR = (0, util_1.mcpError)('No active project was found. Use the `firebase_update_environment` tool to set the project directory to an absolute folder location containing a firebase.json config file. Alternatively, change the MCP server config to add [...,"--dir","/absolute/path/to/project/directory"] in its command-line arguments.', "PRECONDITION_FAILED");
|
|
6
|
-
function mcpAuthError() {
|
|
6
|
+
function mcpAuthError(skipADC) {
|
|
7
7
|
const cmd = (0, util_1.commandExistsSync)("firebase") ? "firebase" : "npx -y firebase-tools";
|
|
8
|
+
if (skipADC) {
|
|
9
|
+
return (0, util_1.mcpError)(`The user is not currently logged into the Firebase CLI, which is required to use this tool. Please instruct the user to execute this shell command to sign in.
|
|
10
|
+
\`\`\`sh
|
|
11
|
+
${cmd} login
|
|
12
|
+
\`\`\``);
|
|
13
|
+
}
|
|
8
14
|
return (0, util_1.mcpError)(`The user is not currently logged into the Firebase CLI, which is required to use this tool. Please instruct the user to execute this shell command to sign in or to configure [Application Default Credentials][ADC] on their machine.
|
|
9
15
|
\`\`\`sh
|
|
10
16
|
${cmd} login
|
package/lib/mcp/index.js
CHANGED
|
@@ -4,26 +4,26 @@ 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
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
7
|
+
const util_1 = require("./util");
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
const index_1 = require("./tools/index");
|
|
10
|
+
const configstore_1 = require("../configstore");
|
|
11
|
+
const command_1 = require("../command");
|
|
12
|
+
const requireAuth_1 = require("../requireAuth");
|
|
13
|
+
const projectUtils_1 = require("../projectUtils");
|
|
14
|
+
const errors_1 = require("./errors");
|
|
15
|
+
const track_1 = require("../track");
|
|
16
|
+
const config_1 = require("../config");
|
|
17
|
+
const rc_1 = require("../rc");
|
|
18
|
+
const hubClient_1 = require("../emulator/hubClient");
|
|
19
19
|
const node_fs_1 = require("node:fs");
|
|
20
|
-
const
|
|
21
|
-
const api = require("../api
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
20
|
+
const ensureApiEnabled_1 = require("../ensureApiEnabled");
|
|
21
|
+
const api = require("../api");
|
|
22
|
+
const logging_transport_1 = require("./logging-transport");
|
|
23
|
+
const env_1 = require("../env");
|
|
24
|
+
const timeout_1 = require("../timeout");
|
|
25
25
|
const SERVER_VERSION = "0.2.0";
|
|
26
|
-
const cmd = new
|
|
26
|
+
const cmd = new command_1.Command("experimental:mcp");
|
|
27
27
|
const orderedLogLevels = [
|
|
28
28
|
"debug",
|
|
29
29
|
"info",
|
|
@@ -38,12 +38,12 @@ class FirebaseMcpServer {
|
|
|
38
38
|
async trackGA4(event, params = {}) {
|
|
39
39
|
var _a, _b;
|
|
40
40
|
if (!this.clientInfo)
|
|
41
|
-
await (0,
|
|
41
|
+
await (0, timeout_1.timeoutFallback)(this.ready(), null, 2000);
|
|
42
42
|
const clientInfoParams = {
|
|
43
43
|
mcp_client_name: ((_a = this.clientInfo) === null || _a === void 0 ? void 0 : _a.name) || "<unknown-client>",
|
|
44
44
|
mcp_client_version: ((_b = this.clientInfo) === null || _b === void 0 ? void 0 : _b.version) || "<unknown-version>",
|
|
45
45
|
};
|
|
46
|
-
(0,
|
|
46
|
+
(0, track_1.trackGA4)(event, Object.assign(Object.assign({}, params), clientInfoParams));
|
|
47
47
|
}
|
|
48
48
|
constructor(options) {
|
|
49
49
|
this._ready = false;
|
|
@@ -89,22 +89,22 @@ class FirebaseMcpServer {
|
|
|
89
89
|
}
|
|
90
90
|
get clientName() {
|
|
91
91
|
var _a, _b;
|
|
92
|
-
return (_b = (_a = this.clientInfo) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : ((0,
|
|
92
|
+
return (_b = (_a = this.clientInfo) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : ((0, env_1.isFirebaseStudio)() ? "Firebase Studio" : "<unknown-client>");
|
|
93
93
|
}
|
|
94
94
|
get clientConfigKey() {
|
|
95
95
|
return `mcp.clientConfigs.${this.clientName}:${this.startupRoot || process.cwd()}`;
|
|
96
96
|
}
|
|
97
97
|
getStoredClientConfig() {
|
|
98
|
-
return
|
|
98
|
+
return configstore_1.configstore.get(this.clientConfigKey) || {};
|
|
99
99
|
}
|
|
100
100
|
updateStoredClientConfig(update) {
|
|
101
|
-
const config =
|
|
101
|
+
const config = configstore_1.configstore.get(this.clientConfigKey) || {};
|
|
102
102
|
const newConfig = Object.assign(Object.assign({}, config), update);
|
|
103
|
-
|
|
103
|
+
configstore_1.configstore.set(this.clientConfigKey, newConfig);
|
|
104
104
|
return newConfig;
|
|
105
105
|
}
|
|
106
106
|
async detectProjectRoot() {
|
|
107
|
-
await (0,
|
|
107
|
+
await (0, timeout_1.timeoutFallback)(this.ready(), null, 2000);
|
|
108
108
|
if (this.cachedProjectRoot)
|
|
109
109
|
return this.cachedProjectRoot;
|
|
110
110
|
const storedRoot = this.getStoredClientConfig().projectRoot;
|
|
@@ -119,8 +119,8 @@ class FirebaseMcpServer {
|
|
|
119
119
|
this.log("debug", "detecting active features of Firebase MCP server...");
|
|
120
120
|
const options = await this.resolveOptions();
|
|
121
121
|
const projectId = await this.getProjectId();
|
|
122
|
-
const detected = await Promise.all(
|
|
123
|
-
if (await (0,
|
|
122
|
+
const detected = await Promise.all(types_1.SERVER_FEATURES.map(async (f) => {
|
|
123
|
+
if (await (0, util_1.checkFeatureActive)(f, projectId, options))
|
|
124
124
|
return f;
|
|
125
125
|
return null;
|
|
126
126
|
}));
|
|
@@ -136,7 +136,7 @@ class FirebaseMcpServer {
|
|
|
136
136
|
if (!projectId) {
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
|
-
this.emulatorHubClient = new
|
|
139
|
+
this.emulatorHubClient = new hubClient_1.EmulatorHubClient(projectId);
|
|
140
140
|
return this.emulatorHubClient;
|
|
141
141
|
}
|
|
142
142
|
async getEmulatorUrl(emulatorType) {
|
|
@@ -154,7 +154,7 @@ class FirebaseMcpServer {
|
|
|
154
154
|
}
|
|
155
155
|
get availableTools() {
|
|
156
156
|
var _a;
|
|
157
|
-
return (0,
|
|
157
|
+
return (0, index_1.availableTools)(((_a = this.activeFeatures) === null || _a === void 0 ? void 0 : _a.length) ? this.activeFeatures : this.detectedFeatures);
|
|
158
158
|
}
|
|
159
159
|
getTool(name) {
|
|
160
160
|
return this.availableTools.find((t) => t.mcp.name === name) || null;
|
|
@@ -171,14 +171,14 @@ class FirebaseMcpServer {
|
|
|
171
171
|
return options;
|
|
172
172
|
}
|
|
173
173
|
async getProjectId() {
|
|
174
|
-
return (0,
|
|
174
|
+
return (0, projectUtils_1.getProjectId)(await this.resolveOptions());
|
|
175
175
|
}
|
|
176
176
|
async getAuthenticatedUser(skipAutoAuth = false) {
|
|
177
177
|
try {
|
|
178
178
|
this.log("debug", `calling requireAuth`);
|
|
179
|
-
const email = await (0,
|
|
179
|
+
const email = await (0, requireAuth_1.requireAuth)(await this.resolveOptions(), skipAutoAuth);
|
|
180
180
|
this.log("debug", `detected authenticated account: ${email || "<none>"}`);
|
|
181
|
-
return
|
|
181
|
+
return email !== null && email !== void 0 ? email : (skipAutoAuth ? null : "Application Default Credentials");
|
|
182
182
|
}
|
|
183
183
|
catch (e) {
|
|
184
184
|
this.log("debug", `error in requireAuth: ${e}`);
|
|
@@ -189,7 +189,7 @@ class FirebaseMcpServer {
|
|
|
189
189
|
await Promise.all([this.detectActiveFeatures(), this.detectProjectRoot()]);
|
|
190
190
|
const hasActiveProject = !!(await this.getProjectId());
|
|
191
191
|
await this.trackGA4("mcp_list_tools");
|
|
192
|
-
const skipAutoAuthForStudio = (0,
|
|
192
|
+
const skipAutoAuthForStudio = (0, env_1.isFirebaseStudio)();
|
|
193
193
|
this.log("debug", `skip auto-auth in studio environment: ${skipAutoAuthForStudio}`);
|
|
194
194
|
return {
|
|
195
195
|
tools: this.availableTools.map((t) => t.mcp),
|
|
@@ -212,24 +212,25 @@ class FirebaseMcpServer {
|
|
|
212
212
|
throw new Error(`Tool '${toolName}' could not be found.`);
|
|
213
213
|
if (tool.mcp.name !== "firebase_update_environment" &&
|
|
214
214
|
(!this.cachedProjectRoot || !(0, node_fs_1.existsSync)(this.cachedProjectRoot))) {
|
|
215
|
-
return (0,
|
|
215
|
+
return (0, util_1.mcpError)(`The current project directory '${this.cachedProjectRoot || "<NO PROJECT DIRECTORY FOUND>"}' does not exist. Please use the 'update_firebase_environment' tool to target a different project directory.`);
|
|
216
216
|
}
|
|
217
217
|
let projectId = await this.getProjectId();
|
|
218
218
|
if (((_a = tool.mcp._meta) === null || _a === void 0 ? void 0 : _a.requiresProject) && !projectId) {
|
|
219
|
-
return
|
|
219
|
+
return errors_1.NO_PROJECT_ERROR;
|
|
220
220
|
}
|
|
221
221
|
projectId = projectId || "";
|
|
222
|
-
const
|
|
222
|
+
const skipAutoAuthForStudio = (0, env_1.isFirebaseStudio)();
|
|
223
|
+
const accountEmail = await this.getAuthenticatedUser(skipAutoAuthForStudio);
|
|
223
224
|
if (((_b = tool.mcp._meta) === null || _b === void 0 ? void 0 : _b.requiresAuth) && !accountEmail) {
|
|
224
|
-
return (0,
|
|
225
|
+
return (0, errors_1.mcpAuthError)(skipAutoAuthForStudio);
|
|
225
226
|
}
|
|
226
227
|
if ((_c = tool.mcp._meta) === null || _c === void 0 ? void 0 : _c.requiresGemini) {
|
|
227
|
-
if (
|
|
228
|
-
await (0,
|
|
228
|
+
if (configstore_1.configstore.get("gemini")) {
|
|
229
|
+
await (0, ensureApiEnabled_1.ensure)(projectId, api.cloudAiCompanionOrigin(), "");
|
|
229
230
|
}
|
|
230
231
|
else {
|
|
231
|
-
if (!(await (0,
|
|
232
|
-
return (0,
|
|
232
|
+
if (!(await (0, ensureApiEnabled_1.check)(projectId, api.cloudAiCompanionOrigin(), ""))) {
|
|
233
|
+
return (0, errors_1.mcpGeminiError)(projectId);
|
|
233
234
|
}
|
|
234
235
|
}
|
|
235
236
|
}
|
|
@@ -237,8 +238,8 @@ class FirebaseMcpServer {
|
|
|
237
238
|
const toolsCtx = {
|
|
238
239
|
projectId: projectId,
|
|
239
240
|
host: this,
|
|
240
|
-
config:
|
|
241
|
-
rc: (0,
|
|
241
|
+
config: config_1.Config.load(options, true) || new config_1.Config({}, options),
|
|
242
|
+
rc: (0, rc_1.loadRC)(options),
|
|
242
243
|
accountEmail,
|
|
243
244
|
};
|
|
244
245
|
try {
|
|
@@ -254,12 +255,12 @@ class FirebaseMcpServer {
|
|
|
254
255
|
tool_name: toolName,
|
|
255
256
|
error: 1,
|
|
256
257
|
});
|
|
257
|
-
return (0,
|
|
258
|
+
return (0, util_1.mcpError)(err);
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
async start() {
|
|
261
262
|
const transport = process.env.FIREBASE_MCP_DEBUG_LOG
|
|
262
|
-
? new
|
|
263
|
+
? new logging_transport_1.LoggingStdioServerTransport(process.env.FIREBASE_MCP_DEBUG_LOG)
|
|
263
264
|
: new stdio_js_1.StdioServerTransport();
|
|
264
265
|
await this.server.connect(transport);
|
|
265
266
|
}
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.fetch_logs = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
exports.fetch_logs = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const apphosting_1 = require("../../../gcp/apphosting");
|
|
8
|
+
const utils_1 = require("../../../utils");
|
|
9
|
+
const error_1 = require("../../../error");
|
|
10
|
+
const run_1 = require("../../../gcp/run");
|
|
11
|
+
const cloudlogging_1 = require("../../../gcp/cloudlogging");
|
|
12
|
+
exports.fetch_logs = (0, tool_1.tool)({
|
|
13
13
|
name: "fetch_logs",
|
|
14
14
|
description: "Fetches the most recent logs for a specified App Hosting backend. If `buildLogs` is specified, the logs from the build process for the latest build are returned. The most recent logs are listed first.",
|
|
15
15
|
inputSchema: zod_1.z.object({
|
|
@@ -34,36 +34,36 @@ exports.fetch_logs = (0, tool_js_1.tool)({
|
|
|
34
34
|
var _a, _b;
|
|
35
35
|
location || (location = "");
|
|
36
36
|
if (!backendId) {
|
|
37
|
-
return (0,
|
|
37
|
+
return (0, util_1.toContent)(`backendId must be specified.`);
|
|
38
38
|
}
|
|
39
|
-
const backend = await (0,
|
|
40
|
-
const traffic = await (0,
|
|
39
|
+
const backend = await (0, apphosting_1.getBackend)(projectId, location, backendId);
|
|
40
|
+
const traffic = await (0, apphosting_1.getTraffic)(projectId, location, backendId);
|
|
41
41
|
const data = Object.assign(Object.assign({}, backend), { traffic });
|
|
42
42
|
if (buildLogs) {
|
|
43
|
-
const builds = await (0,
|
|
43
|
+
const builds = await (0, apphosting_1.listBuilds)(projectId, location, backendId);
|
|
44
44
|
builds.builds.sort((a, b) => new Date(a.createTime).getTime() - new Date(b.createTime).getTime());
|
|
45
|
-
const build = (0,
|
|
45
|
+
const build = (0, utils_1.last)(builds.builds);
|
|
46
46
|
const r = new RegExp(`region=${location}/([0-9a-f-]+)?`);
|
|
47
47
|
const match = r.exec((_a = build.buildLogsUri) !== null && _a !== void 0 ? _a : "");
|
|
48
48
|
if (!match) {
|
|
49
|
-
throw new
|
|
49
|
+
throw new error_1.FirebaseError("Unable to determine the build ID.");
|
|
50
50
|
}
|
|
51
51
|
const buildId = match[1];
|
|
52
52
|
const thirtyDaysAgo = new Date();
|
|
53
53
|
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
|
54
54
|
const timestampFilter = `timestamp >= "${thirtyDaysAgo.toISOString()}"`;
|
|
55
55
|
const filter = `resource.type="build" resource.labels.build_id="${buildId}" ${timestampFilter}`;
|
|
56
|
-
const entries = await (0,
|
|
56
|
+
const entries = await (0, cloudlogging_1.listEntries)(projectId, filter, 100, "asc");
|
|
57
57
|
if (!Array.isArray(entries) || !entries.length) {
|
|
58
|
-
return (0,
|
|
58
|
+
return (0, util_1.toContent)("No logs found.");
|
|
59
59
|
}
|
|
60
|
-
return (0,
|
|
60
|
+
return (0, util_1.toContent)(entries);
|
|
61
61
|
}
|
|
62
|
-
const serviceName = (_b = (0,
|
|
62
|
+
const serviceName = (_b = (0, utils_1.last)(data.managedResources)) === null || _b === void 0 ? void 0 : _b.runService.service;
|
|
63
63
|
if (!serviceName) {
|
|
64
|
-
throw new
|
|
64
|
+
throw new error_1.FirebaseError("Unable to get service name from managedResources.");
|
|
65
65
|
}
|
|
66
|
-
const serviceId = (0,
|
|
67
|
-
const logs = await (0,
|
|
68
|
-
return (0,
|
|
66
|
+
const serviceId = (0, utils_1.last)(serviceName.split("/"));
|
|
67
|
+
const logs = await (0, run_1.fetchServiceLogs)(projectId, serviceId);
|
|
68
|
+
return (0, util_1.toContent)(logs);
|
|
69
69
|
});
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.list_backends = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
exports.list_backends = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const apphosting_1 = require("../../../gcp/apphosting");
|
|
8
|
+
exports.list_backends = (0, tool_1.tool)({
|
|
9
9
|
name: "list_backends",
|
|
10
10
|
description: "Retrieves a list of App Hosting backends in the current project. An empty list means that there are no backends. " +
|
|
11
11
|
"The `uri` is the public URL of the backend. " +
|
|
@@ -34,18 +34,18 @@ exports.list_backends = (0, tool_js_1.tool)({
|
|
|
34
34
|
projectId = projectId || "";
|
|
35
35
|
if (!location)
|
|
36
36
|
location = "-";
|
|
37
|
-
const backends = await (0,
|
|
37
|
+
const backends = await (0, apphosting_1.listBackends)(projectId, location);
|
|
38
38
|
if (!backends.backends.length) {
|
|
39
|
-
return (0,
|
|
39
|
+
return (0, util_1.toContent)(`No backends exist for project ${projectId}${location !== "-" ? ` in ${location}` : ""}.`);
|
|
40
40
|
}
|
|
41
41
|
const promises = backends.backends.map(async (backend) => {
|
|
42
|
-
const { location, id } = (0,
|
|
42
|
+
const { location, id } = (0, apphosting_1.parseBackendName)(backend.name);
|
|
43
43
|
const [traffic, domains] = await Promise.all([
|
|
44
|
-
(0,
|
|
45
|
-
(0,
|
|
44
|
+
(0, apphosting_1.getTraffic)(projectId, location, id),
|
|
45
|
+
(0, apphosting_1.listDomains)(projectId, location, id),
|
|
46
46
|
]);
|
|
47
47
|
return Object.assign(Object.assign({}, backend), { traffic: traffic, domains: domains });
|
|
48
48
|
});
|
|
49
49
|
const data = await Promise.all(promises);
|
|
50
|
-
return (0,
|
|
50
|
+
return (0, util_1.toContent)(data);
|
|
51
51
|
});
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.disable_user = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
exports.disable_user = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const auth_1 = require("../../../gcp/auth");
|
|
8
|
+
exports.disable_user = (0, tool_1.tool)({
|
|
9
9
|
name: "disable_user",
|
|
10
10
|
description: "Disables or enables a user based on a UID.",
|
|
11
11
|
inputSchema: zod_1.z.object({
|
|
@@ -22,9 +22,9 @@ exports.disable_user = (0, tool_js_1.tool)({
|
|
|
22
22
|
requiresProject: true,
|
|
23
23
|
},
|
|
24
24
|
}, async ({ uid, disabled }, { projectId }) => {
|
|
25
|
-
const res = await (0,
|
|
25
|
+
const res = await (0, auth_1.disableUser)(projectId, uid, disabled);
|
|
26
26
|
if (res) {
|
|
27
|
-
return (0,
|
|
27
|
+
return (0, util_1.toContent)(`User ${uid} as been ${disabled ? "disabled" : "enabled"}`);
|
|
28
28
|
}
|
|
29
|
-
return (0,
|
|
29
|
+
return (0, util_1.toContent)(`Failed to ${disabled ? "disable" : "enable"} user ${uid}`);
|
|
30
30
|
});
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.get_user = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
exports.get_user = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const auth_1 = require("../../../gcp/auth");
|
|
8
|
+
exports.get_user = (0, tool_1.tool)({
|
|
9
9
|
name: "get_user",
|
|
10
10
|
description: "Retrieves a user based on an email address, phone number, or UID.",
|
|
11
11
|
inputSchema: zod_1.z.object({
|
|
@@ -32,7 +32,7 @@ exports.get_user = (0, tool_js_1.tool)({
|
|
|
32
32
|
},
|
|
33
33
|
}, async ({ email, phone_number, uid }, { projectId }) => {
|
|
34
34
|
if (email === undefined && phone_number === undefined && uid === undefined) {
|
|
35
|
-
return (0,
|
|
35
|
+
return (0, util_1.mcpError)(`No user identifier supplied in auth_get_user tool`);
|
|
36
36
|
}
|
|
37
|
-
return (0,
|
|
37
|
+
return (0, util_1.toContent)(await (0, auth_1.findUser)(projectId, email, phone_number, uid));
|
|
38
38
|
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.authTools = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
4
|
+
const get_user_1 = require("./get_user");
|
|
5
|
+
const disable_user_1 = require("./disable_user");
|
|
6
|
+
const set_claims_1 = require("./set_claims");
|
|
7
|
+
const set_sms_region_policy_1 = require("./set_sms_region_policy");
|
|
8
|
+
const list_users_1 = require("./list_users");
|
|
9
9
|
exports.authTools = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
get_user_1.get_user,
|
|
11
|
+
disable_user_1.disable_user,
|
|
12
|
+
list_users_1.list_users,
|
|
13
|
+
set_claims_1.set_claim,
|
|
14
|
+
set_sms_region_policy_1.set_sms_region_policy,
|
|
15
15
|
];
|
|
@@ -13,10 +13,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.list_users = void 0;
|
|
15
15
|
const zod_1 = require("zod");
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
exports.list_users = (0,
|
|
16
|
+
const tool_1 = require("../../tool");
|
|
17
|
+
const util_1 = require("../../util");
|
|
18
|
+
const auth_1 = require("../../../gcp/auth");
|
|
19
|
+
exports.list_users = (0, tool_1.tool)({
|
|
20
20
|
name: "list_users",
|
|
21
21
|
description: "Retrieves all users in the project up to the specified limit.",
|
|
22
22
|
inputSchema: zod_1.z.object({
|
|
@@ -38,10 +38,10 @@ exports.list_users = (0, tool_js_1.tool)({
|
|
|
38
38
|
if (!limit) {
|
|
39
39
|
limit = 100;
|
|
40
40
|
}
|
|
41
|
-
const users = await (0,
|
|
41
|
+
const users = await (0, auth_1.listUsers)(projectId, limit);
|
|
42
42
|
const usersPruned = users.map((user) => {
|
|
43
43
|
const { passwordHash, salt } = user, prunedUser = __rest(user, ["passwordHash", "salt"]);
|
|
44
44
|
return prunedUser;
|
|
45
45
|
});
|
|
46
|
-
return (0,
|
|
46
|
+
return (0, util_1.toContent)(usersPruned);
|
|
47
47
|
});
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.set_claim = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
exports.set_claim = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const auth_1 = require("../../../gcp/auth");
|
|
8
|
+
exports.set_claim = (0, tool_1.tool)({
|
|
9
9
|
name: "set_claim",
|
|
10
10
|
description: "Sets a custom claim on a specific user's account. Use to create trusted values associated with a user e.g. marking them as an admin. Claims are limited in size and should be succinct in name and value. Specify ONLY ONE OF `value` or `json_value` parameters.",
|
|
11
11
|
inputSchema: zod_1.z.object({
|
|
@@ -30,14 +30,14 @@ exports.set_claim = (0, tool_js_1.tool)({
|
|
|
30
30
|
},
|
|
31
31
|
}, async ({ uid, claim, value, json_value }, { projectId }) => {
|
|
32
32
|
if (value && json_value)
|
|
33
|
-
return (0,
|
|
33
|
+
return (0, util_1.mcpError)("Must supply only `value` or `json_value`, not both.");
|
|
34
34
|
if (json_value) {
|
|
35
35
|
try {
|
|
36
36
|
value = JSON.parse(json_value);
|
|
37
37
|
}
|
|
38
38
|
catch (e) {
|
|
39
|
-
return (0,
|
|
39
|
+
return (0, util_1.mcpError)(`Provided \`json_value\` was not valid JSON: ${json_value}`);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
return (0,
|
|
42
|
+
return (0, util_1.toContent)(await (0, auth_1.setCustomClaim)(projectId, uid, { [claim]: value }, { merge: true }));
|
|
43
43
|
});
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.set_sms_region_policy = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
exports.set_sms_region_policy = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const auth_1 = require("../../../gcp/auth");
|
|
8
|
+
exports.set_sms_region_policy = (0, tool_1.tool)({
|
|
9
9
|
name: "set_sms_region_policy",
|
|
10
10
|
description: "Sets an SMS Region Policy for Firebase Auth to restrict the regions which can receive text messages based on an ALLOW or DENY list of country codes. This policy will override any existing policies when set.",
|
|
11
11
|
inputSchema: zod_1.z.object({
|
|
@@ -30,7 +30,7 @@ exports.set_sms_region_policy = (0, tool_js_1.tool)({
|
|
|
30
30
|
return code.toUpperCase();
|
|
31
31
|
});
|
|
32
32
|
if (policy_type === "ALLOW") {
|
|
33
|
-
return (0,
|
|
33
|
+
return (0, util_1.toContent)(await (0, auth_1.setAllowSmsRegionPolicy)(projectId, country_codes));
|
|
34
34
|
}
|
|
35
|
-
return (0,
|
|
35
|
+
return (0, util_1.toContent)(await (0, auth_1.setDenySmsRegionPolicy)(projectId, country_codes));
|
|
36
36
|
});
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.consult_assistant = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
exports.consult_assistant = (0,
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const fdcExperience_1 = require("../../../gemini/fdcExperience");
|
|
8
|
+
exports.consult_assistant = (0, tool_1.tool)({
|
|
9
9
|
name: "consult_assistant",
|
|
10
10
|
description: "Send a question to an AI assistant specifically enhanced to answer Firebase questions.",
|
|
11
11
|
inputSchema: zod_1.z.object({
|
|
@@ -23,6 +23,6 @@ exports.consult_assistant = (0, tool_js_1.tool)({
|
|
|
23
23
|
requiresGemini: true,
|
|
24
24
|
},
|
|
25
25
|
}, async ({ prompt }, { projectId }) => {
|
|
26
|
-
const schema = await (0,
|
|
27
|
-
return (0,
|
|
26
|
+
const schema = await (0, fdcExperience_1.chatWithFirebase)(prompt, projectId);
|
|
27
|
+
return (0, util_1.toContent)(schema);
|
|
28
28
|
});
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.create_android_sha = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
5
|
+
const tool_1 = require("../../tool");
|
|
6
|
+
const util_1 = require("../../util");
|
|
7
|
+
const apps_1 = require("../../../management/apps");
|
|
8
8
|
function getCertHashType(shaHash) {
|
|
9
9
|
shaHash = shaHash.replace(/:/g, "");
|
|
10
10
|
const shaHashCount = shaHash.length;
|
|
11
11
|
if (shaHashCount === 40)
|
|
12
|
-
return
|
|
12
|
+
return apps_1.ShaCertificateType.SHA_1.toString();
|
|
13
13
|
if (shaHashCount === 64)
|
|
14
|
-
return
|
|
15
|
-
return
|
|
14
|
+
return apps_1.ShaCertificateType.SHA_256.toString();
|
|
15
|
+
return apps_1.ShaCertificateType.SHA_CERTIFICATE_TYPE_UNSPECIFIED.toString();
|
|
16
16
|
}
|
|
17
|
-
exports.create_android_sha = (0,
|
|
17
|
+
exports.create_android_sha = (0, tool_1.tool)({
|
|
18
18
|
name: "create_android_sha",
|
|
19
19
|
description: "Adds a SHA certificate hash to an existing Android app.",
|
|
20
20
|
inputSchema: zod_1.z.object({
|
|
@@ -32,9 +32,9 @@ exports.create_android_sha = (0, tool_js_1.tool)({
|
|
|
32
32
|
},
|
|
33
33
|
}, async ({ app_id, sha_hash }, { projectId }) => {
|
|
34
34
|
const certType = getCertHashType(sha_hash);
|
|
35
|
-
const shaCertificate = await (0,
|
|
35
|
+
const shaCertificate = await (0, apps_1.createAppAndroidSha)(projectId, app_id, {
|
|
36
36
|
shaHash: sha_hash,
|
|
37
37
|
certType,
|
|
38
38
|
});
|
|
39
|
-
return (0,
|
|
39
|
+
return (0, util_1.toContent)(Object.assign(Object.assign({}, shaCertificate), { message: `Successfully added ${certType} certificate to Android app ${app_id}` }));
|
|
40
40
|
});
|