Skip to content

Commit 609bb02

Browse files
authored
[MCP] Gate Gemini in Firebase Tools behind ToS Ack (#8647)
1 parent 007b308 commit 609bb02

File tree

9 files changed

+42
-12
lines changed

9 files changed

+42
-12
lines changed

src/mcp/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ npx -y firebase-tools login
5151
| firebase_create_project | core | Creates a new Firebase project. |
5252
| firebase_create_app | core | Creates a new app in your Firebase project for Web, iOS, or Android. |
5353
| firebase_create_android_sha | core | Adds a SHA certificate hash to an existing Android app. |
54+
| firebase_consult_assistant | core | Send a question to an AI assistant specifically enhanced to answer Firebase questions. |
5455
| firebase_get_environment | core | Retrieves information about the current Firebase environment including current authenticated user, project directory, active project, and more. |
5556
| firebase_update_environment | core | Updates Firebase environment config such as project directory, active project, active user account, and more. Use `firebase_get_environment` to see the currently configured environment. |
5657
| firebase_init | core | Initializes selected Firebase features in the workspace (Firestore, Data Connect, Realtime Database). All features are optional; provide only the products you wish to set up. You can initialize new features into an existing project directory, but re-initializing an existing feature may overwrite configuration. To deploy the initialized features, run the `firebase deploy` command after `firebase_init` tool. |
@@ -66,6 +67,8 @@ npx -y firebase-tools login
6667
| auth_set_claim | auth | 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. |
6768
| auth_set_sms_region_policy | auth | 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. |
6869
| dataconnect_list_services | dataconnect | List the Firebase Data Connect services available in the current project. |
70+
| dataconnect_generate_schema | dataconnect | Generates a Firebase Data Connect Schema based on the users description of an app. |
71+
| dataconnect_generate_operation | dataconnect | Generates a single Firebase Data Connect query or mutation based on the currently deployed schema and the provided prompt. |
6972
| dataconnect_get_schema | dataconnect | Retrieve information about the Firebase Data Connect Schema in the project, including Cloud SQL data sources and the GraphQL Schema describing the data model. |
7073
| dataconnect_get_connectors | dataconnect | Get the Firebase Data Connect Connectors in the project, which includes the pre-defined GraphQL queries accessible to client SDKs. |
7174
| dataconnect_execute_graphql | dataconnect | Executes an arbitrary GraphQL against a Data Connect service or its emulator. |

src/mcp/errors.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { CallToolResult } from "@modelcontextprotocol/sdk/types";
12
import { commandExistsSync, mcpError } from "./util";
23

34
export const NO_PROJECT_ERROR = mcpError(
45
'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.',
56
"PRECONDITION_FAILED",
67
);
78

8-
export function mcpAuthError() {
9+
export function mcpAuthError(): CallToolResult {
910
const cmd = commandExistsSync("firebase") ? "firebase" : "npx -y firebase-tools";
1011
return 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.
1112
\`\`\`sh
@@ -14,3 +15,11 @@ ${cmd} login
1415
1516
[ADC]: https://cloud.google.com/docs/authentication/application-default-credentials`);
1617
}
18+
19+
export function mcpGeminiError(projectId: string) {
20+
const consoleUrl = `https://firebase.corp.google.com/project/${projectId}/overview`;
21+
return mcpError(
22+
`This tool uses the Gemini in Firebase API. Visit Firebase Console to enable the Gemini in Firebase API ${consoleUrl} and try again.`,
23+
"PRECONDITION_FAILED",
24+
);
25+
}

src/mcp/index.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ import { Command } from "../command.js";
1616
import { requireAuth } from "../requireAuth.js";
1717
import { Options } from "../options.js";
1818
import { getProjectId } from "../projectUtils.js";
19-
import { mcpAuthError, NO_PROJECT_ERROR } from "./errors.js";
19+
import { mcpAuthError, NO_PROJECT_ERROR, mcpGeminiError } from "./errors.js";
2020
import { trackGA4 } from "../track.js";
2121
import { Config } from "../config.js";
2222
import { loadRC } from "../rc.js";
2323
import { EmulatorHubClient } from "../emulator/hubClient.js";
2424
import { Emulators } from "../emulator/types.js";
2525
import { existsSync } from "node:fs";
26+
import { ensure, check } from "../ensureApiEnabled.js";
27+
import * as api from "../api.js";
2628

2729
const SERVER_VERSION = "0.1.0";
2830

@@ -207,6 +209,7 @@ export class FirebaseMcpServer {
207209
const tool = this.getTool(toolName);
208210
if (!tool) throw new Error(`Tool '${toolName}' could not be found.`);
209211

212+
// Check if the current project directory exists.
210213
if (
211214
tool.mcp.name !== "firebase_update_environment" && // allow this tool only, to fix the issue
212215
(!this.cachedProjectRoot || !existsSync(this.cachedProjectRoot))
@@ -215,17 +218,31 @@ export class FirebaseMcpServer {
215218
`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.`,
216219
);
217220
}
221+
222+
// Check if the project ID is set.
218223
let projectId = await this.getProjectId();
219224
if (tool.mcp._meta?.requiresProject && !projectId) {
220225
return NO_PROJECT_ERROR;
221226
}
222227
projectId = projectId || "";
223228

229+
// Check if the user is logged in.
224230
const accountEmail = await this.getAuthenticatedUser();
225231
if (tool.mcp._meta?.requiresAuth && !accountEmail) {
226232
return mcpAuthError();
227233
}
228234

235+
// Check if the tool requires Gemini in Firebase API.
236+
if (tool.mcp._meta?.requiresGemini) {
237+
if (configstore.get("gemini")) {
238+
await ensure(projectId, api.cloudAiCompanionOrigin(), "");
239+
} else {
240+
if (!(await check(projectId, api.cloudAiCompanionOrigin(), ""))) {
241+
return mcpGeminiError(projectId);
242+
}
243+
}
244+
}
245+
229246
const options = { projectDir: this.cachedProjectRoot, cwd: this.cachedProjectRoot };
230247
const toolsCtx: ServerToolContext = {
231248
projectId: projectId,

src/mcp/tool.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export interface ServerTool<InputSchema extends ZodTypeAny = ZodTypeAny> {
3131
requiresProject?: boolean;
3232
/** Set this on a tool if it *always* requires a signed-in user to work. */
3333
requiresAuth?: boolean;
34+
/** Set this on a tool if it uses Gemini in Firebase API in any way. */
35+
requiresGemini?: boolean;
3436
/** Tools are grouped by feature. --only can configure what tools is available. */
3537
feature?: string;
3638
};

src/mcp/tools/core/consult_assistant.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const consult_assistant = tool(
2020
_meta: {
2121
requiresProject: true,
2222
requiresAuth: true,
23-
// TODO: Create an endpoint to check for GiF activation.
23+
requiresGemini: true,
2424
},
2525
},
2626
async ({ prompt }, { projectId }) => {

src/mcp/tools/core/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { init } from "./init.js";
1111
import { get_environment } from "./get_environment.js";
1212
import { update_environment } from "./update_environment.js";
1313
import { list_projects } from "./list_projects.js";
14-
// import { consult_assistant } from "./consult_assistant.js";
14+
import { consult_assistant } from "./consult_assistant.js";
1515

1616
export const coreTools: ServerTool[] = [
1717
get_project,
@@ -22,7 +22,7 @@ export const coreTools: ServerTool[] = [
2222
create_project,
2323
create_app,
2424
create_android_sha,
25-
// consult_assistant,
25+
consult_assistant,
2626
get_environment,
2727
update_environment,
2828
init,

src/mcp/tools/dataconnect/generate_operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const generate_operation = tool(
3030
_meta: {
3131
requiresProject: true,
3232
requiresAuth: true,
33-
// TODO: Create an endpoint to check for GiF activiation.
33+
requiresGemini: true,
3434
},
3535
},
3636
async ({ prompt, service_id }, { projectId, config }) => {

src/mcp/tools/dataconnect/generate_schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const generate_schema = tool(
1818
_meta: {
1919
requiresProject: true,
2020
requiresAuth: true,
21-
// TODO: Create an endpoint to check for GiF activiation.
21+
requiresGemini: true,
2222
},
2323
},
2424
async ({ prompt }, { projectId }) => {

src/mcp/tools/dataconnect/index.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { ServerTool } from "../../tool.js";
2-
// import { generate_operation } from "./generate_operation.js";
3-
// import { generate_schema } from "./generate_schema.js";
4-
2+
import { generate_operation } from "./generate_operation.js";
3+
import { generate_schema } from "./generate_schema.js";
54
import { list_services } from "./list_services.js";
65
import { get_schema } from "./get_schema.js";
76
import { get_connectors } from "./get_connector.js";
@@ -12,8 +11,8 @@ import { execute_mutation } from "./execute_mutation.js";
1211

1312
export const dataconnectTools: ServerTool[] = [
1413
list_services,
15-
// generate_schema,
16-
// generate_operation,
14+
generate_schema,
15+
generate_operation,
1716
get_schema,
1817
get_connectors,
1918
execute_graphql,

0 commit comments

Comments
 (0)