Skip to content

feat(plexosdb): PLEXOSDB connector — plexosdb-mcp CRUD + translate_to_sienna/compare_solutions via r2x - #55

Open
elasticdotventures wants to merge 2 commits into
Power-Agent:mainfrom
elasticdotventures:feat/plexosdb-connector
Open

feat(plexosdb): PLEXOSDB connector — plexosdb-mcp CRUD + translate_to_sienna/compare_solutions via r2x#55
elasticdotventures wants to merge 2 commits into
Power-Agent:mainfrom
elasticdotventures:feat/plexosdb-connector

Conversation

@elasticdotventures

@elasticdotventures elasticdotventures commented Aug 7, 2026

Copy link
Copy Markdown

Relates to #53.

Summary

  • New PLEXOSDB connector: thin re-export of plexosdb-mcp's ~29 CRUD tools (matches powerio/powerio_mcp.py's re-export pattern), plus translate_to_sienna/compare_solutions calling r2x-plexos/r2x-plexos-to-sienna/r2x-sienna directly (no PowerMCP-authored bridge module).
  • powermcp/registry.py: new "plexosdb" entry.
  • Standalone PLEXOSDB/pyproject.toml, README (including the manual git-install step for plexosdb-mcp, which isn't on PyPI), and tests.

What's verified for real (not mocked)

  • plexosdb, r2x, and the git-only plexosdb-mcp all install and run for real.
  • A real PLEXOS XML study (103 classes, 7 models) loads and is fully inspectable through the live re-exported tools (open_xml_session, list_classes, list_objects_by_class, get_object_properties, list_object_memberships).
  • run_kind="script" (not module, unlike PSCAD/HOPE) — testing caught that the module-launch path shadows the upstream plexosdb_mcp import via sys.path; documented in the registry entry, main.py, pyproject.toml, and README.
  • pytest tests/ PLEXOSDB/tests/ -q → 111 passed, 4 pre-existing skips, 0 failures. test_registry.py passes unmodified. Wheel/sdist build cleanly with PLEXOSDB/ force-included.

Update: translation blocker resolved

r2x_plexos==0.2.0 (pulled in by the r2x meta-package) didn't catch the exception plexosdb raises on Horizons without explicit Chrono Date attributes — the common case, reproducing on all 7 models in the real test fixture. Fixed upstream in r2x_plexos>=0.3.0 (verified against the released wheel); this PR now pins that directly rather than the r2x meta-package. That version needs plexosdb>=1.6.0, whose plexos2duckdb dependency has no non-yanked stable release, so install currently needs --prerelease=allow. Both gaps filed upstream: NatLabRockies/R2X#299, epri-dev/plexos2duckdb#3. Full translate_to_sienna pipeline re-verified end-to-end against the same fixture — see PLEXOSDB/README.md.

Test plan

  • pytest tests/ PLEXOSDB/tests/ -q
  • Live PLEXOS XML load/inspect against real study data
  • python -m build (wheel + sdist)
  • translate_to_sienna full round-trip — verified against the real fixture after pinning r2x-plexos>=0.3.0 (--prerelease=allow)

…_to_sienna/compare_solutions via r2x)

Closes Power-Agent#53.

- powermcp/registry.py: new "plexosdb" Tool entry (server_dir="PLEXOSDB",
  kind="closed-source" per the PLEXOS engine it wraps, windows_only=False since
  plexosdb needs no PLEXOS install). Launched as run_kind="script" rather than
  "module": PLEXOSDB/plexosdb_mcp/main.py deliberately shares its package name
  with the upstream plexosdb-mcp distribution it re-exports, and module-style
  launch (which would add PLEXOSDB/ itself to sys.path) causes a confirmed
  self-shadow where `import plexosdb_mcp` inside main.py resolves to itself
  instead of the real installed package. Script launch avoids this.

- PLEXOSDB/plexosdb_mcp/main.py: thin re-export of plexosdb-mcp's FastMCP
  server (mcp = build_mcp_server()), covering all 29 upstream CRUD tools, plus
  translate_to_sienna and compare_solutions calling r2x's real public API
  directly (r2x_plexos.PLEXOSParser -> r2x_plexos_to_sienna.plexos_to_sienna ->
  r2x_sienna.SiennaExporter) with no PowerMCP-authored bridge module.

