NatLabRockies / NatLabRockies/plexosdb

Split plexosdb_mcp.server into focused state tool-registration and CLI modules

Open
#158 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

improve tech-debt workon-ready
Dominant language
Python
Stars
37
Forks
21
Avg merge
1h 23m
Merged PRs (30d)
3

Description

Split plexosdb_mcp.server into focused state, tool-registration, and CLI modules

Executor instructions: Follow this issue step by step. Run every
verification command and confirm the expected result before moving on. If any
STOP condition is true, stop and report instead of improvising.

Drift check (run first): git diff --stat a11b6a3..HEAD -- src/plexosdb-mcp/src/plexosdb_mcp/server.py src/plexosdb-mcp/src/plexosdb_mcp/__init__.py src/plexosdb-mcp/src/plexosdb_mcp/__main__.py src/plexosdb-mcp/tests/test_mcp_server.py docs/source/howtos/mcp_server.md
If any in-scope file changed since this issue was written, compare the
Current behavior excerpts against live code before proceeding. If they do not
match, stop and ask for /plan to refresh this issue.

Status

  • Priority: P3
  • Effort: M
  • Risk: MED
  • Depends on: #155 and #157
  • Category: tech-debt
  • Planned at: commit a11b6a3, 2026-07-08

Current behavior

The new MCP adapter keeps session state, empty-model bootstrapping, parser
helpers, all MCP tool registration groups, admin/capabilities metadata, CLI
argument parsing, one-shot diagnostic commands, and runtime entrypoint logic in a
single module.

  • src/plexosdb-mcp/src/plexosdb_mcp/server.py is 1014 lines at the planned commit.
$ wc -l src/plexosdb-mcp/src/plexosdb_mcp/server.py
1014 src/plexosdb-mcp/src/plexosdb_mcp/server.py
  • src/plexosdb-mcp/src/plexosdb_mcp/server.py mixes multiple ownership areas in one file.
# src/plexosdb-mcp/src/plexosdb_mcp/server.py:30,130,180,208,362,507,621,691,719,762,787,840,922,962,1002
30:class MCPServerState:
130:def _bootstrap_empty_model(db: PlexosDB) -> None:
180:def _register_session_tools(mcp: Any, server_state: MCPServerState) -> None:
208:def _register_object_tools(mcp: Any, server_state: MCPServerState) -> None:
362:def _register_edit_tools(mcp: Any, server_state: MCPServerState) -> None:
507:def _register_discovery_catalog_tools(mcp: Any, server_state: MCPServerState) -> None:
621:def _register_discovery_query_tools(mcp: Any, server_state: MCPServerState) -> None:
691:def _register_export_tools(mcp: Any, server_state: MCPServerState) -> None:
719:def _register_admin_tools(mcp: Any, server_state: MCPServerState) -> None:
762:def build_mcp_server(state: MCPServerState | None = None, *, read_only: bool | None = None) -> Any:
787:def _parse_cli_args(argv: list[str] | None = None) -> argparse.Namespace:
840:def _run_cli_command(command: str, xml_path: str | None = None) -> None:
922:def _run_capabilities_command() -> None:
962:def _main_impl(argv: list[str] | None) -> None:
1002:def main(argv: list[str] | None = None) -> None:
  • Public package exports currently come through src/plexosdb-mcp/src/plexosdb_mcp/__init__.py.
# src/plexosdb-mcp/src/plexosdb_mcp/__init__.py
from plexosdb_mcp.server import (
    MCPServerState,
    build_mcp_server,
    main,
)

__all__ = ("MCPServerState", "build_mcp_server", "main")

Desired behavior or Goal

Refactor the MCP adapter into focused modules while preserving public behavior.
The server.py file should become a small orchestration/compatibility module,
not the owner of every concern. Maintainers should be able to change CLI
behavior, tool registration, session state, and diagnostic metadata without
scrolling through a thousand-line mixed-concern file.

Acceptance criteria

  • src/plexosdb-mcp/src/plexosdb_mcp/server.py is reduced below 500 lines.
  • No new Python source file introduced by this refactor exceeds 800 lines.
  • Public imports remain compatible: from plexosdb_mcp import MCPServerState, build_mcp_server, main still works.
  • The console script plexosdb-mcp still delegates through plexosdb_mcp.__main__:main and preserves existing CLI behavior.
  • MCP tool names and successful JSON response shapes remain unchanged.
  • get_server_config() and plexosdb-mcp capabilities behavior remains compatible with #157's centralized metadata design if #157 has already landed.
  • Existing MCP tests pass after the refactor.

