Skip to content

Tools: Geometry

3D geometry viewer tool — renders building surfaces in an interactive Three.js viewport.

geometry_viewer_html()

Return the self-contained Three.js viewer HTML.

Source code in src/idfkit_mcp/tools/geometry.py
@resource(
    "ui://idfkit/geometry-viewer.html",
    name="geometry_viewer",
    title="3D Geometry Viewer",
    description="Interactive Three.js viewer for EnergyPlus building geometry.",
    meta={
        "ui": app_config_to_meta_dict(
            AppConfig(
                csp=ResourceCSP(resourceDomains=["https://cdn.jsdelivr.net", "https://unpkg.com"]),
                prefersBorder=False,
            )
        )
    },
)
def geometry_viewer_html() -> str:
    """Return the self-contained Three.js viewer HTML."""
    return VIEWER_HTML

view_geometry(color_by='type')

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),
        ]
    )