Skip to content

Centralize MCP capability metadata so runtime CLI tests and docs do not drift #157

Description

@pesap

Centralize MCP capability metadata so runtime, CLI, tests, and docs do not drift

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/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

Current behavior

MCP tool capability metadata is duplicated in multiple places. The runtime
admin tool and the one-shot CLI capabilities command each hard-code a category
map, docs hard-code the tool count/list, and tests only assert minimal category
presence.

  • src/plexosdb-mcp/src/plexosdb_mcp/server.py:719-757get_server_config() hard-codes categories.
# src/plexosdb-mcp/src/plexosdb_mcp/server.py:719-757
def _register_admin_tools(mcp: Any, server_state: MCPServerState) -> None:
    """Register administrative and server-introspection tools."""

    @mcp.tool()
    def get_server_config() -> dict[str, Any]:
        """Return server runtime configuration for host diagnostics."""
        return {
            "read_only": server_state.read_only,
            "active_sessions": server_state.active_session_count,
            "categories": {
                "session": ["health", "create_empty_session", "open_xml_session", "close_session"],
                "discovery": [
                    "list_classes",
                    "list_collections",
                    ...
                ],
                "edit": [
                    "add_object",
                    ...
                ],
                "export": ["save_xml", "to_csv"],
                "admin": ["get_server_config"],
            },
        }
  • src/plexosdb-mcp/src/plexosdb_mcp/server.py:922-955_run_capabilities_command() repeats the same category map.
# src/plexosdb-mcp/src/plexosdb_mcp/server.py:922-955
def _run_capabilities_command() -> None:
    """Print available MCP tools by category as JSON to stdout."""
    payload: dict[str, Any] = {
        "ok": True,
        "tools": {
            "session": ["health", "create_empty_session", "open_xml_session", "close_session"],
            "discovery": [
                "list_classes",
                "list_collections",
                ...
            ],
            "edit": [
                "add_object",
                ...
            ],
            "export": ["save_xml", "to_csv"],
            "admin": ["get_server_config"],
        },
        "subcommands": ["health", "version", "doctor", "capabilities"],
    }
  • docs/source/howtos/mcp_server.md:7-18 — docs hard-code a count and tool list.
# docs/source/howtos/mcp_server.md:7-18
The server exposes a curated set of **29 tools**, grouped in categories similar
to toolsets:

- Session: `health`, `create_empty_session`, `open_xml_session`, `close_session`
- Discovery: `list_objects_by_class`, `list_object_memberships`,
  ...
  • src/plexosdb-mcp/tests/test_mcp_server.py:581 and src/plexosdb-mcp/tests/test_mcp_server.py:787-788 — tests assert category presence but not equality with registered tools.
# src/plexosdb-mcp/tests/test_mcp_server.py:581
assert "discovery" in config["categories"]

# src/plexosdb-mcp/tests/test_mcp_server.py:787-788
assert set(payload["tools"]) == {"session", "discovery", "edit", "export", "admin"}
assert "health" in payload["tools"]["session"]

Desired behavior or Goal

The MCP server should define tool category metadata once and reuse it for
runtime admin output, one-shot CLI capabilities output, and tests. User-facing
docs should avoid a brittle hard-coded tool count or clearly direct users to the
capabilities command as the source of truth.

Acceptance criteria

  • src/plexosdb-mcp/src/plexosdb_mcp/server.py contains one module-level category metadata structure for MCP tool groups.
  • get_server_config() returns categories derived from that single metadata structure.
  • _run_capabilities_command() returns tools derived from that same metadata structure.
  • Tests assert that get_server_config()["categories"] and capabilities command payload["tools"] are equal.
  • Tests assert that the union of categorized tool names matches the fake FastMCP registered tool names after build_mcp_server(), with no undocumented extras or omissions.
  • docs/source/howtos/mcp_server.md removes the brittle hard-coded count or updates the wording so plexosdb-mcp capabilities is the source of truth for the current tool list.

Non-goals

  • Do not add, remove, or rename MCP tools in this issue.
  • Do not change public JSON keys returned by get_server_config() or plexosdb-mcp capabilities.
  • Do not restructure the CLI parser or change subcommand behavior.
  • Do not address release/CI wiring in this issue.

Work Plan

Validation

  • uv run --project src/plexosdb-mcp pytest -q -c src/plexosdb-mcp/pyproject.toml src/plexosdb-mcp/tests/test_mcp_server.py -k "capabilities or config" exits 0.
  • uv run --project src/plexosdb-mcp pytest -q -c src/plexosdb-mcp/pyproject.toml src/plexosdb-mcp/tests exits 0.
  • uv run sphinx-build docs/source/ docs/_build/ exits 0 after doc wording changes.
  • 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 to avoid a manually maintained numeric tool count.
  • Keep the how-to focused on usage; point users to plexosdb-mcp capabilities --json for the authoritative current list.

Testing

  • Update src/plexosdb-mcp/tests/test_mcp_server.py to compare get_server_config() categories and CLI capabilities output.
  • Add a test that builds the fake MCP server and compares registered fake tool names to the categorized metadata union.
  • Preserve the existing smoke tests for capabilities --json and get_server_config().

Risks

Breaking-change

Low. The intended public JSON shape remains unchanged. Risk is accidental tool name/category drift during refactor.

Review-size

Low. Scope is limited to one source file, one focused test file, and one docs page.

Implementation notes

Scope

In scope:

  • src/plexosdb-mcp/src/plexosdb_mcp/server.py
  • src/plexosdb-mcp/tests/test_mcp_server.py
  • docs/source/howtos/mcp_server.md

Out of scope:

  • .github/workflows/CI.yaml — covered by the MCP CI/pre-push issue this packet depends on.
  • .github/workflows/release.yaml — covered by the release/publishing issue.
  • src/plexosdb/db.py and root package internals — no root API changes are needed.

Suggested steps

  1. Add a module-level constant such as MCP_TOOL_CATEGORIES: dict[str, tuple[str, ...]] in src/plexosdb-mcp/src/plexosdb_mcp/server.py.
    • Preserve current category names and tool names exactly.
  2. Add a small helper that returns a JSON-serializable copy of the category map.
    • Use it in get_server_config() and _run_capabilities_command().
  3. Strengthen tests in src/plexosdb-mcp/tests/test_mcp_server.py.
    • Compare admin config categories to CLI capabilities tools.
    • Compare the categorized tool-name union to FakeFastMCP.tools.keys() after registration.
  4. Update docs/source/howtos/mcp_server.md.
    • Remove or soften the hard-coded numeric count.
    • Keep a concise category overview and direct users to plexosdb-mcp capabilities --json for the complete current list.
  5. Run focused MCP tests, docs build, and the broad pre-push gate.

Test details

  • Capture plexosdb-mcp capabilities output using the existing capsys pattern in test_smoke_capabilities_subcommand.
  • Use the existing FakeFastMCP registry in test_build_mcp_server_registers_tool_categories style tests.

Maintenance notes

  • Future MCP tool additions must update the single metadata structure and should fail tests if registration and metadata diverge.
  • Reviewers should verify that public output keys remain categories for get_server_config() and tools for the capabilities command.

Metadata

Metadata

Assignees

No one assigned

    Labels

    improveGenerated improvement work packettech-debtTechnical debt and architecture cleanupworkon-readyReady for autonomous /workon execution

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions