Skip to main content
Glama
room.ts7.65 kB
// Room Tools for BULC MCP Server import { z } from "zod"; import { getBulcClient } from "../bulc-client.js"; // Tool definitions export const roomTools = [ { name: "bulc_create_room", description: "Create a new rectangular room at the specified position. " + "All coordinates are in centimeters (cm). " + "Use bulc_get_spatial_context first if you need to position relative to existing rooms. " + "Example: To create a 5m x 4m room, use width=500, depth=400.", inputSchema: { type: "object" as const, properties: { x: { type: "number", description: "X coordinate of bottom-left corner in centimeters", }, y: { type: "number", description: "Y coordinate of bottom-left corner in centimeters", }, width: { type: "number", description: "Room width in centimeters (X direction). 1m = 100cm", }, depth: { type: "number", description: "Room depth in centimeters (Y direction). 1m = 100cm", }, name: { type: "string", description: "Room name for display (e.g., 'Living Room', '거실')", }, level: { type: "integer", description: "Floor level index. 0 = ground floor, 1 = first floor. Default: current level", }, }, required: ["x", "y", "width", "depth"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_create_room_polygon", description: "Create a room with a custom polygon shape defined by an array of points. " + "Use this for non-rectangular rooms like L-shaped rooms. " + "All coordinates are in centimeters.", inputSchema: { type: "object" as const, properties: { points: { type: "array", description: "Array of [x, y] coordinate pairs defining the room polygon in centimeters. " + "Minimum 3 points required. Points should be in order (clockwise or counter-clockwise).", items: { type: "array", items: { type: "number" }, minItems: 2, maxItems: 2, }, minItems: 3, }, name: { type: "string", description: "Room name for display", }, level: { type: "integer", description: "Floor level index. Default: current level", }, }, required: ["points"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_list_rooms", description: "Get a list of all rooms with their IDs, names, positions, and dimensions. " + "Use the returned IDs for modify/delete operations.", inputSchema: { type: "object" as const, properties: { level: { type: "integer", description: "Filter by floor level index. Omit to list all rooms.", }, }, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_modify_room", description: "Modify properties of an existing room. Only specified properties will be changed. " + "Get room IDs from bulc_list_rooms first.", inputSchema: { type: "object" as const, properties: { id: { type: "string", description: "Room ID to modify (from bulc_list_rooms)", }, name: { type: "string", description: "New room name", }, x: { type: "number", description: "New X coordinate of bottom-left corner (cm)", }, y: { type: "number", description: "New Y coordinate of bottom-left corner (cm)", }, width: { type: "number", description: "New width (cm)", }, depth: { type: "number", description: "New depth (cm)", }, }, required: ["id"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_delete_room", description: "Delete a room by its ID. Get room IDs from bulc_list_rooms.", inputSchema: { type: "object" as const, properties: { id: { type: "string", description: "Room ID to delete", }, }, required: ["id"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, ]; // Input validation schemas const CreateRoomSchema = z.object({ x: z.number(), y: z.number(), width: z.number().positive(), depth: z.number().positive(), name: z.string().optional(), level: z.number().int().optional(), }); const CreateRoomPolygonSchema = z.object({ points: z.array(z.tuple([z.number(), z.number()])).min(3), name: z.string().optional(), level: z.number().int().optional(), }); const ListRoomsSchema = z.object({ level: z.number().int().optional(), }); const ModifyRoomSchema = z.object({ id: z.string(), name: z.string().optional(), x: z.number().optional(), y: z.number().optional(), width: z.number().positive().optional(), depth: z.number().positive().optional(), }); const DeleteRoomSchema = z.object({ id: z.string(), }); // Handler function export async function handleRoomTool( name: string, args: Record<string, unknown> ): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> { const client = getBulcClient(); try { let result; switch (name) { case "bulc_create_room": { const validated = CreateRoomSchema.parse(args); result = await client.sendCommand({ action: "create_room", params: validated, }); break; } case "bulc_create_room_polygon": { const validated = CreateRoomPolygonSchema.parse(args); result = await client.sendCommand({ action: "create_room_polygon", params: validated, }); break; } case "bulc_list_rooms": { const validated = ListRoomsSchema.parse(args); result = await client.sendCommand({ action: "list_rooms", params: validated, }); break; } case "bulc_modify_room": { const validated = ModifyRoomSchema.parse(args); result = await client.sendCommand({ action: "modify_room", params: validated, }); break; } case "bulc_delete_room": { const validated = DeleteRoomSchema.parse(args); result = await client.sendCommand({ action: "delete_room", params: validated, }); break; } default: throw new Error(`Unknown room tool: ${name}`); } if (result.success) { return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } else { return { content: [{ type: "text", text: result.error || "Operation failed" }], isError: true, }; } } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Error: ${message}` }], isError: true, }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/using76/BULC_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server