hecras-mcp
README.md
# hecras-mcp
**An MCP server that lets Claude run HEC-RAS headless: inspect projects, execute plans and read results.**
[HEC-RAS](https://www.hec.usace.army.mil/software/hec-ras/) is the US Army Corps of Engineers' river hydraulics
software. It is a Windows desktop application with no usable programmatic API. This server wraps it in the
[Model Context Protocol](https://modelcontextprotocol.io) so an AI agent (Claude Code, Claude Desktop) can drive
1D steady, 1D unsteady and 2D models end to end.
**Status: 19 tools · 126 automated tests passing** (113 library tests + 13 end-to-end MCP protocol tests),
including a full 2D simulation and validation against USACE's official Muncie 2D model mesh.
> 📄 Full technical notes in Spanish: [README.es.md](README.es.md)
---
## Why this was harder than it looks
Every item below failed **silently or with a misleading error**, and each one cost real debugging time.
| Problem | What happens | How the server handles it |
|---|---|---|
| The COM API (`HECRASController`) is registered **only in 32-bit** | 64-bit Python gets `CLASS_NOT_REGISTERED`; 32-bit COM breaks on `ByRef` array marshalling | Skip COM entirely: drive `Ras.exe -c <project> <plan>` headless and read HDF5 results with `h5py` |
| **Exit code is always 0**, even when the engine aborts | A failed run looks like a success | The source of truth is the `Solution` attribute in the plan's HDF file plus `data_errors.txt` |
| An unreadable plan file (LF instead of CRLF) | HEC-RAS **silently computes a different plan** | Verifies that the outputs that changed belong to the requested plan (`requested_plan_computed`) |
| Fixed-width fields are **not uniform** (8 vs 16 chars) | Coordinates get truncated and **the engine hangs forever** | Width-aware writers, and every compute call carries a mandatory `timeout_s` that kills the process tree |
| Windows regional format in Spanish (`31dic2025`) | The Fortran engine only reads English months: `Error in the time window` | `ras_check_plan` detects it **before** computing; `ras_compute` diagnoses it after |
| `.prj` is also the GIS projection extension | Wrong files picked up as projects | Requires the `Proj Title=` key to accept a file as a HEC-RAS project |
## Architecture
| Layer | Mechanism |
|---|---|
| Compute | `Ras.exe -c` headless, with timeout and process-tree kill |
| Run status | `Solution` attribute of the plan HDF (never the exit code) |
| Results | `h5py` directly over `<plan>.hdf`, 64-bit |
| Model files | Custom fixed-width parsers for `.prj / .gXX / .fXX / .uXX / .pXX` |
| 2D terrain | `RasProcess.exe CreateTerrain` from a GeoTIFF, no RAS Mapper needed |
| Safety | Path allow-list (`HECRAS_MCP_ROOTS`); `.bak` copy before any write |
## Tools
| Group | Tools |
|---|---|
| Discovery & inspection | `ras_info`, `ras_find_projects`, `ras_project_info`, `ras_plan_info`, `ras_geometry_info`, `ras_cross_section`, `ras_steady_flow_info`, `ras_unsteady_flow_info`, `ras_2d_areas` |
| Compute | `ras_check_plan`, `ras_compute`, `ras_compute_messages` |
| Results | `ras_result_variables`, `ras_results`, `ras_results_timeseries`, `ras_results_summary`, `ras_2d_results`, `ras_hdf_tree` |
| Modification | `ras_set_steady_discharges` |
Arguments `plan`, `geometry` and `flow` are file extensions (`p01`, `g01`, `f01`), not full paths.
## Testing: physical validation, not just "it didn't crash"
Tests run on disposable synthetic models generated in `sandbox/` and **never touch a real model**.
- **Steady 1D:** discharge conserved exactly (50 / 150 / 300 m³/s); uniform flow drops 1.00 m per 1000 m (= bed slope);
energy line always above the water surface; normal depth of 1.726 m checked by hand against Manning's equation.
- **Unsteady 1D:** the inflow hydrograph is reproduced (peak 320 m³/s), the flood wave rises and recedes, and the peak
attenuates downstream (320 → 310.5 m³/s).
- **2D:** 1,104 seeded points → 1,246 cells / 2,279 faces, run finishes with **0.016 % volume balance error**; the max
water level follows the hydrograph and never drops below the minimum terrain elevation.
- **Deliberate failures:** paths outside the allow-list, missing projects, GIS `.prj` files, nonexistent plans/sections,
malformed discharge lists, invented variables, results requested before computing, corrupted geometry, timeouts,
2D tools on a 1D model, and the regional-date failure. Each one must fail **cleanly, with an explanation**.
```bash
.venv\Scripts\python.exe tests\run_tests.py # 113 library tests
.venv\Scripts\python.exe tests\test_protocol.py # 13 MCP protocol tests
```
The official USACE Muncie model (used to validate reading a production mesh: 5,765 cells, 11,164 faces) is not
included because of its size. Get it from USACE's
[Example_Projects_7_0.zip](https://github.com/HydrologicEngineeringCenter/hec-downloads/releases/download/1.0.45/Example_Projects_7_0.zip)
with `tests/extract_example.ps1`; if it's missing, that stage is skipped automatically.
## Setup
Requirements: Windows, HEC-RAS 7.0.x, Python 3.10+.
```bash
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
claude mcp add hecras --scope user "C:\path\to\hecras-mcp\start_hecras_mcp.cmd"
```
Configure in `start_hecras_mcp.cmd`:
- `HECRAS_MCP_ROOTS` — folders the server may read and write (`;`-separated). Everything else is rejected.
- `HECRAS_EXE` *(optional)* — a specific `Ras.exe`. Without it, the installation is detected from the Windows registry.
- `HECRAS_VERSION` *(optional)* — choose among several installations, e.g. `6.5`.
## Not covered
Geometry authoring through the tools, unsteady hydrograph editing, bridges and structures, sediment transport, water
quality and inundation mapping (RAS Mapper).
---
Built by **Oscar Daniel Montero Miranda**. Independent project, not affiliated with or endorsed by USACE or the
Hydrologic Engineering Center. Code comments are in Spanish.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues