@exposify/firebase 0.0.1 → 0.0.3
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/README.md +6 -2
- package/dist/cli.js +2 -2
- package/dist/index.cjs +13 -7
- package/dist/index.js +14 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ root.
|
|
|
22
22
|
From your Firebase project root (where `firebase.json` is):
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npx exposify
|
|
25
|
+
npx @exposify/firebase init
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
It reads `firebase.json` to find your functions directory and
|
|
@@ -70,7 +70,11 @@ broker as the authorization server, and the client sends the user through
|
|
|
70
70
|
sign-in. Tool calls then reach Firestore with the `Authorization` the broker
|
|
71
71
|
resolves for that user, never the broker token itself, so your rules still
|
|
72
72
|
decide. Requests without a connection are refused rather
|
|
73
|
-
than run anonymously; pass `authRequired: false` to allow them.
|
|
73
|
+
than run anonymously; pass `authRequired: false` to allow them. The
|
|
74
|
+
exception: when the project has no sign-in method yet (add the Firebase
|
|
75
|
+
preset in the dashboard), agents use the function signed out, as the
|
|
76
|
+
anonymous user, with no sign-in asked. The startup log says which it is
|
|
77
|
+
(`[agentready] How agents sign in: ...`).
|
|
74
78
|
|
|
75
79
|
`auth: hostedBroker()` does the same explicitly. If the function is
|
|
76
80
|
reached through a URL other than the one it sees (a custom domain or a
|
package/dist/cli.js
CHANGED
|
@@ -75,7 +75,7 @@ function stripComments(source) {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// bin/init.ts
|
|
78
|
-
var GENERATED_MARKER = "Generated by `exposify
|
|
78
|
+
var GENERATED_MARKER = "Generated by `npx @exposify/firebase init`";
|
|
79
79
|
function planInit(root) {
|
|
80
80
|
const warnings = [];
|
|
81
81
|
const firebaseJsonPath = join(root, "firebase.json");
|
|
@@ -194,7 +194,7 @@ function nextSteps(plan) {
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
// bin/cli.ts
|
|
197
|
-
var USAGE = `Usage: exposify
|
|
197
|
+
var USAGE = `Usage: @exposify/firebase init [--dry-run]
|
|
198
198
|
|
|
199
199
|
Run from your Firebase project root (where firebase.json is). Writes an MCP
|
|
200
200
|
function to your functions source directory, with collections proposed from
|
package/dist/index.cjs
CHANGED
|
@@ -104,7 +104,7 @@ function toolName(prefix, suffix, taken) {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// src/config.ts
|
|
107
|
-
var LOG_PREFIX = "[exposify
|
|
107
|
+
var LOG_PREFIX = "[@exposify/firebase]";
|
|
108
108
|
var WRITE_OPS = ["create", "update", "delete"];
|
|
109
109
|
function parseWrites(writes = []) {
|
|
110
110
|
const grants = /* @__PURE__ */ new Map();
|
|
@@ -654,7 +654,7 @@ function toNodeHandler(handle) {
|
|
|
654
654
|
try {
|
|
655
655
|
response = await handle(await toWebRequest(req));
|
|
656
656
|
} catch (err) {
|
|
657
|
-
console.error("[exposify
|
|
657
|
+
console.error("[@exposify/firebase] MCP request failed", err);
|
|
658
658
|
response = Response.json({ error: "internal MCP server error" }, { status: 503 });
|
|
659
659
|
}
|
|
660
660
|
res.statusCode = response.status;
|
|
@@ -791,7 +791,7 @@ function createFirebaseMcpHandler(options = {}) {
|
|
|
791
791
|
}
|
|
792
792
|
};
|
|
793
793
|
return buildFirebaseMcpServer({
|
|
794
|
-
appName: "exposify
|
|
794
|
+
appName: "@exposify/firebase",
|
|
795
795
|
appVersion: "0.0.0",
|
|
796
796
|
cfg,
|
|
797
797
|
client: createFirestoreClient(baseUrl, authorization, fetchImpl),
|
|
@@ -807,13 +807,19 @@ function createFirebaseMcpHandler(options = {}) {
|
|
|
807
807
|
if (!auth) return core;
|
|
808
808
|
const brokerGate = authRequired ? (0, import_core2.createBrokerGate)(auth) : null;
|
|
809
809
|
return async (req) => {
|
|
810
|
+
let open = false;
|
|
810
811
|
if (brokerGate) {
|
|
811
812
|
const own = (0, import_core2.publicRequestUrl)(req.url, req.headers);
|
|
812
813
|
const isPrm = own.endsWith(import_core2.PRM_PATH);
|
|
813
814
|
const resource = brokerGate.resourceFor(functionPublicUrl(isPrm ? own.slice(0, -import_core2.PRM_PATH.length) : own, functionName));
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
815
|
+
open = await (0, import_core2.reportAppLogin)(auth, resource, null, { stacks: ["firebase-admin"], why: "Firebase Auth sign-in for agents is the Firebase preset in the dashboard's sign-in methods.", log: logReady }) === "open";
|
|
816
|
+
if (open) {
|
|
817
|
+
if (isPrm) return new Response("not found", { status: 404 });
|
|
818
|
+
} else {
|
|
819
|
+
if (isPrm) return brokerGate.metadataResponse(req.method, resource);
|
|
820
|
+
const result = await brokerGate.check(req.headers, resource, `${resource}${import_core2.PRM_PATH}`);
|
|
821
|
+
if (!result.ok) return result.response;
|
|
822
|
+
}
|
|
817
823
|
}
|
|
818
824
|
let resolved;
|
|
819
825
|
try {
|
|
@@ -822,7 +828,7 @@ function createFirebaseMcpHandler(options = {}) {
|
|
|
822
828
|
console.error(`${LOG_PREFIX} auth resolver failed`, err);
|
|
823
829
|
return Response.json({ error: "internal MCP server error" }, { status: 503 });
|
|
824
830
|
}
|
|
825
|
-
if (authRequired && !resolved.get("authorization")) {
|
|
831
|
+
if (authRequired && !open && !resolved.get("authorization")) {
|
|
826
832
|
return Response.json({ error: "unauthorized" }, { status: 401, headers: { "www-authenticate": "Bearer" } });
|
|
827
833
|
}
|
|
828
834
|
resolvedAuth.set(req, resolved);
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
KnowledgeBase,
|
|
11
11
|
PRM_PATH,
|
|
12
12
|
publicRequestUrl,
|
|
13
|
+
reportAppLogin,
|
|
13
14
|
startupLogEnabled
|
|
14
15
|
} from "@exposify/core";
|
|
15
16
|
import { loadDocsFromFs } from "@exposify/core/node";
|
|
@@ -83,7 +84,7 @@ function toolName(prefix, suffix, taken) {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
// src/config.ts
|
|
86
|
-
var LOG_PREFIX = "[exposify
|
|
87
|
+
var LOG_PREFIX = "[@exposify/firebase]";
|
|
87
88
|
var WRITE_OPS = ["create", "update", "delete"];
|
|
88
89
|
function parseWrites(writes = []) {
|
|
89
90
|
const grants = /* @__PURE__ */ new Map();
|
|
@@ -633,7 +634,7 @@ function toNodeHandler(handle) {
|
|
|
633
634
|
try {
|
|
634
635
|
response = await handle(await toWebRequest(req));
|
|
635
636
|
} catch (err) {
|
|
636
|
-
console.error("[exposify
|
|
637
|
+
console.error("[@exposify/firebase] MCP request failed", err);
|
|
637
638
|
response = Response.json({ error: "internal MCP server error" }, { status: 503 });
|
|
638
639
|
}
|
|
639
640
|
res.statusCode = response.status;
|
|
@@ -770,7 +771,7 @@ function createFirebaseMcpHandler(options = {}) {
|
|
|
770
771
|
}
|
|
771
772
|
};
|
|
772
773
|
return buildFirebaseMcpServer({
|
|
773
|
-
appName: "exposify
|
|
774
|
+
appName: "@exposify/firebase",
|
|
774
775
|
appVersion: "0.0.0",
|
|
775
776
|
cfg,
|
|
776
777
|
client: createFirestoreClient(baseUrl, authorization, fetchImpl),
|
|
@@ -786,13 +787,19 @@ function createFirebaseMcpHandler(options = {}) {
|
|
|
786
787
|
if (!auth) return core;
|
|
787
788
|
const brokerGate = authRequired ? createBrokerGate(auth) : null;
|
|
788
789
|
return async (req) => {
|
|
790
|
+
let open = false;
|
|
789
791
|
if (brokerGate) {
|
|
790
792
|
const own = publicRequestUrl(req.url, req.headers);
|
|
791
793
|
const isPrm = own.endsWith(PRM_PATH);
|
|
792
794
|
const resource = brokerGate.resourceFor(functionPublicUrl(isPrm ? own.slice(0, -PRM_PATH.length) : own, functionName));
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
795
|
+
open = await reportAppLogin(auth, resource, null, { stacks: ["firebase-admin"], why: "Firebase Auth sign-in for agents is the Firebase preset in the dashboard's sign-in methods.", log: logReady }) === "open";
|
|
796
|
+
if (open) {
|
|
797
|
+
if (isPrm) return new Response("not found", { status: 404 });
|
|
798
|
+
} else {
|
|
799
|
+
if (isPrm) return brokerGate.metadataResponse(req.method, resource);
|
|
800
|
+
const result = await brokerGate.check(req.headers, resource, `${resource}${PRM_PATH}`);
|
|
801
|
+
if (!result.ok) return result.response;
|
|
802
|
+
}
|
|
796
803
|
}
|
|
797
804
|
let resolved;
|
|
798
805
|
try {
|
|
@@ -801,7 +808,7 @@ function createFirebaseMcpHandler(options = {}) {
|
|
|
801
808
|
console.error(`${LOG_PREFIX} auth resolver failed`, err);
|
|
802
809
|
return Response.json({ error: "internal MCP server error" }, { status: 503 });
|
|
803
810
|
}
|
|
804
|
-
if (authRequired && !resolved.get("authorization")) {
|
|
811
|
+
if (authRequired && !open && !resolved.get("authorization")) {
|
|
805
812
|
return Response.json({ error: "unauthorized" }, { status: 401, headers: { "www-authenticate": "Bearer" } });
|
|
806
813
|
}
|
|
807
814
|
resolvedAuth.set(req, resolved);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exposify/firebase",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.19"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"prepack": "yarn build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@exposify/core": "0.3.
|
|
32
|
+
"@exposify/core": "0.3.16",
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
34
34
|
"zod": "^3.24.0"
|
|
35
35
|
},
|