Skip to content

Commit 06a1533

Browse files
Claudeclaude
authored andcommitted
feat: schema auto-apply falls back to DATABASE_URL when no access token
Previously auto-schema required SUPABASE_ACCESS_TOKEN (from npx supabase login). Now it tries three methods in order: 1. Management API (SUPABASE_ACCESS_TOKEN) — no extra credentials 2. Direct Postgres connection (DATABASE_URL) — user copies from Connect panel 3. Interactive prompt for DATABASE_URL (TTY only) 4. Manual SQL paste instructions (last resort) This eliminates the hidden fourth dependency. Users only need: - Supabase URL + service role key (for the MCP server) - DATABASE_URL (for schema setup — same dashboard, Connect panel) - OpenRouter API key (for embeddings) Uses the pg package (already a dependency) for direct DDL execution. Resolves GIT-45 concern #1 (SUPABASE_ACCESS_TOKEN hidden dependency). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1df260b commit 06a1533

2 files changed

Lines changed: 85 additions & 28 deletions

File tree

docs/pro-setup-guide.md

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,22 @@
99

1010
## Setup
1111

12-
### 1. Log in to Supabase CLI
13-
14-
```bash
15-
npx supabase login
16-
```
17-
18-
This stores an access token locally that gitmem uses to set up your database schema automatically.
19-
20-
### 2. Set environment variables
12+
### 1. Set environment variables
2113

2214
Set these in your shell profile (`.bashrc`, `.zshrc`) or `.env` file:
2315

2416
```bash
2517
export SUPABASE_URL="https://yourproject.supabase.co"
2618
export SUPABASE_SERVICE_ROLE_KEY="eyJ..."
2719
export OPENROUTER_API_KEY="sk-or-v1-..."
20+
export DATABASE_URL="postgresql://postgres.yourref:yourpassword@aws-0-region.pooler.supabase.com:5432/postgres"
2821
```
2922

3023
**Where to find these:**
3124
- **SUPABASE_URL**: Supabase Dashboard → Settings → API → Project URL
3225
- **SUPABASE_SERVICE_ROLE_KEY**: Supabase Dashboard → Settings → API → `service_role` key (under "Project API keys")
3326
- **OPENROUTER_API_KEY**: [openrouter.ai/keys](https://openrouter.ai/keys) → Create Key
27+
- **DATABASE_URL**: Supabase Dashboard → Connect → Connection string (Session pooler or Direct)
3428

3529
### 3. Activate
3630

@@ -197,22 +191,23 @@ This removes the device from the license server (freeing a device slot), clears
197191

198192
### Schema not applied automatically
199193

200-
If you see "Missing tables" after activation, the auto-schema needs a Supabase access token:
194+
Auto-schema uses either `DATABASE_URL` (direct Postgres connection) or `SUPABASE_ACCESS_TOKEN` (Management API). If neither is available, apply manually:
201195

202196
```bash
203-
npx supabase login # stores token locally
204-
npx gitmem-mcp activate # re-run, schema will auto-apply
205-
```
197+
# Option 1: Set DATABASE_URL and re-run
198+
export DATABASE_URL="postgresql://postgres.ref:password@pooler.supabase.com:5432/postgres"
199+
npx gitmem-mcp activate
206200

207-
Or apply manually:
201+
# Option 2: Set SUPABASE_ACCESS_TOKEN and re-run
202+
npx supabase login
203+
npx gitmem-mcp activate
208204

209-
```bash
205+
# Option 3: Apply manually
210206
npx gitmem-mcp setup | pbcopy # macOS — copies SQL to clipboard
211207
npx gitmem-mcp setup # prints SQL
208+
# Then paste into Supabase Dashboard → SQL Editor → Run
212209
```
213210

214-
Then paste into Supabase Dashboard → SQL Editor → Run.
215-
216211
### Device limit reached
217212

218213
Each license allows 3 concurrent devices. Deactivate unused devices:

src/commands/activate.ts

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,34 @@ function loadSetupSql(): string | null {
180180
}
181181
}
182182

