Ships the combined filesystem/Supabase storage adapter + MCP scene lifecycle tools + Next.js API routes + editor /scene/[id] route, so an MCP save is directly openable at /scene/<id> without any injection hack. End-to-end verified: 10/10 e2e steps pass. Storage (A1/A2/A3): - SceneStore interface + error classes + slug helpers - FilesystemSceneStore at $PASCAL_DATA_DIR (defaults XDG/~/.pascal) with atomic writes, .index sidecar, optimistic locking - SupabaseSceneStore with scenes + scene_revisions tables, RLS migration SQL, mock-backed unit tests - createSceneStore(env) auto-selects based on SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY MCP tools (A4, A8, A9, A10): - save_scene / load_scene / list_scenes / delete_scene / rename_scene - list_templates / create_from_template (3 seed templates: empty-studio, two-bedroom, garden-house) - generate_variants (7 mutation kinds, seeded RNG, save=true|false) - photo_to_scene (vision sampling → scene graph → save) Editor (A5, A6): - /api/scenes + /api/scenes/[id] with RFC 7232 If-Match locking - /scene/[id] and /scenes route pages with save button, SceneLoader - Removed the window.__pascalScene dev injection hack Security + UX edges (A7, A8): - AssetUrl Zod validator: asset:// blob: data:image/ /path https: (http://localhost for dev) + PASCAL_ALLOWED_ASSET_ORIGINS env allowlist. Hardens scan.url, guide.url, item.asset.src, material.texture.url, MaterialMaps.*Map - Auto-frame camera on empty→non-empty scene transition (camera-controls:fit-scene emitter event) Shared utilities: - rehydrateSiteChildren() extracted to packages/mcp/src/lib/ and used by both create-from-template and generate-variants to work around the SiteNode.children-as-objects vs. ids inconsistency (CROSS_CUTTING §2) - Storage + MCP subpath exports added to packages/mcp/package.json (CROSS_CUTTING §4) Tests: 293 pass / 0 fail across 40 files (was 142 pre-Phase-7). Biome: clean. Phase-7 e2e script at packages/mcp/test-reports/phase7-e2e.ts: MCP HTTP + editor Next.js both point at $PASCAL_DATA_DIR = /tmp/pascal-e2e, save_scene from MCP, GET /api/scenes/<id> from editor server, /scenes list page renders all saved scenes, scene page renders SceneLoader, delete_scene works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.6 KiB
Pascal MCP — Supabase Migrations
Numbered SQL files in migrations/ set up (and later evolve) the Pascal
Supabase schema. Each file is idempotent where possible (create ... if not exists, create or replace function) and should be applied in order.
Currently shipped:
| File | Purpose |
|---|---|
0001_scenes.sql |
Creates projects, scenes, scene_revisions + RLS. |
Prerequisites
- A Supabase project (
Settings → Project Settings → APIgives you the URL and keys). - The
service_rolekey, stored asSUPABASE_SERVICE_ROLE_KEYon any process that runsSupabaseSceneStore(the MCP server, the Next.js API route). Never expose this key to a browser.
Option 1 — Apply via Supabase CLI (recommended)
# One-time: link this repo to your Supabase project
supabase login
supabase link --project-ref <your-project-ref>
# Each migration — run once, in order
supabase db execute --file packages/mcp/sql/migrations/0001_scenes.sql
For a brand-new project you can also drop the files into
supabase/migrations/ and use supabase db push, but the
db execute --file form works for any existing project without adopting the
CLI's migration tracking.
Option 2 — Apply via the Supabase Dashboard
- Open your project at https://supabase.com/dashboard.
SQL Editor → New query.- Paste the contents of
packages/mcp/sql/migrations/0001_scenes.sql. Run. You should seeSuccess. No rows returned.
Re-running the file is safe; every statement is guarded with
if not exists / create or replace.
Verifying the install
In the dashboard SQL editor:
select table_name
from information_schema.tables
where table_schema = 'public'
and table_name in ('projects', 'scenes', 'scene_revisions')
order by table_name;
All three should be present. Check Database → Policies to confirm RLS is
enabled with the scenes_owner_all, scenes_public_read,
revisions_owner_read, and projects_owner_all policies.
Environment variables consumed by the MCP server
| Variable | Required | Notes |
|---|---|---|
SUPABASE_URL |
yes | https://<ref>.supabase.co |
SUPABASE_SERVICE_ROLE_KEY |
yes | Server-side only. Never log this value. |
When both are set, createSceneStore() picks the Supabase backend; otherwise
it falls back to the filesystem store.