From 76c2f104e58bb2edba08f7abfef2072c1f7669ff Mon Sep 17 00:00:00 2001 From: matthallett1 Date: Tue, 17 Mar 2026 15:18:55 -0700 Subject: [PATCH 1/2] [docs] Add .env.example files to all extensions + dashboard Closes #17. Each extension gets an .env.example documenting the 3 required env vars (SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, MCP_ACCESS_KEY). Dashboard gets its own with the 4 vars needed for local dev. Also hardens .gitignore: adds .env.local, .env.*.local, and deno.lock. Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 5 +++++ dashboards/open-brain-dashboard/.env.example | 8 ++++++++ extensions/family-calendar/.env.example | 6 ++++++ extensions/home-maintenance/.env.example | 6 ++++++ extensions/household-knowledge/.env.example | 6 ++++++ extensions/job-hunt/.env.example | 6 ++++++ extensions/meal-planning/.env.example | 6 ++++++ extensions/professional-crm/.env.example | 6 ++++++ 8 files changed, 49 insertions(+) create mode 100644 dashboards/open-brain-dashboard/.env.example create mode 100644 extensions/family-calendar/.env.example create mode 100644 extensions/home-maintenance/.env.example create mode 100644 extensions/household-knowledge/.env.example create mode 100644 extensions/job-hunt/.env.example create mode 100644 extensions/meal-planning/.env.example create mode 100644 extensions/professional-crm/.env.example diff --git a/.gitignore b/.gitignore index d63e4024..12248633 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,12 @@ supabase/ # Recipe credentials & runtime state .env +.env.local +.env.*.local credentials.json token.json gmail-sync-log.json sync-log.json + +# Deno lock files +deno.lock diff --git a/dashboards/open-brain-dashboard/.env.example b/dashboards/open-brain-dashboard/.env.example new file mode 100644 index 00000000..307550a4 --- /dev/null +++ b/dashboards/open-brain-dashboard/.env.example @@ -0,0 +1,8 @@ +# Copy this file to .env.local and fill in your values. +# Tip: symlink from the repo root so all dashboards share one file: +# ln -s ../../.env.local dashboards/open-brain-dashboard/.env.local + +MCP_URL=https://your-project.supabase.co/functions/v1/open-brain-mcp +MCP_KEY=your-mcp-access-key +PUBLIC_SUPABASE_URL=https://your-project.supabase.co +PUBLIC_SUPABASE_ANON_KEY=your-anon-key diff --git a/extensions/family-calendar/.env.example b/extensions/family-calendar/.env.example new file mode 100644 index 00000000..91155206 --- /dev/null +++ b/extensions/family-calendar/.env.example @@ -0,0 +1,6 @@ +# These are set automatically by Supabase when you deploy an Edge Function. +# You only need to set MCP_ACCESS_KEY manually. + +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key +MCP_ACCESS_KEY=your-mcp-access-key diff --git a/extensions/home-maintenance/.env.example b/extensions/home-maintenance/.env.example new file mode 100644 index 00000000..91155206 --- /dev/null +++ b/extensions/home-maintenance/.env.example @@ -0,0 +1,6 @@ +# These are set automatically by Supabase when you deploy an Edge Function. +# You only need to set MCP_ACCESS_KEY manually. + +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key +MCP_ACCESS_KEY=your-mcp-access-key diff --git a/extensions/household-knowledge/.env.example b/extensions/household-knowledge/.env.example new file mode 100644 index 00000000..91155206 --- /dev/null +++ b/extensions/household-knowledge/.env.example @@ -0,0 +1,6 @@ +# These are set automatically by Supabase when you deploy an Edge Function. +# You only need to set MCP_ACCESS_KEY manually. + +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key +MCP_ACCESS_KEY=your-mcp-access-key diff --git a/extensions/job-hunt/.env.example b/extensions/job-hunt/.env.example new file mode 100644 index 00000000..91155206 --- /dev/null +++ b/extensions/job-hunt/.env.example @@ -0,0 +1,6 @@ +# These are set automatically by Supabase when you deploy an Edge Function. +# You only need to set MCP_ACCESS_KEY manually. + +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key +MCP_ACCESS_KEY=your-mcp-access-key diff --git a/extensions/meal-planning/.env.example b/extensions/meal-planning/.env.example new file mode 100644 index 00000000..91155206 --- /dev/null +++ b/extensions/meal-planning/.env.example @@ -0,0 +1,6 @@ +# These are set automatically by Supabase when you deploy an Edge Function. +# You only need to set MCP_ACCESS_KEY manually. + +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key +MCP_ACCESS_KEY=your-mcp-access-key diff --git a/extensions/professional-crm/.env.example b/extensions/professional-crm/.env.example new file mode 100644 index 00000000..91155206 --- /dev/null +++ b/extensions/professional-crm/.env.example @@ -0,0 +1,6 @@ +# These are set automatically by Supabase when you deploy an Edge Function. +# You only need to set MCP_ACCESS_KEY manually. + +SUPABASE_URL=https://your-project.supabase.co +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key +MCP_ACCESS_KEY=your-mcp-access-key From 38bc1330af64e902daf4df6a94ca8670ffe3e810 Mon Sep 17 00:00:00 2001 From: matthallett1 Date: Wed, 25 Mar 2026 10:33:01 -0700 Subject: [PATCH 2/2] feat: use content fingerprint dedup in capture_thought Made-with: Cursor --- server/index.ts | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/server/index.ts b/server/index.ts index 458cb1b7..cd611d1d 100644 --- a/server/index.ts +++ b/server/index.ts @@ -316,15 +316,27 @@ server.registerTool( extractMetadata(content), ]); - const { error } = await supabase.from("thoughts").insert({ - content, - embedding, - metadata: { ...metadata, source: "mcp" }, + const { data: upsertResult, error: upsertError } = await supabase.rpc("upsert_thought", { + p_content: content, + p_payload: { metadata: { ...metadata, source: "mcp" } }, }); - if (error) { + if (upsertError) { + return { + content: [{ type: "text" as const, text: `Failed to capture: ${upsertError.message}` }], + isError: true, + }; + } + + const thoughtId = upsertResult?.id; + const { error: embError } = await supabase + .from("thoughts") + .update({ embedding }) + .eq("id", thoughtId); + + if (embError) { return { - content: [{ type: "text" as const, text: `Failed to capture: ${error.message}` }], + content: [{ type: "text" as const, text: `Failed to save embedding: ${embError.message}` }], isError: true, }; }