From 074471d06d5bee722e7cf3c54f441f657bb326f9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 23 Oct 2025 18:48:56 +0000 Subject: [PATCH 1/6] feat: Add hosting to firebase_init MCP tool Adds hosting to the firebase_init MCP tool. It lets users configure the siteId, public directory, and whether to configure it as a single page app. --- src/mcp/tools/core/init.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/mcp/tools/core/init.ts b/src/mcp/tools/core/init.ts index bf62f593c96..3c900b711ab 100644 --- a/src/mcp/tools/core/init.ts +++ b/src/mcp/tools/core/init.ts @@ -140,6 +140,27 @@ export const init = tool( }) .optional() .describe("Enable Firebase AI Logic feature for existing app"), + hosting: z + .object({ + site: z + .string() + .optional() + .describe("The ID of the hosting site to configure."), + public: z + .string() + .optional() + .default("public") + .describe("The directory to use as the public root."), + spa: z + .boolean() + .optional() + .default(false) + .describe("Configure as a single-page app."), + }) + .optional() + .describe( + "Provide this object to initialize Firebase Hosting in this project directory.", + ), }), }), annotations: { @@ -219,6 +240,14 @@ export const init = tool( displayName: appData.displayName, }; } + if (features.hosting) { + featuresList.push("hosting"); + featureInfo.hosting = { + newSiteId: features.hosting.site, + public: features.hosting.public, + spa: features.hosting.spa, + }; + } const setup: Setup = { config: config?.src, rcfile: rc?.data, From 2c1bca4b5b7cce1d00c70099f7a0ec7a11efd3bc Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 23 Oct 2025 11:57:01 -0700 Subject: [PATCH 2/6] Improvements and changelog --- CHANGELOG.md | 1 + src/mcp/tools/core/init.ts | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..e25cd25abf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- Added 'hosting' to the 'firebase_init' MCP tool. diff --git a/src/mcp/tools/core/init.ts b/src/mcp/tools/core/init.ts index 3c900b711ab..9bb95d7f389 100644 --- a/src/mcp/tools/core/init.ts +++ b/src/mcp/tools/core/init.ts @@ -145,13 +145,17 @@ export const init = tool( site: z .string() .optional() - .describe("The ID of the hosting site to configure."), - public: z + .describe( + "The ID of the hosting site to configure. If omitted and there is a default hosting site, that will be used.", + ), + publicDirectory: z .string() .optional() .default("public") - .describe("The directory to use as the public root."), - spa: z + .describe( + "The directory containing public files that will be served. If using a build tool, this likely should be the output directory of that tool.", + ), + singlePageApp: z .boolean() .optional() .default(false) @@ -244,8 +248,8 @@ export const init = tool( featuresList.push("hosting"); featureInfo.hosting = { newSiteId: features.hosting.site, - public: features.hosting.public, - spa: features.hosting.spa, + public: features.hosting.publicDirectory, + spa: features.hosting.singlePageApp, }; } const setup: Setup = { From d62059f53a10fb1ee8b95e95a79ec26c245cb2fe Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 23 Oct 2025 12:13:27 -0700 Subject: [PATCH 3/6] More arg renaming for consistency, and use the tool in init prompt --- src/mcp/resources/guides/init_hosting.ts | 26 +++++++++++++++--------- src/mcp/tools/core/init.ts | 12 +++++------ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/mcp/resources/guides/init_hosting.ts b/src/mcp/resources/guides/init_hosting.ts index 091631f52d4..57ecbdac12e 100644 --- a/src/mcp/resources/guides/init_hosting.ts +++ b/src/mcp/resources/guides/init_hosting.ts @@ -1,3 +1,4 @@ +import { getDefaultHostingSite } from "../../../getDefaultHostingSite"; import { resource } from "../../resource"; export const init_hosting = resource( @@ -8,7 +9,9 @@ export const init_hosting = resource( description: "guides the coding agent through deploying to Firebase Hosting in the current project", }, - async (uri) => { + async (uri, ctx) => { + + const defaultHostingSite = await getDefaultHostingSite(ctx); return { contents: [ { @@ -16,18 +19,21 @@ export const init_hosting = resource( type: "text", text: ` ### Configure Firebase Hosting +Default hosting site for ${ctx.projectId}: ${defaultHostingSite || "Does not exist"} +If there is not default hosting site configure, ask the user what the site ID should be, and suggest ${ctx.projectId} as a good choice. +Next, use the 'firebase_init' tool to set up hosting. Below is an example of what the arguments to do so look like; +however, you should change the values to match the user's choices and project structure: +{ + features: { + hosting: { + site_id: ${ctx.projectId}, + public_directory: public, + } + } +} **Security Warning:** - Files included in the public folder of a hosting site are publicly accessible. Do not include sensitive API keys for services other than Firebase in these files. - -**When to Deploy:** -- Introduce Firebase Hosting when developers are ready to deploy their application to production. -- Alternative: Developers can deploy later using the \`/firebase:deploy\` command. - -**Deployment Process:** -- Request developer's permission before implementing Firebase Hosting -- Request developer's permission before deploying Firebase Hosting app to production. -- Configure Firebase Hosting and deploy the application to production `.trim(), }, ], diff --git a/src/mcp/tools/core/init.ts b/src/mcp/tools/core/init.ts index 9bb95d7f389..03b1133c1ef 100644 --- a/src/mcp/tools/core/init.ts +++ b/src/mcp/tools/core/init.ts @@ -142,20 +142,20 @@ export const init = tool( .describe("Enable Firebase AI Logic feature for existing app"), hosting: z .object({ - site: z + site_id: z .string() .optional() .describe( "The ID of the hosting site to configure. If omitted and there is a default hosting site, that will be used.", ), - publicDirectory: z + public_directory: z .string() .optional() .default("public") .describe( "The directory containing public files that will be served. If using a build tool, this likely should be the output directory of that tool.", ), - singlePageApp: z + single_page_app: z .boolean() .optional() .default(false) @@ -247,9 +247,9 @@ export const init = tool( if (features.hosting) { featuresList.push("hosting"); featureInfo.hosting = { - newSiteId: features.hosting.site, - public: features.hosting.publicDirectory, - spa: features.hosting.singlePageApp, + newSiteId: features.hosting.site_id, + public: features.hosting.public_directory, + spa: features.hosting.single_page_app, }; } const setup: Setup = { From a1b561700106cce9cdce0640b95bc23db94a1489 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 23 Oct 2025 12:17:42 -0700 Subject: [PATCH 4/6] Move deploy up into backend guide --- src/mcp/resources/guides/init_backend.ts | 29 +++--------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/src/mcp/resources/guides/init_backend.ts b/src/mcp/resources/guides/init_backend.ts index f7272160fea..764aba913ac 100644 --- a/src/mcp/resources/guides/init_backend.ts +++ b/src/mcp/resources/guides/init_backend.ts @@ -8,7 +8,7 @@ export const init_backend = resource( description: "guides the coding agent through configuring Firebase backend services in the current project", }, - async (uri) => { + async (uri, ctx) => { return { contents: [ { @@ -25,31 +25,8 @@ The user will likely need to setup Firestore, Authentication, and Hosting. Read 3. [Firestore Rules](firebase://guides/init/firestore_rules): read this to setup the \`firestore.rules\` file for securing your database 4. [Hosting](firebase://guides/init/hosting): read this if the user would like to deploy to Firebase Hosting -**firebase.json** -The firebase.json file is used to deploy Firebase products with the firebase deploy command. - -Here is an example firebase.json file with Firebase Hosting, Firestore, and Cloud Functions. Note that you do not need entries for services that the user isn't using. Do not remove sections from the user's firebase.json unless the user gives explicit permission. For more information, refer to [firebase.json file documentation](https://firebase.google.com/docs/cli/#the_firebasejson_file) -\`\`\`json -{ - "hosting": { - "public": "public", - "ignore": [ - "firebase.json", - "**/.*", - "**/node_modules/**" - ] - }, - "firestore": { - "rules": "firestore.rules", - "indexes": "firestore.indexes.json" - }, - "functions": { - "predeploy": [ - "npm --prefix "$RESOURCE_DIR" run lint", - "npm --prefix "$RESOURCE_DIR" run build" - ] - } -} +Once you are done setting up, ask the user if they would like to deploy. +If they say yes, run the command '${ctx.firebaseCliCommand} deploy --non-interactive' to do so. \`\`\` `.trim(), }, From 3164f0c808c2edea3635540e1cdab706b02a9c84 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 23 Oct 2025 12:27:31 -0700 Subject: [PATCH 5/6] format --- src/mcp/resources/guides/init_hosting.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mcp/resources/guides/init_hosting.ts b/src/mcp/resources/guides/init_hosting.ts index 57ecbdac12e..b7466185072 100644 --- a/src/mcp/resources/guides/init_hosting.ts +++ b/src/mcp/resources/guides/init_hosting.ts @@ -10,7 +10,6 @@ export const init_hosting = resource( "guides the coding agent through deploying to Firebase Hosting in the current project", }, async (uri, ctx) => { - const defaultHostingSite = await getDefaultHostingSite(ctx); return { contents: [ From 2f5c0e2b3ab7b3989eea18794b929ac370d9bfa3 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 23 Oct 2025 13:53:54 -0700 Subject: [PATCH 6/6] typo --- src/mcp/resources/guides/init_hosting.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mcp/resources/guides/init_hosting.ts b/src/mcp/resources/guides/init_hosting.ts index b7466185072..bbe13f95da2 100644 --- a/src/mcp/resources/guides/init_hosting.ts +++ b/src/mcp/resources/guides/init_hosting.ts @@ -19,7 +19,7 @@ export const init_hosting = resource( text: ` ### Configure Firebase Hosting Default hosting site for ${ctx.projectId}: ${defaultHostingSite || "Does not exist"} -If there is not default hosting site configure, ask the user what the site ID should be, and suggest ${ctx.projectId} as a good choice. +If there is not a default hosting site configured, ask the user what the site ID should be, and suggest ${ctx.projectId} as a good choice. Next, use the 'firebase_init' tool to set up hosting. Below is an example of what the arguments to do so look like; however, you should change the values to match the user's choices and project structure: {