Metadata-Version: 2.4
Name: ifcopenshell-mcp
Version: 0.8.6
Summary: MCP server for querying and editing IFC building models
Author-email: Bruno Postle <bruno@postle.net>
Project-URL: Homepage, http://ifcopenshell.org
Project-URL: Documentation, https://docs.ifcopenshell.org
Project-URL: Issues, https://github.com/IfcOpenShell/IfcOpenShell/issues
Keywords: IFC,BIM,MCP
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Description-Content-Type: text/markdown
Requires-Dist: ifcopenshell
Requires-Dist: ifcquery
Requires-Dist: ifcedit
Provides-Extra: mcp
Requires-Dist: mcp; extra == "mcp"

<!-- This file was generated with the assistance of an AI coding tool. -->
# ifcmcp

An MCP (Model Context Protocol) server that wraps `ifcquery` and `ifcedit`,
holding the IFC model in memory across tool calls for fast interactive editing
sessions.

## Installation

```bash
pip install ifcopenshell-mcp
```

Requires `ifcopenshell`, `ifcquery`, and `ifcedit`. The `mcp` package is an optional dependency needed to run the server; install it with `pip install ifcopenshell-mcp[mcp]` or add `mcp` separately.

## Running the server

```bash
ifcmcp
```

This starts the server on stdio transport, suitable for use with Claude Code
or any MCP client.

### Claude Code configuration

Use the `claude mcp add` command:

```bash
claude mcp add --transport stdio ifc -- ifcmcp
```

Or create a `.mcp.json` file in your project root:

```json
{
  "mcpServers": {
    "ifc": {
      "type": "stdio",
      "command": "ifcmcp"
    }
  }
}
```

After adding the server, restart Claude Code for the tools to become available.
Then load a model by asking Claude to use `ifc_load`:

```
load model.ifc using ifc_load
```

## Tools

### Session

#### ifc_new

Create a new empty IFC model in memory, replacing any currently loaded model.

```
ifc_new()
ifc_new(schema="IFC4X3")
```

Default schema is `IFC4`.

#### ifc_load

Open an IFC file into memory.

```
ifc_load(path="/path/to/model.ifc")
-> "Loaded /path/to/model.ifc: schema IFC4, 1847 entities"
```

#### ifc_reset

Unload the current model from memory, freeing all session state.

```
ifc_reset()
```

#### ifc_save

Write the in-memory model to disk. Empty path overwrites the original file.

```
ifc_save()
ifc_save(path="/path/to/output.ifc")
```

### Query tools

All query tools require a model to be loaded first via `ifc_load`.

#### ifc_summary

Model overview: schema, entity counts, project info.

```json
{
  "schema": "IFC4",
  "total_entities": 1847,
  "project": {"id": 1, "name": "Office Building"},
  "types": {"IfcWall": 42, "IfcSlab": 12, "IfcWindow": 36}
}
```

#### ifc_tree

Full spatial hierarchy from IfcProject down through sites, buildings, storeys,
and contained elements.

```json
{
  "id": 1,
  "type": "IfcProject",
  "name": "Office Building",
  "children": [
    {
      "id": 2,
      "type": "IfcSite",
      "children": [{"id": 3, "type": "IfcBuilding", "children": ["..."]}]
    }
  ]
}
```

#### ifc_info

Deep inspection of an entity by step ID: attributes, property sets, type,
material, container, and 4x4 placement matrix.

```
ifc_info(element_id=10)
```

#### ifc_select

Filter elements using ifcopenshell selector syntax.

```
ifc_select(query="IfcWall")
ifc_select(query="IfcWindow")
```

Returns a sorted list of `{"id", "type", "name"}` references.

#### ifc_relations

Show all relationships for an element: hierarchy, children, type, groups,
systems, material, connections.

```
ifc_relations(element_id=10)
ifc_relations(element_id=10, traverse="up")
```

With `traverse="up"`, walks the hierarchy from element up to IfcProject.

#### ifc_contexts

List all geometric representation contexts and subcontexts in the loaded model.

```
ifc_contexts()
```

#### ifc_materials

List all materials and material sets in the loaded model, with their assigned elements.

```
ifc_materials()
```

#### ifc_clash

Check an element for geometric intersections and clearance violations.

```
ifc_clash(element_id=10)
ifc_clash(element_id=10, clearance=0.5, scope="all")
```

Parameters:

- `clearance` -- minimum clearance distance in meters (0.0 = no clearance check)
- `tolerance` -- intersection tolerance in meters (default: 0.002)
- `scope` -- `"storey"` or `"all"` (default: `"storey"`)

#### ifc_validate

Check the model for schema and constraint violations.

```
ifc_validate()
ifc_validate(express_rules=True)
```

Returns `{"valid": true, "issues": []}` or `{"valid": false, "issues": [{"level": "ERROR", "message": "..."}]}`.

#### ifc_schedule

List all work schedules and their nested task trees.

```
ifc_schedule()
ifc_schedule(max_depth=1)   # top-level phases only
```

`max_depth` limits subtask expansion. At the cutoff, `subtasks` is replaced
with `{"truncated": true, "count": N}` so you know children exist without
fetching them all. Omit for unlimited depth.

#### ifc_cost

List all cost schedules and their nested cost item trees.

```
ifc_cost()
ifc_cost(max_depth=2)   # top two levels of the BoQ
```

`max_depth` limits cost item expansion, same truncation convention as
`ifc_schedule`.

