Model Context Protocol server for OpenStudio building energy simulation. It lets MCP hosts — Claude Desktop, Claude Code, Cursor, VS Code — create, query, and modify OpenStudio models, run EnergyPlus, and read results, all in plain language. The server handles the OpenStudio/EnergyPlus complexity behind MCP tool calls.
146 tools · 12 workflow skills · 480+ integration tests
- "Create a 10-zone office with VAV reheat and run an annual simulation."
- "What's the EUI? Show me the unmet heating hours."
- "Switch the HVAC from VAV to VRF heat pumps and compare energy use."
- "Add R-30 roof insulation and see how it affects the cooling load."
- "Build two adjacent zones from floor plans, match the shared wall, add 40% south glazing."
- "Write a measure that sets all lights to 8 W/m², test it, apply it, and compare the EUI."
The AI picks the right tools, calls them in sequence, and summarizes — no scripting.
Runs the server locally over stdio — one container per user, launched by your MCP host. For a shared deployment, see Remote & multi-user.
Prerequisites: Docker Desktop running, and an MCP host (Claude Desktop is the easiest start).
git clone https://github.com/NatLabRockies/openstudio-mcp.git
cd openstudio-mcp| Machine | Build command |
|---|---|
| Intel/AMD (Linux, Windows, Intel Mac) | docker build -t openstudio-mcp:dev -f docker/Dockerfile . |
| Apple Silicon (M-series) | docker build --platform linux/arm64 -t openstudio-mcp:dev -f docker/Dockerfile.arm64 . |
Both produce the same openstudio-mcp:dev image. The arm64 Dockerfile builds natively from NREL's arm64 .deb (the upstream nrel/openstudio base is amd64-only, so plain Dockerfile runs under slow emulation on Apple Silicon).
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows), then restart Claude Desktop:
{
"mcpServers": {
"openstudio-mcp": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "./tests/assets:/inputs",
"-v", "./runs:/runs",
"-v", "./.claude/skills:/skills:ro",
"-e", "OPENSTUDIO_MCP_MODE=prod",
"openstudio-mcp:dev", "openstudio-mcp"
]
}
}
}The -v host:container mounts expose your folders inside the container: /inputs for your models (starts with the bundled test models), /runs for simulation outputs, /skills for the workflow guides. Use absolute paths if ./ doesn't resolve from where your host launches Docker.
Look for the hammer icon in Claude Desktop's input — click it to see the openstudio-mcp tools. Then try, in order:
"Create an example model and tell me about it" → "Create a baseline office with ASHRAE System 3 and show me the HVAC components" → "Load /inputs/MyBuilding.osm, apply the 90.1-2019 typical template, and run a simulation"
Use the /inputs mount for your own files rather than uploading through chat — Claude Desktop's upload sandbox can't reach MCP tools, so the AI may fall back to writing scripts. Drop a file in the host folder mapped to /inputs and reference it by that path. Simulation outputs in /runs are already reachable.
Other hosts: Claude Code, VS Code Copilot, Windsurf, and Gemini CLI use similar JSON config — see the MCP docs.
| Client | Status | Notes |
|---|---|---|
| Claude Desktop | ✅ Full | all tools available |
| Claude Code | ✅ Full | ToolSearch auto-defers tools for efficient discovery |
| VS Code Copilot | ✅ Compatible | MCP via config |
| Windsurf | ✅ Compatible | under the 100-tool limit |
| Gemini CLI | ✅ Compatible | use includeTools/excludeTools if needed |
| OpenAI API | ✅ Compatible | use defer_loading for best results |
| Cursor | 40-tool hard cap — use Claude Code or Windsurf |
The quick start runs one container per user over stdio. To host it on one machine and let teammates connect from their own laptops — each with an isolated session, run directory, and optional bearer-token or JWT auth — run it over streamable HTTP (-e MCP_TRANSPORT=http). Works with Claude Code, Cursor, and VS Code.
See docs/remote-multi-user.md for setup, auth, the isolation model, and log access — and docs/run-retention.md for optional disk garbage-collection.
In Claude Code, 12 bundled skills add workflow automation and domain knowledge:
| Skill | Type | What it does |
|---|---|---|
/simulate |
Workflow | one-command simulate + results extraction |
/energy-report |
Workflow | comprehensive multi-category energy report |
/new-building |
Workflow | full model creation from scratch |
/retrofit |
Workflow | before/after ECM analysis |
/add-hvac |
Task | guided HVAC system selection |
/qaqc |
Task | pre-simulation model quality check |
/view |
Task | quick 3D model visualization |
/troubleshoot |
Task | diagnose simulation failures |
measure-authoring |
Knowledge | measure creation, SDK verification, wiring patterns |
ashrae-baseline-guide |
Knowledge | ASHRAE 90.1 system selection |
openstudio-patterns |
Knowledge | tool dependencies and model relationships |
tool-workflows |
Knowledge | multi-tool recipes for common operations |
Workflow/task skills are invoked with /name; knowledge skills load automatically. Any MCP host can also discover these guides via the list_skills() and get_skill(name) tools (mount -v ./.claude/skills:/skills:ro).
146 tools, grouped by area — expand a group to see its tools. New here? create_new_building, run_simulation, and extract_summary_metrics cover most workflows; list_skills() and recommend_tools(task) help the AI find the rest.
Model creation & management — 13 tools
| Tool | Description |
|---|---|
create_new_building |
Create a complete building end-to-end (geometry + weather + typical template) |
create_bar_building |
Create bar-building geometry from type, floor area, aspect ratio |
create_typical_building |
Add constructions, loads, HVAC, SWH to a model with geometry |
create_example_osm |
Minimal single-zone example (testing/demos) |
create_baseline_osm |
10-zone baseline with ASHRAE system 1–10 (testing/demos) |
inspect_osm_summary |
Quick structural summary of an OSM file |
load_osm_model |
Load OSM into memory for querying/editing |
save_osm_model |
Save the in-memory model to disk |
list_files |
Discover files in /inputs and /runs |
get_building_info |
Building name, area, volume, orientation |
get_model_summary |
Object counts by category |
delete_object |
Delete any named object (28+ types) |
rename_object |
Rename any named object |
Generic object access — 3 tools
Read/write any OpenStudio object by introspection — covers types without a dedicated tool.
| Tool | Description |
|---|---|
list_model_objects |
List objects of any type (CamelCase, IDD colon, or underscore) |
get_object_fields |
Read all properties of an object — returns values + available setters |
set_object_property |
Write any property via official setters — auto-coerces types |
Spaces & thermal zones — 6 tools
| Tool | Description |
|---|---|
list_spaces |
List spaces with area/volume |
get_space_details |
Surfaces, loads, zone for a space |
list_thermal_zones |
List thermal zones with spaces |
get_thermal_zone_details |
Zone equipment, thermostat, multiplier |
create_space |
Create a space (optional story/space type) |
create_thermal_zone |
Create a thermal zone, assign spaces |
Geometry — 9 tools
| Tool | Description |
|---|---|
list_surfaces |
List surfaces (walls, floors, roofs) |
get_surface_details |
Vertices, construction, boundary |
list_subsurfaces |
List windows, doors, skylights |
create_surface |
Create a surface from explicit 3D vertices |
create_subsurface |
Create a window/door on a parent surface |
create_space_from_floor_print |
Extrude a floor polygon into a space with all surfaces |
match_surfaces |
Intersect + match shared walls between adjacent spaces |
set_window_to_wall_ratio |
Add a centered window by glazing ratio |
import_floorspacejs |
Import geometry from a FloorSpaceJS JSON file |
Constructions & materials — 5 tools
List constructions/sets via list_model_objects("Construction") / ("DefaultConstructionSet").
| Tool | Description |
|---|---|
list_materials |
Materials with thermal properties |
get_construction_details |
Construction layers with thermal properties |
create_standard_opaque_material |
Material with conductivity/density |
create_construction |
Layered construction from materials |
assign_construction_to_surface |
Assign a construction to a surface |
Schedules — 2 tools
List schedules via list_model_objects("ScheduleRuleset").
| Tool | Description |
|---|---|
get_schedule_details |
Schedule type, values, rules |
create_schedule_ruleset |
Constant schedule (Fractional/Temp/OnOff) |
Loads — 6 tools
List loads via list_model_objects("People"), ("Lights"), etc.; use get_object_fields for definitions.
| Tool | Description |
|---|---|
get_load_details |
Detailed info for any load by name |
create_people_definition |
People load (by area or count) |
create_lights_definition |
Lighting load (by area or wattage) |
create_electric_equipment |
Electric equipment load |
create_gas_equipment |
Gas equipment load |
create_infiltration |
Infiltration (by area or ACH) |
Space types — 1 tool
List space types via list_model_objects("SpaceType").
| Tool | Description |
|---|---|
get_space_type_details |
Space-type loads, schedules, standards |
HVAC — query & build — 7 tools
| Tool | Description |
|---|---|
list_air_loops |
Air loops with zones served |
get_air_loop_details |
Air-loop components, sizing, OA system |
add_air_loop |
Create an air loop and connect zones |
list_plant_loops |
Plant loops (heating, cooling, condenser) |
get_plant_loop_details |
Plant-loop supply/demand components |
list_zone_hvac_equipment |
Zone-level HVAC equipment |
get_zone_hvac_details |
Zone equipment details |
HVAC systems (templates) — 8 tools
| Tool | Description |
|---|---|
add_baseline_system |
ASHRAE 90.1 baseline system (types 1–10) |
list_baseline_systems |
All baseline + modern template types |
get_baseline_system_info |
Metadata for a specific system type |
replace_air_terminals |
Replace ALL terminals on an air loop |
replace_zone_terminal |
Replace the terminal on a single zone |
add_doas_system |
DOAS with fan coils, radiant, or chilled beams |
add_vrf_system |
VRF multi-zone heat-pump system |
add_radiant_system |
Low-temperature radiant heating/cooling |
HVAC component properties — 10 tools
List components via list_model_objects("BoilerHotWater"), loop detail tools, etc. Covers 15 component types (see reference).
| Tool | Description |
|---|---|
get_component_properties |
Read all properties of a named component |
set_component_properties |
Modify properties on a named component |
set_economizer_properties |
OA economizer settings on an air loop |
set_sizing_properties |
Plant-loop sizing (exit temp, delta-T) |
set_sizing_system_properties |
Air-loop SizingSystem (SAT, OA, flow methods) |
get_sizing_system_properties |
Read all SizingSystem properties |
set_sizing_zone_properties |
SizingZone properties (supports zone lists) |
get_sizing_zone_properties |
Read all SizingZone properties |
get_setpoint_manager_properties |
Read SPM properties (7 types) |
set_setpoint_manager_properties |
Modify SPM properties (7 types) |
Plant loops & zone equipment — 9 tools
| Tool | Description |
|---|---|
create_plant_loop |
Plant loop with pump, bypass, SPM |
add_supply_equipment |
Add boiler/chiller/tower to supply side |
remove_supply_equipment |
Remove supply-side equipment |
add_demand_component |
Add coil/heater to the demand side |
remove_demand_component |
Remove a demand-side component |
add_zone_equipment |
Add baseboard/unit heater to a zone |
remove_zone_equipment |
Remove zone equipment |
remove_all_zone_equipment |
Batch-remove all equipment from zones |
set_zone_equipment_priority |
Reorder zone cooling/heating priority |
Weather & simulation config — 7 tools
| Tool | Description |
|---|---|
list_weather_files |
Available EPW files (with .stat/.ddy) |
get_weather_info |
City, lat, lon, timezone from a weather file |
add_design_day |
Add a heating/cooling design day |
get_simulation_control |
Read sizing flags and timesteps/hour |
set_simulation_control |
Modify sizing flags and/or timestep |
get_run_period |
Read run-period dates |
set_run_period |
Set run-period dates |
Simulation & outputs — 10 tools
| Tool | Description |
|---|---|
run_simulation |
Run a simulation from an OSM + optional EPW |
run_osw |
Run EnergyPlus from an OSW file |
validate_osw |
Validate an OSW workflow file |
validate_model |
Pre-sim check: weather, design days, HVAC, constructions |
get_run_status |
Poll run status |
get_run_logs |
Tail simulation logs |
get_run_artifacts |
List output files |
cancel_run |
Cancel a running simulation |
add_output_variable |
Add an EnergyPlus output variable |
add_output_meter |
Add an EnergyPlus output meter |
Run retention — 4 tools
Reclaim disk from old run directories. See docs/run-retention.md.
| Tool | Description |
|---|---|
cleanup_runs |
Delete old run dirs you own (preview with dry_run, then delete) |
delete_run |
Delete one of your run directories |
pin_run |
Protect a run from automatic cleanup |
unpin_run |
Allow a pinned run to be cleaned up again |
Results extraction — 12 tools
| Tool | Description |
|---|---|
extract_summary_metrics |
EUI, energy, unmet hours |
extract_end_use_breakdown |
Energy by end use and fuel (IP/SI) |
extract_envelope_summary |
Opaque + fenestration U-values and areas |
extract_hvac_sizing |
Autosized zone/system HVAC capacities |
extract_zone_summary |
Per-zone areas, conditions, multipliers |
extract_component_sizing |
Autosized component values (filterable) |
query_timeseries |
Time-series output data with date/cap filters |
extract_simulation_errors |
Parse eplusout.err into Fatal/Severe/Warning |
list_output_variables |
Output variables from a completed run |
compare_runs |
Compare two runs: EUI delta + end-use breakdown |
read_file |
Read any file by absolute path (mounts only) |
copy_file |
Copy a file to a host-mounted path |
Measures & authoring — 7 tools
Apply bundled measures, or write/test/apply custom ones. See examples 1, 2, 19.
| Tool | Description |
|---|---|
apply_measure |
Apply an OpenStudio measure to the in-memory model |
list_measure_arguments |
List a measure's arguments, defaults, choices |
create_measure |
Create a custom Ruby/Python ModelMeasure |
edit_measure |
Edit a custom measure's code or arguments |
test_measure |
Run a custom measure's tests (auto-detects language) |
list_custom_measures |
List custom measures you've created |
list_comstock_measures |
List ~61 bundled ComStock measures |
Common measures (curated wrappers) — 20 tools
Typed wrappers over ~79 bundled common measures (reporting, envelope, renewables, visualization, cleanup).
| Tool | Description |
|---|---|
list_common_measures |
List bundled measures by category |
view_model |
Interactive 3D Three.js viewer of geometry |
view_simulation_data |
3D viewer with simulation data on surfaces |
generate_results_report |
~25-section HTML report |
run_qaqc_checks |
ASHRAE baseline QA/QC checks |
adjust_thermostat_setpoints |
Shift heating/cooling setpoints |
replace_window_constructions |
Bulk-replace exterior window constructions |
enable_ideal_air_loads |
Ideal air loads on all zones (quick sizing) |
clean_unused_objects |
Remove orphan/unused objects |
change_building_location |
Set weather + climate zone + design days |
set_thermostat_schedules |
Apply thermostat schedules from a library |
replace_thermostat_schedules |
Replace existing thermostat schedules |
shift_schedule_time |
Shift schedule profiles by hours |
add_rooftop_pv |
Add rooftop PV panels |
add_pv_to_shading |
Add PV to shading surfaces |
add_ev_load |
Add EV charging load |
add_zone_ventilation |
Add zone ventilation design flow |
set_lifecycle_cost_params |
Set lifecycle-cost parameters |
add_cost_per_floor_area |
Add cost per floor area |
set_adiabatic_boundaries |
Set walls/floors adiabatic |
Discovery, info & routing — 7 tools
| Tool | Description |
|---|---|
list_skills |
List available workflow guides |
get_skill |
Step-by-step instructions for a workflow |
recommend_tools |
Recommend the relevant tool group for a task |
search_api |
Look up OpenStudio SDK classes + methods (verify before calling) |
search_wiring_patterns |
Ruby wiring recipes for HVAC (24 patterns) |
get_server_status |
Server health check |
get_versions |
OpenStudio, EnergyPlus, Ruby versions |
All 10 ASHRAE 90.1 Appendix G baseline systems via add_baseline_system, plus modern templates DOAS, VRF, Radiant.
| # | Type | Description |
|---|---|---|
| 1 | PTAC | Packaged terminal AC (zone-level) |
| 2 | PTHP | Packaged terminal heat pump (zone-level) |
| 3 | PSZ-AC | Packaged single-zone rooftop AC |
| 4 | PSZ-HP | Packaged single-zone heat pump |
| 5 | Packaged VAV w/ Reheat | VAV with hot-water reheat |
| 6 | Packaged VAV w/ PFP Boxes | VAV with parallel fan-powered boxes |
| 7 | VAV w/ Reheat | Central VAV, chiller + boiler + tower |
| 8 | VAV w/ PFP Boxes | Central VAV, parallel fan-powered terminals |
| 9 | Gas Unit Heater | Heating-only (warehouses, garages) |
| 10 | Electric Unit Heater | Heating-only, electric |
The component-properties tools query/modify these 15 types:
| Category | Components |
|---|---|
| Coils | CoilHeatingGas, CoilHeatingElectric, CoilHeatingWater, CoilCoolingWater, CoilCoolingDXSingleSpeed, CoilCoolingDXTwoSpeed, CoilHeatingDXSingleSpeed |
| Plant | BoilerHotWater, ChillerElectricEIR, CoolingTowerSingleSpeed |
| Fans | FanConstantVolume, FanVariableVolume, FanOnOff |
| Pumps | PumpConstantSpeed, PumpVariableSpeed |
19 worked examples with full tool-call sequences:
| # | Example | # | Example |
|---|---|---|---|
| 1 | Custom Measure: Lighting | 11 | Results Deep Dive |
| 2 | Custom Measure: Chilled Beams | 12 | /simulate |
| 3 | Baseline Comparison | 13 | /energy-report |
| 4 | HVAC Design Exploration | 14 | /qaqc |
| 5 | Envelope Retrofit | 15 | /add-hvac |
| 6 | Internal Loads | 16 | /new-building |
| 7 | Full Building Model | 17 | /retrofit |
| 8 | Geometry from Scratch | 18 | /view |
| 9 | Fenestration by Orientation | 19 | Four-Pipe Beam Retrofit (E2E) |
| 10 | Typical Building (ComStock) |
Full guide — framework, annotated examples, CI shards, writing tests — in docs/testing/.
# Unit tests (no Docker)
pytest tests/test_skill_registration.py -v
# Integration tests (Docker)
docker build -t openstudio-mcp:dev -f docker/Dockerfile .
docker run --rm -v "$PWD:/repo" -v "$PWD/runs:/runs" \
-e RUN_OPENSTUDIO_INTEGRATION=1 -e MCP_SERVER_CMD=openstudio-mcp \
openstudio-mcp:dev bash -lc 'cd /repo && pytest -vv -s tests/'- Transport: stdio (default) or streamable HTTP for remote/multi-user
- Protocol: MCP (JSON-RPC); in stdio prod mode, stdout is reserved for JSON-RPC and logs go to stderr
- Skills: 27 skill modules under
mcp_server/skills/<name>/, each withtools.py(MCP registration) +operations.py(business logic); they auto-register - State: per-session in-memory model via
model_manager; runs under/runs/<run_id>/(or/runs/<user>/<run_id>/in HTTP mode)
Set OPENSTUDIO_MCP_MODE=prod for MCP hosts (quiet logs, no banner). Full system diagram, security analysis, and hardening notes: docs/architecture.md.
Contributing — adding skills, tools, and component types
New MCP skill
- Create
mcp_server/skills/<name>/__init__.py,operations.py,tools.py operations.py— pure logic, returns{"ok": True/False, ...}tools.py— exportsregister(mcp), defines tool schemas- Add
tests/test_<name>.pyand a CI step in.github/workflows/ci.yml - Auto-registers via
skills/__init__.py; add names toEXPECTED_TOOLSand bump counts intests/test_tool_baseline.py
New Claude Code skill (workflow guide)
- Create
.claude/skills/<name>/SKILL.mdwith YAML frontmatter (name,description) - Add workflow instructions referencing MCP tool names;
user-invocable: true|false,context: forkfor fire-and-forget - Add
tests/test_skill_<name>.py+ a CI shard, an example indocs/examples/, and a README row - Auto-appears in
list_skills()via the/skillsmount
New HVAC component type
- Add
_get_<type>_props(obj)/_set_<type>_props(obj, props)incomponents.py - Add an entry to
COMPONENT_TYPES; add a test intests/test_component_properties.py - No dynamic dispatch — every OpenStudio API call must be explicit and grepable
See LICENSE.