Non-goals

  • Do not add, remove, or rename MCP tools.
  • Do not change the public CLI command names, JSON keys, or exit-code contract.
  • Do not change the query_readonly security behavior here; #154 owns that fix.
  • Do not wire new CI/release behavior here; #155 and #156 own those changes.
  • Do not rewrite PlexosDB core package internals under src/plexosdb/.

Work Plan

Validation
  • uv run --project src/plexosdb-mcp pytest -q -c src/plexosdb-mcp/pyproject.toml src/plexosdb-mcp/tests exits 0.
  • uv run --project src/plexosdb-mcp plexosdb-mcp health --json exits 0 and prints JSON with "ok": true.
  • uv run --project src/plexosdb-mcp plexosdb-mcp capabilities --json exits 0 and returns the same tool categories as before the refactor.
  • python - <<'PY'\nfrom plexosdb_mcp import MCPServerState, build_mcp_server, main\nprint(MCPServerState, build_mcp_server, main)\nPY exits 0 when run in the nested project environment.
  • wc -l src/plexosdb-mcp/src/plexosdb_mcp/server.py reports fewer than 500 lines.
  • uv run prek run --show-diff-on-failure --color=always --all-files --hook-stage pre-push exits 0 before handoff.
Documentation
  • Update docs/source/howtos/mcp_server.md only if import paths, CLI commands, or public behavior described there changes. Otherwise use None.
Testing
  • Update src/plexosdb-mcp/tests/test_mcp_server.py imports only as needed to follow the new module layout.
  • Preserve all behavior assertions; this is a refactor, so tests should prove behavior did not change.
  • If new internal helpers are non-trivial, add focused unit tests near existing MCP tests rather than relying only on smoke coverage.

Risks

Breaking-change

Medium. The intended behavior is unchanged, but moving entrypoint, registration, and state logic can break public imports or the console script if compatibility exports are missed.

Review-size

Medium. This should stay under about 500 changed lines by moving cohesive blocks rather than rewriting behavior. If the refactor starts changing behavior or adding abstractions, stop and split.

Implementation notes

Scope

In scope:

  • src/plexosdb-mcp/src/plexosdb_mcp/server.py
  • New focused modules under src/plexosdb-mcp/src/plexosdb_mcp/, for example:
    • state.py for MCPServerState and empty-session bootstrapping
    • parsing.py for enum/env/read-only helpers
    • tools.py or tools/*.py for MCP tool registration groups
    • cli.py for argument parsing and one-shot diagnostic commands
  • src/plexosdb-mcp/src/plexosdb_mcp/__init__.py
  • src/plexosdb-mcp/src/plexosdb_mcp/__main__.py
  • src/plexosdb-mcp/tests/test_mcp_server.py
  • docs/source/howtos/mcp_server.md only if public docs need path/behavior updates

Out of scope:

  • src/plexosdb/ root package internals.
  • .github/workflows/CI.yaml, .pre-commit-config.yaml, and release workflow files.
  • Security hardening of SQL read-only enforcement, which is #154.
  • Capability metadata centralization, which is #157 unless #157 has already landed and this refactor only preserves it.
Suggested steps
  1. Start with characterization: run the nested MCP test suite and capture current health, version, doctor, and capabilities JSON shapes.
  2. Move MCPServerState and _bootstrap_empty_model into a state-focused module.
    • Keep compatibility imports from server.py or __init__.py so external imports continue to work.
  3. Move CLI parsing and one-shot command functions into a CLI-focused module.
    • Keep main available through plexosdb_mcp.__main__ and plexosdb_mcp.__init__.
  4. Move MCP tool registration groups into one or more tool-focused modules.
    • Preserve tool names exactly.
  5. Leave server.py as a small compatibility/orchestration module exporting MCPServerState, build_mcp_server, and main.
  6. Run focused validation and broad pre-push validation.
Test details
  • Model import compatibility tests after existing package import style in src/plexosdb-mcp/tests/test_mcp_server.py.
  • Use the existing FakeFastMCP tool registry to assert registration did not lose or rename tools.
Maintenance notes
  • Future MCP tool additions should land in the relevant tool-registration module rather than growing server.py again.
  • Reviewers should verify this PR mostly moves code and preserves behavior; semantic changes should be pushed to their own issues.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the nested MCP pytest suite and the health, version, doctor, and capabilities commands to capture current behavior. Refactor src/plexosdb-mcp/src/plexosdb_mcp/server.py into focused state, parsing, tool-registration, and CLI modules while preserving compatibility exports in init.py and main.py. Done means server.py is under 500 lines, tool names and JSON shapes are unchanged, imports still work, and all listed validation commands pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, cli, testing-qa, tooling
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
54/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.