- README.md: install/quick start; configs for Claude Desktop, Claude Code, and Cursor; programmatic usage; tables covering all 21 tools, 4 resources, and 3 prompts; limitations; development commands. - CHANGELOG.md: 0.1.0 entry in Keep a Changelog format. - examples/generate-apartment.md: prose transcript using from_brief to build an 80 m² 2-bed apartment, showing apply_patch, set_zone, cut_opening, validate_scene. - examples/renovate-from-photos.md: prose transcript using the vision tools + renovation_from_photos prompt. - examples/embed-in-agent.ts: compilable TypeScript showing programmatic usage via InMemoryTransport. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83 lines
2.7 KiB
TypeScript
83 lines
2.7 KiB
TypeScript
/**
|
|
* Programmatic `@pascal-app/mcp` usage.
|
|
*
|
|
* Runs a full MCP client/server pair over the in-memory transport inside a
|
|
* single Node process. Useful for agent frameworks and tests that want to
|
|
* drive Pascal without spawning a subprocess.
|
|
*
|
|
* Compile with the package's `tsc --build`, or run directly with Bun:
|
|
*
|
|
* bun run packages/mcp/examples/embed-in-agent.ts
|
|
*/
|
|
|
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'
|
|
import { createPascalMcpServer, SceneBridge } from '@pascal-app/mcp'
|
|
|
|
async function main(): Promise<void> {
|
|
// 1. Spin up the headless bridge. `loadDefault()` seeds a Site → Building →
|
|
// Level stack so the client has something to query immediately.
|
|
const bridge = new SceneBridge()
|
|
bridge.loadDefault()
|
|
const server = createPascalMcpServer({ bridge })
|
|
|
|
// 2. Link the server to an in-memory client. Exactly the same API surface
|
|
// as the stdio / HTTP transports, but without any process boundary.
|
|
const [srvT, cliT] = InMemoryTransport.createLinkedPair()
|
|
const client = new Client({ name: 'my-agent', version: '0.1.0' })
|
|
await Promise.all([server.connect(srvT), client.connect(cliT)])
|
|
|
|
// 3. Discover available capabilities.
|
|
const tools = await client.listTools()
|
|
console.log(
|
|
'available tools:',
|
|
tools.tools.map((t) => t.name),
|
|
)
|
|
|
|
// 4. Inspect the current scene.
|
|
const scene = await client.callTool({ name: 'get_scene', arguments: {} })
|
|
console.log('scene snapshot:', JSON.stringify(scene, null, 2))
|
|
|
|
// 5. Find the default level, create a 5 m wall, and undo it.
|
|
const levels = await client.callTool({
|
|
name: 'find_nodes',
|
|
arguments: { type: 'level' },
|
|
})
|
|
const levelId = (levels.structuredContent as { nodes: Array<{ id: string }> }).nodes[0]?.id
|
|
|
|
if (levelId) {
|
|
const created = await client.callTool({
|
|
name: 'create_wall',
|
|
arguments: {
|
|
levelId,
|
|
start: [0, 0],
|
|
end: [5, 0],
|
|
thickness: 0.2,
|
|
height: 2.5,
|
|
},
|
|
})
|
|
console.log('created wall:', created.structuredContent)
|
|
|
|
const undone = await client.callTool({ name: 'undo', arguments: { steps: 1 } })
|
|
console.log('undone:', undone.structuredContent)
|
|
}
|
|
|
|
// 6. Validate and export.
|
|
const validation = await client.callTool({ name: 'validate_scene', arguments: {} })
|
|
console.log('validation:', validation.structuredContent)
|
|
|
|
const exported = await client.callTool({
|
|
name: 'export_json',
|
|
arguments: { pretty: true },
|
|
})
|
|
console.log('export size:', (exported.structuredContent as { json: string }).json.length)
|
|
|
|
await client.close()
|
|
await server.close()
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err)
|
|
process.exit(1)
|
|
})
|