@exposify/supabase 0.3.10 → 0.3.11

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 CHANGED
@@ -15,7 +15,7 @@ root.
15
15
 
16
16
  - A Supabase project (local via the [Supabase CLI](https://supabase.com/docs/guides/cli), or hosted).
17
17
  - The Supabase CLI (`supabase` on your `PATH`) for `db push` / `functions deploy`.
18
- - Node or Yarn to run `npx exposify-supabase` (the CLI is a regular npm
18
+ - Node or Yarn to run `npx @exposify/supabase` (the CLI is a regular npm
19
19
  package; the edge function itself runs on Deno and needs no local install).
20
20
 
21
21
  ## 1. Scaffold
@@ -23,7 +23,7 @@ root.
23
23
  From your Supabase project's root (the directory containing `supabase/`):
24
24
 
25
25
  ```bash
26
- npx exposify-supabase init
26
+ npx @exposify/supabase init
27
27
  ```
28
28
 
29
29
  This is safe to re-run; see "Re-running `init`" below. It writes:
@@ -216,7 +216,7 @@ or edit the managed block in `supabase/functions/mcp/index.ts` by hand,
216
216
  keeping its format. Anything else goes below the block:
217
217
 
218
218
  ```ts
219
- // exposify:begin -- generated by `npx exposify-supabase init`, ...
219
+ // exposify:begin -- generated by `npx @exposify/supabase init`, ...
220
220
  import { aiReady } from "npm:@exposify/supabase";
221
221
 
222
222
  const generated = {
@@ -328,8 +328,8 @@ RLS enforcement, not anything in this SDK, is what makes that true.
328
328
  ## 5. Check it: `doctor`
329
329
 
330
330
  ```bash
331
- npx exposify-supabase doctor # finds the project the same way init does
332
- npx exposify-supabase doctor --token <user-jwt | extb_...>
331
+ npx @exposify/supabase doctor # finds the project the same way init does
332
+ npx @exposify/supabase doctor --token <user-jwt | extb_...>
333
333
  ```
334
334
 
335
335
  A read-only health check of everything `init` sets up. It never writes a file
@@ -535,7 +535,7 @@ project (local `supabase start` or linked):
535
535
  ```bash
536
536
  SUPABASE_URL=http://localhost:54321 \
537
537
  SUPABASE_SERVICE_ROLE_KEY=<service-role-key> \
538
- npx exposify-supabase generate
538
+ npx @exposify/supabase generate
539
539
  ```
540
540
 
541
541
  Uses the **service role key**, deliberately the same key runtime
@@ -565,7 +565,7 @@ the function prints whether MCP is up. It shows in `supabase functions serve`
565
565
  locally and in the function's logs in production:
566
566
 
567
567
  ```
568
- [exposify-supabase] MCP ready at https://<ref>.supabase.co/functions/v1/mcp: 9 tools (5 query, 2 write, 1 rpc, search_docs), 3 docs indexed, auth: passthrough (caller's JWT)
568
+ [@exposify/supabase] MCP ready at https://<ref>.supabase.co/functions/v1/mcp: 9 tools (5 query, 2 write, 1 rpc, search_docs), 3 docs indexed, auth: passthrough (caller's JWT)
569
569
  ```
570
570
 
571
571
  - **Manifest fallback:** the same line, marked "from the bundled manifest",
@@ -582,7 +582,7 @@ overrides that.
582
582
 
583
583
  ## Troubleshooting
584
584
 
585
- Start with `npx exposify-supabase doctor`. It checks most of what's below
585
+ Start with `npx @exposify/supabase doctor`. It checks most of what's below
586
586
  and names the fix.
587
587
 
588
588
  **"exposify_meta() is not reachable" / "PGRST202" errors in function logs.**
@@ -617,7 +617,7 @@ above — pointing at a project where the migration is already applied). On a
617
617
  brand-new project's first `init`, that's not true yet — say yes to the
618
618
  deploy prompt (or run `supabase db push` yourself) and the wizard picks up
619
619
  automatically once the migration is live, in the same run if you said yes,
620
- or on your next `exposify-supabase init` otherwise.
620
+ or on your next `@exposify/supabase init` otherwise.
621
621
 
622
622
  **`PostgREST OpenAPI fetch failed: HTTP 401`, and the error body (if you
623
623
  curl it directly) says `"Only the service_role API key can be used for this
package/dist/cli.js CHANGED
@@ -40,7 +40,7 @@ async function fetchExposifyMeta(postgrestUrl, headers, fetchImpl) {
40
40
  });
41
41
  if (res.status === 404) {
42
42
  throw new MissingExposifyMetaError(
43
- "exposify_meta() is not reachable at /rpc/exposify_meta (404). Run `npx exposify-supabase init` (or apply sql/exposify_meta.sql directly) and `supabase db push`, then redeploy the function."
43
+ "exposify_meta() is not reachable at /rpc/exposify_meta (404). Run `npx @exposify/supabase init` (or apply sql/exposify_meta.sql directly) and `supabase db push`, then redeploy the function."
44
44
  );
45
45
  }
46
46
  if (!res.ok) {
@@ -399,6 +399,9 @@ async function discoverConnection(deps) {
399
399
  return { connection: local ? fromLocal() : null, notes };
400
400
  }
401
401
 
402
+ // bin/doctor.ts
403
+ import { DEFAULT_BROKER_URL, parseExposifyKey, readSupabaseAuth } from "@exposify/core";
404
+
402
405
  // bin/function-file.ts
403
406
  var KEY_SECRET = "EXPOSIFY_KEY";
404
407
  var EMPTY_CONFIG = { writes: [], rpc: [], anonymousSignIn: false, broker: null, oauth: false };
@@ -422,7 +425,7 @@ var ANONYMOUS_MARKER = "anonymous sign-in enabled";
422
425
  function buildManagedBlock(config) {
423
426
  if (config.broker && config.oauth) throw new Error("the hosted broker and Supabase Auth OAuth can't be combined");
424
427
  const lines = [
425
- `${BEGIN} -- generated by \`npx exposify-supabase init\`, which rewrites`,
428
+ `${BEGIN} -- generated by \`npx @exposify/supabase init\`, which rewrites`,
426
429
  `// everything down to exposify:end when you re-run it. Add your own code below.`
427
430
  ];
428
431
  if (config.anonymousSignIn) lines.push(...ANONYMOUS_SIGN_IN_WARNING);
@@ -669,12 +672,12 @@ async function runDoctor(deps) {
669
672
  const files = [];
670
673
  const migration = findExistingMigration(await deps.listDir(MIGRATIONS_DIR), "_exposify_meta.sql");
671
674
  files.push(
672
- migration ? { status: "pass", message: `migration ${MIGRATIONS_DIR}/${migration}` } : { status: "fail", message: "no *_exposify_meta.sql migration", fix: "npx exposify-supabase init" }
675
+ migration ? { status: "pass", message: `migration ${MIGRATIONS_DIR}/${migration}` } : { status: "fail", message: "no *_exposify_meta.sql migration", fix: "npx @exposify/supabase init" }
673
676
  );
674
677
  const functionSource = await deps.readText(FUNCTION_PATH);
675
678
  const authMode = functionSource === null ? null : detectAuthMode(functionSource);
676
679
  files.push(
677
- functionSource !== null ? { status: "pass", message: `function ${FUNCTION_PATH} (auth: ${AUTH_LABEL[authMode]})` } : { status: "fail", message: `no ${FUNCTION_PATH}`, fix: "npx exposify-supabase init" }
680
+ functionSource !== null ? { status: "pass", message: `function ${FUNCTION_PATH} (auth: ${AUTH_LABEL[authMode]})` } : { status: "fail", message: `no ${FUNCTION_PATH}`, fix: "npx @exposify/supabase init" }
678
681
  );
679
682
  if (bypassesGatewayJwt2(authMode)) {
680
683
  const verifyJwt = toml === null ? null : readFunctionVerifyJwt(toml);
@@ -686,7 +689,7 @@ async function runDoctor(deps) {
686
689
  } : {
687
690
  status: "fail",
688
691
  message: `verify_jwt is ${verifyJwt === null ? "unset (defaults to on)" : "on"} for ${FUNCTION_NAME}; ` + (oauth ? "MCP clients will never get the OAuth login challenge" : "the gateway will reject every extb_... token"),
689
- fix: "re-run `npx exposify-supabase init` (it sets it), or add `[functions.mcp] verify_jwt = false` to config.toml and redeploy"
692
+ fix: "re-run `npx @exposify/supabase init` (it sets it), or add `[functions.mcp] verify_jwt = false` to config.toml and redeploy"
690
693
  }
691
694
  );
692
695
  }
@@ -747,7 +750,7 @@ async function runDoctor(deps) {
747
750
  db.push({
748
751
  status: "warn",
749
752
  message: `${undocumented.length} table(s) missing comments, so tools have thin descriptions: ${undocumented.map((t) => t.name).join(", ")}`,
750
- fix: "re-run `npx exposify-supabase init` and write descriptions, or add COMMENT ON TABLE/COLUMN"
753
+ fix: "re-run `npx @exposify/supabase init` and write descriptions, or add COMMENT ON TABLE/COLUMN"
751
754
  });
752
755
  }
753
756
  }
@@ -763,8 +766,35 @@ async function runDoctor(deps) {
763
766
  }
764
767
  if (authMode === "broker") fn.push(licenseSecretCheck(deps));
765
768
  sections.push({ title: "Deployed function", checks: fn });
769
+ if (authMode === "broker" && conn) sections.push({ title: "Connect (agents sign in to your Supabase Auth)", checks: await connectChecks(deps, conn) });
766
770
  return sections;
767
771
  }
772
+ async function connectChecks(deps, conn) {
773
+ const auth = conn.anonKey ? await readSupabaseAuth(conn.url, conn.anonKey, deps.fetch) : void 0;
774
+ const checks = [];
775
+ if (!auth) {
776
+ checks.push({ status: "warn", message: "couldn't read the project's Auth settings (/auth/v1/settings)", fix: "pass the anon key with --key, or check Auth is enabled" });
777
+ return checks;
778
+ }
779
+ checks.push(
780
+ auth.providers.length ? { status: "pass", message: `social sign-in offered to agents: ${auth.providers.join(", ")}` } : {
781
+ status: "warn",
782
+ message: "no social provider is switched on, so agents can only sign in with an email code",
783
+ fix: "switch one on in Auth \u2192 Sign In / Providers, or turn on email codes in the agemno dashboard"
784
+ }
785
+ );
786
+ if (!auth.signupsDisabled) {
787
+ checks.push({ status: "warn", message: "sign-ups are allowed: a new user who signs in with a social provider through Connect gets an account" });
788
+ }
789
+ const projectId = deps.exposifyKey ? parseExposifyKey(deps.exposifyKey)?.projectId : void 0;
790
+ const callback = projectId ? `${(deps.brokerUrl ?? DEFAULT_BROKER_URL).replace(/\/+$/, "")}/projects/${projectId}/supabase-callback` : null;
791
+ checks.push({
792
+ status: "warn",
793
+ message: callback ? `Redirect URLs must include ${callback} (can't be checked from here)` : "Redirect URLs must include the broker's callback (can't be checked from here)",
794
+ fix: callback ? "add it in Auth \u2192 URL Configuration \u2192 Redirect URLs" : "the agemno dashboard's sign-in page shows it; or run doctor with EXPOSIFY_KEY set to print it"
795
+ });
796
+ return checks;
797
+ }
768
798
  function probeChecks(url, outcome, authMode, local) {
769
799
  switch (outcome.kind) {
770
800
  case "ok": {
@@ -1470,14 +1500,14 @@ No files were changed. Merge the block above into ${FUNCTION_PATH2}, then re-run
1470
1500
  }
1471
1501
  if (!c) {
1472
1502
  console.log(
1473
- "\nNothing changed locally. Couldn't check the project itself (no --url/--key, env vars, or local/linked project) -- run `npx exposify-supabase doctor` once it's reachable."
1503
+ "\nNothing changed locally. Couldn't check the project itself (no --url/--key, env vars, or local/linked project) -- run `npx @exposify/supabase doctor` once it's reachable."
1474
1504
  );
1475
1505
  return;
1476
1506
  }
1477
1507
  console.log("\nNothing changed locally, but the project is behind:");
1478
1508
  for (const n of verdict.notes) console.log(` - ${n}`);
1479
1509
  if (!verdict.push && !verdict.deploy) {
1480
- console.log("Run `npx exposify-supabase doctor` for details.");
1510
+ console.log("Run `npx @exposify/supabase doctor` for details.");
1481
1511
  return;
1482
1512
  }
1483
1513
  if (c.source === "local") {
@@ -1493,7 +1523,7 @@ That's the local stack: run ${todo.join(" and ")}.`);
1493
1523
  const again = await tryIntrospect(await getConn());
1494
1524
  if (!again.introspection) {
1495
1525
  console.log(
1496
- "\nDeployed, but couldn't reach the project to introspect tables (no --url/--key, no SUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY, and no local stack or linked project the Supabase CLI could supply keys for). Re-run `exposify-supabase init` with those set to configure writes, RPCs, and documentation interactively."
1526
+ "\nDeployed, but couldn't reach the project to introspect tables (no --url/--key, no SUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY, and no local stack or linked project the Supabase CLI could supply keys for). Re-run `npx @exposify/supabase init` with those set to configure writes, RPCs, and documentation interactively."
1497
1527
  );
1498
1528
  console.log(`
1499
1529
  Done. ${clientStep(effectiveAuth)}`);
@@ -1567,7 +1597,9 @@ async function cmdDoctor() {
1567
1597
  connectionNotes: notes,
1568
1598
  projectRef,
1569
1599
  fetch: fetchWithTimeout,
1570
- token: argValue("--token")
1600
+ token: argValue("--token"),
1601
+ ...process.env.EXPOSIFY_KEY ? { exposifyKey: process.env.EXPOSIFY_KEY } : {},
1602
+ ...process.env.EXPOSIFY_BROKER_URL ? { brokerUrl: process.env.EXPOSIFY_BROKER_URL } : {}
1571
1603
  });
1572
1604
  console.log(formatReport(sections));
1573
1605
  if (hasFailures(sections)) process.exitCode = 1;
@@ -1587,7 +1619,7 @@ async function main() {
1587
1619
  if (cmd === "generate") return cmdGenerate();
1588
1620
  if (cmd === "doctor") return cmdDoctor();
1589
1621
  console.log(
1590
- "Usage: exposify-supabase <init|generate|doctor> [--url <url>] [--key <service-role-key>] [--local|--linked] [--broker [--broker-url <url>] | --oauth] [--token <token>] [--check]"
1622
+ "Usage: @exposify/supabase <init|generate|doctor> [--url <url>] [--key <service-role-key>] [--local|--linked] [--broker [--broker-url <url>] | --oauth] [--token <token>] [--check]"
1591
1623
  );
1592
1624
  console.log(" init Scaffold the exposify_meta() migration + supabase/functions/mcp/index.ts, then (when the");
1593
1625
  console.log(" project is reachable) walk through anonymous sign-in, per-table writes, RPC exposure, and");
package/dist/index.cjs CHANGED
@@ -107,7 +107,7 @@ function warnOnce(message) {
107
107
  if (warned.has(message)) return;
108
108
  warned.add(message);
109
109
  try {
110
- console.warn(`[exposify-supabase] ${message}`);
110
+ console.warn(`[@exposify/supabase] ${message}`);
111
111
  } catch {
112
112
  }
113
113
  }
@@ -206,7 +206,7 @@ async function fetchExposifyMeta(postgrestUrl, headers, fetchImpl) {
206
206
  });
207
207
  if (res.status === 404) {
208
208
  throw new MissingExposifyMetaError(
209
- "exposify_meta() is not reachable at /rpc/exposify_meta (404). Run `npx exposify-supabase init` (or apply sql/exposify_meta.sql directly) and `supabase db push`, then redeploy the function."
209
+ "exposify_meta() is not reachable at /rpc/exposify_meta (404). Run `npx @exposify/supabase init` (or apply sql/exposify_meta.sql directly) and `supabase db push`, then redeploy the function."
210
210
  );
211
211
  }
212
212
  if (!res.ok) {
@@ -624,7 +624,7 @@ function registerDiagnosticsResource(server, warnings) {
624
624
  server.registerResource(
625
625
  "exposify-diagnostics",
626
626
  "exposify://diagnostics",
627
- { title: "exposify-supabase diagnostics", mimeType: "application/json" },
627
+ { title: "@exposify/supabase diagnostics", mimeType: "application/json" },
628
628
  async (uri) => ({ contents: [{ uri: uri.href, text: JSON.stringify(warnings, null, 2) }] })
629
629
  );
630
630
  }
@@ -698,8 +698,8 @@ function createSupabaseOAuthGate(oauth, supabaseUrl, fetchImpl) {
698
698
 
699
699
  // src/startup.ts
700
700
  var import_core4 = require("@exposify/core");
701
- var LOG_PREFIX = "[exposify-supabase]";
702
- var INTROSPECTION_FIX = "check that SUPABASE_SERVICE_ROLE_KEY is available to the function and the exposify_meta migration is applied (`supabase db push`); the reason is logged above. To survive this, bundle a manifest with `exposify-supabase generate`";
701
+ var LOG_PREFIX = "[@exposify/supabase]";
702
+ var INTROSPECTION_FIX = "check that SUPABASE_SERVICE_ROLE_KEY is available to the function and the exposify_meta migration is applied (`supabase db push`); the reason is logged above. To survive this, bundle a manifest with `npx @exposify/supabase generate`";
703
703
  function supabaseToolsPhrase(ladder, cfg, hasDocs) {
704
704
  const query = ladder.tables.length;
705
705
  let write = 0;
@@ -797,7 +797,7 @@ function aiReady(options = {}) {
797
797
  manifest: options.manifest
798
798
  }).then((ladder) => {
799
799
  for (const w of ladder.warnings) {
800
- console.error(`[exposify-supabase] degradation ladder: ${w.rung}: ${w.reason}`);
800
+ console.error(`[@exposify/supabase] degradation ladder: ${w.rung}: ${w.reason}`);
801
801
  }
802
802
  return ladder;
803
803
  });
@@ -834,7 +834,7 @@ function aiReady(options = {}) {
834
834
  return { status: res.status, bodyText: await res.text() };
835
835
  };
836
836
  return buildSupabaseMcpServer({
837
- appName: "exposify-supabase",
837
+ appName: "@exposify/supabase",
838
838
  appVersion: "0.0.0",
839
839
  tables: ladder.tables,
840
840
  cfg,
@@ -861,6 +861,16 @@ function aiReady(options = {}) {
861
861
  const authRequired = options.authRequired ?? (envAuth !== void 0 || (0, import_core5.isHostedResolver)(auth));
862
862
  if (!auth) return core;
863
863
  const brokerGate = authRequired ? (0, import_core5.createBrokerGate)(auth) : null;
864
+ const authKey = anonKey || env?.get("SUPABASE_PUBLISHABLE_KEY") || "";
865
+ let supabaseAuth2;
866
+ const supabaseAuthOnce = () => {
867
+ if (!supabaseUrl || !authKey) return Promise.resolve(void 0);
868
+ supabaseAuth2 ??= (0, import_core5.readSupabaseAuth)(supabaseUrl, authKey, fetchImpl).then((found) => {
869
+ if (!found) supabaseAuth2 = void 0;
870
+ return found;
871
+ });
872
+ return supabaseAuth2;
873
+ };
864
874
  const functionUrl = supabaseUrl && functionName ? `${supabaseUrl.replace(/\/+$/, "")}/functions/v1/${functionName}` : null;
865
875
  return async (req) => {
866
876
  let open = false;
@@ -868,7 +878,13 @@ function aiReady(options = {}) {
868
878
  const own = (0, import_core5.publicRequestUrl)(req.url, req.headers);
869
879
  const isPrm = own.endsWith(PRM_SUFFIX);
870
880
  const resource = brokerGate.resourceFor(functionUrl ?? (isPrm ? own.slice(0, -PRM_SUFFIX.length) : own));
871
- open = await (0, import_core5.reportAppLogin)(auth, resource, null, { stacks: ["@supabase/supabase-js"], why: "Supabase Auth sign-in for agents is the Supabase preset in the dashboard's sign-in methods.", log: logReady }) === "open";
881
+ const supabase = await supabaseAuthOnce();
882
+ open = await (0, import_core5.reportAppLogin)(auth, resource, null, {
883
+ stacks: ["@supabase/supabase-js"],
884
+ why: supabase ? "Your Supabase Auth is turned off for agents in the dashboard." : "Couldn't read your project's Supabase Auth settings (/auth/v1/settings with the anon key), so Connect can't offer it yet.",
885
+ log: logReady,
886
+ ...supabase ? { supabase } : {}
887
+ }) === "open";
872
888
  if (open) {
873
889
  if (isPrm) return new Response("not found", { status: 404 });
874
890
  } else {
@@ -881,7 +897,7 @@ function aiReady(options = {}) {
881
897
  try {
882
898
  resolved = await auth(req.headers, {});
883
899
  } catch (err) {
884
- console.error("exposify-supabase: auth resolver failed", err);
900
+ console.error("@exposify/supabase: auth resolver failed", err);
885
901
  return Response.json({ error: "internal MCP server error" }, { status: 503 });
886
902
  }
887
903
  if (authRequired && !open && !resolved.get("authorization")) {
package/dist/index.d.cts CHANGED
@@ -126,7 +126,7 @@ interface AgentifySupabaseOptions {
126
126
  authRequired?: boolean;
127
127
  /** Injectable for tests; defaults to global `fetch`. */
128
128
  fetchImpl?: typeof fetch;
129
- /** Bundled fallback manifest (from `exposify-supabase generate`), used when runtime introspection fails. */
129
+ /** Bundled fallback manifest (from `@exposify/supabase generate`), used when runtime introspection fails. */
130
130
  manifest?: unknown;
131
131
  rateLimit?: number;
132
132
  rateWindowMs?: number;
@@ -196,7 +196,7 @@ interface ExposifyManifest {
196
196
  generatedAt: string;
197
197
  tables: TableSchema[];
198
198
  }
199
- /** Built by `npx exposify-supabase generate` against a local/linked project. */
199
+ /** Built by `npx @exposify/supabase generate` against a local/linked project. */
200
200
  declare function buildManifest(openapi: PostgrestOpenApiDoc, metaRows: MetaRow[], generatedAt: string): ExposifyManifest;
201
201
  /**
202
202
  * Defensive load: a manifest is bundled JSON shipped alongside the function
package/dist/index.d.ts CHANGED
@@ -126,7 +126,7 @@ interface AgentifySupabaseOptions {
126
126
  authRequired?: boolean;
127
127
  /** Injectable for tests; defaults to global `fetch`. */
128
128
  fetchImpl?: typeof fetch;
129
- /** Bundled fallback manifest (from `exposify-supabase generate`), used when runtime introspection fails. */
129
+ /** Bundled fallback manifest (from `@exposify/supabase generate`), used when runtime introspection fails. */
130
130
  manifest?: unknown;
131
131
  rateLimit?: number;
132
132
  rateWindowMs?: number;
@@ -196,7 +196,7 @@ interface ExposifyManifest {
196
196
  generatedAt: string;
197
197
  tables: TableSchema[];
198
198
  }
199
- /** Built by `npx exposify-supabase generate` against a local/linked project. */
199
+ /** Built by `npx @exposify/supabase generate` against a local/linked project. */
200
200
  declare function buildManifest(openapi: PostgrestOpenApiDoc, metaRows: MetaRow[], generatedAt: string): ExposifyManifest;
201
201
  /**
202
202
  * Defensive load: a manifest is bundled JSON shipped alongside the function
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { createBrokerGate, createWebMcpHandler, formatFailed as formatFailed2, publicRequestUrl, formatWarning as formatWarning2, hostedResolverFromEnv, isHostedResolver, readEnv, reportAppLogin, startupLogEnabled } from "@exposify/core";
2
+ import { createBrokerGate, createWebMcpHandler, formatFailed as formatFailed2, publicRequestUrl, formatWarning as formatWarning2, hostedResolverFromEnv, isHostedResolver, readEnv, readSupabaseAuth, reportAppLogin, startupLogEnabled } from "@exposify/core";
3
3
 
4
4
  // src/kb.ts
5
5
  import { KnowledgeBase } from "@exposify/core";
@@ -70,7 +70,7 @@ function warnOnce(message) {
70
70
  if (warned.has(message)) return;
71
71
  warned.add(message);
72
72
  try {
73
- console.warn(`[exposify-supabase] ${message}`);
73
+ console.warn(`[@exposify/supabase] ${message}`);
74
74
  } catch {
75
75
  }
76
76
  }
@@ -169,7 +169,7 @@ async function fetchExposifyMeta(postgrestUrl, headers, fetchImpl) {
169
169
  });
170
170
  if (res.status === 404) {
171
171
  throw new MissingExposifyMetaError(
172
- "exposify_meta() is not reachable at /rpc/exposify_meta (404). Run `npx exposify-supabase init` (or apply sql/exposify_meta.sql directly) and `supabase db push`, then redeploy the function."
172
+ "exposify_meta() is not reachable at /rpc/exposify_meta (404). Run `npx @exposify/supabase init` (or apply sql/exposify_meta.sql directly) and `supabase db push`, then redeploy the function."
173
173
  );
174
174
  }
175
175
  if (!res.ok) {
@@ -590,7 +590,7 @@ function registerDiagnosticsResource(server, warnings) {
590
590
  server.registerResource(
591
591
  "exposify-diagnostics",
592
592
  "exposify://diagnostics",
593
- { title: "exposify-supabase diagnostics", mimeType: "application/json" },
593
+ { title: "@exposify/supabase diagnostics", mimeType: "application/json" },
594
594
  async (uri) => ({ contents: [{ uri: uri.href, text: JSON.stringify(warnings, null, 2) }] })
595
595
  );
596
596
  }
@@ -664,8 +664,8 @@ function createSupabaseOAuthGate(oauth, supabaseUrl, fetchImpl) {
664
664
 
665
665
  // src/startup.ts
666
666
  import { formatFailed, formatReady, formatWarning } from "@exposify/core";
667
- var LOG_PREFIX = "[exposify-supabase]";
668
- var INTROSPECTION_FIX = "check that SUPABASE_SERVICE_ROLE_KEY is available to the function and the exposify_meta migration is applied (`supabase db push`); the reason is logged above. To survive this, bundle a manifest with `exposify-supabase generate`";
667
+ var LOG_PREFIX = "[@exposify/supabase]";
668
+ var INTROSPECTION_FIX = "check that SUPABASE_SERVICE_ROLE_KEY is available to the function and the exposify_meta migration is applied (`supabase db push`); the reason is logged above. To survive this, bundle a manifest with `npx @exposify/supabase generate`";
669
669
  function supabaseToolsPhrase(ladder, cfg, hasDocs) {
670
670
  const query = ladder.tables.length;
671
671
  let write = 0;
@@ -763,7 +763,7 @@ function aiReady(options = {}) {
763
763
  manifest: options.manifest
764
764
  }).then((ladder) => {
765
765
  for (const w of ladder.warnings) {
766
- console.error(`[exposify-supabase] degradation ladder: ${w.rung}: ${w.reason}`);
766
+ console.error(`[@exposify/supabase] degradation ladder: ${w.rung}: ${w.reason}`);
767
767
  }
768
768
  return ladder;
769
769
  });
@@ -800,7 +800,7 @@ function aiReady(options = {}) {
800
800
  return { status: res.status, bodyText: await res.text() };
801
801
  };
802
802
  return buildSupabaseMcpServer({
803
- appName: "exposify-supabase",
803
+ appName: "@exposify/supabase",
804
804
  appVersion: "0.0.0",
805
805
  tables: ladder.tables,
806
806
  cfg,
@@ -827,6 +827,16 @@ function aiReady(options = {}) {
827
827
  const authRequired = options.authRequired ?? (envAuth !== void 0 || isHostedResolver(auth));
828
828
  if (!auth) return core;
829
829
  const brokerGate = authRequired ? createBrokerGate(auth) : null;
830
+ const authKey = anonKey || env?.get("SUPABASE_PUBLISHABLE_KEY") || "";
831
+ let supabaseAuth2;
832
+ const supabaseAuthOnce = () => {
833
+ if (!supabaseUrl || !authKey) return Promise.resolve(void 0);
834
+ supabaseAuth2 ??= readSupabaseAuth(supabaseUrl, authKey, fetchImpl).then((found) => {
835
+ if (!found) supabaseAuth2 = void 0;
836
+ return found;
837
+ });
838
+ return supabaseAuth2;
839
+ };
830
840
  const functionUrl = supabaseUrl && functionName ? `${supabaseUrl.replace(/\/+$/, "")}/functions/v1/${functionName}` : null;
831
841
  return async (req) => {
832
842
  let open = false;
@@ -834,7 +844,13 @@ function aiReady(options = {}) {
834
844
  const own = publicRequestUrl(req.url, req.headers);
835
845
  const isPrm = own.endsWith(PRM_SUFFIX);
836
846
  const resource = brokerGate.resourceFor(functionUrl ?? (isPrm ? own.slice(0, -PRM_SUFFIX.length) : own));
837
- open = await reportAppLogin(auth, resource, null, { stacks: ["@supabase/supabase-js"], why: "Supabase Auth sign-in for agents is the Supabase preset in the dashboard's sign-in methods.", log: logReady }) === "open";
847
+ const supabase = await supabaseAuthOnce();
848
+ open = await reportAppLogin(auth, resource, null, {
849
+ stacks: ["@supabase/supabase-js"],
850
+ why: supabase ? "Your Supabase Auth is turned off for agents in the dashboard." : "Couldn't read your project's Supabase Auth settings (/auth/v1/settings with the anon key), so Connect can't offer it yet.",
851
+ log: logReady,
852
+ ...supabase ? { supabase } : {}
853
+ }) === "open";
838
854
  if (open) {
839
855
  if (isPrm) return new Response("not found", { status: 404 });
840
856
  } else {
@@ -847,7 +863,7 @@ function aiReady(options = {}) {
847
863
  try {
848
864
  resolved = await auth(req.headers, {});
849
865
  } catch (err) {
850
- console.error("exposify-supabase: auth resolver failed", err);
866
+ console.error("@exposify/supabase: auth resolver failed", err);
851
867
  return Response.json({ error: "internal MCP server error" }, { status: 503 });
852
868
  }
853
869
  if (authRequired && !open && !resolved.get("authorization")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exposify/supabase",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -27,7 +27,7 @@
27
27
  "prepack": "yarn build"
28
28
  },
29
29
  "dependencies": {
30
- "@exposify/core": "0.3.14",
30
+ "@exposify/core": "0.3.16",
31
31
  "@modelcontextprotocol/sdk": "^1.12.0",
32
32
  "zod": "^3.24.0"
33
33
  },
@@ -1,4 +1,4 @@
1
- -- exposify-supabase: schema introspection function.
1
+ -- @exposify/supabase: schema introspection function.
2
2
  --
3
3
  -- Exposes, per PostgREST's RPC convention (POST /rpc/exposify_meta), one row
4
4
  -- per column of every ordinary table in the `public` schema: whether Row