Show interactive 3D building geometry from the loaded model.
Renders all building surfaces, fenestration, and shading geometry in a
Three.js viewport with orbit controls. Click surfaces to inspect
properties; toggle visibility by surface type or zone.
Source code in src/idfkit_mcp/tools/geometry.py
| @tool(
annotations=_READ_ONLY,
meta={
"ui": app_config_to_meta_dict(
AppConfig(
resourceUri="ui://idfkit/geometry-viewer.html",
prefersBorder=False,
)
)
},
)
def view_geometry(
color_by: Annotated[
Literal["type", "zone"],
Field(description="Color surfaces by type (wall/floor/roof/window) or zone."),
] = "type",
) -> ToolResult:
"""Show interactive 3D building geometry from the loaded model.
Renders all building surfaces, fenestration, and shading geometry in a
Three.js viewport with orbit controls. Click surfaces to inspect
properties; toggle visibility by surface type or zone.
"""
data = _extract_geometry(color_by)
surfaces = data["surfaces"]
zones = data["zones"]
count = len(surfaces) # type: ignore[arg-type]
zone_count = len(zones) # type: ignore[arg-type]
logger.info("Extracted %d surfaces across %d zones for geometry viewer", count, zone_count)
# Build a text summary for clients that don't support MCP Apps.
type_counts: dict[str, int] = {}
for s in surfaces: # type: ignore[union-attr]
st = s["surfaceType"] # type: ignore[index]
type_counts[st] = type_counts.get(st, 0) + 1 # type: ignore[arg-type]
breakdown = ", ".join(f"{c} {t}" for t, c in sorted(type_counts.items()))
summary = f"Model geometry: {count} surfaces across {zone_count} zones ({breakdown})."
# The content array is delivered to the viewer via ontoolresult.
# Non-Apps hosts display the text content to the LLM as a fallback.
return ToolResult(
content=[
TextContent(type="text", text=json.dumps(data)),
TextContent(type="text", text=summary),
]
)
|