firebase-tools 14.2.2 → 14.3.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.
Files changed (118) hide show
  1. package/lib/api.js +4 -2
  2. package/lib/apphosting/backend.js +12 -23
  3. package/lib/apphosting/config.js +9 -20
  4. package/lib/apphosting/githubConnections.js +52 -80
  5. package/lib/apphosting/repo.js +22 -36
  6. package/lib/apphosting/secrets/dialogs.js +2 -3
  7. package/lib/apphosting/utils.js +1 -3
  8. package/lib/auth.js +1 -4
  9. package/lib/commands/apphosting-backends-delete.js +5 -5
  10. package/lib/commands/apphosting-secrets-set.js +2 -6
  11. package/lib/commands/apps-create.js +2 -3
  12. package/lib/commands/apps-sdkconfig.js +2 -7
  13. package/lib/commands/database-import.js +4 -6
  14. package/lib/commands/database-remove.js +4 -6
  15. package/lib/commands/database-set.js +6 -6
  16. package/lib/commands/database-update.js +5 -5
  17. package/lib/commands/dataconnect-sql-shell.js +4 -6
  18. package/lib/commands/ext-dev-deprecate.js +1 -0
  19. package/lib/commands/ext-dev-init.js +3 -12
  20. package/lib/commands/ext-dev-register.js +2 -4
  21. package/lib/commands/ext-dev-undeprecate.js +1 -2
  22. package/lib/commands/ext-dev-usage.js +1 -3
  23. package/lib/commands/ext-export.js +1 -2
  24. package/lib/commands/ext-install.js +1 -0
  25. package/lib/commands/ext-sdk-install.js +1 -0
  26. package/lib/commands/ext-update.js +1 -0
  27. package/lib/commands/firestore-backups-delete.js +1 -2
  28. package/lib/commands/firestore-backups-schedules-delete.js +1 -2
  29. package/lib/commands/firestore-databases-delete.js +1 -5
  30. package/lib/commands/firestore-delete.js +6 -6
  31. package/lib/commands/functions-artifacts-setpolicy.js +12 -2
  32. package/lib/commands/functions-config-export.js +5 -9
  33. package/lib/commands/functions-delete.js +5 -5
  34. package/lib/commands/functions-deletegcfartifacts.js +4 -4
  35. package/lib/commands/functions-secrets-destroy.js +8 -10
  36. package/lib/commands/functions-secrets-prune.js +12 -13
  37. package/lib/commands/functions-secrets-set.js +11 -15
  38. package/lib/commands/hosting-channel-create.js +1 -2
  39. package/lib/commands/hosting-channel-delete.js +4 -4
  40. package/lib/commands/hosting-channel-open.js +2 -3
  41. package/lib/commands/hosting-disable.js +5 -5
  42. package/lib/commands/hosting-sites-delete.js +4 -4
  43. package/lib/commands/init.js +41 -58
  44. package/lib/commands/login.js +1 -5
  45. package/lib/commands/logout.js +2 -3
  46. package/lib/commands/open.js +1 -2
  47. package/lib/commands/projects-create.js +1 -2
  48. package/lib/commands/remoteconfig-rollback.js +5 -5
  49. package/lib/commands/use.js +110 -110
  50. package/lib/config.js +1 -2
  51. package/lib/dataconnect/build.js +2 -4
  52. package/lib/dataconnect/client.js +20 -1
  53. package/lib/dataconnect/schemaMigration.js +1 -6
  54. package/lib/deploy/functions/params.js +10 -17
  55. package/lib/deploy/functions/prompts.js +6 -28
  56. package/lib/emulator/commandUtils.js +4 -13
  57. package/lib/emulator/controller.js +1 -2
  58. package/lib/emulator/downloadableEmulators.js +12 -12
  59. package/lib/emulator/initEmulators.js +9 -20
  60. package/lib/extensions/askUserForEventsConfig.js +6 -15
  61. package/lib/extensions/askUserForParam.js +23 -52
  62. package/lib/extensions/checkProjectBilling.js +3 -9
  63. package/lib/extensions/diagnose.js +3 -6
  64. package/lib/extensions/extensionsHelper.js +17 -27
  65. package/lib/extensions/manifest.js +1 -2
  66. package/lib/extensions/tos.js +10 -2
  67. package/lib/extensions/utils.js +1 -10
  68. package/lib/frameworks/index.js +1 -2
  69. package/lib/frameworks/next/index.js +7 -4
  70. package/lib/frameworks/vite/index.js +1 -2
  71. package/lib/functions/secrets.js +14 -15
  72. package/lib/gcp/auth.js +29 -1
  73. package/lib/gif/fdcExperience.js +45 -0
  74. package/lib/hosting/interactive.js +2 -3
  75. package/lib/init/features/account.js +2 -4
  76. package/lib/init/features/database.js +11 -20
  77. package/lib/init/features/dataconnect/index.js +7 -14
  78. package/lib/init/features/dataconnect/sdk.js +15 -22
  79. package/lib/init/features/emulators.js +19 -41
  80. package/lib/init/features/firestore/index.js +2 -6
  81. package/lib/init/features/firestore/indexes.js +17 -31
  82. package/lib/init/features/firestore/rules.js +17 -31
  83. package/lib/init/features/functions/index.js +9 -16
  84. package/lib/init/features/functions/javascript.js +16 -30
  85. package/lib/init/features/functions/npm-dependencies.js +4 -8
  86. package/lib/init/features/functions/python.js +1 -3
  87. package/lib/init/features/functions/typescript.js +24 -43
  88. package/lib/init/features/genkit/index.js +23 -38
  89. package/lib/init/features/hosting/github.js +20 -51
  90. package/lib/init/features/hosting/index.js +36 -57
  91. package/lib/init/features/project.js +6 -16
  92. package/lib/init/features/remoteconfig.js +2 -8
  93. package/lib/init/features/storage.js +1 -3
  94. package/lib/management/apps.js +19 -44
  95. package/lib/management/projects.js +17 -28
  96. package/lib/mcp/index.js +12 -1
  97. package/lib/mcp/tools/auth/index.js +7 -1
  98. package/lib/mcp/tools/auth/set_sms_region_policy.js +36 -0
  99. package/lib/mcp/tools/core/consult_firebase_assistant.js +27 -0
  100. package/lib/mcp/tools/core/index.js +6 -1
  101. package/lib/mcp/tools/dataconnect/converter.js +33 -0
  102. package/lib/mcp/tools/dataconnect/generate_dataconnect_operation.js +33 -0
  103. package/lib/mcp/tools/dataconnect/generate_dataconnect_schema.js +25 -0
  104. package/lib/mcp/tools/dataconnect/get_dataconnect_connector.js +31 -0
  105. package/lib/mcp/tools/dataconnect/get_dataconnect_schema.js +31 -0
  106. package/lib/mcp/tools/dataconnect/index.js +11 -1
  107. package/lib/mcp/tools/firestore/{get_documents.js → get_firestore_documents.js} +5 -5
  108. package/lib/mcp/tools/firestore/index.js +7 -3
  109. package/lib/mcp/tools/firestore/{list_collections.js → list_firestore_collections.js} +3 -3
  110. package/lib/mcp/tools/index.js +2 -1
  111. package/lib/mcp/tools/storage/get_storage_rules.js +26 -0
  112. package/lib/mcp/tools/storage/index.js +5 -0
  113. package/lib/prompt.js +78 -65
  114. package/lib/requireTosAcceptance.js +4 -0
  115. package/lib/rulesDeploy.js +10 -15
  116. package/lib/track.js +1 -34
  117. package/lib/utils.js +27 -5
  118. package/package.json +2 -3
