Skip to main content

ifcviewx

The pip package behind IFCViewX Local Studio. One install serves the full viewer at http://127.0.0.1:8765 and adds everything a browser tab alone cannot do:

  • IFC to .ifcx conversion with IfcOpenShell, with live progress and cancel
  • native IfcOpenShell Python, so the browser never downloads a runtime
  • model checks and element schedules that need no generated code
  • the viewer exposed to MCP clients (Claude Desktop, Claude Code) as tools
  • an optional assistant proxy so the provider key never reaches the browser

Everything stays on your machine.

Install and run

Until the package is on PyPI, install the wheel from the latest release by URL. IfcOpenShell comes with it, so there is nothing else to add (~100 MB):

pip install https://github.com/nbharathik/ifc-viewx/releases/latest/download/ifcviewx-0.1.0-py3-none-any.whl
ifcviewx                            # serves the viewer and opens the browser
ifcviewx model.ifc                  # same, with the model staged and opened
ifcviewx model.ifc --convert        # convert to .ifcx first, then open
ifcviewx convert model.ifc          # terminal conversion (also: ifcx-convert)
ifcviewx mcp                        # MCP over stdio, for AI clients

IfcOpenShell is a plain dependency, so conversion, native Python and model checks are there by default. On a Python it has no wheel for, the install still succeeds and those three report themselves as not configured rather than breaking the viewer. A second ifcviewx model.ifc while one instance runs reuses it: the file is staged into the shared store and the browser opens on the running service.

Local Studio is a self-contained app, not an add-on to the hosted viewer. It carries its own copy of the viewer, serves it from 127.0.0.1, and hands that page its session token, so it opens with everything on and nothing to type. The hosted copy is a separate app that never talks to this service: there is no pairing step and no token to paste anywhere.

Working from a checkout: cd local-bridge && pip install -e .. The service then serves the repo's dist/ from npm run build at the root.

CLI flags

Flag Meaning
--port N serve on this port (default 8765)
--token T fix the session token instead of a random one
--convert convert the given model to .ifcx before opening
--readonly refuse uploads, conversions and edits
--no-python disable code execution entirely
--no-browser do not open a browser

Configuration

Environment variables use the IFCVIEWX_ prefix (the pre-rename IFC_BRIDGE_ names are still read as a fallback).

Variable Default Purpose
IFCVIEWX_TOKEN random 128-bit fixes the session token across runs
IFCVIEWX_PORT 8765 HTTP/WebSocket port
IFCVIEWX_APP packaged app / repo dist/ a built viewer to serve
IFCVIEWX_MODELS ~/.cache/ifcviewx/models model store
IFCVIEWX_STATE store parent audit log location
IFCVIEWX_ORIGINS (unset) extra browser origins to trust besides localhost; only for hosting the viewer yourself
IFCVIEWX_ROOTS (unset) restrict convert_model to these directories
IFCVIEWX_ALLOW_PYTHON 1 set 0 to disable code execution entirely
IFCVIEWX_READONLY 0 set 1 to refuse uploads, conversions and edits
IFCVIEWX_STORE_GB 20 store quota; oldest models are evicted past it
IFCVIEWX_MAX_UPLOAD_MB 2048 per-upload ceiling
IFCVIEWX_PYTHON_TIMEOUT 120 seconds before generated code is killed
IFCVIEWX_CONVERT_TIMEOUT 900 seconds before a conversion is killed
IFCVIEWX_MEMORY_GB 4 address-space cap for child processes (POSIX)
IFCVIEWX_RESULT_TTL_S 3600 how long an unapplied edit result is kept
IFCVIEWX_LLM_PROVIDER (unset) openai-compatible or anthropic to enable the proxy
IFCVIEWX_LLM_BASE_URL / _API_KEY / _MODEL (unset) proxy target

HTTP API

Route Purpose
GET /health version and capabilities; store and posture with a token
POST /model upload an IFC, stored by SHA-256
POST /convert start a conversion job
GET /jobs/{id} job status with percent
POST /jobs/{id}/cancel kill a running conversion
GET /models/{sha}.ifcx the converted model (.ifc serves the source)
POST /python run guarded code, query or edit
GET /python/result/{id} download an edit result
POST /guard check code without running it
POST /validate structural QA, no code execution
POST /schedule element/property table, no code execution
GET /store, POST /store/prune model cache stats and cleanup
POST /llm/chat assistant proxy (when configured)
GET /audit recent activity
WS /ws?token= MCP bridge to the browser

Everything except /health and /models/{sha} requires the X-IFC-Token header.

Security

