firebase-tools 14.3.1 → 14.5.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/api.js +10 -2
- package/lib/apphosting/backend.js +74 -18
- package/lib/apphosting/rollout.js +2 -2
- package/lib/apphosting/secrets/dialogs.js +4 -4
- package/lib/apphosting/secrets/index.js +2 -2
- package/lib/auth.js +22 -2
- package/lib/bin/cli.js +1 -33
- package/lib/bin/mcp.js +13 -2
- package/lib/checkValidTargetFilters.js +1 -0
- package/lib/command.js +3 -2
- package/lib/commands/apphosting-secrets-grantaccess.js +1 -1
- package/lib/commands/deploy.js +1 -0
- package/lib/commands/init.js +1 -4
- package/lib/commands/login-use.js +2 -11
- package/lib/commands/use.js +9 -8
- package/lib/config.js +43 -24
- package/lib/crashlytics/listTopIssues.js +44 -0
- package/lib/dataconnect/cloudAICompanionClient.js +72 -0
- package/lib/dataconnect/cloudAICompanionTypes.js +2 -0
- package/lib/dataconnect/fileUtils.js +11 -4
- package/lib/dataconnect/schemaMigration.js +6 -7
- package/lib/deploy/apphosting/args.js +2 -0
- package/lib/deploy/apphosting/deploy.js +77 -0
- package/lib/deploy/apphosting/index.js +9 -0
- package/lib/deploy/apphosting/prepare.js +147 -0
- package/lib/deploy/apphosting/release.js +56 -0
- package/lib/deploy/apphosting/util.js +65 -0
- package/lib/deploy/extensions/v2FunctionHelper.js +2 -1
- package/lib/deploy/firestore/deploy.js +47 -4
- package/lib/deploy/functions/checkIam.js +3 -3
- package/lib/deploy/functions/ensure.js +2 -1
- package/lib/deploy/functions/prepare.js +23 -16
- package/lib/deploy/functions/release/fabricator.js +4 -4
- package/lib/deploy/functions/release/index.js +1 -1
- package/lib/deploy/functions/runtimes/python/index.js +3 -0
- package/lib/deploy/functions/runtimes/supported/types.js +17 -11
- package/lib/deploy/index.js +2 -0
- package/lib/emulator/apphosting/index.js +1 -0
- package/lib/emulator/apphosting/serve.js +77 -3
- package/lib/emulator/auth/widget_ui.js +2 -1
- package/lib/emulator/controller.js +18 -4
- package/lib/emulator/dataconnectEmulator.js +9 -2
- package/lib/emulator/downloadableEmulatorInfo.json +81 -0
- package/lib/emulator/downloadableEmulators.js +28 -108
- package/lib/experiments.js +1 -1
- package/lib/extensions/manifest.js +2 -5
- package/lib/frameworks/angular/index.js +1 -1
- package/lib/frameworks/angular/utils.js +17 -6
- package/lib/fsAsync.js +9 -2
- package/lib/gcp/apphosting.js +13 -1
- package/lib/gcp/auth.js +32 -2
- package/lib/gcp/cloudbilling.js +12 -1
- package/lib/gcp/cloudfunctions.js +1 -2
- package/lib/gcp/cloudfunctionsv2.js +1 -2
- package/lib/gcp/cloudscheduler.js +2 -2
- package/lib/gcp/computeEngine.js +19 -2
- package/lib/gcp/devConnect.js +6 -1
- package/lib/gcp/firestore.js +24 -1
- package/lib/gcp/iam.js +1 -5
- package/lib/gcp/run.js +19 -1
- package/lib/gcp/storage.js +25 -1
- package/lib/index.js +1 -2
- package/lib/init/features/apphosting.js +85 -6
- package/lib/init/features/database.js +63 -52
- package/lib/init/features/dataconnect/index.js +78 -79
- package/lib/init/features/dataconnect/sdk.js +19 -6
- package/lib/init/features/emulators.js +12 -7
- package/lib/init/features/firestore/index.js +80 -39
- package/lib/init/features/firestore/indexes.js +29 -31
- package/lib/init/features/firestore/rules.js +35 -48
- package/lib/init/features/functions/index.js +2 -0
- package/lib/init/features/functions/javascript.js +3 -2
- package/lib/init/features/functions/typescript.js +3 -2
- package/lib/init/features/genkit/index.js +18 -10
- package/lib/init/features/hosting/github.js +3 -2
- package/lib/init/features/hosting/index.js +9 -8
- package/lib/init/features/index.js +10 -5
- package/lib/init/features/remoteconfig.js +3 -2
- package/lib/init/features/storage.js +31 -8
- package/lib/init/index.js +80 -24
- package/lib/logger.js +71 -7
- package/lib/management/projects.js +24 -1
- package/lib/mcp/errors.js +1 -1
- package/lib/mcp/index.js +142 -46
- package/lib/mcp/tool.js +2 -1
- package/lib/mcp/tools/apphosting/fetch_logs.js +69 -0
- package/lib/mcp/tools/apphosting/index.js +6 -0
- package/lib/mcp/tools/apphosting/list_backends.js +51 -0
- package/lib/mcp/tools/auth/get_user.js +16 -7
- package/lib/mcp/tools/auth/index.js +8 -1
- package/lib/mcp/tools/auth/list_users.js +47 -0
- package/lib/mcp/tools/auth/set_claims.js +20 -11
- package/lib/mcp/tools/auth/set_sms_region_policy.js +1 -1
- package/lib/mcp/tools/core/consult_assistant.js +1 -1
- package/lib/mcp/tools/core/create_android_sha.js +40 -0
- package/lib/mcp/tools/core/create_app.js +90 -0
- package/lib/mcp/tools/core/create_project.js +68 -0
- package/lib/mcp/tools/core/get_admin_sdk_config.js +26 -0
- package/lib/mcp/tools/core/get_environment.js +51 -0
- package/lib/mcp/tools/core/get_sdk_config.js +6 -3
- package/lib/mcp/tools/core/index.js +21 -2
- package/lib/mcp/tools/core/init.js +153 -0
- package/lib/mcp/tools/core/list_apps.js +10 -5
- package/lib/mcp/tools/core/list_projects.js +45 -0
- package/lib/mcp/tools/core/update_environment.js +55 -0
- package/lib/mcp/tools/crashlytics/index.js +5 -0
- package/lib/mcp/tools/crashlytics/list_top_issues.js +34 -0
- package/lib/mcp/tools/dataconnect/converter.js +13 -1
- package/lib/mcp/tools/dataconnect/emulator.js +32 -0
- package/lib/mcp/tools/dataconnect/execute_graphql.js +24 -8
- package/lib/mcp/tools/dataconnect/execute_graphql_read.js +24 -8
- package/lib/mcp/tools/dataconnect/execute_mutation.js +27 -15
- package/lib/mcp/tools/dataconnect/execute_query.js +26 -14
- package/lib/mcp/tools/dataconnect/generate_operation.js +7 -7
- package/lib/mcp/tools/dataconnect/generate_schema.js +1 -1
- package/lib/mcp/tools/dataconnect/get_connector.js +7 -7
- package/lib/mcp/tools/dataconnect/get_schema.js +5 -5
- package/lib/mcp/tools/dataconnect/index.js +1 -5
- package/lib/mcp/tools/dataconnect/list_services.js +1 -1
- package/lib/mcp/tools/firestore/converter.js +47 -1
- package/lib/mcp/tools/firestore/delete_document.js +37 -0
- package/lib/mcp/tools/firestore/index.js +12 -2
- package/lib/mcp/tools/firestore/list_collections.js +1 -6
- package/lib/mcp/tools/firestore/query_collection.js +122 -0
- package/lib/mcp/tools/index.js +37 -16
- package/lib/mcp/tools/messaging/index.js +5 -0
- package/lib/mcp/tools/messaging/send_message.js +42 -0
- package/lib/mcp/tools/remoteconfig/get_template.js +27 -0
- package/lib/mcp/tools/remoteconfig/index.js +7 -0
- package/lib/mcp/tools/remoteconfig/publish_template.js +34 -0
- package/lib/mcp/tools/remoteconfig/rollback_template.js +29 -0
- package/lib/mcp/tools/rules/get_rules.js +29 -0
- package/lib/mcp/tools/rules/validate_rules.js +98 -0
- package/lib/mcp/tools/storage/get_download_url.js +8 -5
- package/lib/mcp/tools/storage/index.js +7 -2
- package/lib/mcp/types.js +10 -1
- package/lib/mcp/util.js +165 -2
- package/lib/mcp/util.test.js +468 -0
- package/lib/messaging/interfaces.js +2 -0
- package/lib/messaging/sendMessage.js +48 -0
- package/lib/prompt.js +1 -1
- package/lib/remoteconfig/publish.js +39 -0
- package/lib/requireAuth.js +2 -2
- package/lib/track.js +1 -1
- package/lib/utils.js +2 -37
- package/package.json +2 -1
- package/schema/connector-yaml.json +12 -0
- package/schema/extension-yaml.json +17 -4
- package/schema/firebase-config.json +65 -10
- package/standalone/package.json +1 -1
- package/templates/dataconnect-prompts/operation-generation-cursor-windsurf-rule.txt +273 -0
- package/templates/dataconnect-prompts/schema-generation-cursor-windsurf-rule.txt +653 -0
- package/templates/genkit/firebase.1.0.0.template +5 -0
- package/templates/init/firestore/firestore.rules +2 -0
- package/templates/init/functions/javascript/package.lint.json +1 -1
- package/templates/init/functions/javascript/package.nolint.json +1 -1
- package/templates/init/functions/typescript/package.lint.json +2 -2
- package/templates/init/functions/typescript/package.nolint.json +3 -3
- package/lib/mcp/tools/directory/get_project_directory.js +0 -20
- package/lib/mcp/tools/directory/index.js +0 -6
- package/lib/mcp/tools/directory/set_project_directory.js +0 -33
- package/lib/mcp/tools/firestore/get_rules.js +0 -26
|
@@ -12,22 +12,22 @@ exports.generate_operation = (0, tool_js_1.tool)({
|
|
|
12
12
|
inputSchema: zod_1.z.object({
|
|
13
13
|
prompt: zod_1.z
|
|
14
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
|
|
16
|
-
|
|
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 request"),
|
|
16
|
+
service_id: zod_1.z
|
|
17
17
|
.string()
|
|
18
|
-
.
|
|
19
|
-
.describe("Optional: Uses the
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Optional: Uses the service ID from the firebase.json file if nothing provided. The service ID of the deployed Firebase resource."),
|
|
20
20
|
}),
|
|
21
21
|
annotations: {
|
|
22
|
-
title: "Generate
|
|
22
|
+
title: "Generate Data Connect Operation",
|
|
23
23
|
readOnlyHint: true,
|
|
24
24
|
},
|
|
25
25
|
_meta: {
|
|
26
26
|
requiresProject: true,
|
|
27
27
|
requiresAuth: true,
|
|
28
28
|
},
|
|
29
|
-
}, async ({ prompt,
|
|
30
|
-
const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config,
|
|
29
|
+
}, async ({ prompt, service_id }, { projectId, config }) => {
|
|
30
|
+
const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config, service_id || undefined);
|
|
31
31
|
const schema = await (0, fdcExperience_js_1.generateOperation)(prompt, serviceInfo.serviceName, projectId);
|
|
32
32
|
return (0, util_js_1.toContent)(schema);
|
|
33
33
|
});
|
|
@@ -12,7 +12,7 @@ exports.generate_schema = (0, tool_js_1.tool)({
|
|
|
12
12
|
prompt: zod_1.z.string().describe("A description of an app that you are interested in building"),
|
|
13
13
|
}),
|
|
14
14
|
annotations: {
|
|
15
|
-
title: "Generate
|
|
15
|
+
title: "Generate Data Connect Schema",
|
|
16
16
|
readOnlyHint: true,
|
|
17
17
|
},
|
|
18
18
|
_meta: {
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.get_connectors = 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 client = require("../../../dataconnect/client.js");
|
|
8
8
|
const fileUtils_js_1 = require("../../../dataconnect/fileUtils.js");
|
|
9
9
|
const converter_js_1 = require("./converter.js");
|
|
10
|
-
exports.
|
|
11
|
-
name: "
|
|
10
|
+
exports.get_connectors = (0, tool_js_1.tool)({
|
|
11
|
+
name: "get_connectors",
|
|
12
12
|
description: "Get the Firebase Data Connect Connectors in the project, which includes the pre-defined GraphQL queries accessible to client SDKs.",
|
|
13
13
|
inputSchema: zod_1.z.object({
|
|
14
|
-
|
|
14
|
+
service_id: zod_1.z
|
|
15
15
|
.string()
|
|
16
16
|
.nullable()
|
|
17
17
|
.describe("The Firebase Data Connect service ID to look for. If there is only one service defined in firebase.json, this can be omitted and that will be used."),
|
|
18
18
|
}),
|
|
19
19
|
annotations: {
|
|
20
|
-
title: "
|
|
20
|
+
title: "Get Data Connect Connectors",
|
|
21
21
|
readOnlyHint: true,
|
|
22
22
|
},
|
|
23
23
|
_meta: {
|
|
24
24
|
requiresProject: true,
|
|
25
25
|
requiresAuth: true,
|
|
26
26
|
},
|
|
27
|
-
}, async ({
|
|
28
|
-
const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config,
|
|
27
|
+
}, async ({ service_id }, { projectId, config }) => {
|
|
28
|
+
const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config, service_id || undefined);
|
|
29
29
|
const connectors = await client.listConnectors(serviceInfo.serviceName, ["*"]);
|
|
30
30
|
return (0, util_js_1.toContent)(connectors.map(converter_js_1.connectorToText).join("\n\n"));
|
|
31
31
|
});
|
|
@@ -9,23 +9,23 @@ const fileUtils_js_1 = require("../../../dataconnect/fileUtils.js");
|
|
|
9
9
|
const converter_js_1 = require("./converter.js");
|
|
10
10
|
exports.get_schema = (0, tool_js_1.tool)({
|
|
11
11
|
name: "get_schema",
|
|
12
|
-
description: "
|
|
12
|
+
description: "Retrieve information about the Firebase Data Connect Schema in the project, including Cloud SQL data sources and the GraphQL Schema describing the data model.",
|
|
13
13
|
inputSchema: zod_1.z.object({
|
|
14
|
-
|
|
14
|
+
service_id: zod_1.z
|
|
15
15
|
.string()
|
|
16
16
|
.nullable()
|
|
17
17
|
.describe("The Firebase Data Connect service ID to look for. If there is only one service defined in firebase.json, this can be omitted and that will be used."),
|
|
18
18
|
}),
|
|
19
19
|
annotations: {
|
|
20
|
-
title: "
|
|
20
|
+
title: "Get Data Connect Schemas",
|
|
21
21
|
readOnlyHint: true,
|
|
22
22
|
},
|
|
23
23
|
_meta: {
|
|
24
24
|
requiresProject: true,
|
|
25
25
|
requiresAuth: true,
|
|
26
26
|
},
|
|
27
|
-
}, async ({
|
|
28
|
-
const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config,
|
|
27
|
+
}, async ({ service_id }, { projectId, config }) => {
|
|
28
|
+
const serviceInfo = await (0, fileUtils_js_1.pickService)(projectId, config, service_id || undefined);
|
|
29
29
|
const schemas = await client.listSchemas(serviceInfo.serviceName, ["*"]);
|
|
30
30
|
return (0, util_js_1.toContent)(schemas === null || schemas === void 0 ? void 0 : schemas.map(converter_js_1.schemaToText).join("\n\n"));
|
|
31
31
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.dataconnectTools = void 0;
|
|
4
|
-
const generate_operation_js_1 = require("./generate_operation.js");
|
|
5
|
-
const generate_schema_js_1 = require("./generate_schema.js");
|
|
6
4
|
const list_services_js_1 = require("./list_services.js");
|
|
7
5
|
const get_schema_js_1 = require("./get_schema.js");
|
|
8
6
|
const get_connector_js_1 = require("./get_connector.js");
|
|
@@ -12,10 +10,8 @@ const execute_query_js_1 = require("./execute_query.js");
|
|
|
12
10
|
const execute_mutation_js_1 = require("./execute_mutation.js");
|
|
13
11
|
exports.dataconnectTools = [
|
|
14
12
|
list_services_js_1.list_services,
|
|
15
|
-
generate_schema_js_1.generate_schema,
|
|
16
|
-
generate_operation_js_1.generate_operation,
|
|
17
13
|
get_schema_js_1.get_schema,
|
|
18
|
-
get_connector_js_1.
|
|
14
|
+
get_connector_js_1.get_connectors,
|
|
19
15
|
execute_graphql_js_1.execute_graphql,
|
|
20
16
|
execute_graphql_read_js_1.execute_graphql_read,
|
|
21
17
|
execute_mutation_js_1.execute_mutation,
|
|
@@ -10,7 +10,7 @@ exports.list_services = (0, tool_js_1.tool)({
|
|
|
10
10
|
description: "List the Firebase Data Connect services available in the current project.",
|
|
11
11
|
inputSchema: zod_1.z.object({}),
|
|
12
12
|
annotations: {
|
|
13
|
-
title: "List
|
|
13
|
+
title: "List Data Connect Services",
|
|
14
14
|
readOnlyHint: true,
|
|
15
15
|
},
|
|
16
16
|
_meta: {
|
|
@@ -1,7 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.firestoreDocumentToJson = void 0;
|
|
3
|
+
exports.firestoreDocumentToJson = exports.convertInputToValue = void 0;
|
|
4
4
|
const logger_1 = require("../../../logger");
|
|
5
|
+
function convertInputToValue(inputValue) {
|
|
6
|
+
if (inputValue === null) {
|
|
7
|
+
return { nullValue: null };
|
|
8
|
+
}
|
|
9
|
+
else if (typeof inputValue === "boolean") {
|
|
10
|
+
return { booleanValue: inputValue };
|
|
11
|
+
}
|
|
12
|
+
else if (typeof inputValue === "number") {
|
|
13
|
+
if (Number.isInteger(inputValue)) {
|
|
14
|
+
return { integerValue: inputValue.toString() };
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return { doubleValue: inputValue };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (typeof inputValue === "string") {
|
|
21
|
+
return { stringValue: inputValue };
|
|
22
|
+
}
|
|
23
|
+
else if (Array.isArray(inputValue)) {
|
|
24
|
+
const arrayValue = {
|
|
25
|
+
values: inputValue.map((item) => convertInputToValue(item)),
|
|
26
|
+
};
|
|
27
|
+
return { arrayValue: arrayValue };
|
|
28
|
+
}
|
|
29
|
+
else if (typeof inputValue === "object") {
|
|
30
|
+
if (inputValue.hasOwnProperty("latitude") &&
|
|
31
|
+
typeof inputValue.latitude === "number" &&
|
|
32
|
+
inputValue.hasOwnProperty("longitude") &&
|
|
33
|
+
typeof inputValue.longitude === "number") {
|
|
34
|
+
return { geoPointValue: inputValue };
|
|
35
|
+
}
|
|
36
|
+
const mapValue = {
|
|
37
|
+
fields: {},
|
|
38
|
+
};
|
|
39
|
+
for (const key in inputValue) {
|
|
40
|
+
if (Object.prototype.hasOwnProperty.call(inputValue, key)) {
|
|
41
|
+
if (mapValue.fields) {
|
|
42
|
+
mapValue.fields[key] = convertInputToValue(inputValue[key]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { mapValue: mapValue };
|
|
47
|
+
}
|
|
48
|
+
return { nullValue: null };
|
|
49
|
+
}
|
|
50
|
+
exports.convertInputToValue = convertInputToValue;
|
|
5
51
|
function firestoreValueToJson(firestoreValue) {
|
|
6
52
|
var _a, _b;
|
|
7
53
|
if ("nullValue" in firestoreValue)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.delete_document = 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 firestore_js_1 = require("../../../gcp/firestore.js");
|
|
8
|
+
const delete_js_1 = require("../../../firestore/delete.js");
|
|
9
|
+
exports.delete_document = (0, tool_js_1.tool)({
|
|
10
|
+
name: "delete_document",
|
|
11
|
+
description: "Deletes a 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
|
+
inputSchema: zod_1.z.object({
|
|
13
|
+
path: zod_1.z
|
|
14
|
+
.string()
|
|
15
|
+
.describe("A document path (e.g. `collectionName/documentId` or `parentCollection/parentDocument/collectionName/documentId`)"),
|
|
16
|
+
}),
|
|
17
|
+
annotations: {
|
|
18
|
+
title: "Delete Firestore document",
|
|
19
|
+
destructiveHint: true,
|
|
20
|
+
},
|
|
21
|
+
_meta: {
|
|
22
|
+
requiresAuth: true,
|
|
23
|
+
requiresProject: true,
|
|
24
|
+
},
|
|
25
|
+
}, async ({ path }, { projectId }) => {
|
|
26
|
+
const { documents, missing } = await (0, firestore_js_1.getDocuments)(projectId, [path]);
|
|
27
|
+
if (missing.length > 0 && documents && documents.length === 0) {
|
|
28
|
+
return (0, util_js_1.mcpError)(`None of the specified documents were found in project '${projectId}'`);
|
|
29
|
+
}
|
|
30
|
+
const firestoreDelete = new delete_js_1.FirestoreDelete(projectId, path, { databaseId: "(default)" });
|
|
31
|
+
await firestoreDelete.execute();
|
|
32
|
+
const { documents: postDeleteDocuments, missing: postDeleteMissing } = await (0, firestore_js_1.getDocuments)(projectId, [path]);
|
|
33
|
+
if (postDeleteMissing.length > 0 && postDeleteDocuments.length === 0) {
|
|
34
|
+
return (0, util_js_1.toContent)(`Successfully removed document located at : ${path}`);
|
|
35
|
+
}
|
|
36
|
+
return (0, util_js_1.mcpError)(`Failed to remove document located at : ${path}`);
|
|
37
|
+
});
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.firestoreTools = void 0;
|
|
4
|
+
const delete_document_1 = require("./delete_document");
|
|
4
5
|
const get_documents_1 = require("./get_documents");
|
|
5
|
-
const get_rules_1 = require("./get_rules");
|
|
6
6
|
const list_collections_1 = require("./list_collections");
|
|
7
|
-
|
|
7
|
+
const query_collection_1 = require("./query_collection");
|
|
8
|
+
const validate_rules_1 = require("../rules/validate_rules");
|
|
9
|
+
const get_rules_1 = require("../rules/get_rules");
|
|
10
|
+
exports.firestoreTools = [
|
|
11
|
+
delete_document_1.delete_document,
|
|
12
|
+
get_documents_1.get_documents,
|
|
13
|
+
list_collections_1.list_collections,
|
|
14
|
+
query_collection_1.query_collection,
|
|
15
|
+
(0, get_rules_1.getRulesTool)("Firestore", "cloud.firestore"),
|
|
16
|
+
(0, validate_rules_1.validateRulesTool)("Firestore"),
|
|
17
|
+
];
|
|
@@ -9,12 +9,7 @@ const errors_js_1 = require("../../errors.js");
|
|
|
9
9
|
exports.list_collections = (0, tool_js_1.tool)({
|
|
10
10
|
name: "list_collections",
|
|
11
11
|
description: "Retrieves a list of collections from a Firestore database in the current project.",
|
|
12
|
-
inputSchema: zod_1.z.object({
|
|
13
|
-
document_path: zod_1.z
|
|
14
|
-
.string()
|
|
15
|
-
.nullish()
|
|
16
|
-
.describe("a parent document to list subcollections under. only needed for subcollections, omit to list top-level collections"),
|
|
17
|
-
}),
|
|
12
|
+
inputSchema: zod_1.z.object({}),
|
|
18
13
|
annotations: {
|
|
19
14
|
title: "List Firestore collections",
|
|
20
15
|
readOnlyHint: true,
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.query_collection = 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 firestore_js_1 = require("../../../gcp/firestore.js");
|
|
8
|
+
const converter_js_1 = require("./converter.js");
|
|
9
|
+
exports.query_collection = (0, tool_js_1.tool)({
|
|
10
|
+
name: "query_collection",
|
|
11
|
+
description: "Retrieves one or more Firestore documents from a collection is a database in the current project by a collection with a full document path. Use this if you know the exact path of a collection and the filtering clause you would like for the document.",
|
|
12
|
+
inputSchema: zod_1.z.object({
|
|
13
|
+
collection_path: zod_1.z
|
|
14
|
+
.string()
|
|
15
|
+
.describe("A collection path (e.g. `collectionName/` or `parentCollection/parentDocument/collectionName`)"),
|
|
16
|
+
filters: zod_1.z
|
|
17
|
+
.object({
|
|
18
|
+
compare_value: zod_1.z
|
|
19
|
+
.object({
|
|
20
|
+
string_value: zod_1.z.string().optional().describe("The string value to compare against."),
|
|
21
|
+
boolean_value: zod_1.z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("The boolean value to compare against."),
|
|
25
|
+
string_array_value: zod_1.z
|
|
26
|
+
.array(zod_1.z.string())
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("The string value to compare against."),
|
|
29
|
+
integer_value: zod_1.z
|
|
30
|
+
.number()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("The integer value to compare against."),
|
|
33
|
+
double_value: zod_1.z.number().optional().describe("The double value to compare against."),
|
|
34
|
+
})
|
|
35
|
+
.describe("One and only one value may be specified per filters object."),
|
|
36
|
+
field: zod_1.z.string().describe("the field searching against"),
|
|
37
|
+
op: zod_1.z
|
|
38
|
+
.enum([
|
|
39
|
+
"OPERATOR_UNSPECIFIED",
|
|
40
|
+
"LESS_THAN",
|
|
41
|
+
"LESS_THAN_OR_EQUAL",
|
|
42
|
+
"GREATER_THAN",
|
|
43
|
+
"GREATER_THAN_OR_EQUAL",
|
|
44
|
+
"EQUAL",
|
|
45
|
+
"NOT_EQUAL",
|
|
46
|
+
"ARRAY_CONTAINS",
|
|
47
|
+
"ARRAY_CONTAINS_ANY",
|
|
48
|
+
"IN",
|
|
49
|
+
"NOT_IN",
|
|
50
|
+
])
|
|
51
|
+
.describe("the equality evaluator to use"),
|
|
52
|
+
})
|
|
53
|
+
.array()
|
|
54
|
+
.describe("the multiple filters to use in querying against the existing collection."),
|
|
55
|
+
order: zod_1.z
|
|
56
|
+
.object({
|
|
57
|
+
orderBy: zod_1.z.string().describe("the field to order by"),
|
|
58
|
+
orderByDirection: zod_1.z
|
|
59
|
+
.enum(["ASCENDING", "DESCENDING"])
|
|
60
|
+
.describe("the direction to order values"),
|
|
61
|
+
})
|
|
62
|
+
.optional()
|
|
63
|
+
.describe("Specifies the field and direction to order the results. If not provided, the order is undefined."),
|
|
64
|
+
limit: zod_1.z
|
|
65
|
+
.number()
|
|
66
|
+
.describe("The maximum amount of records to return. Default is 10.")
|
|
67
|
+
.optional(),
|
|
68
|
+
}),
|
|
69
|
+
annotations: {
|
|
70
|
+
title: "Query Firestore collection",
|
|
71
|
+
readOnlyHint: true,
|
|
72
|
+
},
|
|
73
|
+
_meta: {
|
|
74
|
+
requiresAuth: true,
|
|
75
|
+
requiresProject: true,
|
|
76
|
+
},
|
|
77
|
+
}, async ({ collection_path, filters, order, limit }, { projectId }) => {
|
|
78
|
+
if (!collection_path || !collection_path.length)
|
|
79
|
+
return (0, util_js_1.mcpError)("Must supply at least one collection path.");
|
|
80
|
+
const structuredQuery = {
|
|
81
|
+
from: [{ collectionId: collection_path, allDescendants: false }],
|
|
82
|
+
};
|
|
83
|
+
if (filters) {
|
|
84
|
+
structuredQuery.where = {
|
|
85
|
+
compositeFilter: {
|
|
86
|
+
op: "AND",
|
|
87
|
+
filters: filters.map((f) => {
|
|
88
|
+
if (f.compare_value.boolean_value &&
|
|
89
|
+
f.compare_value.double_value &&
|
|
90
|
+
f.compare_value.integer_value &&
|
|
91
|
+
f.compare_value.string_array_value &&
|
|
92
|
+
f.compare_value.string_value) {
|
|
93
|
+
throw (0, util_js_1.mcpError)("One and only one value may be specified per filters object.");
|
|
94
|
+
}
|
|
95
|
+
const out = Object.entries(f.compare_value).filter(([, value]) => {
|
|
96
|
+
return value !== null && value !== undefined;
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
fieldFilter: {
|
|
100
|
+
field: { fieldPath: f.field },
|
|
101
|
+
op: f.op,
|
|
102
|
+
value: (0, converter_js_1.convertInputToValue)(out[0][1]),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (order) {
|
|
110
|
+
structuredQuery.orderBy = [
|
|
111
|
+
{
|
|
112
|
+
field: { fieldPath: order.orderBy },
|
|
113
|
+
direction: order.orderByDirection,
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
structuredQuery.limit = limit ? limit : 10;
|
|
118
|
+
const { documents } = await (0, firestore_js_1.queryCollection)(projectId, structuredQuery);
|
|
119
|
+
const docs = documents.map(converter_js_1.firestoreDocumentToJson);
|
|
120
|
+
const docsContent = (0, util_js_1.toContent)(docs);
|
|
121
|
+
return docsContent;
|
|
122
|
+
});
|
package/lib/mcp/tools/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.availableTools = void 0;
|
|
3
|
+
exports.markdownDocsOfTools = exports.availableTools = void 0;
|
|
4
4
|
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
|
-
const index_js_4 = require("./
|
|
8
|
-
const index_js_5 = require("./
|
|
9
|
-
const index_js_6 = require("./
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!activeFeatures ||
|
|
7
|
+
const index_js_4 = require("./core/index.js");
|
|
8
|
+
const index_js_5 = require("./storage/index.js");
|
|
9
|
+
const index_js_6 = require("./messaging/index.js");
|
|
10
|
+
const index_js_7 = require("./remoteconfig/index.js");
|
|
11
|
+
const index_js_8 = require("./crashlytics/index.js");
|
|
12
|
+
const index_js_9 = require("./apphosting/index.js");
|
|
13
|
+
function availableTools(activeFeatures) {
|
|
14
|
+
const toolDefs = addFeaturePrefix("firebase", index_js_4.coreTools);
|
|
15
|
+
if (!(activeFeatures === null || activeFeatures === void 0 ? void 0 : activeFeatures.length)) {
|
|
16
16
|
activeFeatures = Object.keys(tools);
|
|
17
17
|
}
|
|
18
18
|
for (const key of activeFeatures) {
|
|
@@ -22,11 +22,32 @@ function availableTools(fixedRoot, activeFeatures) {
|
|
|
22
22
|
}
|
|
23
23
|
exports.availableTools = availableTools;
|
|
24
24
|
const tools = {
|
|
25
|
-
firestore:
|
|
26
|
-
auth:
|
|
27
|
-
dataconnect:
|
|
28
|
-
storage:
|
|
25
|
+
firestore: addFeaturePrefix("firestore", index_js_3.firestoreTools),
|
|
26
|
+
auth: addFeaturePrefix("auth", index_js_1.authTools),
|
|
27
|
+
dataconnect: addFeaturePrefix("dataconnect", index_js_2.dataconnectTools),
|
|
28
|
+
storage: addFeaturePrefix("storage", index_js_5.storageTools),
|
|
29
|
+
messaging: addFeaturePrefix("messaging", index_js_6.messagingTools),
|
|
30
|
+
remoteconfig: addFeaturePrefix("remoteconfig", index_js_7.remoteConfigTools),
|
|
31
|
+
crashlytics: addFeaturePrefix("crashlytics", index_js_8.crashlyticsTools),
|
|
32
|
+
apphosting: addFeaturePrefix("apphosting", index_js_9.appHostingTools),
|
|
29
33
|
};
|
|
30
|
-
function
|
|
31
|
-
return tools.map((tool) => (Object.assign(Object.assign({}, tool), { mcp: Object.assign(Object.assign({}, tool.mcp), { name: `${
|
|
34
|
+
function addFeaturePrefix(feature, tools) {
|
|
35
|
+
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 }) }) })));
|
|
36
|
+
}
|
|
37
|
+
function markdownDocsOfTools() {
|
|
38
|
+
var _a, _b, _c;
|
|
39
|
+
const allTools = availableTools([]);
|
|
40
|
+
let doc = `
|
|
41
|
+
| Tool Name | Feature Group | Description |
|
|
42
|
+
| --------- | ------------- | ----------- |`;
|
|
43
|
+
for (const tool of allTools) {
|
|
44
|
+
let feature = ((_b = (_a = tool.mcp) === null || _a === void 0 ? void 0 : _a._meta) === null || _b === void 0 ? void 0 : _b.feature) || "";
|
|
45
|
+
if (feature === "firebase") {
|
|
46
|
+
feature = "core";
|
|
47
|
+
}
|
|
48
|
+
doc += `
|
|
49
|
+
| ${tool.mcp.name} | ${feature} | ${((_c = tool.mcp) === null || _c === void 0 ? void 0 : _c.description) || ""} |`;
|
|
50
|
+
}
|
|
51
|
+
return doc;
|
|
32
52
|
}
|
|
53
|
+
exports.markdownDocsOfTools = markdownDocsOfTools;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.send_message = 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 sendMessage_js_1 = require("../../../messaging/sendMessage.js");
|
|
8
|
+
exports.send_message = (0, tool_js_1.tool)({
|
|
9
|
+
name: "send_message",
|
|
10
|
+
description: "Sends a message to a Firebase Cloud Messaging registration token or topic. ONLY ONE of `registration_token` or `topic` may be supplied in a specific call.",
|
|
11
|
+
inputSchema: zod_1.z.object({
|
|
12
|
+
registration_token: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("A specific device registration token for delivery. Supply either this or topic."),
|
|
16
|
+
topic: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("A topic name for delivery. Supply either this or registration_token."),
|
|
20
|
+
title: zod_1.z.string().optional().describe("The title of the push notification message."),
|
|
21
|
+
body: zod_1.z.string().optional().describe("The body of the push notification message."),
|
|
22
|
+
image: zod_1.z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("The URL of an image that will be displayed with the notification. JPEG, PNG, BMP have full support across platforms. Animated GIF and video only work on iOS. WebP and HEIF have varying levels of support across platforms and platform versions."),
|
|
26
|
+
}),
|
|
27
|
+
annotations: {
|
|
28
|
+
title: "Send FCM Message",
|
|
29
|
+
},
|
|
30
|
+
_meta: {
|
|
31
|
+
requiresAuth: true,
|
|
32
|
+
requiresProject: true,
|
|
33
|
+
},
|
|
34
|
+
}, async ({ registration_token, topic, title, body }, { projectId }) => {
|
|
35
|
+
if (!registration_token && !topic) {
|
|
36
|
+
return (0, util_js_1.mcpError)("Must supply either a `registration_token` or `topic` parameter to `send_message`.");
|
|
37
|
+
}
|
|
38
|
+
if (registration_token && topic) {
|
|
39
|
+
return (0, util_js_1.mcpError)("Cannot supply both `registration_token` and `topic` in a single `send_message` request.");
|
|
40
|
+
}
|
|
41
|
+
return (0, util_js_1.toContent)(await (0, sendMessage_js_1.sendFcmMessage)(projectId, { token: registration_token, topic, title, body }));
|
|
42
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.get_template = 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 get_js_1 = require("../../../remoteconfig/get.js");
|
|
8
|
+
exports.get_template = (0, tool_js_1.tool)({
|
|
9
|
+
name: "get_template",
|
|
10
|
+
description: "Retrieves a remote config template for the project",
|
|
11
|
+
inputSchema: zod_1.z.object({
|
|
12
|
+
version_number: zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("The version number of the template to retrieve. If not provided, retrieves the active template."),
|
|
16
|
+
}),
|
|
17
|
+
annotations: {
|
|
18
|
+
title: "Get Remote Config template",
|
|
19
|
+
readOnlyHint: true,
|
|
20
|
+
},
|
|
21
|
+
_meta: {
|
|
22
|
+
requiresAuth: true,
|
|
23
|
+
requiresProject: true,
|
|
24
|
+
},
|
|
25
|
+
}, async ({ version_number }, { projectId }) => {
|
|
26
|
+
return (0, util_js_1.toContent)(await (0, get_js_1.getTemplate)(projectId, version_number));
|
|
27
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.remoteConfigTools = void 0;
|
|
4
|
+
const get_template_js_1 = require("./get_template.js");
|
|
5
|
+
const rollback_template_js_1 = require("./rollback_template.js");
|
|
6
|
+
const publish_template_js_1 = require("./publish_template.js");
|
|
7
|
+
exports.remoteConfigTools = [get_template_js_1.get_template, publish_template_js_1.publish_template, rollback_template_js_1.rollback_template];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.publish_template = 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 publish_js_1 = require("../../../remoteconfig/publish.js");
|
|
8
|
+
exports.publish_template = (0, tool_js_1.tool)({
|
|
9
|
+
name: "publish_template",
|
|
10
|
+
description: "Publishes a new remote config template for the project",
|
|
11
|
+
inputSchema: zod_1.z.object({
|
|
12
|
+
template: zod_1.z.object({}).describe("The Remote Config template object to publish."),
|
|
13
|
+
force: zod_1.z
|
|
14
|
+
.boolean()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("If true, the publish will bypass ETag validation and overwrite the current template. Defaults to false if not provided."),
|
|
17
|
+
}),
|
|
18
|
+
annotations: {
|
|
19
|
+
title: "Publish Remote Config template",
|
|
20
|
+
readOnlyHint: false,
|
|
21
|
+
},
|
|
22
|
+
_meta: {
|
|
23
|
+
requiresAuth: true,
|
|
24
|
+
requiresProject: true,
|
|
25
|
+
},
|
|
26
|
+
}, async ({ template, force }, { projectId }) => {
|
|
27
|
+
if (template === undefined) {
|
|
28
|
+
return (0, util_js_1.mcpError)(`No template specified in the publish requests`);
|
|
29
|
+
}
|
|
30
|
+
if (force === undefined) {
|
|
31
|
+
return (0, util_js_1.toContent)(await (0, publish_js_1.publishTemplate)(projectId, template));
|
|
32
|
+
}
|
|
33
|
+
return (0, util_js_1.toContent)(await (0, publish_js_1.publishTemplate)(projectId, template, { force }));
|
|
34
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rollback_template = 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 rollback_js_1 = require("../../../remoteconfig/rollback.js");
|
|
8
|
+
exports.rollback_template = (0, tool_js_1.tool)({
|
|
9
|
+
name: "rollback_template",
|
|
10
|
+
description: "Rollback to a specific version of Remote Config template for a project",
|
|
11
|
+
inputSchema: zod_1.z.object({
|
|
12
|
+
version_number: zod_1.z
|
|
13
|
+
.number()
|
|
14
|
+
.describe("The version number to roll back to. This field is required."),
|
|
15
|
+
}),
|
|
16
|
+
annotations: {
|
|
17
|
+
title: "Rollback remote config template",
|
|
18
|
+
readOnlyHint: false,
|
|
19
|
+
},
|
|
20
|
+
_meta: {
|
|
21
|
+
requiresAuth: true,
|
|
22
|
+
requiresProject: true,
|
|
23
|
+
},
|
|
24
|
+
}, async ({ version_number }, { projectId }) => {
|
|
25
|
+
if (version_number === undefined) {
|
|
26
|
+
return (0, util_js_1.mcpError)(`No version number specified in the rollback requests`);
|
|
27
|
+
}
|
|
28
|
+
return (0, util_js_1.toContent)(await (0, rollback_js_1.rollbackTemplate)(projectId, version_number));
|
|
29
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRulesTool = 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 rules_js_1 = require("../../../gcp/rules.js");
|
|
8
|
+
function getRulesTool(productName, releaseName) {
|
|
9
|
+
return (0, tool_js_1.tool)({
|
|
10
|
+
name: "get_rules",
|
|
11
|
+
description: `Retrieves the active ${productName} security rules for the current project.`,
|
|
12
|
+
inputSchema: zod_1.z.object({}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: `Get Current ${productName} Rules`,
|
|
15
|
+
readOnlyHint: true,
|
|
16
|
+
},
|
|
17
|
+
_meta: {
|
|
18
|
+
requiresProject: true,
|
|
19
|
+
requiresAuth: true,
|
|
20
|
+
},
|
|
21
|
+
}, async (_, { projectId }) => {
|
|
22
|
+
const rulesetName = await (0, rules_js_1.getLatestRulesetName)(projectId, releaseName);
|
|
23
|
+
if (!rulesetName)
|
|
24
|
+
return (0, util_js_1.mcpError)(`No active Firestore rules were found in project '${projectId}'`);
|
|
25
|
+
const rules = await (0, rules_js_1.getRulesetContent)(rulesetName);
|
|
26
|
+
return (0, util_js_1.toContent)(rules[0].content);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.getRulesTool = getRulesTool;
|