@@ -13,9 +13,7 @@ async function doSetup(setup, config) {
13
13
  logger_1.logger.info("uploads and downloads. You can keep these rules in your project directory");
14
14
  logger_1.logger.info("and publish them with " + clc.bold("firebase deploy") + ".");
15
15
  logger_1.logger.info();
16
- const storageRulesFile = await (0, prompt_1.promptOnce)({
17
- type: "input",
18
- name: "rules",
16
+ const storageRulesFile = await (0, prompt_1.input)({
19
17
  message: "What file should be used for Storage Rules?",
20
18
  default: "storage.rules",
21
19
  });
@@ -11,23 +11,20 @@ const logger_1 = require("../logger");
11
11
  const operation_poller_1 = require("../operation-poller");
12
12
  const types_1 = require("../dataconnect/types");
13
13
  const projectUtils_1 = require("../projectUtils");
14
- const prompt_1 = require("../prompt");
14
+ const prompt = require("../prompt");
15
15
  const projects_1 = require("./projects");
16
16
  const fileUtils_1 = require("../dataconnect/fileUtils");
17
17
  const utils_1 = require("../utils");
18
18
  const TIMEOUT_MILLIS = 30000;
19
19
  exports.APP_LIST_PAGE_SIZE = 100;
20
20
  const CREATE_APP_API_REQUEST_TIMEOUT_MILLIS = 15000;
21
- const DISPLAY_NAME_QUESTION = {
22
- type: "input",
23
- name: "displayName",
24
- default: "",
25
- message: "What would you like to call your app?",
26
- };
21
+ async function getDisplayName() {
22
+ return await prompt.input("What would you like to call your app?");
23
+ }
27
24
  async function getPlatform(appDir, config) {
28
25
  let targetPlatform = await (0, fileUtils_1.getPlatformFromFolder)(appDir);
29
26
  if (targetPlatform === types_1.Platform.NONE) {
30
- appDir = await (0, prompt_1.promptForDirectory)({
27
+ appDir = await (0, utils_1.promptForDirectory)({
31
28
  config,
32
29
  relativeTo: appDir,
33
30
  message: "We couldn't determine what kind of app you're using. Where is your app directory?",
@@ -46,9 +43,8 @@ async function getPlatform(appDir, config) {
46
43
  { name: "Web (JavaScript)", value: types_1.Platform.WEB },
47
44
  { name: "Android (Kotlin)", value: types_1.Platform.ANDROID },
48
45
  ];
49
- targetPlatform = await (0, prompt_1.promptOnce)({
46
+ targetPlatform = await prompt.select({
50
47
  message: "Which platform do you want to set up an SDK for? Note: We currently do not support automatically setting up C++ or Unity projects.",
51
- type: "list",
52
48
  choices: platforms,
53
49
  });
54
50
  }
@@ -69,21 +65,11 @@ https://firebase.google.com/docs/flutter/setup
69
65
  exports.getPlatform = getPlatform;
70
66
  async function initiateIosAppCreation(options) {
71
67
  if (!options.nonInteractive) {
72
- await (0, prompt_1.prompt)(options, [
73
- DISPLAY_NAME_QUESTION,
74
- {
75
- type: "input",
76
- default: "",
77
- name: "bundleId",
78
- message: "Please specify your iOS app bundle ID:",
79
- },
80
- {
81
- type: "input",
82
- default: "",
83
- name: "appStoreId",
84
- message: "Please specify your iOS app App Store ID:",
85
- },
86
- ]);
68
+ options.displayName = options.displayName || (await getDisplayName());
69
+ options.bundleId =
70
+ options.bundleId || (await prompt.input("Please specify your iOS app bundle ID:"));
71
+ options.appStoreId =
72
+ options.appStoreId || (await prompt.input("Please specify your iOS app App Store ID:"));
87
73
  }
88
74
  if (!options.bundleId) {
89
75
  throw new error_1.FirebaseError("Bundle ID for iOS app cannot be empty");
@@ -105,15 +91,9 @@ async function initiateIosAppCreation(options) {
105
91
  }
106
92
  async function initiateAndroidAppCreation(options) {
107
93
  if (!options.nonInteractive) {
108
- await (0, prompt_1.prompt)(options, [
109
- DISPLAY_NAME_QUESTION,
110
- {
111
- type: "input",
112
- default: "",
113
- name: "packageName",
114
- message: "Please specify your Android app package name:",
115
- },
116
- ]);
94
+ options.displayName = options.displayName || (await getDisplayName());
95
+ options.packageName =
96
+ options.packageName || (await prompt.input("Please specify your Android app package name:"));
117
97
  }
118
98
  if (!options.packageName) {
119
99
  throw new error_1.FirebaseError("Package name for Android app cannot be empty");
@@ -134,7 +114,7 @@ async function initiateAndroidAppCreation(options) {
134
114
  }
135
115
  async function initiateWebAppCreation(options) {
136
116
  if (!options.nonInteractive) {
137
- await (0, prompt_1.prompt)(options, [DISPLAY_NAME_QUESTION]);
117
+ options.displayName = options.displayName || (await getDisplayName());
138
118
  }
139
119
  if (!options.displayName) {
140
120
  throw new error_1.FirebaseError("Display name for Web app cannot be empty");
@@ -198,8 +178,7 @@ async function selectAppInteractively(apps, appPlatform) {
198
178
  value: app,
199
179
  };
200
180
  });
201
- return await (0, prompt_1.promptOnce)({
202
- type: "list",
181
+ return await prompt.select({
203
182
  message: `Select the ${appPlatform === AppPlatform.ANY ? "" : appPlatform + " "}` +
204
183
  "app to get the configuration data:",
205
184
  choices,
@@ -436,11 +415,7 @@ async function writeConfigToFile(filename, nonInteractive, fileContents) {
436
415
  if (nonInteractive) {
437
416
  throw new error_1.FirebaseError(`${filename} already exists`);
438
417
  }
439
- const overwrite = await (0, prompt_1.promptOnce)({
440
- type: "confirm",
441
- default: false,
442
- message: `${filename} already exists. Do you want to overwrite?`,
443
- });
418
+ const overwrite = await prompt.confirm(`${filename} already exists. Do you want to overwrite?`);
444
419
  if (!overwrite) {
445
420
  return false;
446
421
  }
@@ -544,7 +519,7 @@ async function findIntelligentPathForIOS(appDir, options) {
544
519
  }
545
520
  let outputPath = null;
546
521
  if (!options.nonInteractive) {
547
- outputPath = await (0, prompt_1.promptForDirectory)({
522
+ outputPath = await (0, utils_1.promptForDirectory)({
548
523
  config: options.config,
549
524
  message: `We weren't able to automatically determine the output directory. Where would you like to output your config file?`,
550
525
  relativeTo: appDir,
@@ -579,7 +554,7 @@ async function findIntelligentPathForAndroid(appDir, options) {
579
554
  return module;
580
555
  }
581
556
  if (!options.nonInteractive) {
582
- module = await (0, prompt_1.promptForDirectory)({
557
+ module = await (0, utils_1.promptForDirectory)({
583
558
  config: options.config,
584
559
  message: `We weren't able to automatically determine the output directory. Where would you like to output your config file?`,
585
560
  });
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getProject = exports.getFirebaseProject = exports.listFirebaseProjects = exports.getAvailableCloudProjectPage = exports.getFirebaseProjectPage = exports.addFirebaseToCloudProject = exports.createCloudProject = exports.promptAvailableProjectId = exports.getOrPromptProject = exports.addFirebaseToCloudProjectAndLog = exports.createFirebaseProjectAndLog = exports.PROJECTS_CREATE_QUESTIONS = exports.ProjectParentResourceType = void 0;
3
+ exports.getProject = exports.getFirebaseProject = exports.listFirebaseProjects = exports.getAvailableCloudProjectPage = exports.getFirebaseProjectPage = exports.addFirebaseToCloudProject = exports.createCloudProject = exports.promptAvailableProjectId = exports.getOrPromptProject = exports.addFirebaseToCloudProjectAndLog = exports.createFirebaseProjectAndLog = exports.promptProjectCreation = exports.ProjectParentResourceType = void 0;
4
4
  const clc = require("colorette");
5
5
  const ora = require("ora");
6
6
  const apiv2_1 = require("../apiv2");
7
7
  const error_1 = require("../error");
8
8
  const operation_poller_1 = require("../operation-poller");
9
- const prompt_1 = require("../prompt");
9
+ const prompt = require("../prompt");
10
10
  const api = require("../api");
11
11
  const logger_1 = require("../logger");
12
12
  const utils = require("../utils");
13
+ const ensureApiEnabled_1 = require("../ensureApiEnabled");
13
14
  const TIMEOUT_MILLIS = 30000;
14
15
  const MAXIMUM_PROMPT_LIST = 100;
15
16
  const PROJECT_LIST_PAGE_SIZE = 1000;
@@ -19,11 +20,8 @@ var ProjectParentResourceType;
19
20
  ProjectParentResourceType["ORGANIZATION"] = "organization";
20
21
  ProjectParentResourceType["FOLDER"] = "folder";
21
22
  })(ProjectParentResourceType = exports.ProjectParentResourceType || (exports.ProjectParentResourceType = {}));
22
- exports.PROJECTS_CREATE_QUESTIONS = [
23
- {
24
- type: "input",
25
- name: "projectId",
26
- default: "",
23
+ async function promptProjectCreation() {
24
+ const projectId = await prompt.input({
27
25
  message: "Please specify a unique project id " +
28
26
  `(${clc.yellow("warning")}: cannot be modified afterward) [6-30 characters]:\n`,
29
27
  validate: (projectId) => {
@@ -37,11 +35,9 @@ exports.PROJECTS_CREATE_QUESTIONS = [
37
35
  return true;
38
36
  }
39
37
  },
40
- },
41
- {
42
- type: "input",
43
- name: "displayName",
44
- default: (answers) => answers.projectId,
38
+ });
39
+ const displayName = await prompt.input({
40
+ default: projectId,
45
41
  message: "What would you like to call your project? (defaults to your project ID)",
46
42
  validate: (displayName) => {
47
43
  if (displayName.length < 4) {
@@ -54,8 +50,10 @@ exports.PROJECTS_CREATE_QUESTIONS = [
54
50
  return true;
55
51
  }
56
52
  },
57
- },
58
- ];
53
+ });
54
+ return { projectId, displayName };
55
+ }
56
+ exports.promptProjectCreation = promptProjectCreation;
59
57
  const firebaseAPIClient = new apiv2_1.Client({
60
58
  urlPrefix: api.firebaseApiOrigin(),
61
59
  auth: true,
@@ -130,10 +128,7 @@ async function selectProjectInteractively(pageSize = MAXIMUM_PROMPT_LIST) {
130
128
  return selectProjectFromList(projects);
131
129
  }
132
130
  async function selectProjectByPrompting() {
133
- const projectId = await (0, prompt_1.promptOnce)({
134
- type: "input",
135
- message: "Please input the project ID you would like to use:",
136
- });
131
+ const projectId = await prompt.input("Please input the project ID you would like to use:");
137
132
  return await getFirebaseProject(projectId);
138
133
  }
139
134
  async function selectProjectFromList(projects = []) {
@@ -150,9 +145,7 @@ async function selectProjectFromList(projects = []) {
150
145
  utils.logBullet(`Don't want to scroll through all your projects? If you know your project ID, ` +
151
146
  `you can initialize it directly using ${clc.bold("firebase init --project <project_id>")}.\n`);
152
147
  }
153
- const projectId = await (0, prompt_1.promptOnce)({
154
- type: "list",
155
- name: "id",
148
+ const projectId = await prompt.select({
156
149
  message: "Select a default Firebase project for this directory:",
157
150
  choices,
158
151
  });
@@ -172,10 +165,7 @@ async function promptAvailableProjectId() {
172
165
  throw new error_1.FirebaseError("There are no available Google Cloud projects to add Firebase services.");
173
166
  }
174
167
  if (nextPageToken) {
175
- return await (0, prompt_1.promptOnce)({
176
- type: "input",
177
- message: "Please input the ID of the Google Cloud Project you would like to add Firebase:",
178
- });
168
+ return await prompt.input("Please input the ID of the Google Cloud Project you would like to add Firebase:");
179
169
  }
180
170
  else {
181
171
  const choices = projects
@@ -188,9 +178,7 @@ async function promptAvailableProjectId() {
188
178
  };
189
179
  })
190
180
  .sort((a, b) => a.name.localeCompare(b.name));
191
- return await (0, prompt_1.promptOnce)({
192
- type: "list",
193
- name: "id",
181
+ return await prompt.select({
194
182
  message: "Select the Google Cloud Platform project you would like to add Firebase:",
195
183
  choices,
196
184
  });
@@ -348,6 +336,7 @@ async function getFirebaseProject(projectId) {
348
336
  }
349
337
  exports.getFirebaseProject = getFirebaseProject;
350
338
  async function getProject(projectId) {
339
+ await (0, ensureApiEnabled_1.ensure)(projectId, api.resourceManagerOrigin(), "firebase", true);
351
340
  const response = await resourceManagerClient.get(`/projects/${projectId}`);
352
341
  return response.body;
353
342
  }
package/lib/mcp/index.js CHANGED
@@ -12,6 +12,8 @@ const command_js_1 = require("../command.js");
12
12
  const requireAuth_js_1 = require("../requireAuth.js");
13
13
  const projectUtils_js_1 = require("../projectUtils.js");
14
14
  const errors_js_1 = require("./errors.js");
15
+ const track_js_1 = require("../track.js");
16
+ const config_js_1 = require("../config.js");
15
17
  const SERVER_VERSION = "0.0.1";
16
18
  const PROJECT_ROOT_KEY = "mcp.projectRoot";
17
19
  const cmd = new command_js_1.Command("experimental:mcp").before(requireAuth_js_1.requireAuth);
@@ -44,6 +46,7 @@ class FirebaseMcpServer {
44
46
  }
45
47
  async mcpListTools() {
46
48
  const hasActiveProject = !!(await this.getProjectId());
49
+ await (0, track_js_1.trackGA4)("mcp_list_tools", {});
47
50
  return {
48
51
  tools: this.availableTools.map((t) => t.mcp),
49
52
  _meta: {
@@ -95,9 +98,17 @@ class FirebaseMcpServer {
95
98
  if (((_b = tool.mcp._meta) === null || _b === void 0 ? void 0 : _b.requiresProject) && !projectId)
96
99
  return errors_js_1.NO_PROJECT_ERROR;
97
100
  try {
98
- return tool.fn(toolArgs, { projectId: await this.getProjectId(), host: this });
101
+ const config = config_js_1.Config.load({ cwd: this.projectRoot });
102
+ const res = await tool.fn(toolArgs, {
103
+ projectId: await this.getProjectId(),
104
+ host: this,
105
+ config,
106
+ });
107
+ await (0, track_js_1.trackGA4)("mcp_tool_call", { tool_name: toolName, error: res.isError ? 1 : 0 });
108
+ return res;
99
109
  }
100
110
  catch (err) {
111
+ await (0, track_js_1.trackGA4)("mcp_tool_call", { tool_name: toolName, error: 1 });
101
112
  return (0, util_js_1.mcpError)(err);
102
113
  }
103
114
  }
@@ -4,4 +4,10 @@ exports.authTools = void 0;
4
4
  const get_auth_user_js_1 = require("./get_auth_user.js");
5
5
  const disable_auth_user_js_1 = require("./disable_auth_user.js");
6
6
  const set_auth_claims_js_1 = require("./set_auth_claims.js");
7
- exports.authTools = [get_auth_user_js_1.get_auth_user, disable_auth_user_js_1.disable_auth_user, set_auth_claims_js_1.set_auth_claim];
7
+ const set_sms_region_policy_js_1 = require("./set_sms_region_policy.js");
8
+ exports.authTools = [
9
+ get_auth_user_js_1.get_auth_user,
10
+ disable_auth_user_js_1.disable_auth_user,
11
+ set_auth_claims_js_1.set_auth_claim,
12
+ set_sms_region_policy_js_1.set_sms_region_policy,
13
+ ];
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.set_sms_region_policy = void 0;
4
+ const zod_1 = require("zod");
5
+ const tool_js_1 = require("../../tool.js");
6
+ const util_js_1 = require("../../util.js");
7
+ const auth_js_1 = require("../../../gcp/auth.js");
8
+ exports.set_sms_region_policy = (0, tool_js_1.tool)({
9
+ name: "set_sms_region_policy",
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
+ inputSchema: zod_1.z.object({
12
+ policy_type: zod_1.z
13
+ .enum(["ALLOW", "DENY"])
14
+ .describe("with an ALLOW policy, only the specified country codes can use SMS auth. with a DENY policy, all countries can use SMS auth except the ones specified"),
15
+ country_codes: zod_1.z
16
+ .array(zod_1.z.string())
17
+ .describe("the country codes to allow or deny based on ISO 3166"),
18
+ }),
19
+ annotations: {
20
+ title: "Set the SMS Region Policy on your Firebase Project",
21
+ idempotentHint: true,
22
+ destructiveHint: true,
23
+ },
24
+ _meta: {
25
+ requiresProject: true,
26
+ requiresAuth: true,
27
+ },
28
+ }, async ({ policy_type, country_codes }, { projectId }) => {
29
+ country_codes = country_codes.map((code) => {
30
+ return code.toUpperCase();
31
+ });
32
+ if (policy_type === "ALLOW") {
33
+ return (0, util_js_1.toContent)(await (0, auth_js_1.setAllowSmsRegionPolicy)(projectId, country_codes));
34
+ }
35
+ return (0, util_js_1.toContent)(await (0, auth_js_1.setDenySmsRegionPolicy)(projectId, country_codes));
36
+ });
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.consult_firebase_assistant = void 0;
4
+ const zod_1 = require("zod");
5
+ const tool_js_1 = require("../../tool.js");
6
+ const util_js_1 = require("../../util.js");
7
+ const fdcExperience_js_1 = require("../../../gif/fdcExperience.js");
8
+ exports.consult_firebase_assistant = (0, tool_js_1.tool)({
9
+ name: "consult_firebase_assistant",
10
+ description: "Send a question to an AI assistant specifically enhanced to answer Firebase questions.",
11
+ inputSchema: zod_1.z.object({
12
+ prompt: zod_1.z
13
+ .string()
14
+ .describe("A description of what the user is trying to do or learn with Firebase."),
15
+ }),
16
+ annotations: {
17
+ title: "Helps answer queries and provide information related to Firebase.",
18
+ readOnlyHint: true,
19
+ },
20
+ _meta: {
21
+ requiresProject: true,
22
+ requiresAuth: true,
23
+ },
24
+ }, async ({ prompt }, { projectId }) => {
25
+ const schema = await (0, fdcExperience_js_1.chatWithFirebase)(prompt, projectId);
26
+ return (0, util_js_1.toContent)(schema);
27
+ });
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.coreTools = void 0;
4
+ const consult_firebase_assistant_1 = require("./consult_firebase_assistant");
4
5
  const get_firebase_directory_1 = require("./get_firebase_directory");
5
6
  const set_firebase_directory_1 = require("./set_firebase_directory");
6
- exports.coreTools = [get_firebase_directory_1.get_firebase_directory, set_firebase_directory_1.set_firebase_directory];
7
+ exports.coreTools = [
8
+ get_firebase_directory_1.get_firebase_directory,
9
+ set_firebase_directory_1.set_firebase_directory,
10
+ consult_firebase_assistant_1.consult_firebase_assistant,
11
+ ];
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sourceToText = exports.connectorToText = exports.schemaToText = void 0;
4
+ const js_yaml_1 = require("js-yaml");
5
+ function schemaToText(s) {
6
+ return ((0, js_yaml_1.dump)({
7
+ name: s.name,
8
+ datasources: s.datasources,
9
+ }) +
10
+ "\n\n" +
11
+ sourceToText(s.source));
12
+ }
13
+ exports.schemaToText = schemaToText;
14
+ function connectorToText(s) {
15
+ return ((0, js_yaml_1.dump)({
16
+ name: s.name,
17
+ }) +
18
+ "\n\n" +
19
+ sourceToText(s.source));
20
+ }
21
+ exports.connectorToText = connectorToText;
22
+ function sourceToText(s) {
23
+ var _a;
24
+ let output = "";
25
+ (_a = s.files) === null || _a === void 0 ? void 0 : _a.forEach((f) => {
26
+ output += `\n# ${f.path}`;
27
+ output += "\n```graphql\n";
28
+ output += `${f.content.trim()}\n`;
29
+ output += "```\n";
30
+ });
31
+ return output;
32
+ }
33
+ exports.sourceToText = sourceToText;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generate_dataconnect_operation = void 0;
4
+ const zod_1 = require("zod");
5
+ const tool_js_1 = require("../../tool.js");
6
+ const util_js_1 = require("../../util.js");
7
+ const fdcExperience_js_1 = require("../../../gif/fdcExperience.js");
8
+ const fileUtils_js_1 = require("../../../dataconnect/fileUtils.js");
9
+ exports.generate_dataconnect_operation = (0, tool_js_1.tool)({
10
+ name: "generate_dataconnect_operation",
11
+ description: "Generates a single Firebase Data Connect query or mutation based on the currently deployed schema and the provided prompt.",
12
+ inputSchema: zod_1.z.object({
13
+ prompt: zod_1.z
14
+ .string()
15
+ .describe("Write the prompt like you're talking to a person, describe the task you're trying to accomplish and give details that are specific to the users requst"),
16
+ serviceId: zod_1.z
17
+ .string()
18
+ .nullish()
19
+ .describe("Optional: Uses the serviceId from the firebase.json file if nothing provided. The serviceId of the deployed Firebase resource."),
20
+ }),
21
+ annotations: {
22
+ title: "Generate a Firebase Data Connect Operation on a deployed Firebase Data Connect Schema.",
23
+ readOnlyHint: true,
24
+ },
25
+ _meta: {
26
+ requiresProject: true,
27
+ requiresAuth: true,
28
+ },
29
+ }, async ({ prompt, serviceId }, { projectId, config }) => {
30
+ const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config, serviceId || undefined);
31
+ const schema = await (0, fdcExperience_js_1.generateOperation)(prompt, serviceInfo.serviceName, projectId);
32
+ return (0, util_js_1.toContent)(schema);
33
+ });
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generate_dataconnect_schema = void 0;
4
+ const zod_1 = require("zod");
5
+ const tool_js_1 = require("../../tool.js");
6
+ const util_js_1 = require("../../util.js");
7
+ const fdcExperience_js_1 = require("../../../gif/fdcExperience.js");
8
+ exports.generate_dataconnect_schema = (0, tool_js_1.tool)({
9
+ name: "generate_dataconnect_schema",
10
+ description: "Generates a Firebase Data Connect Schema based on the users description of an app.",
11
+ inputSchema: zod_1.z.object({
12
+ prompt: zod_1.z.string().describe("A description of an app that you are interested in building"),
13
+ }),
14
+ annotations: {
15
+ title: "Generate a Firebase Data Connect Schema for a new Firebase project.",
16
+ readOnlyHint: true,
17
+ },
18
+ _meta: {
19
+ requiresProject: true,
20
+ requiresAuth: true,
21
+ },
22
+ }, async ({ prompt }, { projectId }) => {
23
+ const schema = await (0, fdcExperience_js_1.generateSchema)(prompt, projectId);
24
+ return (0, util_js_1.toContent)(schema);
25
+ });
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.get_dataconnect_connector = void 0;
4
+ const zod_1 = require("zod");
5
+ const tool_js_1 = require("../../tool.js");
6
+ const util_js_1 = require("../../util.js");
7
+ const client = require("../../../dataconnect/client");
8
+ const fileUtils_js_1 = require("../../../dataconnect/fileUtils.js");
9
+ const converter_js_1 = require("./converter.js");
10
+ exports.get_dataconnect_connector = (0, tool_js_1.tool)({
11
+ name: "get_dataconnect_connector",
12
+ description: "Get the Firebase Data Connect Connectors in the project, which includes the pre-defined GraphQL queries accessible to client SDKs.",
13
+ inputSchema: zod_1.z.object({
14
+ serviceId: zod_1.z
15
+ .string()
16
+ .nullable()
17
+ .describe("The Firebase Data Connect service ID to look for. By default, it would pick the the service ID project directory."),
18
+ }),
19
+ annotations: {
20
+ title: "Obtain the Firebase Data Connect Connectors that's available in the backend",
21
+ readOnlyHint: true,
22
+ },
23
+ _meta: {
24
+ requiresProject: true,
25
+ requiresAuth: true,
26
+ },
27
+ }, async ({ serviceId }, { projectId, config }) => {
28
+ const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config, serviceId || undefined);
29
+ const connectors = await client.listConnectors(serviceInfo.serviceName, ["*"]);
30
+ return (0, util_js_1.toContent)(connectors.map(converter_js_1.connectorToText).join("\n\n"));
31
+ });
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.get_dataconnect_schema = void 0;
4
+ const zod_1 = require("zod");
5
+ const tool_js_1 = require("../../tool.js");
6
+ const util_js_1 = require("../../util.js");
7
+ const client = require("../../../dataconnect/client");
8
+ const fileUtils_js_1 = require("../../../dataconnect/fileUtils.js");
9
+ const converter_js_1 = require("./converter.js");
10
+ exports.get_dataconnect_schema = (0, tool_js_1.tool)({
11
+ name: "get_dataconnect_schema",
12
+ description: "List the Firebase Data Connect Schema in the project, which includes Cloud SQL data sources and the GraphQL Schema describing what tables are available.",
13
+ inputSchema: zod_1.z.object({
14
+ serviceId: zod_1.z
15
+ .string()
16
+ .nullable()
17
+ .describe("The Firebase Data Connect service ID to look for. By default, it would pick the the service ID project directory."),
18
+ }),
19
+ annotations: {
20
+ title: "Obtain the Firebase Data Connect Schemas that's available in the backend",
21
+ readOnlyHint: true,
22
+ },
23
+ _meta: {
24
+ requiresProject: true,
25
+ requiresAuth: true,
26
+ },
27
+ }, async ({ serviceId }, { projectId, config }) => {
28
+ const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config, serviceId || undefined);
29
+ const schemas = await client.listSchemas(serviceInfo.serviceName, ["*"]);
30
+ return (0, util_js_1.toContent)(schemas === null || schemas === void 0 ? void 0 : schemas.map(converter_js_1.schemaToText).join("\n\n"));
31
+ });
@@ -1,5 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dataconnectTools = void 0;
4
+ const generate_dataconnect_operation_js_1 = require("./generate_dataconnect_operation.js");
5
+ const generate_dataconnect_schema_js_1 = require("./generate_dataconnect_schema.js");
4
6
  const list_dataconnect_services_js_1 = require("./list_dataconnect_services.js");
5
- exports.dataconnectTools = [list_dataconnect_services_js_1.list_dataconnect_services];
7
+ const get_dataconnect_schema_js_1 = require("./get_dataconnect_schema.js");
8
+ const get_dataconnect_connector_js_1 = require("./get_dataconnect_connector.js");
9
+ exports.dataconnectTools = [
10
+ list_dataconnect_services_js_1.list_dataconnect_services,
11
+ generate_dataconnect_schema_js_1.generate_dataconnect_schema,
12
+ generate_dataconnect_operation_js_1.generate_dataconnect_operation,
13
+ get_dataconnect_schema_js_1.get_dataconnect_schema,
14
+ get_dataconnect_connector_js_1.get_dataconnect_connector,
15
+ ];
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.get_documents = void 0;
3
+ exports.get_firestore_documents = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const tool_js_1 = require("../../tool.js");
6
6
  const util_js_1 = require("../../util.js");
7
7
  const firestore_js_1 = require("../../../gcp/firestore.js");
8
8
  const converter_js_1 = require("./converter.js");
9
- exports.get_documents = (0, tool_js_1.tool)({
10
- name: "get_documents",
9
+ exports.get_firestore_documents = (0, tool_js_1.tool)({
10
+ name: "get_firestore_documents",
11
11
  description: "Retrieves one or more Firestore documents from a database in the current project by full document paths. Use this if you know the exact path of a document.",
12
12
  inputSchema: zod_1.z.object({
13
13
  paths: zod_1.z
@@ -23,10 +23,10 @@ exports.get_documents = (0, tool_js_1.tool)({
23
23
  requiresProject: true,
24
24
  },
25
25
  }, async ({ paths }, { projectId }) => {
26
- if (!paths.length)
26
+ if (!paths || !paths.length)
27
27
  return (0, util_js_1.mcpError)("Must supply at least one document path.");
28
28
  const { documents, missing } = await (0, firestore_js_1.getDocuments)(projectId, paths);
29
- if (missing.length > 0 && documents.length === 0) {
29
+ if (missing.length > 0 && documents && documents.length === 0) {
30
30
  return (0, util_js_1.mcpError)(`None of the specified documents were found in project '${projectId}'`);
31
31
  }
32
32
  const docs = documents.map(converter_js_1.firestoreDocumentToJson);
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.firestoreTools = void 0;
4
- const get_documents_1 = require("./get_documents");
4
+ const get_firestore_documents_1 = require("./get_firestore_documents");
5
5
  const get_firestore_rules_1 = require("./get_firestore_rules");
6
- const list_collections_1 = require("./list_collections");
7
- exports.firestoreTools = [list_collections_1.list_collections, get_documents_1.get_documents, get_firestore_rules_1.get_firestore_rules];
6
+ const list_firestore_collections_1 = require("./list_firestore_collections");
7
+ exports.firestoreTools = [
8
+ list_firestore_collections_1.list_firestore_collections,
9
+ get_firestore_documents_1.get_firestore_documents,
10
+ get_firestore_rules_1.get_firestore_rules,
11
+ ];
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.list_collections = void 0;
3
+ exports.list_firestore_collections = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const tool_js_1 = require("../../tool.js");
6
6
  const util_js_1 = require("../../util.js");
7
7
  const firestore_js_1 = require("../../../gcp/firestore.js");
8
8
  const errors_js_1 = require("../../errors.js");
9
- exports.list_collections = (0, tool_js_1.tool)({
10
- name: "list_collections",
9
+ exports.list_firestore_collections = (0, tool_js_1.tool)({
10
+ name: "list_firestore_collections",
11
11
  description: "Retrieves a list of collections from a Firestore database in the current project.",
12
12
  inputSchema: zod_1.z.object({
13
13
  document_path: zod_1.z
@@ -5,10 +5,11 @@ const index_js_1 = require("./auth/index.js");
5
5
  const index_js_2 = require("./dataconnect/index.js");
6
6
  const index_js_3 = require("./firestore/index.js");
7
7
  const index_js_4 = require("./project/index.js");
8
+ const index_js_5 = require("./storage/index.js");
8
9
  exports.tools = {
9
10
  project: index_js_4.projectTools,
10
11
  firestore: index_js_3.firestoreTools,
11
12
  auth: index_js_1.authTools,
12
13
  dataconnect: index_js_2.dataconnectTools,
13
- storage: [],
14
+ storage: index_js_5.storageTools,
14
15
  };