183+
/**
184+
* Apply schema SQL via direct Postgres connection (pg client)
185+
* Uses DATABASE_URL connection string from env/config/prompt
186+
*/
187+
async function applySchemaViaPg(
188+
databaseUrl: string,
189+
sql: string
190+
): Promise<{ success: boolean; error?: string }> {
191+
try {
192+
const pg = await import("pg");
193+
const client = new pg.default.Client({
194+
connectionString: databaseUrl,
195+
ssl: { rejectUnauthorized: false },
196+
connectionTimeoutMillis: 15_000,
197+
statement_timeout: 30_000,
198+
});
199+
await client.connect();
200+
await client.query(sql);
201+
// Reload PostgREST schema cache
202+
await client.query("NOTIFY pgrst, 'reload schema'");
203+
await client.end();
204+
return { success: true };
205+
} catch (err: unknown) {
206+
const message = err instanceof Error ? err.message : "Unknown error";
207+
return { success: false, error: message };
208+
}
209+
}
210+
183211
/**
184212
* Apply schema SQL to user's Supabase via Management API
185213
*/
@@ -397,17 +425,51 @@ export async function main(args: string[]): Promise<void> {
397425
} else if (!setupSql) {
398426
console.log(" ⚠ Could not load schema SQL file");
399427
} else {
400-
// No access token — give clear instructions
401-
console.log(" ⚠ Missing tables: " + missingTables.join(", "));
402-
console.log("");
403-
console.log(" To apply automatically, set SUPABASE_ACCESS_TOKEN:");
404-
console.log(" npx supabase login");
405-
console.log(" Then re-run: npx gitmem-mcp activate");
406-
console.log("");
407-
console.log(" Or apply manually:");
408-
console.log(" npx gitmem-mcp setup | pbcopy (macOS — copies SQL to clipboard)");
409-
console.log(" npx gitmem-mcp setup (prints SQL to paste manually)");
410-
console.log(" Then: Supabase Dashboard → SQL Editor → Paste → Run");
428+
// No access token — try DATABASE_URL as fallback
429+
const dbUrlResult = await resolveCredential({
430+
envVar: "DATABASE_URL",
431+
configValue: config.database_url as string | undefined,
432+
promptLabel: "Database URL (from Supabase Connect panel)",
433+
required: false,
434+
rl,
435+
});
436+
437+
if (dbUrlResult.value) {
438+
console.log(" Applying schema via direct connection...");
439+
const pgResult = await applySchemaViaPg(dbUrlResult.value, setupSql);
440+
if (pgResult.success) {
441+
// Save DATABASE_URL to config for future use
442+
config.database_url = dbUrlResult.value;
443+
// Wait for PostgREST cache reload
444+
await new Promise((r) => setTimeout(r, 2000));
445+
const stillMissing = await checkSchemaExists(supabaseUrl, supabaseKey);
446+
if (stillMissing.length === 0) {
447+
console.log(" ✓ Schema applied via direct connection");
448+
missingTables = [];
449+
} else {
450+
console.log(" ⚠ Schema applied but PostgREST cache may be stale");
451+
console.log(" Try: npx gitmem-mcp check");
452+
missingTables = stillMissing;
453+
}
454+
} else {
455+
console.log(" ⚠ Direct connection failed: " + pgResult.error);
456+
console.log(" Apply manually:");
457+
console.log(" npx gitmem-mcp setup | pbcopy (macOS)");
458+
console.log(" Then: Supabase Dashboard → SQL Editor → Paste → Run");
459+
}
460+
} else {
461+
// No access token AND no DATABASE_URL
462+
console.log(" ⚠ Missing tables: " + missingTables.join(", "));
463+
console.log("");
464+
console.log(" To apply automatically, provide one of:");
465+
console.log(" - DATABASE_URL (from Supabase Dashboard → Connect)");
466+
console.log(" - SUPABASE_ACCESS_TOKEN (from: npx supabase login)");
467+
console.log(" Then re-run: npx gitmem-mcp activate");
468+
console.log("");
469+
console.log(" Or apply manually:");
470+
console.log(" npx gitmem-mcp setup | pbcopy (macOS)");
471+
console.log(" Then: Supabase Dashboard → SQL Editor → Paste → Run");
472+
}
411473
}
412474
} else {
413475
console.log(" ✓ Schema verified (all tables present)");

0 commit comments

Comments
 (0)