Skip to main content
Glama
evac.js38.3 kB
// EVAC (Evacuation Simulation) Tools for BULC MCP Server // Configure and run JuPedSim-based pedestrian evacuation simulations import { z } from "zod"; import { getBulcClient } from "../bulc-client.js"; // Tool definitions export const evacTools = [ // Setup Tools { name: "bulc_set_evac_time", description: "Set evacuation simulation time parameters. " + "Controls total simulation duration and time step resolution.", inputSchema: { type: "object", properties: { simulationTime: { type: "number", description: "Total simulation time in seconds. Default: 300", }, timeStep: { type: "number", description: "Simulation time step in seconds. Default: 0.1", }, }, required: ["simulationTime"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_get_evac_settings", description: "Get current EVAC simulation settings including model type, " + "agent parameters, and stair configurations.", inputSchema: { type: "object", properties: {}, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_set_evac_model", description: "Set the evacuation simulation model type and parameters. " + "Supports CollisionFreeSpeed, SocialForce, and GeneralizedCentrifugal models.", inputSchema: { type: "object", properties: { model: { type: "string", description: "Model type: 'CollisionFreeSpeed', 'SocialForce', 'GeneralizedCentrifugal'. Default: CollisionFreeSpeed", enum: ["CollisionFreeSpeed", "SocialForce", "GeneralizedCentrifugal"], }, simulationTime: { type: "number", description: "Maximum simulation time in seconds. Default: 300", }, timeStep: { type: "number", description: "Simulation time step in seconds. Default: 0.1", }, // CollisionFreeSpeed params strengthNeighborRepulsion: { type: "number", description: "Neighbor repulsion strength (CollisionFreeSpeed). Default: 8.0", }, rangeNeighborRepulsion: { type: "number", description: "Neighbor repulsion range in meters (CollisionFreeSpeed). Default: 0.1", }, // SocialForce params bodyForce: { type: "number", description: "Body force constant (SocialForce). Default: 120000", }, friction: { type: "number", description: "Friction coefficient (SocialForce). Default: 240000", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Stair Tools { name: "bulc_list_evac_stairs", description: "List all configured evacuation stairs for multi-level buildings.", inputSchema: { type: "object", properties: {}, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_setup_evac_stair", description: "Configure a furniture item as an evacuation stair connection between floors. " + "Defines entry/exit positions, capacity, and travel speed.", inputSchema: { type: "object", properties: { furnitureId: { type: "string", description: "Furniture ID to configure as stair", }, fromFloor: { type: "integer", description: "Source floor index (0=ground floor)", }, toFloor: { type: "integer", description: "Destination floor index", }, entryX: { type: "number", description: "Entry point X coordinate in cm", }, entryY: { type: "number", description: "Entry point Y coordinate in cm", }, exitX: { type: "number", description: "Exit point X coordinate in cm", }, exitY: { type: "number", description: "Exit point Y coordinate in cm", }, width: { type: "number", description: "Stair width in meters. Default: 1.2", }, capacity: { type: "integer", description: "Max people on stair at once. Default: 10", }, travelSpeed: { type: "number", description: "Travel speed in m/s. Default: 0.6", }, }, required: ["furnitureId", "fromFloor", "toFloor"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_clear_evac_stair", description: "Remove stair configuration from a furniture item.", inputSchema: { type: "object", properties: { furnitureId: { type: "string", description: "Furniture ID to clear stair config from", }, }, required: ["furnitureId"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Agent Tools { name: "bulc_list_evac_agents", description: "List all evacuation agents with their positions and properties.", inputSchema: { type: "object", properties: { level: { type: "integer", description: "Filter by floor level. Omit for all levels.", }, room: { type: "string", description: "Filter by room name or ID", }, }, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_place_evac_agents", description: "Place evacuation agents in rooms or at specific positions. " + "Can place by count (random distribution) or at exact coordinates.", inputSchema: { type: "object", properties: { room: { type: "string", description: "Room name or ID to place agents in", }, level: { type: "integer", description: "Floor level index. Default: current level", }, count: { type: "integer", description: "Number of agents to place randomly. Required if no positions given.", }, positions: { type: "array", description: "Specific positions as [[x1,y1], [x2,y2], ...] in cm. Alternative to count.", items: { type: "array", items: { type: "number" }, }, }, agentRadius: { type: "number", description: "Agent radius in meters. Default: 0.25", }, desiredSpeed: { type: "number", description: "Desired walking speed in m/s. Default: 1.2", }, maxSpeed: { type: "number", description: "Maximum walking speed in m/s. Default: 1.5", }, minSpacing: { type: "number", description: "Minimum spacing between agents in meters. Default: 0.5", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_clear_evac_agents", description: "Clear evacuation agents from specified room or all rooms.", inputSchema: { type: "object", properties: { room: { type: "string", description: "Room name or ID to clear. Omit to clear all.", }, level: { type: "integer", description: "Floor level to clear. Omit to clear all levels.", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_set_agent_properties", description: "Set default properties for evacuation agents (radius, speed, etc.).", inputSchema: { type: "object", properties: { agentRadius: { type: "number", description: "Default agent radius in meters. Default: 0.25", }, desiredSpeed: { type: "number", description: "Default desired speed in m/s. Default: 1.2", }, maxSpeed: { type: "number", description: "Default max speed in m/s. Default: 1.5", }, minSpacing: { type: "number", description: "Minimum spacing for random placement in meters. Default: 0.5", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Advanced Tools { name: "bulc_list_evac_exits", description: "List all detected evacuation exits (doors converted to exits).", inputSchema: { type: "object", properties: { level: { type: "integer", description: "Filter by floor level", }, }, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_validate_evac", description: "Validate evacuation setup for errors and warnings. " + "Checks agents, exits, walkable areas, and stair configurations.", inputSchema: { type: "object", properties: {}, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, // Run Tools { name: "bulc_run_evac", description: "Start evacuation simulation using JuPedSim. " + "Returns immediately; use bulc_get_evac_status to monitor progress.", inputSchema: { type: "object", properties: { multiLevel: { type: "boolean", description: "Use multi-level simulation with stairs. Default: auto-detect", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_get_evac_status", description: "Get current evacuation simulation status including progress, " + "evacuated count, and estimated completion time.", inputSchema: { type: "object", properties: {}, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_stop_evac", description: "Stop a running evacuation simulation.", inputSchema: { type: "object", properties: {}, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Result Tools { name: "bulc_load_evac_result", description: "Load evacuation results from a .evac file for visualization.", inputSchema: { type: "object", properties: { evacPath: { type: "string", description: "Path to .evac file. Default: auto-detect from last simulation", }, }, }, annotations: { readOnlyHint: false, destructiveHint: false, }, }, { name: "bulc_get_evac_summary", description: "Get evacuation result summary including total time, " + "per-agent exit times, and statistics.", inputSchema: { type: "object", properties: {}, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, { name: "bulc_generate_rset_report", description: "Generate RSET (Required Safe Egress Time) analysis report " + "from evacuation simulation results.", inputSchema: { type: "object", properties: { outputPath: { type: "string", description: "Output directory for report. Default: same as results", }, language: { type: "string", description: "Report language: 'EN', 'KO', 'JP', 'CN'. Default: EN", enum: ["EN", "KO", "JP", "CN"], }, includeAgentDetails: { type: "boolean", description: "Include per-agent exit times. Default: true", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, { name: "bulc_save_evac_result", description: "Save current evacuation results to a .evac file.", inputSchema: { type: "object", properties: { outputPath: { type: "string", description: "Output path for .evac file. Default: project folder", }, filename: { type: "string", description: "Filename without extension. Default: project name", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Advanced Stair Tools { name: "bulc_modify_evac_stair", description: "Modify an existing evacuation stair configuration. " + "Update capacity, speed, or position properties.", inputSchema: { type: "object", properties: { furnitureId: { type: "string", description: "Furniture ID of the stair to modify", }, entryX: { type: "number", description: "New entry point X coordinate in cm", }, entryY: { type: "number", description: "New entry point Y coordinate in cm", }, exitX: { type: "number", description: "New exit point X coordinate in cm", }, exitY: { type: "number", description: "New exit point Y coordinate in cm", }, width: { type: "number", description: "New stair width in meters", }, capacity: { type: "integer", description: "New maximum capacity", }, travelSpeed: { type: "number", description: "New travel speed in m/s", }, }, required: ["furnitureId"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Exit Assignment Tools { name: "bulc_set_exit_assignment", description: "Set the exit assignment strategy for evacuation agents. " + "Determines how agents choose which exit to use.", inputSchema: { type: "object", properties: { mode: { type: "string", description: "Assignment mode: 'NEAREST' (closest exit), 'SHORTEST_PATH' (shortest walking path), 'BALANCED' (balance exit flow), 'CUSTOM' (manual assignment)", enum: ["NEAREST", "SHORTEST_PATH", "BALANCED", "CUSTOM"], }, balanceThreshold: { type: "number", description: "For BALANCED mode: max agents per exit ratio difference. Default: 0.2", }, customAssignments: { type: "array", description: "For CUSTOM mode: array of {agentIds: [...], exitId: '...'} assignments", items: { type: "object", properties: { agentIds: { type: "array", items: { type: "integer" }, }, exitId: { type: "string", }, }, }, }, }, required: ["mode"], }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Pre-movement Time Tools { name: "bulc_set_premovement_time", description: "Set pre-movement time parameters for evacuation agents. " + "Includes detection time and reaction time with statistical distributions.", inputSchema: { type: "object", properties: { detectionTime: { type: "number", description: "Fire detection time in seconds. Default: 0 (instant detection)", }, reactionTimeMean: { type: "number", description: "Mean reaction time in seconds. Default: 30", }, reactionTimeStdDev: { type: "number", description: "Reaction time standard deviation in seconds. Default: 10", }, distribution: { type: "string", description: "Distribution type: 'NORMAL', 'LOGNORMAL', 'UNIFORM'. Default: NORMAL", enum: ["NORMAL", "LOGNORMAL", "UNIFORM"], }, minReactionTime: { type: "number", description: "Minimum reaction time in seconds. Default: 0", }, maxReactionTime: { type: "number", description: "Maximum reaction time in seconds. For UNIFORM distribution.", }, applyPerRoom: { type: "boolean", description: "Apply different reaction times per room. Default: false", }, roomSettings: { type: "array", description: "Per-room settings: [{room: '...', reactionTimeMean: ...}, ...]", items: { type: "object", properties: { room: { type: "string" }, reactionTimeMean: { type: "number" }, reactionTimeStdDev: { type: "number" }, }, }, }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Fire-EVAC Coupling Tools { name: "bulc_set_fire_coupling", description: "Configure fire-evacuation coupling for FDS+EVAC integration. " + "Sets visibility and temperature thresholds that affect agent behavior.", inputSchema: { type: "object", properties: { enabled: { type: "boolean", description: "Enable fire-EVAC coupling. Default: false", }, visibilityThreshold: { type: "number", description: "Visibility threshold in meters. Agents avoid areas below this. Default: 5", }, temperatureThreshold: { type: "number", description: "Temperature threshold in Celsius. Agents avoid areas above this. Default: 60", }, coThreshold: { type: "number", description: "CO concentration threshold in ppm. Default: 1400", }, speedReductionFactor: { type: "number", description: "Speed reduction factor in smoke (0-1). Default: 0.5", }, updateInterval: { type: "number", description: "Fire data update interval in seconds. Default: 1.0", }, fdsResultPath: { type: "string", description: "Path to FDS result files (.smv). Auto-detected if not specified.", }, }, }, annotations: { readOnlyHint: false, destructiveHint: true, }, }, // Detailed Result Tools { name: "bulc_get_evac_result", description: "Get detailed evacuation results including per-agent trajectories, " + "exit statistics, and flow rate analysis.", inputSchema: { type: "object", properties: { includeTrajectories: { type: "boolean", description: "Include full trajectory data for each agent. Default: false", }, includeFlowRates: { type: "boolean", description: "Include exit flow rate analysis. Default: true", }, includeBottlenecks: { type: "boolean", description: "Identify bottleneck locations. Default: true", }, timeRange: { type: "array", description: "Time range [startTime, endTime] in seconds. Default: full simulation", items: { type: "number" }, }, agentIds: { type: "array", description: "Specific agent IDs to include. Default: all agents", items: { type: "integer" }, }, }, }, annotations: { readOnlyHint: true, destructiveHint: false, }, }, // Viewer Tools { name: "bulc_open_evac_viewer", description: "Open the 3D evacuation result viewer window. " + "Displays agents on the building model with timeline playback.", inputSchema: { type: "object", properties: { evacPath: { type: "string", description: "Path to .evac file. Default: auto-detect from last simulation", }, objPath: { type: "string", description: "Path to .obj 3D model file. Default: auto-detect", }, autoPlay: { type: "boolean", description: "Start playback automatically. Default: false", }, playbackSpeed: { type: "number", description: "Playback speed multiplier (0.25 to 8.0). Default: 1.0", }, agentScale: { type: "number", description: "Agent display scale (0.5 to 5.0). Default: 1.0", }, }, }, annotations: { readOnlyHint: false, destructiveHint: false, }, }, ]; // Input validation schemas const SetEvacModelSchema = z.object({ model: z.enum(["CollisionFreeSpeed", "SocialForce", "GeneralizedCentrifugal"]).optional(), simulationTime: z.number().positive().optional(), timeStep: z.number().positive().optional(), strengthNeighborRepulsion: z.number().optional(), rangeNeighborRepulsion: z.number().optional(), bodyForce: z.number().optional(), friction: z.number().optional(), }); const SetupEvacStairSchema = z.object({ furnitureId: z.string(), fromFloor: z.number().int().min(0), toFloor: z.number().int().min(0), entryX: z.number().optional(), entryY: z.number().optional(), exitX: z.number().optional(), exitY: z.number().optional(), width: z.number().positive().optional(), capacity: z.number().int().positive().optional(), travelSpeed: z.number().positive().optional(), }); const ClearEvacStairSchema = z.object({ furnitureId: z.string(), }); const ListEvacAgentsSchema = z.object({ level: z.number().int().optional(), room: z.string().optional(), }); const PlaceEvacAgentsSchema = z.object({ room: z.string().optional(), level: z.number().int().optional(), count: z.number().int().positive().optional(), positions: z.array(z.array(z.number()).length(2)).optional(), agentRadius: z.number().positive().optional(), desiredSpeed: z.number().positive().optional(), maxSpeed: z.number().positive().optional(), minSpacing: z.number().positive().optional(), }); const ClearEvacAgentsSchema = z.object({ room: z.string().optional(), level: z.number().int().optional(), }); const SetAgentPropertiesSchema = z.object({ agentRadius: z.number().positive().optional(), desiredSpeed: z.number().positive().optional(), maxSpeed: z.number().positive().optional(), minSpacing: z.number().positive().optional(), }); const ListEvacExitsSchema = z.object({ level: z.number().int().optional(), }); const RunEvacSchema = z.object({ multiLevel: z.boolean().optional(), }); const LoadEvacResultSchema = z.object({ evacPath: z.string().optional(), }); const GenerateRsetReportSchema = z.object({ outputPath: z.string().optional(), language: z.enum(["EN", "KO", "JP", "CN"]).optional(), includeAgentDetails: z.boolean().optional(), }); const SaveEvacResultSchema = z.object({ outputPath: z.string().optional(), filename: z.string().optional(), }); const SetEvacTimeSchema = z.object({ simulationTime: z.number().positive(), timeStep: z.number().positive().optional(), }); const ModifyEvacStairSchema = z.object({ furnitureId: z.string(), entryX: z.number().optional(), entryY: z.number().optional(), exitX: z.number().optional(), exitY: z.number().optional(), width: z.number().positive().optional(), capacity: z.number().int().positive().optional(), travelSpeed: z.number().positive().optional(), }); const SetExitAssignmentSchema = z.object({ mode: z.enum(["NEAREST", "SHORTEST_PATH", "BALANCED", "CUSTOM"]), balanceThreshold: z.number().positive().optional(), customAssignments: z.array(z.object({ agentIds: z.array(z.number().int()), exitId: z.string(), })).optional(), }); const SetPremovementTimeSchema = z.object({ detectionTime: z.number().min(0).optional(), reactionTimeMean: z.number().min(0).optional(), reactionTimeStdDev: z.number().min(0).optional(), distribution: z.enum(["NORMAL", "LOGNORMAL", "UNIFORM"]).optional(), minReactionTime: z.number().min(0).optional(), maxReactionTime: z.number().positive().optional(), applyPerRoom: z.boolean().optional(), roomSettings: z.array(z.object({ room: z.string(), reactionTimeMean: z.number().optional(), reactionTimeStdDev: z.number().optional(), })).optional(), }); const SetFireCouplingSchema = z.object({ enabled: z.boolean().optional(), visibilityThreshold: z.number().positive().optional(), temperatureThreshold: z.number().positive().optional(), coThreshold: z.number().positive().optional(), speedReductionFactor: z.number().min(0).max(1).optional(), updateInterval: z.number().positive().optional(), fdsResultPath: z.string().optional(), }); const GetEvacResultSchema = z.object({ includeTrajectories: z.boolean().optional(), includeFlowRates: z.boolean().optional(), includeBottlenecks: z.boolean().optional(), timeRange: z.array(z.number()).length(2).optional(), agentIds: z.array(z.number().int()).optional(), }); const OpenEvacViewerSchema = z.object({ evacPath: z.string().optional(), objPath: z.string().optional(), autoPlay: z.boolean().optional(), playbackSpeed: z.number().min(0.25).max(8.0).optional(), agentScale: z.number().min(0.5).max(5.0).optional(), }); // Handler function export async function handleEvacTool(name, args) { const client = getBulcClient(); try { let result; switch (name) { case "bulc_get_evac_settings": { result = await client.sendCommand({ action: "get_evac_settings", params: {}, }); break; } case "bulc_set_evac_model": { const validated = SetEvacModelSchema.parse(args); result = await client.sendCommand({ action: "set_evac_model", params: validated, }); break; } case "bulc_list_evac_stairs": { result = await client.sendCommand({ action: "list_evac_stairs", params: {}, }); break; } case "bulc_setup_evac_stair": { const validated = SetupEvacStairSchema.parse(args); result = await client.sendCommand({ action: "setup_evac_stair", params: validated, }); break; } case "bulc_clear_evac_stair": { const validated = ClearEvacStairSchema.parse(args); result = await client.sendCommand({ action: "clear_evac_stair", params: validated, }); break; } case "bulc_list_evac_agents": { const validated = ListEvacAgentsSchema.parse(args); result = await client.sendCommand({ action: "list_evac_agents", params: validated, }); break; } case "bulc_place_evac_agents": { const validated = PlaceEvacAgentsSchema.parse(args); result = await client.sendCommand({ action: "place_evac_agents", params: validated, }); break; } case "bulc_clear_evac_agents": { const validated = ClearEvacAgentsSchema.parse(args); result = await client.sendCommand({ action: "clear_evac_agents", params: validated, }); break; } case "bulc_set_agent_properties": { const validated = SetAgentPropertiesSchema.parse(args); result = await client.sendCommand({ action: "set_agent_properties", params: validated, }); break; } case "bulc_list_evac_exits": { const validated = ListEvacExitsSchema.parse(args); result = await client.sendCommand({ action: "list_evac_exits", params: validated, }); break; } case "bulc_validate_evac": { result = await client.sendCommand({ action: "validate_evac", params: {}, }); break; } case "bulc_run_evac": { const validated = RunEvacSchema.parse(args); result = await client.sendCommand({ action: "run_evac", params: validated, }); break; } case "bulc_get_evac_status": { result = await client.sendCommand({ action: "get_evac_status", params: {}, }); break; } case "bulc_stop_evac": { result = await client.sendCommand({ action: "stop_evac", params: {}, }); break; } case "bulc_load_evac_result": { const validated = LoadEvacResultSchema.parse(args); result = await client.sendCommand({ action: "load_evac_result", params: validated, }); break; } case "bulc_get_evac_summary": { result = await client.sendCommand({ action: "get_evac_summary", params: {}, }); break; } case "bulc_generate_rset_report": { const validated = GenerateRsetReportSchema.parse(args); result = await client.sendCommand({ action: "generate_rset_report", params: validated, }); break; } case "bulc_save_evac_result": { const validated = SaveEvacResultSchema.parse(args); result = await client.sendCommand({ action: "save_evac_result", params: validated, }); break; } case "bulc_set_evac_time": { const validated = SetEvacTimeSchema.parse(args); result = await client.sendCommand({ action: "set_evac_time", params: validated, }); break; } case "bulc_modify_evac_stair": { const validated = ModifyEvacStairSchema.parse(args); result = await client.sendCommand({ action: "modify_evac_stair", params: validated, }); break; } case "bulc_set_exit_assignment": { const validated = SetExitAssignmentSchema.parse(args); result = await client.sendCommand({ action: "set_exit_assignment", params: validated, }); break; } case "bulc_set_premovement_time": { const validated = SetPremovementTimeSchema.parse(args); result = await client.sendCommand({ action: "set_premovement_time", params: validated, }); break; } case "bulc_set_fire_coupling": { const validated = SetFireCouplingSchema.parse(args); result = await client.sendCommand({ action: "set_fire_coupling", params: validated, }); break; } case "bulc_get_evac_result": { const validated = GetEvacResultSchema.parse(args); result = await client.sendCommand({ action: "get_evac_result", params: validated, }); break; } case "bulc_open_evac_viewer": { const validated = OpenEvacViewerSchema.parse(args); result = await client.sendCommand({ action: "open_evac_viewer", params: validated, }); break; } default: throw new Error(`Unknown EVAC 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