- PLEXOSDB/pyproject.toml: standalone installable package (PSCAD precedent),
  distribution name "powermcp-plexosdb" to avoid PyPI confusion with the
  upstream plexosdb-mcp project; depends only on r2x (the one PyPI-installable
  piece needed at import time by our own tools).

- Root pyproject.toml: "plexosdb" extra covers only r2x (PyPI-installable);
  plexosdb-mcp's git install is documented, not silently assumed. PLEXOSDB/
  force-included in the wheel/sdist build like every other connector.

- PLEXOSDB/tests/test_tools.py: MagicMock-based tests for translate_to_sienna/
  compare_solutions (PSCAD/tests/test_tools.py style), plus a re-export shape
  check. tests/test_vendor_import.py: side-effect-free import test for
  plexosdb_mcp.main, monkeypatching plexosdb_mcp in sys.modules (same pattern
  as the PSS/E psspy and PSLF PSLF_PYTHON tests) so no PLEXOS/plexosdb install
  is required to run it.

- PLEXOSDB/README.md: install steps (including the manual plexosdb-mcp git
  install), usage, and a documented upstream limitation found while verifying
  translate_to_sienna against a real PLEXOS XML study (plexosdb's own
  run_of_river_case/TestSystem.xml fixture, 103 classes / 7 models): r2x_plexos
  0.2.0's horizon resolution only catches AssertionError for a missing Horizon
  Chrono Date attribute, but plexosdb raises NotFoundError instead, so
  PLEXOSParser.run() fails on any PLEXOS model without explicit chronological
  horizon config -- the common case, reproduced on every model in the fixture.
  Session inspection (open XML, list classes/objects/properties/memberships)
  was verified working end-to-end against the same real fixture.

Verified for real (not just mocked): `uv pip install plexosdb r2x` and
`uv pip install "plexosdb-mcp @ git+https://github.com/NatLabRockies/plexosdb.git@main#subdirectory=src/plexosdb-mcp"`
both succeed; plexosdb-mcp's build_mcp_server() registers all 29 tools; a real
PLEXOS XML study loads and is fully inspectable through the re-exported tools.
…tion

r2x (the meta-package) transitively pins the buggy r2x-plexos==0.2.0.
0.3.0 already fixes the NotFoundError/AssertionError mismatch that broke
translate_to_sienna on every model in the real test fixture. Verified
against the same fixture: full PLEXOS XML -> Sienna PSY JSON translation
now succeeds end-to-end.

r2x-plexos>=0.3.0 requires plexosdb>=1.6.0, whose plexos2duckdb>=0.1.0b11
dependency has no non-yanked stable release, so this currently needs
--prerelease=allow. Filed upstream:
- NatLabRockies/R2X#299 (bump r2x's r2x-plexos pin)
- epri-dev/plexos2duckdb#3 (cut a non-yanked stable release)
@elasticdotventures

Copy link
Copy Markdown
Author

Update: the translation blocker noted in the original PR description is now fixed and verified end-to-end.

Root cause (confirmed by inspecting real released wheels and reproducing against plexosdb's own test fixture): r2x_plexos==0.2.0 — pulled in transitively by pinning the r2x meta-package — only catches AssertionError around a Horizon-attribute lookup that plexosdb can also fail with NotFoundError. Already fixed in r2x_plexos>=0.3.0 (verified against the released wheel). Filed NatLabRockies/R2X#299 so r2x itself picks up the fix.

Getting r2x_plexos>=0.3.0 installed hits a second, unrelated blocker: it requires plexosdb>=1.6.0, whose plexos2duckdb>=0.1.0b11 dependency has no non-yanked stable release (0.1.0 is yanked). Filed epri-dev/plexos2duckdb#3.

This PR now pins r2x-plexos>=0.3.0/r2x-plexos-to-sienna>=0.1.0/r2x-sienna>=0.4.0 directly (not the r2x meta-package), documents the --prerelease=allow requirement until plexos2duckdb ships a stable release, and re-verifies the full translate_to_sienna pipeline against the same real fixture that failed before:

{'ACBus': 3, 'PowerLoad': 1, 'Area': 1, 'Arc': 3, 'Line': 3}

Full detail in PLEXOSDB/README.md's "Known upstream issues" section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant