Skip to content

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

Merged
qian-harvard merged 4 commits into
Power-Agent:mainfrom
elasticdotventures:feat/plexosdb-connector
Aug 22, 2026
Merged

feat(plexosdb): PLEXOSDB connector — plexosdb-mcp CRUD + translate_to_sienna/compare_solutions via r2x#55
qian-harvard merged 4 commits into
Power-Agent:mainfrom
elasticdotventures:feat/plexosdb-connector

Conversation

@elasticdotventures

@elasticdotventures elasticdotventures commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

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
Contributor 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.

samtalki and others added 2 commits August 22, 2026 14:59
…gent#57)

Updates the bundled servers for MCP 2 (mcp>=2,<3; MCPServer) and powerio 0.9.0
(JSON transports, filesystem helpers, path containment via checked_path).
Validates model-supplied inputs and generated output paths before backend access.
Sets the package version to 0.3.0 and requires an existing published tag for
PyPI retries. Keeps pandapower on pandas 2. Imports and starts every advertised
server in CI.

Local verification (Windows, py3.12): tests/ 297 passed 10 skipped;
PSCAD/tests 16 passed 1 skipped; HOPE/tests 26 passed; powermcp --version 0.3.0.
Conflict resolution and adaptation to the new main:
- pyproject.toml: keep 0.3.0 layout (powerio is core, no fastmcp in
  powerfactory extra); re-apply the plexosdb extra, its all-group entry,
  the PLEXOSDB wheel force-include, and sdist include/exclude.
- tests/server_entry_smoke.py, tests/standalone_entry_smoke.py: stub the
  git-only upstream plexosdb-mcp with a real MCPServer so the new
  every-advertised-server-starts CI checks cover the plexosdb entry.
- PLEXOSDB/plexosdb_mcp/main.py: route xml_path/output_path arguments
  through powermcp.sandbox.checked_path (the containment policy every
  bundled server now applies) and register the tools in
  tests/test_sandbox.py's GUARDED map.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@qian-harvard
qian-harvard merged commit b4d3895 into Power-Agent:main Aug 22, 2026
2 checks passed
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.

3 participants