Skip to main content
Glama
README.md
# RETICOLO MCP — RCWA Solver via MATLAB Engine API

English | [中文](README_CN.md)

MCP server for the [RETICOLO V10](https://zenodo.org/records/14631951) rigorous
coupled-wave analysis (RCWA) solver. Wraps MATLAB R2025b via the Engine API.

## Quick start

```powershell
# 1. Create conda env
conda create --name reticolo-mcp python=3.11 -y
conda activate reticolo-mcp

# 2. Install dependencies
pip install mcp numpy pydantic

# 3. Install MATLAB Engine API (one-time)
cd "D:\Program Files\MATLAB\R2025b\extern\engines\python"
pip install .

# 4. Install this package
pip install .

# 5. Set RETICOLO path and run
$env:RETICOLO_MCP_DIR = "D:\RETICOLO V10\V10_2025\reticolo_allege_v10"
python -m reticolo_mcp.server
```

### opencode / Codex MCP config

```json
{
  "reticolo": {
    "type": "local",
    "command": ["D:\\condaenvs\\reticolo-mcp\\python.exe", "-m", "reticolo_mcp.server"],
    "cwd": "D:\\reticolo_runtime",
    "environment": { "RETICOLO_MCP_DIR": "D:\\RETICOLO V10\\V10_2025\\reticolo_allege_v10" },
    "enabled": true,
    "timeout": 120000
  }
}
```

Use an ASCII-only `cwd` outside the checkout. A source-tree `cwd` can shadow the
non-editable installation and makes the deployment receipt report `source_tree`.

## Tools

| Tool | Status | Description |
|---|---|---|
| `reticolo_capabilities` | Verified solver-free | Tool maturity, schemas, build identity |
| `reticolo_resource_preflight` | Verified solver-free + staged real | Hashed admission plus nn=9/15/21/31 real gate |
| `solver_status` | Verified read-only | Lease state + COMSOL collision check |
| `reticolo_status` | Verified read-only | Engine handle + lease status |
| `reticolo_start` / `reticolo_stop` | Verified real lifecycle | Three clean cycles, rollback, and >90 s heartbeat ownership passed |
| `reticolo_solve_point` | Verified TE/TM one-point translation | Normal and signed-angle analytical/direct fixtures plus patterned TE |
| `reticolo_sweep` | Experimental, disabled by default | Legacy synchronous sweep; prefer durable jobs |
| `job_submit/status/tail/cancel/resume` | Experimental | Real restart/resume and safe-boundary cancellation receipts passed; interface remains experimental |
| `reticolo_convergence` | Experimental | MCP execution is not release accepted; external archived evidence cannot promote it |
| `reticolo_field_export` | Experimental; verified uniform TE artifact | Bounded `res3` export passed; paired mode comparison is not accepted |
| `reticolo_field_pair` | Experimental; real-artifact pair verified | Two hashed uniform-TE artifacts passed caller-bounded coordinate matching and shared-limit assembly; no mode classification |

Use `reticolo_capabilities` as the live maturity and deployment receipt. Historical
real-engine results below remain fixture evidence; they do not promote every current
tool revision to verified status.

Synchronous sweep, convergence, and field export are disabled by default. Development-only
access requires `RETICOLO_MCP_ENABLE_EXPERIMENTAL=1` followed by an MCP host restart;
the flag does not promote these tools to verified status.

Field artifacts, when experimental access is enabled, may only be written under
`RETICOLO_ARTIFACT_DIR` (default: `<runtime>/artifacts`).

One-point incidence uses signed `theta_deg` and degree-valued `azimuth_deg`. RETICOLO
receives `ro=n_superstrate*sin(theta)`; nonzero angle requires a positive real uniform
incident medium. Durable jobs currently remain normal-incidence only.

Durable `job_submit` requires an explicit resource policy. A warning decision must be
resubmitted with the returned `decision_hash`; a refusal never launches a worker.
Scientific acceptance policy is also caller-owned: point solves, sweeps, durable
jobs, and convergence require `passivity_tolerance`; convergence additionally
requires center, absorption, FWHM, and branch-match tolerances. Field export requires
`slice_tol`, while field pairing requires a bounded `coordinate_tolerance_um`. These
values enter artifacts or durable identity instead of server defaults.

## Verification

After a non-editable install, verify the actual stdio transport from an ASCII
directory outside the checkout. Supply identities from the reviewed build receipt:

```powershell
python scripts\verify_installed_transport.py `
  --python "D:\condaenvs\reticolo-mcp\python.exe" `
  --cwd "D:\reticolo_runtime" `
  --reticolo-dir "D:\RETICOLO V10\V10_2025\reticolo_allege_v10" `
  --expected-version "<version>" `
  --expected-tool-count <count> `
  --expected-build-id "<build-sha256>" `
  --expected-schema-id "<schema-sha256>" `
  --output "D:\reticolo_runtime\installed_stdio_receipt.json"
```

The gate performs MCP initialization, tool discovery, and a capability call in a
fresh child process. It fails if the installed identity/profile differs, MATLAB is
imported during discovery, or the MATLAB PID set changes. Use `--experimental` only
for a separately declared restart-bound profile check, then restart without it.

Archived convergence data can be audited without MATLAB by using
`scripts\audit_external_evidence.py`. The audit first binds the manifest, script,
point CSV, and summary CSV by SHA-256 and exact configuration identity. With
the required `--balance-tolerance`, it checks derived R/T/A consistency. With
`--convergence-group-column` plus center, absorption, FWHM, numeric-consistency, and
maximum order-gap policy arguments, it then reconstructs
each peak, two-sided half-prominence FWHM, Q, and adjacent-order center/A/width gate
from raw rows. Provenance can pass while scientific acceptance returns exit code `2`;
such a receipt is a bounded residual, not an execution failure or capability promotion.

| Gate | Evidence |
|---|---|
| G0 — Engine lifecycle | Start → health → stop, no MATLAB leak, no orphans |
| G1 — M0 resource | nn=9×2 + nn=15×1, C: Δ=0 GB, no `retXXXX` orphans, memory mode |
| G2 — Numerical baseline | TE slab n=1.5: R=0.147929 vs analytical 0.1479 (0.03% err); lossy slab passive ✓ |
| G3 — Durable jobs | Worker → results match G2; resume skips completed rows |
| Historical unit baseline | 133 passed before v0.2 development changes |
| M3 — High-order smoke | nn=21 (32s) + nn=31 (261s), memory-mode stable, no OOM |
| M4 — Scratch mode | solves correctly, matches memory-mode results |
| V2 real lifecycle | 3/3 cycles + post-start rollback passed; no MATLAB/lease/scratch residue |
| V2 long heartbeat | 100.016 s blocking call; heartbeats at ~30/60/90 s; 95 s contender refused |
| V2 TE analytical slab | raw R/T/A_balance = 0.1479289941 / 0.8520710059 / 2.22e-16; analytical errors < 2e-16 |
| V2 lossy slab | raw R/T/A_balance = 0.0030686604 / 0.8847234795 / 0.1122078601; analytical errors < 3e-16 |
| V2 patterned translation | Three direct/wrapper ledgers exact; Sun M5 raw R/T/A_balance = 0.8439529179 / 2.2009066e-6 / 0.1560448812 |
| V2 staged resources | nn=9/15/21/31 all green and passive; solve times 0.936/5.616/28.800/227.452 s; exact lease retained |
| V2 durable restart/resume | Host exit preserved worker; exact first point resumed to a two-row passive result with no duplicate |
| V2 safe-boundary cancel | In-flight nn=21 point persisted; cancellation stopped before the next admission and cleanup was proven |
| External Xu convergence audit | 1346/1346 rows bound; 7/7 groups reconstruct center/A/FWHM convergence; not MCP execution |
| External Sun convergence audit | 170/170 rows pass provenance; scientific contract rejected because the summary lacks FWHM evidence |

## Known limitations

- **Convergence:** the MCP convergence path remains experimental and disabled by
  default. Archived Xu evidence passes an independent three-metric reconstruction,
  while the archived Sun summary lacks the width contract. Neither external result
  promotes MCP execution maturity.
- **Field export:** the old `imag(apod)` failure came from passing `ef` to RETICOLO's
  one-argument `retchamp` apodization helper. The corrected bounded `res3` path has
  verified uniform-TE artifacts with embedded source/config/point/request identities.
  A solver-free recovery paired two real artifacts at a caller-selected `1e-12 um`
  coordinate tolerance; the measured maximum delta was `5.55e-17 um`. TM,
  resonant-mode classification, visual mode claims, and publication claims remain
  unaccepted.

## ⚠ Disk safety

RETICOLO's internal `retio` system spills large matrices to `retXXXX/` scratch
directories during high-order scans. This server defaults to **memory mode**
(`vmax=inf`, no disk spill). MATLAB temp files are redirected to `D:\matlab_temp`.

Startup applies:
- `retio([], inf*1i)` — disable scratch writes
- `TMP/TEMP/TMPDIR` → `D:\matlab_temp`
- Working directory → `D:\reticolo_scratch`
- Lease with COMSOL MCP collision detection

## Configuration

The server requires an external RETICOLO V10 installation. The bundled
`reticolo_v10/` directory in the repository is for development only and
is **not included in the PyPI wheel** (CC-BY 4.0 — separate from the MIT wrapper).

```powershell
$env:RETICOLO_MCP_DIR = "D:\RETICOLO V10\V10_2025\reticolo_allege_v10"
python -m reticolo_mcp.server --reticolo-dir "D:\RETICOLO V10\V10_2025\reticolo_allege_v10"
```

## Architecture

```
reticolo-mcp/
├── src/reticolo_mcp/
│   ├── server.py        # FastMCP server, all tools
│   ├── engine.py        # MATLAB Engine lifecycle + solve
│   ├── lease.py         # Atomic solver lease (named mutex)
│   ├── sweep.py         # Resumable sweep + peak analysis
│   ├── jobs.py          # Durable job store (spec/state/events)
│   ├── worker.py        # Detached worker process
│   ├── convergence.py   # Progressive harmonic convergence
│   ├── evidence_audit.py # Solver-free archived evidence and claim reconstruction
│   ├── field_export.py  # bounded res3 field export
│   ├── schema.py        # Pydantic models for materials/geometry
│   ├── config_hash.py   # Canonical SHA-256 config identity
│   └── config.py        # Paths, limits, env vars
├── reticolo_v10/        # Bundled RETICOLO V10 (CC-BY 4.0, dev only)
├── tests/               # Unit + integration tests
├── pyproject.toml
├── LICENSE              # MIT (wrapper code)
├── NOTICE               # CC-BY 4.0 attribution
└── README.md
```

## License

- **MCP wrapper code** (all Python files): MIT License.
- **Bundled RETICOLO V10** (`reticolo_v10/`): CC-BY 4.0,
  © Jean Paul Hugonin & Philippe Lalanne.
  DOI: [10.5281/zenodo.14631951](https://doi.org/10.5281/zenodo.14631951).

See LICENSE and NOTICE for details.

Maintenance

ActivitySlowing
ResponsivenessNo issues