test(mcp): add populate-gallery script for post-ship demo
Seeds the shared scene store with Casa del Sol + 3 templates + 3 Villa Azul variants so /scenes can be browsed end-to-end after a fresh `bun dev` + `pascal-mcp --http` restart. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
f230d9a401
commit
08e7b6db71
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* Populate the shared scene store with all reference scenes so /scenes
|
||||||
|
* shows the full gallery: Villa Azul + 3 templates + Casa del Sol (imported
|
||||||
|
* from the Phase 8 store).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { readFileSync, existsSync } from 'node:fs'
|
||||||
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
||||||
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
||||||
|
|
||||||
|
const transport = new StreamableHTTPClientTransport(new URL('http://localhost:3917/mcp'))
|
||||||
|
const client = new Client({ name: 'gallery', version: '0.0.0' })
|
||||||
|
await client.connect(transport)
|
||||||
|
|
||||||
|
function parse<T>(r: Awaited<ReturnType<Client['callTool']>>): T {
|
||||||
|
return JSON.parse((r.content as Array<{ text: string }>)[0]!.text) as T
|
||||||
|
}
|
||||||
|
|
||||||
|
async function call<T>(name: string, args: Record<string, unknown> = {}): Promise<T> {
|
||||||
|
const r = await client.callTool({ name, arguments: args })
|
||||||
|
if (r.isError) throw new Error(`${name}: ${JSON.stringify(r.content).slice(0, 300)}`)
|
||||||
|
return parse<T>(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Meta = { id: string; name: string; nodeCount: number; url: string }
|
||||||
|
|
||||||
|
// 1. Import Casa del Sol (if it exists on disk from Phase 8)
|
||||||
|
const casaSrcPath = '/tmp/pascal-phase8/scenes/6f87c59c1535.json'
|
||||||
|
if (existsSync(casaSrcPath)) {
|
||||||
|
const raw = JSON.parse(readFileSync(casaSrcPath, 'utf8'))
|
||||||
|
const meta = await call<Meta>('save_scene', {
|
||||||
|
name: 'Casa del Sol',
|
||||||
|
includeCurrentScene: false,
|
||||||
|
graph: { nodes: raw.graph?.nodes ?? raw.nodes, rootNodeIds: raw.graph?.rootNodeIds ?? raw.rootNodeIds },
|
||||||
|
})
|
||||||
|
console.log(`casa-sol imported: ${meta.name} (${meta.nodeCount} nodes) ${meta.url}`)
|
||||||
|
} else {
|
||||||
|
console.log('casa-sol src missing; skipping')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Create 3 template scenes
|
||||||
|
const templates = ['empty-studio', 'two-bedroom', 'garden-house'] as const
|
||||||
|
for (const t of templates) {
|
||||||
|
// create_from_template applies to the bridge
|
||||||
|
await call('create_from_template', { id: t, name: `Template: ${t}` })
|
||||||
|
const meta = await call<Meta>('save_scene', { name: `Template: ${t}` })
|
||||||
|
console.log(`${t} saved: ${meta.name} (${meta.nodeCount} nodes) ${meta.url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Generate 3 variants of Villa Azul
|
||||||
|
await call('load_scene', { id: 'a6e7919eacbe' })
|
||||||
|
const variants = await call<{ variants: Array<{ sceneId?: string; url?: string; description: string }> }>(
|
||||||
|
'generate_variants',
|
||||||
|
{ baseSceneId: 'a6e7919eacbe', count: 3, vary: ['wall-thickness', 'wall-height'], seed: 7, save: true },
|
||||||
|
)
|
||||||
|
console.log(`variants generated:`)
|
||||||
|
for (const v of variants.variants) {
|
||||||
|
console.log(` ${v.description} → ${v.url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. List final gallery
|
||||||
|
const list = await call<{ scenes: Array<{ id: string; name: string; nodeCount: number }> }>(
|
||||||
|
'list_scenes',
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
console.log(`\n=== Gallery: ${list.scenes.length} scenes ===`)
|
||||||
|
for (const s of list.scenes) {
|
||||||
|
console.log(` http://localhost:3002/scene/${s.id} - ${s.name} (${s.nodeCount} nodes)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.close()
|
||||||
Reference in New Issue
Block a user