feat(plexosdb): PLEXOSDB connector — plexosdb-mcp CRUD + translate_to_sienna/compare_solutions via r2x - #55
Conversation
…_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)
|
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): Getting This PR now pins Full detail in |
…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>
Relates to #53.
Summary
PLEXOSDBconnector: thin re-export ofplexosdb-mcp's ~29 CRUD tools (matchespowerio/powerio_mcp.py's re-export pattern), plustranslate_to_sienna/compare_solutionscallingr2x-plexos/r2x-plexos-to-sienna/r2x-siennadirectly (no PowerMCP-authored bridge module).powermcp/registry.py: new"plexosdb"entry.PLEXOSDB/pyproject.toml, README (including the manual git-install step forplexosdb-mcp, which isn't on PyPI), and tests.What's verified for real (not mocked)
plexosdb,r2x, and the git-onlyplexosdb-mcpall install and run for real.open_xml_session,list_classes,list_objects_by_class,get_object_properties,list_object_memberships).run_kind="script"(notmodule, unlike PSCAD/HOPE) — testing caught that the module-launch path shadows the upstreamplexosdb_mcpimport viasys.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.pypasses unmodified. Wheel/sdist build cleanly withPLEXOSDB/force-included.Update: translation blocker resolved
r2x_plexos==0.2.0(pulled in by ther2xmeta-package) didn't catch the exceptionplexosdbraises on Horizons without explicit Chrono Date attributes — the common case, reproducing on all 7 models in the real test fixture. Fixed upstream inr2x_plexos>=0.3.0(verified against the released wheel); this PR now pins that directly rather than ther2xmeta-package. That version needsplexosdb>=1.6.0, whoseplexos2duckdbdependency has no non-yanked stable release, so install currently needs--prerelease=allow. Both gaps filed upstream: NatLabRockies/R2X#299, epri-dev/plexos2duckdb#3. Fulltranslate_to_siennapipeline re-verified end-to-end against the same fixture — seePLEXOSDB/README.md.Test plan
pytest tests/ PLEXOSDB/tests/ -qpython -m build(wheel + sdist)translate_to_siennafull round-trip — verified against the real fixture after pinningr2x-plexos>=0.3.0(--prerelease=allow)