modelrisk-mcp 0.3.0a5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modelrisk_mcp-0.3.0a5/.gitignore +46 -0
- modelrisk_mcp-0.3.0a5/CHANGELOG.md +236 -0
- modelrisk_mcp-0.3.0a5/LICENSE +21 -0
- modelrisk_mcp-0.3.0a5/PKG-INFO +285 -0
- modelrisk_mcp-0.3.0a5/README.md +237 -0
- modelrisk_mcp-0.3.0a5/docs/architecture.md +155 -0
- modelrisk_mcp-0.3.0a5/docs/authoring-audit-rules.md +161 -0
- modelrisk_mcp-0.3.0a5/docs/claude-code.md +57 -0
- modelrisk_mcp-0.3.0a5/docs/claude-desktop.md +99 -0
- modelrisk_mcp-0.3.0a5/docs/claude-for-excel.md +103 -0
- modelrisk_mcp-0.3.0a5/docs/com-surface.md +169 -0
- modelrisk_mcp-0.3.0a5/docs/community-submission.md +70 -0
- modelrisk_mcp-0.3.0a5/docs/demo-script.md +88 -0
- modelrisk_mcp-0.3.0a5/docs/installation.md +37 -0
- modelrisk_mcp-0.3.0a5/docs/mrservice-spike.md +22 -0
- modelrisk_mcp-0.3.0a5/modelrisk_mcp.spec +121 -0
- modelrisk_mcp-0.3.0a5/pyproject.toml +123 -0
- modelrisk_mcp-0.3.0a5/scripts/encode_activation_key.py +83 -0
- modelrisk_mcp-0.3.0a5/scripts/extract_catalogue.py +593 -0
- modelrisk_mcp-0.3.0a5/scripts/scan_exe_for_key.py +107 -0
- modelrisk_mcp-0.3.0a5/scripts/spike_com_surface.py +235 -0
- modelrisk_mcp-0.3.0a5/scripts/spike_mrservice.py +252 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/__init__.py +1 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/__main__.py +146 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/audit/__init__.py +0 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/audit/engine.py +87 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/audit/rules.py +442 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/__init__.py +0 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/_keymat.py +56 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/catalogue.py +141 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/charts.py +204 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/excel.py +537 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/formulas.py +288 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/modelrisk.py +635 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/mrservice.py +455 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/progids.py +21 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/results.py +398 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/bridge/simulation.py +308 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/config.py +19 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/data/__init__.py +0 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/data/audit_rules.yaml +164 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/data/distributions.yaml +108 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/data/functions.json +40552 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/data/optional_overrides.yaml +21 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/errors.py +42 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/http_auth.py +62 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/prompts/__init__.py +22 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/prompts/add_uncertainty.py +59 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/prompts/audit_model.py +54 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/prompts/build_model.py +78 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/prompts/import_legacy_model.py +56 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/prompts/interpret_results.py +48 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/resources/__init__.py +21 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/resources/audit_rules.py +26 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/resources/distribution_guide.py +25 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/resources/function_reference.py +77 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/resources/methodology.py +81 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/resources/workbook_state.py +66 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/safety.py +283 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/schemas/__init__.py +57 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/schemas/distributions.py +64 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/schemas/results.py +137 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/schemas/workbook.py +142 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/server.py +37 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/tools/__init__.py +11 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/tools/building.py +436 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/tools/reading.py +320 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/tools/restore.py +52 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/tools/simulation.py +154 -0
- modelrisk_mcp-0.3.0a5/src/modelrisk_mcp/tools/workflows.py +427 -0
- modelrisk_mcp-0.3.0a5/tests/__init__.py +0 -0
- modelrisk_mcp-0.3.0a5/tests/integration/__init__.py +0 -0
- modelrisk_mcp-0.3.0a5/tests/integration/conftest.py +53 -0
- modelrisk_mcp-0.3.0a5/tests/integration/test_building.py +136 -0
- modelrisk_mcp-0.3.0a5/tests/integration/test_excel_bridge_smoke.py +62 -0
- modelrisk_mcp-0.3.0a5/tests/integration/test_modelrisk_smoke.py +29 -0
- modelrisk_mcp-0.3.0a5/tests/integration/test_reading.py +96 -0
- modelrisk_mcp-0.3.0a5/tests/unit/__init__.py +0 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_audit_rules_new.py +228 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_catalogue.py +152 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_catalogue_loader.py +99 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_charts.py +312 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_cli.py +43 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_excel_bridge.py +171 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_formulas.py +267 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_http_auth.py +81 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_modelrisk_mocked.py +169 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_mrservice.py +193 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_prompts.py +64 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_resources.py +106 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_safety.py +233 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_schemas.py +126 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_server_boot.py +47 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_simulation_controller.py +350 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_tools_building_mocked.py +494 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_tools_reading_mocked.py +385 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_tools_restore_mocked.py +82 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_tools_simulation_mocked.py +316 -0
- modelrisk_mcp-0.3.0a5/tests/unit/test_tools_workflows_mocked.py +465 -0
- modelrisk_mcp-0.3.0a5/uv.lock +1313 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.egg
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
|
|
15
|
+
# Virtualenvs
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
|
|
20
|
+
# uv
|
|
21
|
+
# (uv.lock IS committed)
|
|
22
|
+
|
|
23
|
+
# Build artefacts
|
|
24
|
+
build/
|
|
25
|
+
dist/
|
|
26
|
+
*.exe
|
|
27
|
+
*.spec.bak
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
*.manifest
|
|
31
|
+
|
|
32
|
+
# IDE
|
|
33
|
+
.vscode/
|
|
34
|
+
.idea/
|
|
35
|
+
*.swp
|
|
36
|
+
*.swo
|
|
37
|
+
|
|
38
|
+
# OS
|
|
39
|
+
Thumbs.db
|
|
40
|
+
ehthumbs.db
|
|
41
|
+
Desktop.ini
|
|
42
|
+
|
|
43
|
+
# Local
|
|
44
|
+
*.log
|
|
45
|
+
.env
|
|
46
|
+
.env.local
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to ModelRisk MCP. Follows [Keep a Changelog](https://keepachangelog.com/) and [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.3.0-alpha.5] — 2026-05-21
|
|
8
|
+
|
|
9
|
+
First publish-ready release. Adds the tornado chart writer, fixes a real `discover_inputs` scoring bug, closes the security verification loop on the obfuscated activation key, and refreshes internal docs to match v0.3 architecture.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `create_tornado_chart(output_name, workbook_name?, sheet_name?)` — renders a SensitivityRanking as a native Excel BarClustered chart on a new sheet (`Tornado_<output_name>` by default, truncated to Excel's 31-char limit). Sheet has a sorted data table (Input | Spearman correlation | |corr| sort key | Regression coefficient) plus the chart with inverted category axis so the largest-magnitude input is at the top — the tornado convention. Idempotent: existing sheets with the target name are replaced, so it's safe to re-run after each new simulation.
|
|
14
|
+
- `bridge/charts.py::TornadoChartWriter` — first member of the chart-writer family. Future siblings: RiskProfileChartWriter (cumulative + density), HistogramWriter, ScenarioComparisonWriter.
|
|
15
|
+
- `scripts/scan_exe_for_key.py` — paranoid scan of a built PyInstaller exe for every encoding of the plain activation key (ASCII decimal, UTF-16 LE wide string, little-endian int64 bytes, big-endian int64 bytes, 8-byte compact form, hex string both cases, and composite first4+last4 across printable runs). Exits non-zero on any hit; wired into `release.yml` as a release-blocker step before the PyPI upload so a regression in the obfuscation can't ship.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- `discover_inputs` no longer over-scores zero-valued cells. The `value not in (0, 1)` exclusion was guarding only the multiple-of-10 bonus; the multiple-of-100 and multiple-of-1000 bonuses still fired for `value=0` because `0 % n == 0`. Result: a cell holding 0 scored 2.0, identical to a cell holding 100 — flags tied with real scenario assumptions. Also added an explicit `not isinstance(value, bool)` guard so `False` cells don't take the same code path (Python's `isinstance(True, int)` is True).
|
|
20
|
+
|
|
21
|
+
### Verified
|
|
22
|
+
|
|
23
|
+
- v0.3.0-alpha.5 builds — wheel (~17 KB), sdist (~140 KB), and PyInstaller exe (~39 MB) — and the exe scan returns clean across every encoding tested. Even the obfuscated base85 blobs from `_keymat.py` aren't directly findable in the binary because PyInstaller compresses bundled Python into a PYZ archive; the source-level base85 strings become compiled `.pyc` bytecode constants. A reverse-engineer would need to extract the PYZ, decompress the bytecode, and reimplement the XOR decoder by hand. Casual `strings`-based extraction yields nothing actionable.
|
|
24
|
+
|
|
25
|
+
### Docs
|
|
26
|
+
|
|
27
|
+
- `docs/architecture.md` and `docs/com-surface.md` rewritten to match the v0.3 stack (MRService.dll via ctypes + XLL `Application.Run` for simulation kickoff; no ATL CoClass dispatch).
|
|
28
|
+
|
|
29
|
+
### Tests
|
|
30
|
+
|
|
31
|
+
303 unit tests pass (was 290 at alpha.4): +11 chart writer tests + 2 regression tests for the discover_inputs zero-value scoring fix.
|
|
32
|
+
|
|
33
|
+
## [0.3.0-alpha.4] — 2026-05-21
|
|
34
|
+
|
|
35
|
+
Four feature additions in one batch: read-path completeness, a one-call session-start tool, deterministic scenario sweeps, and 5 new audit rules. Tool count grows 30 → 34, audit rules 6 → 11. No breaking changes.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- `list_vmrs_variables(workbook_name?)` — enumerates VoseInput / VoseOutput names that exist in the active `.vmrs`. Workbook drives the candidate list (the SDK exposes no name-enumeration call against a `.vmrs` directly — `MRVarsGetModelVarsNames` takes a different ModelID and access-violates against `OpenSimulationModel`'s pointer).
|
|
40
|
+
- `get_samples(output_name, max_n=10000, workbook_name?)` — raw per-iteration sample array for one variable. Unlocks custom histograms, arbitrary percentiles, and any downstream analysis the aggregate-only `get_simulation_results` couldn't cover. Capped at 10 000 by default to stay under MCP-wire budget; configurable up to 1 000 000.
|
|
41
|
+
- `diagnose_workbook(workbook_name?)` — one-call session-start introspection. Returns Excel connection state, MRService activation, active workbook + sheets, input/output/distribution/formula counts, sibling `.vmrs` path + modification timestamp, audit-log location, and an `issues[]` list with human-readable strings flagging anything that would block downstream operations. Saves 4-5 individual tool calls per session. Short-circuits cleanly on Excel-not-reachable.
|
|
42
|
+
- `run_scenarios(sheet, cell, values, samples?, seed?, workbook_name?)` — sweep an input cell across deterministic values, running a full simulation at each, returning per-output P5/P50/P95/mean for every scenario. The cell's original formula is always restored afterwards, even when a scenario raises mid-sweep. `values` capped at 1-20 entries to prevent runaway compute.
|
|
43
|
+
- 5 new audit rules:
|
|
44
|
+
- **VOSE-007** `risk_event_degenerate_probability` — `VoseRiskEvent` with literal probability of 0 or 1 (wrapper is degenerate).
|
|
45
|
+
- **VOSE-008** `voseoutput_missing_name` — `VoseOutput()` with no name or empty-string name.
|
|
46
|
+
- **VOSE-009** `duplicate_output_names` — same `VoseOutput("X")` declared on multiple cells.
|
|
47
|
+
- **VOSE-010** `input_wrapper_without_distribution` — `VoseInput` wrapper but no distribution → input won't vary across iterations.
|
|
48
|
+
- **VOSE-011** `high_volatility_normal_positive_mean` — `VoseNormal(mu, sigma)` with `mu > 0` and `sigma > mu/2` (~16% negative samples; lognormal probably wanted).
|
|
49
|
+
- `docs/authoring-audit-rules.md` — guide for adding new rules. Three-file pattern (YAML + detector + tests), worked example using VOSE-007, when-not-to-add-a-rule discussion.
|
|
50
|
+
|
|
51
|
+
### Bridge / schema changes
|
|
52
|
+
|
|
53
|
+
- `bridge/results.py::ResultsReader.list_variables()` and `.get_samples()` — new methods consumed by the new MCP tools.
|
|
54
|
+
- `bridge/modelrisk.py::ModelRiskBridge.run_scenarios()` — orchestrates Excel write + sim + read with guaranteed cell-state restoration in a `try/finally`.
|
|
55
|
+
- New schemas in `schemas/results.py`: `ScenarioOutcome`, `ScenarioRun`, `ScenarioSweepResult`, `VmrsVariableEntry`.
|
|
56
|
+
|
|
57
|
+
### Tests
|
|
58
|
+
|
|
59
|
+
290 unit tests pass (was 256 at start of alpha.4 work). 34 new tests across the four features: 5 for read-path tools, 6 for `diagnose_workbook`, 6 for scenario sweeps, 17 for the new audit detectors (positive + negative cases per rule, plus threshold-boundary tests for VOSE-011).
|
|
60
|
+
|
|
61
|
+
### Notes
|
|
62
|
+
|
|
63
|
+
False-positive avoidance pattern adopted in the new audit rules: numeric-threshold rules skip cell-reference args (e.g. `VoseRiskEvent(B5, ...)` is NOT flagged because we can't statically know what's in B5). Static analysis should be conservative when it lacks information.
|
|
64
|
+
|
|
65
|
+
## [0.3.0-alpha.3] — 2026-05-21
|
|
66
|
+
|
|
67
|
+
End-user-frictionless activation + obfuscation so the bundled MRService.dll key isn't grep-able from the wheel, plus 50 new MCP-wrapper tests that were missing since the v0.3 refactor.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- Bundled MRService.dll activation. The DLL needs per-process activation to open `.vmrs` files; we now ship a Vose Software-owned key as a fallback in `bridge/mrservice.py::_activate()` so the read path works out of the box. Precedence: `MRSERVICE_ACTIVATION_KEY` env var → `MRSERVICE_ACTIVATION_KEY1`/`_2` env vars → bundled key. `MRSERVICE_DISABLE_BUNDLED_KEY=1` opts out.
|
|
72
|
+
- `bridge/_keymat.py` + `scripts/encode_activation_key.py` — XOR-encoded + base85-stored key material so the literal int never appears in shipped source or `strings` output. Algorithm is public (Kerckhoffs); only the value is secret.
|
|
73
|
+
- `tests/unit/test_tools_{reading,workflows,simulation,restore}_mocked.py` (50 tests) — MCP-tool wrappers were previously untested; these guard against bridge method-rename / kwarg-shape regressions that only surface at end-user runtime.
|
|
74
|
+
- CI guard `test_no_literal_in_package_sources` recursively scans every shipped `.py` for the decoded key's decimal form; fails if anyone re-inlines it.
|
|
75
|
+
|
|
76
|
+
### Verified
|
|
77
|
+
|
|
78
|
+
- Wheel and sdist scans for the plain activation key return zero hits.
|
|
79
|
+
- Bundled key activates the real MRService.dll end-to-end (smoke test in the bridge).
|
|
80
|
+
|
|
81
|
+
### Tests
|
|
82
|
+
|
|
83
|
+
256 unit tests pass (was 206). 50 new MCP-wrapper tests + 3 reworked activation tests.
|
|
84
|
+
|
|
85
|
+
## [0.3.0-alpha.2] — 2026-05-20
|
|
86
|
+
|
|
87
|
+
Adds programmatic simulation triggering via the XLL command surface (no ATL COM dispatch needed), graceful OneDrive path handling, and the missing `read_vmrs` / `set_active_vmrs` tools.
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- `bridge/simulation.py` — `SimulationController` drives runs via plain `Application.Run("VoseStartSimulCustom12", options)` + `Application.Run("VoseGetDataSZ12", session, path)`, replicating exactly what the ATL does internally (`ModelRiskAtl/ModelRisk_Simulate.cpp:102`, `ModelRiskAtl/ModelRiskSimulationResults.cpp:1196`). No ATL Dispatch required, so cross-bitness automation works.
|
|
92
|
+
- `SimulationOptions` dataclass reproduces `CSimulationOptions::PackToStringList` (`SimulationObj.cpp:94`) — `[Key]:Value` lines in exact field order.
|
|
93
|
+
- New MCP tool `run_simulation(workbook_name?, samples=1000, seed=1, save_to?)` — blocks until the sim finishes, saves the `.vmrs` next to the workbook by default, and auto-pins it as the active results source.
|
|
94
|
+
- New MCP tools `set_active_vmrs(path)` and `read_vmrs(path, output_names?)` — formerly referenced in error messages but not registered.
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
- `ExcelBridge.get_active_workbook()` / `list_workbooks()` degrade gracefully when xlwings can't resolve OneDrive paths (`ONEDRIVE_COMMERCIAL_WIN` not set). Returns name-only `WorkbookInfo` with empty path; downstream name-based COM operations still work.
|
|
99
|
+
- `SimulationController` falls back to saving in the user's Desktop folder when the workbook's folder can't be resolved (the OneDrive case).
|
|
100
|
+
- `ModelRiskBridge.run_simulation()` calls `ResultsReader.set_active_vmrs()` automatically after a successful run, so the next `get_simulation_results` call doesn't need a sibling-discovery step.
|
|
101
|
+
|
|
102
|
+
### Tests
|
|
103
|
+
|
|
104
|
+
201 unit tests pass (was 182). New coverage: OneDrive path fallback (5), SimulationController options packing + Application.Run shape + session-name format + failure modes (14).
|
|
105
|
+
|
|
106
|
+
## [0.2.0-alpha.2] — 2026-05-20
|
|
107
|
+
|
|
108
|
+
Auto-activates the ModelRisk add-in inside Excel before reporting the COM surface unreachable. Closes the "modelrisk_loaded: false even though ModelRisk is installed" footgun.
|
|
109
|
+
|
|
110
|
+
### Added
|
|
111
|
+
|
|
112
|
+
- `ExcelBridge.list_com_addins() / list_excel_addins()` — enumerate Excel's COMAddIns and AddIns collections as plain dicts.
|
|
113
|
+
- `ExcelBridge.enable_com_addin(predicate) / enable_excel_addin(predicate)` — flip `.Connect=True` / `.Installed=True` on matching entries, return the names of those actually flipped. Idempotent; no-op on already-on entries.
|
|
114
|
+
- `ModelRiskBridge.ensure_modelrisk_active()` — scans both collections, enables any entry whose description / progid / name mentions ModelRisk or Vose, retries Dispatch, returns a diagnostic dict (`com_addins_enabled`, `excel_addins_enabled`, `com_addins_seen`, `excel_addins_seen`, `modelrisk_dispatchable`).
|
|
115
|
+
- New MCP tool `ensure_modelrisk_active` — explicit invocation for debugging "COM unreachable" reports.
|
|
116
|
+
- Simulation tools (`set_simulation_settings`, `run_simulation`) now call `ensure_modelrisk_active` transparently before touching COM. The LLM no longer needs to ask the user to manually load the add-in.
|
|
117
|
+
|
|
118
|
+
### Changed
|
|
119
|
+
|
|
120
|
+
- `ModelRiskBridge.is_modelrisk_loaded()` now attempts auto-activation if the first Dispatch fails. Returns True iff Dispatch works after activation.
|
|
121
|
+
|
|
122
|
+
### Notes
|
|
123
|
+
|
|
124
|
+
If auto-activation can't find a ModelRisk add-in to flip on, the diagnostic surfaces every COM and Excel add-in it *did* see — useful for ruling out bitness mismatches and broken installs.
|
|
125
|
+
|
|
126
|
+
## [0.2.0-alpha.1] — 2026-05-20
|
|
127
|
+
|
|
128
|
+
HTTP transport — unblocks Claude for Excel and other remote MCP clients that can't spawn local subprocesses.
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
|
|
132
|
+
- `--transport={stdio,streamable-http,sse}` CLI flag in `__main__.py`. stdio remains the default for backwards compatibility.
|
|
133
|
+
- `--host`, `--port`, `--mount-path` flags for HTTP transports. Defaults to `127.0.0.1:8000`.
|
|
134
|
+
- Bearer-token middleware (`http_auth.py`) — required on non-loopback HTTP binds, recommended even on loopback. Constant-time comparison via `hmac.compare_digest`. Token via `--token` or `MODELRISK_MCP_TOKEN` env var.
|
|
135
|
+
- `docs/claude-for-excel.md` — wiring guide covering the Office.js sandbox / COM-bridge architectural story.
|
|
136
|
+
- README section on HTTP transport with the strategic framing.
|
|
137
|
+
- `tests/unit/test_cli.py` + `tests/unit/test_http_auth.py` — 14 new tests covering parser defaults, middleware reject/accept paths, RFC 6750 case-insensitivity of the Bearer keyword.
|
|
138
|
+
|
|
139
|
+
### Changed
|
|
140
|
+
|
|
141
|
+
- Spec §2.2 — "Hosting the MCP server remotely" no longer a non-goal.
|
|
142
|
+
- README front-page table picks up a "Works with Claude for Excel" implication (no UI change needed — Claude for Excel was always in the compatible-clients list).
|
|
143
|
+
|
|
144
|
+
## [0.1.0] — 2026-05-20
|
|
145
|
+
|
|
146
|
+
Public v0.1 release. Repository goes public at this tag.
|
|
147
|
+
|
|
148
|
+
### Added
|
|
149
|
+
|
|
150
|
+
- Public-ready README leading with the strategic narrative (open, agentic, methodology-aware), feature comparison table, and full Safety by design section.
|
|
151
|
+
- `docs/demo-script.md` — beat-by-beat recording guide for the README demo GIF.
|
|
152
|
+
- `docs/community-submission.md` — drafted PR text for the modelcontextprotocol/servers directory.
|
|
153
|
+
- Spec doc updated to v1.4 with the per-phase completion record.
|
|
154
|
+
|
|
155
|
+
### Changed
|
|
156
|
+
|
|
157
|
+
- `Development Status` classifier moved to `5 - Production/Stable`.
|
|
158
|
+
|
|
159
|
+
## [0.1.0-rc.1] — 2026-05-20
|
|
160
|
+
|
|
161
|
+
First release candidate. Feature surface matches the v0.1 spec. PyPI publication path and standalone `.exe` build pipeline both verified locally.
|
|
162
|
+
|
|
163
|
+
### Added
|
|
164
|
+
|
|
165
|
+
- Final `pyproject.toml` metadata: full PyPI classifiers, project URLs (Changelog, Documentation, Vose Software), wheel `force-include` for the four packaged YAML/JSON data files, sdist include list.
|
|
166
|
+
- `.github/workflows/release.yml` — tag-triggered build of wheel, sdist, and standalone Windows `.exe`; uploads to PyPI via trusted publishing and to GitHub Releases.
|
|
167
|
+
- `CHANGELOG.md` — this file. Phase-by-phase history.
|
|
168
|
+
- Updated `modelrisk_mcp.spec` — PyInstaller bundle now declares hidden imports for every tool/resource/prompt module and ships the catalogue + rule YAML files alongside the `.exe`.
|
|
169
|
+
|
|
170
|
+
## [0.1.0-beta.1] — 2026-05-20 (commit `d4431bc`)
|
|
171
|
+
|
|
172
|
+
Phase 5 — workflows, resources, prompts.
|
|
173
|
+
|
|
174
|
+
### Added
|
|
175
|
+
|
|
176
|
+
- 4 workflow tools (`tools/workflows.py`): `propose_distributions_for_inputs`, `discover_inputs`, `audit_model`, `generate_executive_summary`.
|
|
177
|
+
- Audit engine (`audit/engine.py`, `audit/rules.py`) with 6 detectors mapped to rules in `data/audit_rules.yaml`.
|
|
178
|
+
- 7 resources under `modelrisk://`: `functions`, `functions/{name}`, `distributions`, `methodology`, `workbook/current`, `workbook/current/sheet/{name}`, `audit-rules`.
|
|
179
|
+
- 5 prompt templates (slash commands): `/build-risk-model`, `/audit-model`, `/interpret-results`, `/add-uncertainty`, `/import-legacy-model`.
|
|
180
|
+
- `data/distributions.yaml` — keyword-matched distribution selection guide.
|
|
181
|
+
|
|
182
|
+
## [0.1.0-alpha.3] — 2026-05-20 (commit `464c5f3`)
|
|
183
|
+
|
|
184
|
+
Phase 4 — simulation control.
|
|
185
|
+
|
|
186
|
+
### Added
|
|
187
|
+
|
|
188
|
+
- `bridge/simulation.py` with `SimulationController` and `SimulationCom` Protocol abstracting `ModelRiskSimulation` + `ModelRiskSimulationSettings`.
|
|
189
|
+
- 4 simulation tools: `set_simulation_settings`, `run_simulation`, `stop_simulation` (registered stub raising `SimulationNotAvailableError`), `get_simulation_status` (in-process polling fallback).
|
|
190
|
+
- `seed=42` auto-flips `use_fixed_seed=True` when the user doesn't pass it explicitly.
|
|
191
|
+
|
|
192
|
+
## [0.1.0-alpha.2] — 2026-05-20 (commit `2cc7e6b`)
|
|
193
|
+
|
|
194
|
+
Phase 3 — building tools and `restore_cell`.
|
|
195
|
+
|
|
196
|
+
### Added
|
|
197
|
+
|
|
198
|
+
- 10 building tools (`tools/building.py`): `insert_distribution`, `wrap_with_input`, `wrap_with_output`, `replace_constant_with_distribution`, `fit_distribution_to_data`, `create_aggregate_mc`, `create_risk_event`, `create_time_series`, `create_copula`, `set_named_range`. Every tool defaults `dry_run=True`.
|
|
199
|
+
- `restore_cell` MCP tool (`tools/restore.py`) — restores any cell from the audit log.
|
|
200
|
+
- `ModelRiskBridge.safe_write_cell` — every cell write goes through this and gets: writer-mutex acquisition, non-Vose-formula refusal via tokenised detection, audit-log append.
|
|
201
|
+
- `ExcelBridge.set_named_range` + `ExcelBridge.undo` for the Excel-undo-stack acceptance test.
|
|
202
|
+
|
|
203
|
+
## [0.1.0-alpha.1] — 2026-05-20 (commit `793a17c`)
|
|
204
|
+
|
|
205
|
+
Phase 2 — reading tools.
|
|
206
|
+
|
|
207
|
+
### Added
|
|
208
|
+
|
|
209
|
+
- 12 reading tools (`tools/reading.py`): `list_open_workbooks`, `get_active_workbook`, `get_workbook_summary`, `list_modelrisk_inputs`, `list_modelrisk_outputs`, `list_distributions`, `get_cell`, `read_range`, `get_simulation_results`, `get_correlation_matrix`, `get_sensitivity_ranking`, `find_hard_coded_inputs`.
|
|
210
|
+
- `bridge/results.py` — `ResultsReader` wrapping `ISimVariable.GetMean/Percentile/StDev/...`. Pearson + Spearman correlation and Spearman-based tornado computed in numpy from `GetSamples()`.
|
|
211
|
+
- `docs/installation.md`, `docs/claude-desktop.md`, `docs/claude-code.md`.
|
|
212
|
+
|
|
213
|
+
## [0.0.2] — 2026-05-19 (commit `c4fe8b5`)
|
|
214
|
+
|
|
215
|
+
Phase 1 — bridge layer, safety mechanisms, function catalogue.
|
|
216
|
+
|
|
217
|
+
### Added
|
|
218
|
+
|
|
219
|
+
- 1417-entry function catalogue (`data/functions.json`) extracted from the ModelRisk IDL + XLL header.
|
|
220
|
+
- `bridge/{catalogue,excel,formulas,modelrisk,progids}.py` — three-layer architecture.
|
|
221
|
+
- `safety.py` — tokenised `is_vose_formula` detector, bulk-write guard, audit-log appender, Windows-named-mutex `WriterMutex`.
|
|
222
|
+
- Pydantic v2 schemas for every tool input/output (`schemas/{workbook,distributions,results}.py`).
|
|
223
|
+
- `data/optional_overrides.yaml` — flips `VoseModPERT.gamma` (and similar) to optional with their documented defaults.
|
|
224
|
+
- Gated integration test infrastructure (`tests/integration/`) — skips cleanly when Excel isn't running.
|
|
225
|
+
|
|
226
|
+
## [0.0.1] — 2026-05-19 (commit `3741386`)
|
|
227
|
+
|
|
228
|
+
Phase 0 — scaffold.
|
|
229
|
+
|
|
230
|
+
### Added
|
|
231
|
+
|
|
232
|
+
- Empty FastMCP server that responds to `initialize` and returns an empty `tools/list`.
|
|
233
|
+
- `pyproject.toml`, `LICENSE` (MIT), `.gitignore`, `.python-version`.
|
|
234
|
+
- `.github/workflows/ci.yml` — ruff + mypy + pytest on Windows × Python 3.11/3.12/3.13.
|
|
235
|
+
- `scripts/spike_com_surface.py` — probes ModelRisk's COM surface and writes `docs/com-surface.md`.
|
|
236
|
+
- `modelrisk_mcp.spec` — PyInstaller spec used for the Phase 0 smoke build.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vose Software
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modelrisk-mcp
|
|
3
|
+
Version: 0.3.0a5
|
|
4
|
+
Summary: Open MCP server bridging Anthropic Claude (and any MCP-compatible client) with the ModelRisk Excel add-in.
|
|
5
|
+
Project-URL: Homepage, https://github.com/vosesoftware/modelrisk-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/vosesoftware/modelrisk-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/vosesoftware/modelrisk-mcp/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/vosesoftware/modelrisk-mcp/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Documentation, https://github.com/vosesoftware/modelrisk-mcp/tree/main/docs
|
|
10
|
+
Project-URL: Vose Software, https://www.vosesoftware.com
|
|
11
|
+
Author-email: Vose Software <info@vosesoftware.com>
|
|
12
|
+
Maintainer-email: Vose Software <info@vosesoftware.com>
|
|
13
|
+
License-Expression: MIT
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Keywords: anthropic,claude,excel,mcp,modelrisk,monte-carlo,probability,risk-analysis,simulation,vose
|
|
16
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
17
|
+
Classifier: Environment :: Console
|
|
18
|
+
Classifier: Intended Audience :: Developers
|
|
19
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
20
|
+
Classifier: Intended Audience :: Science/Research
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
22
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
23
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
28
|
+
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
|
|
29
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
30
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
31
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
32
|
+
Classifier: Typing :: Typed
|
|
33
|
+
Requires-Python: >=3.11
|
|
34
|
+
Requires-Dist: mcp[cli]>=1.2.0
|
|
35
|
+
Requires-Dist: numpy>=1.26
|
|
36
|
+
Requires-Dist: pydantic>=2.6
|
|
37
|
+
Requires-Dist: pywin32>=306; sys_platform == 'win32'
|
|
38
|
+
Requires-Dist: pyyaml>=6.0
|
|
39
|
+
Requires-Dist: xlwings>=0.31; sys_platform == 'win32'
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
42
|
+
Requires-Dist: pyinstaller>=6.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest-mock>=3.12; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
46
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
|
|
49
|
+
# ModelRisk MCP
|
|
50
|
+
|
|
51
|
+
**An open Model Context Protocol server for [Vose Software's ModelRisk](https://www.vosesoftware.com).**
|
|
52
|
+
|
|
53
|
+
Use it with Claude Desktop, Claude Code, Cursor, Zed, or any MCP-compliant client to read, build, fit, and run Monte Carlo risk models in Excel from a conversation.
|
|
54
|
+
|
|
55
|
+
> ModelRisk MCP is an open MCP server on the standard Anthropic Model Context Protocol. No proprietary layer, no lock-in. The 1417-entry function catalogue, the Vose methodology principles, and the audit rule set are all included in the package — and editable.
|
|
56
|
+
|
|
57
|
+
**Status: `0.3.0-alpha.5`** — programmatic simulation via the `run_simulation` tool wired end-to-end (XLL command surface, no fragile COM dispatch); `.vmrs` results read via the official ModelRisk SDK; activation ships bundled so no environment configuration is required. 35 tools across reading, building, simulation, scenario-sweep, restore, charting, audit, and workflow surfaces.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## What this does
|
|
62
|
+
|
|
63
|
+
This server turns Claude (or any MCP client) into a methodology-aware co-pilot for ModelRisk. It can:
|
|
64
|
+
|
|
65
|
+
- **Build** new Monte Carlo models from a description — insert distributions, fit families to data, build aggregates, copulas, time-series, risk events.
|
|
66
|
+
- **Run** simulations from the conversation. `run_simulation` triggers the same XLL command the ribbon "Simulate" button uses, blocks until the run finishes, saves a `.vmrs` next to the workbook, and auto-pins it as the results source.
|
|
67
|
+
- **Read** model structure and per-iteration results — inputs, outputs, percentiles, correlation matrices, tornado rankings — directly from `.vmrs` files via ModelRisk's official SDK (MRService.dll). No COM dispatch fragility.
|
|
68
|
+
- **Audit** a workbook against Vose's methodology rules and propose fixes.
|
|
69
|
+
- **Interpret** results into structured executive summaries with contingency analysis.
|
|
70
|
+
|
|
71
|
+
Every formula written to Excel is validated against the ModelRisk function catalogue first — there's no path to a hallucinated function name reaching your workbook.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Feature comparison
|
|
76
|
+
|
|
77
|
+
| Capability | ModelRisk MCP | Closed alternatives |
|
|
78
|
+
|---|:---:|:---:|
|
|
79
|
+
| Read model structure (inputs, outputs, distributions) | ✓ | ✓ |
|
|
80
|
+
| Read simulation results, percentiles, sensitivity | ✓ | ✓ |
|
|
81
|
+
| Insert distributions into cells | ✓ | — |
|
|
82
|
+
| Fit distributions from data | ✓ | — |
|
|
83
|
+
| Build aggregate (frequency × severity) models | ✓ | — |
|
|
84
|
+
| Build copulas / correlated inputs | ✓ | — |
|
|
85
|
+
| Build time-series stochastic processes | ✓ | — |
|
|
86
|
+
| Run simulations from the conversation | ✓ | — |
|
|
87
|
+
| Audit model for common methodology mistakes | ✓ | — |
|
|
88
|
+
| Works with Claude Desktop / Code / Cursor / Zed / any MCP client | ✓ | — |
|
|
89
|
+
| Open source, MIT licensed | ✓ | — |
|
|
90
|
+
| Local-only, no telemetry | ✓ | varies |
|
|
91
|
+
| Default-safe (dry-run preview before every write) | ✓ | n/a |
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Install
|
|
96
|
+
|
|
97
|
+
### Prerequisites
|
|
98
|
+
|
|
99
|
+
- Windows 10 or 11, 64-bit
|
|
100
|
+
- Excel 2019 or newer with the ModelRisk add-in installed and loaded
|
|
101
|
+
- One of:
|
|
102
|
+
- Python 3.11+ (recommended via [`uv`](https://docs.astral.sh/uv/))
|
|
103
|
+
- Or the standalone `modelrisk-mcp.exe` from the [latest release](https://github.com/vosesoftware/modelrisk-mcp/releases/latest) — no Python knowledge required
|
|
104
|
+
|
|
105
|
+
**Activation:** None required. MRService.dll (the SDK that reads `.vmrs` files) is activated automatically by a bundled offline key. Set `MRSERVICE_ACTIVATION_KEY` only if you want to override the default with your own.
|
|
106
|
+
|
|
107
|
+
### From PyPI
|
|
108
|
+
|
|
109
|
+
```powershell
|
|
110
|
+
pip install modelrisk-mcp
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### From source
|
|
114
|
+
|
|
115
|
+
```powershell
|
|
116
|
+
git clone https://github.com/vosesoftware/modelrisk-mcp
|
|
117
|
+
cd modelrisk-mcp
|
|
118
|
+
uv sync
|
|
119
|
+
uv run python -m modelrisk_mcp # speaks MCP over stdio
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Standalone `.exe`
|
|
123
|
+
|
|
124
|
+
Download `modelrisk-mcp.exe` from [Releases](https://github.com/vosesoftware/modelrisk-mcp/releases/latest), drop it anywhere on disk, and point Claude Desktop at it. See [docs/claude-desktop.md](docs/claude-desktop.md).
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Wire into Claude Desktop
|
|
129
|
+
|
|
130
|
+
Open `%APPDATA%\Claude\claude_desktop_config.json` and add:
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"mcpServers": {
|
|
135
|
+
"modelrisk": {
|
|
136
|
+
"command": "python",
|
|
137
|
+
"args": ["-m", "modelrisk_mcp"]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Or, if you downloaded the `.exe`:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"mcpServers": {
|
|
148
|
+
"modelrisk": {
|
|
149
|
+
"command": "C:/path/to/modelrisk-mcp.exe"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Restart Claude Desktop. The ModelRisk tools appear under the connections icon. Full guide: [docs/claude-desktop.md](docs/claude-desktop.md). Claude Code setup: [docs/claude-code.md](docs/claude-code.md).
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Wire into Claude for Excel (HTTP transport)
|
|
160
|
+
|
|
161
|
+
Claude for Excel runs inside an Office.js sandbox and can't spawn subprocesses, so it talks to MCP servers over HTTP. Start the server in HTTP mode:
|
|
162
|
+
|
|
163
|
+
```powershell
|
|
164
|
+
$env:MODELRISK_MCP_TOKEN = [Guid]::NewGuid().ToString("N") * 2
|
|
165
|
+
modelrisk-mcp --transport=streamable-http --port=8000 --token=$env:MODELRISK_MCP_TOKEN
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Then in Claude for Excel: Settings → Connectors → Add MCP server, URL `http://127.0.0.1:8000/mcp`, paste the token. Full guide: [docs/claude-for-excel.md](docs/claude-for-excel.md).
|
|
169
|
+
|
|
170
|
+
**Why this is interesting:** Claude for Excel's sandbox can't reach Excel's COM surface or the ModelRisk ribbon on its own. ModelRisk MCP runs outside the sandbox and bridges that gap — Claude for Excel can do things via this server it structurally can't do otherwise (run simulations, dispatch ModelRisk COM, write distributions through the safety pipeline).
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## First conversation
|
|
175
|
+
|
|
176
|
+
Open a workbook in Excel that has at least one Vose function — even a single `=VoseNormal(0,1)`. Then in Claude:
|
|
177
|
+
|
|
178
|
+
> Summarise the active workbook's risk model — inputs, outputs, distributions.
|
|
179
|
+
|
|
180
|
+
Or jump straight into building:
|
|
181
|
+
|
|
182
|
+
> /build-risk-model
|
|
183
|
+
|
|
184
|
+
This walks through 9 steps, from identifying outputs through running the simulation and interpreting results. See [the slash-command catalogue](src/modelrisk_mcp/prompts) for the other workflows.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Safety by design
|
|
189
|
+
|
|
190
|
+
The server can both read *and* modify your workbook — that's the central differentiator. We make that safe with nine layered mechanisms (spec §11):
|
|
191
|
+
|
|
192
|
+
1. **`dry_run=True` is the default** on every building tool. Claude must explicitly pass `dry_run=False` to commit. Previewing comes free; a forgotten flag becomes a preview, never an overwrite.
|
|
193
|
+
2. **Every write lands in Excel's native undo stack.** `Ctrl+Z` works exactly as you'd expect.
|
|
194
|
+
3. **Bulk-write guard.** Tools writing >50 cells in one call require explicit `confirm_bulk=True`. Time-series and copula tools — which write contiguous ranges by design — are exempt.
|
|
195
|
+
4. **No automatic saves.** The server never calls `Workbook.Save()`. You control `Ctrl+S`.
|
|
196
|
+
5. **No overwriting non-Vose formulas.** A formula-tokenised detector (not a substring check) refuses to overwrite a cell whose existing formula uses non-Vose functions. The one tool explicitly allowed to do this is `replace_constant_with_distribution`, by design.
|
|
197
|
+
6. **Audit log** of every write in `%LOCALAPPDATA%\VoseSoftware\modelrisk-mcp\writes.log` — timestamp, cell, before/after formulas, before value. JSONL, append-only.
|
|
198
|
+
7. **Read-only mode.** Launch with `--read-only` to disable every building/simulation tool.
|
|
199
|
+
8. **Single-writer mutex.** Two MCP server instances can't drive the same Excel concurrently — the second instance raises `ConcurrentWriterError` on any building tool call.
|
|
200
|
+
9. **Restore from audit log.** The `restore_cell` tool reads writes.log and rewrites the pre-write formula — even after Excel's undo stack has been cleared.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## What's inside
|
|
205
|
+
|
|
206
|
+
- **35 tools** — 16 reading (incl. `read_vmrs` / `set_active_vmrs` / `list_vmrs_variables` / `get_samples`), 10 building, 2 simulation (`run_simulation` + `run_scenarios`), 1 restore (`restore_cell`), 6 workflow (incl. `diagnose_workbook` + `create_tornado_chart`)
|
|
207
|
+
- **7 resources** — `modelrisk://functions`, `modelrisk://functions/{name}`, `modelrisk://distributions`, `modelrisk://methodology`, `modelrisk://workbook/current`, `modelrisk://workbook/current/sheet/{name}`, `modelrisk://audit-rules`
|
|
208
|
+
- **5 slash-command prompts** — `/build-risk-model`, `/audit-model`, `/interpret-results`, `/add-uncertainty`, `/import-legacy-model`
|
|
209
|
+
- **1417-entry function catalogue** extracted directly from the ModelRisk IDL + XLL header
|
|
210
|
+
- **11 audit rules** with editable severity in `data/audit_rules.yaml`; add your own with `docs/authoring-audit-rules.md`
|
|
211
|
+
- **Methodology-grounded distribution selection guide** in `data/distributions.yaml`
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Methodology
|
|
216
|
+
|
|
217
|
+
The server is opinionated about Monte Carlo methodology — fetch `modelrisk://methodology` from any MCP client to read the 8 core principles. Highlights:
|
|
218
|
+
|
|
219
|
+
- Every uncertain input is a distribution. Treating a noisy input as deterministic understates total uncertainty by exactly the amount it could swing.
|
|
220
|
+
- Distribution fits use `uncertainty=TRUE`. Carry parameter uncertainty through the simulation; don't pretend the best-fit parameters are exact.
|
|
221
|
+
- Risk events use `VoseRiskEvent`, not `probability * impact`. The bimodal nature matters.
|
|
222
|
+
- Correlated inputs use copulas. Independent inputs that are actually correlated produce artificially tight outputs.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Architecture
|
|
227
|
+
|
|
228
|
+
Three internal layers plus two external integration paths:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
┌──────────────────────────────────┐
|
|
232
|
+
│ MCP client │
|
|
233
|
+
│ (Claude Desktop, Code, etc.) │
|
|
234
|
+
└────────────────┬─────────────────┘
|
|
235
|
+
│ JSON-RPC / stdio (or HTTP)
|
|
236
|
+
▼
|
|
237
|
+
┌──────────────────────────────────┐
|
|
238
|
+
│ FastMCP layer (tools, resources,│
|
|
239
|
+
│ prompts) │
|
|
240
|
+
├──────────────────────────────────┤
|
|
241
|
+
│ ModelRiskBridge (domain) │
|
|
242
|
+
│ + SimulationController │
|
|
243
|
+
│ + ResultsReader │
|
|
244
|
+
├──────────────────────────────────┤
|
|
245
|
+
│ ExcelBridge MrServiceBridge│
|
|
246
|
+
│ (xlwings) (ctypes) │
|
|
247
|
+
└──────┬───────────────────┬───────┘
|
|
248
|
+
│ Application.Run │ MRLIB_*
|
|
249
|
+
│ + cell I/O │ (read .vmrs)
|
|
250
|
+
▼ ▼
|
|
251
|
+
┌──────────────┐ ┌──────────────────┐
|
|
252
|
+
│ Excel + │ │ MRService.dll │
|
|
253
|
+
│ ModelRisk XLL│ │ (SDK) │
|
|
254
|
+
└──────────────┘ └──────────────────┘
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Two integration paths, each chosen for what it does best:
|
|
258
|
+
|
|
259
|
+
- **Builds + simulation trigger** → Excel COM via xlwings, plus `Application.Run("VoseStartSimulCustom12", …)` for the simulation kickoff. Mirrors what the ModelRisk ATL does internally; bypasses the fragile ATL CoClass Dispatch surface that doesn't expose IDispatch.
|
|
260
|
+
- **Results read** → MRService.dll directly via ctypes. Vose's official SDK opens `.vmrs` files, returns sample arrays, computes statistics. No COM round-trips per output; per-iteration sample arrays available for arbitrary downstream analysis.
|
|
261
|
+
|
|
262
|
+
More: [docs/architecture.md](docs/architecture.md), [docs/com-surface.md](docs/com-surface.md).
|
|
263
|
+
|
|
264
|
+
## Known caveats
|
|
265
|
+
|
|
266
|
+
- **OneDrive-hosted workbooks**: xlwings can fail to resolve the workbook's full path without `ONEDRIVE_COMMERCIAL_WIN` set. The bridge degrades gracefully — name-based operations still work, and `run_simulation` defaults the `.vmrs` save location to the user's Desktop when the workbook folder can't be resolved.
|
|
267
|
+
- **Active simulation results**: `get_simulation_results` reads from the `.vmrs` file produced by the most recent `run_simulation` call, or the most recent sibling `.vmrs` next to the workbook. Use `set_active_vmrs(path)` or `read_vmrs(path)` to point at a specific file.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## License
|
|
272
|
+
|
|
273
|
+
MIT. See [LICENSE](LICENSE).
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Links
|
|
278
|
+
|
|
279
|
+
- **Vose Software**: <https://www.vosesoftware.com>
|
|
280
|
+
- **ModelRisk product page**: <https://www.vosesoftware.com/products/modelrisk/>
|
|
281
|
+
- **Source**: <https://github.com/vosesoftware/modelrisk-mcp>
|
|
282
|
+
- **Releases**: <https://github.com/vosesoftware/modelrisk-mcp/releases>
|
|
283
|
+
- **Issues**: <https://github.com/vosesoftware/modelrisk-mcp/issues>
|
|
284
|
+
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
|
|
285
|
+
- **MCP spec**: <https://modelcontextprotocol.io>
|