#### ifc_schema

Return IFC class documentation for any entity type, using the loaded model's
schema version.

```
ifc_schema(entity_type="IfcWall")
ifc_schema(entity_type="IfcBuildingStorey")
```

Returns description, predefined types, spec URL, and attribute descriptions.
Returns `{"error": "Unknown entity: Foo"}` for unrecognised types.

#### ifc_quantify

Run quantity take-off (QTO) on the loaded model using an `ifc5d` rule.
Computes physical measurements (volume, area, length, count, weight) and
writes them back as `IfcElementQuantity` property sets. Modifies the model
in-place -- call `ifc_save()` when done.

```
ifc_quantify(rule="IFC4QtoBaseQuantities")
ifc_quantify(rule="IFC4QtoBaseQuantities", selector="IfcWall")
```

Available rules: `IFC4QtoBaseQuantities`, `IFC4X3QtoBaseQuantities`.

`selector` is an optional ifcopenshell selector to restrict which elements
are quantified (default: all `IfcElement`).

Returns `{"ok": true, "rule": "...", "elements_quantified": 42}`.

### Drawing and rendering tools

#### ifc_plot

Generate a 2D technical drawing of the loaded model and return it as an inline image.

```
ifc_plot()
ifc_plot(selector="IfcWall", view="floorplan", scale=0.01, output_path="/tmp/plan.svg")
ifc_plot(element_ids=[10, 11], view="floorplan")
```

Parameters:

- `selector` -- ifcopenshell selector to restrict plotted elements
- `element_ids` -- step IDs of elements to highlight; others are faded
- `view` -- `"floorplan"` (default), `"elevation"`, `"section"`, or `"auto"`
- `width_mm`, `height_mm` -- paper size in mm (default: 297 x 420)
- `scale` -- model-to-paper ratio (default: 0.01 = 1:100)
- `png_width`, `png_height` -- raster output size in pixels (default: 1024 x 1024)
- `output_path` -- optional path to also save to disk (`.svg` for vector, otherwise PNG)

Returns an inline PNG the LLM can inspect. Requires `ifcopenshell.draw`.

#### ifc_render

Render the loaded model to a 3D PNG image.

```
ifc_render()
ifc_render(selector="IfcWall", view="iso", output_path="/tmp/model.png")
ifc_render(element_ids=[10, 11], view="south")
```

Parameters:

- `selector` -- ifcopenshell selector to restrict rendered elements
- `element_ids` -- step IDs of elements to highlight; others are shown translucent
- `view` -- `"iso"` (default), `"top"`, `"south"`, `"north"`, `"east"`, or `"west"`
- `output_path` -- optional path to save the PNG to disk

Returns an inline PNG. Requires `pyvista` and the IfcOpenShell C++ geometry bindings.

### Shape builder tools

#### ifc_shape_list

List all available `ShapeBuilder` methods with brief descriptions.

```
ifc_shape_list()
```

#### ifc_shape_docs

Show full documentation for a specific `ShapeBuilder` method.

```
ifc_shape_docs(method="extrude")
ifc_shape_docs(method="create_ellipse")
```

#### ifc_shape

Execute a `ShapeBuilder` method on the loaded model.

```
ifc_shape(method="extrude", params='{"profile": "42", "magnitude": 3.0}')
```

`params` is a JSON string; entity references are resolved by step ID (same coercion as `ifc_edit`).

### Edit discovery tools

#### ifc_list

List all API modules, or functions within a specific module.

```
ifc_list()              # all modules
ifc_list(module="root") # functions in the root module
```

#### ifc_docs

Show full documentation for an API function including parameters, types,
defaults, and descriptions.

```
ifc_docs(function_path="root.create_entity")
```

### Edit execution

#### ifc_edit

Execute an `ifcopenshell.api` mutation function. Parameters are passed as a
JSON string with string values that get coerced by ifcedit's type system.

```
ifc_edit(
    function_path="root.create_entity",
    params='{"ifc_class": "IfcWall", "name": "My Wall"}'
)
```

Returns `{"ok": true, "result": ...}` or `{"ok": false, "error": "..."}`.

Does NOT auto-save -- call `ifc_save()` when ready to write changes to disk.

**Parameter coercion:**

| Type | JSON value | Python value |
|------|------------|--------------|
| `entity_instance` | `"42"` | resolved from model by step ID |
| `list[entity_instance]` | `"5,6,7"` | list of resolved entities |
| `dict` | `'{"key": "val"}'` | parsed JSON object |
| `bool` | `"true"` | `True` |
| `Optional[X]` | `"none"` | `None` |

## Typical workflow

1. **Load** a model: `ifc_load`
2. **Inspect** with query tools: `ifc_summary`, `ifc_tree`, `ifc_select`, `ifc_info`, `ifc_relations`
3. **Validate** if needed: `ifc_validate`
4. **Browse schedules / costs**: `ifc_schedule`, `ifc_cost` (use `max_depth=1` first on large projects)
5. **Look up IFC classes**: `ifc_schema`
6. **Find** the right API function: `ifc_list`, `ifc_docs`
7. **Edit** the model: `ifc_edit`
8. **Quantify** elements: `ifc_quantify` (writes QTO psets in-place)
9. **Verify** changes with query tools
10. **Save** when satisfied: `ifc_save`

The model stays in memory across all calls, so multi-step editing sessions
are fast -- no file I/O between operations.

## License

LGPLv3+ -- see the IfcOpenShell project license.