Transport. Bound to 127.0.0.1 only. The Host header must be localhost, which blocks DNS rebinding that a token check alone would not. Browser origins must be localhost. The only page this service answers is the copy of the viewer it served itself, so no site on the internet is trusted, including the hosted copy of this same viewer. IFCVIEWX_ORIGINS names extra origins for someone hosting the viewer themselves; it is empty by default, and pointing it at a page you do not control hands that page everything the token protects.

Authentication. A 128-bit per-run token gates every route that writes, executes or describes this machine. Comparisons are constant time, and repeated failures from one client are throttled.

Generated code passes through three layers, because any one of them can be wrong:

  1. an AST guard, not a regex scan, so getattr(x, "__cla" + "ss__") is caught like any other dunder access. Imports are allowlisted, and eval, exec, compile, open, globals and friends are rejected outright.
  2. a throwaway subprocess with curated __builtins__ (the dangerous names are simply absent), an import hook that re-checks the allowlist at runtime, a scrubbed environment, a temporary working directory, and address-space, CPU and file-descriptor limits where the platform provides them.
  3. the edit contract: code never touches the stored source. It runs against a fresh handle, writes a separate result file, and the change only reaches the model after the user clicks Apply in the viewer.

The reply carries a measured diff (added / removed / modified GlobalIds) computed by comparing the model before and after, not the summary the code claims. IFCVIEWX_ALLOW_PYTHON=0 removes the capability altogether.

Data. Uploads are content-addressed, sniffed for a STEP header before they are kept, capped per file and in total, and evicted oldest-first past the quota. Unapplied edit results expire. No filename ever comes from a client.

Auditing. Every guarded action appends one line to ~/.cache/ifcviewx/audit.jsonl: what ran, when, from where, and for code its hash and first line, never the source itself.

What this is not. The service executes IfcOpenShell code on your machine by design. The layers above make accidental and casual-hostile code fail closed; they are not a substitute for an OS sandbox. Run with IFCVIEWX_ALLOW_PYTHON=0 if you only want viewing, conversion and checks.

MCP client configuration (Claude Desktop example)

{
  "mcpServers": {
    "ifcviewx": {
      "command": "ifcviewx",
      "args": ["mcp"],
      "env": { "IFCVIEWX_TOKEN": "choose-a-token" }
    }
  }
}

ifcviewx mcp serves the viewer and the HTTP API too, so the browser side of the bridge is the same app at http://127.0.0.1:8765.

Tools

Viewer: get_status, get_model_info, get_spatial_tree, get_selection, select_element, get_properties, set_visibility, show_all, fit_view.

Analysis without generated code: validate_model, element_schedule.

Files and housekeeping: convert_model, list_converted_models, service_status.

No execution tool. There is no run_python and no other way for an MCP client to execute code. A client reads the model, drives the viewport and stages typed edits, and every edit waits for the user to click Apply. Running IfcOpenShell is the user's, in the viewer's Python Console, which only a human click starts. The service still executes Python for that console over HTTP, authenticated with the session token.

Tests and packaging

python -m pytest tests -q

The suite covers guard bypasses, the route authorisation matrix, store quotas and path safety, and sandbox behaviour end to end against a real IFC file.

Building the wheel bundles the viewer: npm run build at the repo root, then python -m build local-bridge. The hatch hook copies dist/ into the package and refuses to pack without it. Tagging v* publishes to PyPI via .github/workflows/publish-pypi.yml (trusted publishing).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ifcviewx-0.1.1.tar.gz (1.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ifcviewx-0.1.1-py3-none-any.whl (1.6 MB view details)

Uploaded Python 3

File details

Details for the file ifcviewx-0.1.1.tar.gz.

File metadata

  • Download URL: ifcviewx-0.1.1.tar.gz
  • Upload date:
  • Size: 1.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ifcviewx-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7f4a93545cebec87bad59c8b670ee784acb3fcba410952f594e7ea3fca7b69d4
MD5 4279517a80c3141257bdb3c8152ea546
BLAKE2b-256 04688f50805934c2dbaa3b525bf57352dbc92bca3aa8f9d1d7406c173cf2f3b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcviewx-0.1.1.tar.gz:

Publisher: publish-pypi.yml on nbharathik/ifc-viewx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ifcviewx-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: ifcviewx-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 1.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ifcviewx-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 79c5bac4502da7ac73d06857ca93f449af07a09f891f689c03341ede508aa7f0
MD5 91b79c86def7e9ebf4318aad99c51dd4
BLAKE2b-256 cd7aaf5941535a0d0ca85243cd88a8520530a8a47fa9fc257ab1fdc37f463505

See more details on using hashes here.

Provenance

The following attestation bundles were made for ifcviewx-0.1.1-py3-none-any.whl:

Publisher: publish-pypi.yml on nbharathik/ifc-viewx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.1.4

2 files

0.1.2

2 files

This release

0.1.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page