import type { AssetInput } from '@pascal-app/core/schema' /** * Small built-in catalog for standalone/headless MCP use. * * The editor has a much larger UI catalog, but depending on `@pascal-app/editor` * from the MCP package would pull browser/React code into the headless server. * These entries mirror the stable IDs and asset paths used by the editor for * common AI-generated residential layouts. */ export const MCP_CATALOG_ITEMS: AssetInput[] = [ { id: 'double-bed', category: 'furniture', tags: ['floor', 'bedroom'], name: 'Double Bed', thumbnail: '/items/double-bed/thumbnail.webp', src: '/items/double-bed/model.glb', dimensions: [2, 0.8, 2.5], offset: [0, 0, -0.03], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'single-bed', category: 'furniture', tags: ['floor', 'bedroom'], name: 'Single Bed', thumbnail: '/items/single-bed/thumbnail.webp', src: '/items/single-bed/model.glb', dimensions: [1.5, 0.7, 2.5], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'bedside-table', category: 'furniture', tags: ['floor', 'bedroom'], name: 'Bedside Table', thumbnail: '/items/bedside-table/thumbnail.webp', src: '/items/bedside-table/model.glb', dimensions: [0.5, 0.5, 0.5], offset: [0, 0, -0.01], rotation: [0, 0, 0], scale: [1, 1, 1], surface: { height: 0.5 }, }, { id: 'dresser', category: 'furniture', tags: ['floor', 'storage', 'bedroom'], name: 'Dresser', thumbnail: '/items/dresser/thumbnail.webp', src: '/items/dresser/model.glb', dimensions: [1.5, 0.8, 1], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], surface: { height: 0.8 }, }, { id: 'closet', category: 'furniture', tags: ['floor', 'storage', 'bedroom'], name: 'Closet', thumbnail: '/items/closet/thumbnail.webp', src: '/items/closet/model.glb', dimensions: [2, 2.5, 1], offset: [0, 0, -0.01], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'sofa', category: 'furniture', tags: ['floor', 'seating', 'living'], name: 'Sofa', thumbnail: '/items/sofa/thumbnail.webp', src: '/items/sofa/model.glb', dimensions: [2.5, 0.8, 1.5], offset: [0, 0, 0.04], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'livingroom-chair', category: 'furniture', tags: ['floor', 'seating', 'living'], name: 'Livingroom Chair', thumbnail: '/items/livingroom-chair/thumbnail.webp', src: '/items/livingroom-chair/model.glb', dimensions: [1.5, 0.8, 1.5], offset: [0.01, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'coffee-table', category: 'furniture', tags: ['floor', 'table', 'living'], name: 'Coffee Table', thumbnail: '/items/coffee-table/thumbnail.webp', src: '/items/coffee-table/model.glb', dimensions: [2, 0.4, 1.5], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], surface: { height: 0.3 }, }, { id: 'tv-stand', category: 'furniture', tags: ['floor', 'storage', 'living'], name: 'TV Stand', thumbnail: '/items/tv-stand/thumbnail.webp', src: '/items/tv-stand/model.glb', dimensions: [2, 0.4, 0.5], offset: [0, 0.21, 0], rotation: [0, 0, 0], scale: [1, 1, 1], surface: { height: 0.36 }, }, { id: 'shelf', category: 'furniture', tags: ['wall', 'storage'], name: 'Shelf', thumbnail: '/items/shelf/thumbnail.webp', src: '/items/shelf/model.glb', dimensions: [1, 0.5, 0.7], offset: [0, 0.1, 0.01], rotation: [0, 0, 0], scale: [1, 1, 1], attachTo: 'wall-side', surface: { height: 0.12 }, }, { id: 'dining-table', category: 'furniture', tags: ['floor', 'table', 'dining'], name: 'Dining Table', thumbnail: '/items/dining-table/thumbnail.webp', src: '/items/dining-table/model.glb', dimensions: [2.5, 0.8, 1], offset: [0, 0, -0.01], rotation: [0, 0, 0], scale: [1, 1, 1], surface: { height: 0.8 }, }, { id: 'dining-chair', category: 'furniture', tags: ['floor', 'seating', 'dining'], name: 'Dining Chair', thumbnail: '/items/dining-chair/thumbnail.webp', src: '/items/dining-chair/model.glb', dimensions: [0.5, 1, 0.5], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'kitchen', category: 'kitchen', tags: ['floor', 'large', 'kitchen'], name: 'Kitchen', thumbnail: '/items/kitchen/thumbnail.webp', src: '/items/kitchen/model.glb', dimensions: [2.5, 1.1, 1], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'kitchen-counter', category: 'kitchen', tags: ['floor', 'large', 'storage', 'kitchen'], name: 'Kitchen Counter', thumbnail: '/items/kitchen-counter/thumbnail.webp', src: '/items/kitchen-counter/model.glb', dimensions: [2, 0.8, 1], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], surface: { height: 0.75 }, }, { id: 'stove', category: 'kitchen', tags: ['floor', 'large', 'kitchen'], name: 'Stove', thumbnail: '/items/stove/thumbnail.webp', src: '/items/stove/model.glb', dimensions: [1, 1, 1], offset: [0, 0, -0.05], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'fridge', category: 'kitchen', tags: ['floor', 'large', 'kitchen'], name: 'Fridge', thumbnail: '/items/fridge/thumbnail.webp', src: '/items/fridge/model.glb', dimensions: [1, 2, 1], offset: [0.01, 0, -0.05], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'toilet', category: 'bathroom', tags: ['floor', 'large', 'bathroom'], name: 'Toilet', thumbnail: '/items/toilet/thumbnail.webp', src: '/items/toilet/model.glb', dimensions: [1, 0.9, 1], offset: [0, 0, -0.23], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'bathroom-sink', category: 'bathroom', tags: ['floor', 'large', 'bathroom'], name: 'Bathroom Sink', thumbnail: '/items/bathroom-sink/thumbnail.webp', src: '/items/bathroom-sink/model.glb', dimensions: [2, 1, 1.5], offset: [0.11, 0, 0.02], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'shower-square', category: 'bathroom', tags: ['floor', 'large', 'bathroom'], name: 'Squared Shower', thumbnail: '/items/shower-square/thumbnail.webp', src: '/items/shower-square/model.glb', dimensions: [1, 2, 1], offset: [0.41, 0, -0.42], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'bathtub', category: 'bathroom', tags: ['floor', 'large', 'bathroom'], name: 'Bathtub', thumbnail: '/items/bathtub/thumbnail.webp', src: '/items/bathtub/model.glb', dimensions: [2.5, 0.8, 1.5], offset: [0, 0, 0.01], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'washing-machine', category: 'bathroom', tags: ['floor', 'large', 'electronics', 'laundry'], name: 'Washing Machine', thumbnail: '/items/washing-machine/thumbnail.webp', src: '/items/washing-machine/model.glb', dimensions: [1, 1, 1], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'drying-rack', category: 'bathroom', tags: ['floor', 'laundry'], name: 'Drying Rack', thumbnail: '/items/drying-rack/thumbnail.webp', src: '/items/drying-rack/model.glb', dimensions: [2, 1.1, 1], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, { id: 'coat-rack', category: 'furniture', tags: ['floor', 'storage', 'entry'], name: 'Coat Rack', thumbnail: '/items/coat-rack/thumbnail.webp', src: '/items/coat-rack/model.glb', dimensions: [0.5, 1.8, 0.5], offset: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1], }, ] export function findCatalogItem(id: string): AssetInput | undefined { return MCP_CATALOG_ITEMS.find((item) => item.id === id) } export function searchCatalogItems(args: { query: string category?: string | undefined }): AssetInput[] { const terms = args.query.trim().toLowerCase().split(/\s+/).filter(Boolean) return MCP_CATALOG_ITEMS.filter((item) => { if (args.category && item.category !== args.category) return false const haystack = [item.id, item.name, item.category, ...(item.tags ?? [])] .join(' ') .toLowerCase() return terms.every((term) => haystack.includes(term)) }) }