docs(mcp): add README, examples, and changelog
- 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>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
441e97b2b6
commit
3406dad8f5
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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)
|
||||
})
|
||||
Reference in New Issue
Block a user