feat(mcp): add resources and prompts

Resources: pascal://scene/current (JSON), /scene/current/summary
(markdown with per-level counts, floor areas, bbox), /catalog/items
(returns catalog_unavailable in headless mode), and the templated
pascal://constraints/{levelId} which exposes slabs + wall footprints
via @pascal-app/core/wall helpers.

Prompts: from_brief (generate scene from a natural-language brief),
iterate_on_feedback (minimal-diff patch proposals), and
renovation_from_photos (orchestrates the vision tools).

17 tests, all passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adrian Perez
2026-04-18 17:51:15 +02:00
co-authored by Claude Opus 4.7
parent 58ad89e80b
commit 570c605446
11 changed files with 1171 additions and 0 deletions
@@ -0,0 +1,39 @@
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import type { SceneBridge } from '../bridge/scene-bridge'
/**
* `pascal://catalog/items` — item catalog (if the host supplies one).
*
* `@pascal-app/core` does NOT expose a runtime item catalog — that is the host
* app's responsibility. In headless / standalone MCP mode we therefore return
* a stable, machine-readable "unavailable" payload so agents can detect this
* and fall back to free-form item creation.
*/
export function registerCatalogItems(server: McpServer, _bridge: SceneBridge): void {
server.registerResource(
'catalog-items',
'pascal://catalog/items',
{
title: 'Item catalog',
description:
'Catalog of placeable items. Not available in core; the host app is expected to override this resource when it has a catalog.',
mimeType: 'application/json',
},
async (uri) => {
const payload = {
status: 'catalog_unavailable' as const,
items: [] as never[],
note: '@pascal-app/core does not ship a runtime item catalog; the host app is expected to provide one by overriding this resource.',
}
return {
contents: [
{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify(payload),
},
],
}
},
)
}