Skip to content

refactor(mcp): unify MCP onto consolidated registry + fold verified Menu A capabilities - #142

Closed
Hello-QM wants to merge 14 commits into
mainfrom
feat/mcp-unify-menu-b
Closed

refactor(mcp): unify MCP onto consolidated registry + fold verified Menu A capabilities#142
Hello-QM wants to merge 14 commits into
mainfrom
feat/mcp-unify-menu-b

Conversation

@Hello-QM

Copy link
Copy Markdown
Owner

What

CatGO exposed its backend over MCP through two independently hand-maintained registries — the granular stdio one (mcp_tools/tools/, ~69 tools) and the consolidated "Menu B" (server_claude_code.py, action-based mega-tools, served by HTTP /api/mcp + SSE). They drifted: features got added to one and not the other (this bit the recent lateral-heterostructure work, which had to be written twice).

This PR makes Menu B the single MCP surface for all transports and folds in the Menu-A-only capabilities that pass a real functional-test gate (live backend, real fixtures, assert on result content — not mocks, not HTTP-200 checks).

Design + plan: docs/superpowers/specs/2026-05-25-mcp-unify-menu-b-design.md, docs/superpowers/plans/2026-05-26-mcp-unify-menu-b.md.

Tool surface: 15 → 17

  • catgo_structure +4 building actions: defect, strain, passivate, water_layer
  • catgo_analyze +2: energy, calculators (and removed the dead dft_input — it POSTed to /dft-input/generate, which does not exist)
  • NEW catgo_md — 12 trajectory analyses (table-driven; base64 trajectory_b64 + format)
  • NEW catgo_input — LAMMPS/QE/VASP input generation + presets (supersedes the dead dft_input)
  • Transport unification: stdio server.py now serves Menu B (plugin / catgo_create_tool / catgo_ext_* / template-import branches preserved); HTTP + SSE already served it. All 4 dispatch chains verified 17/17, no orphans.

Result lists (per the test-gate)

✅ Folded (verified live):

  • catgo_structure: defect, strain, passivate (real TiO2(110) slab+bulk), water_layer
  • catgo_analyze: energy (real MACE single-point), calculators
  • catgo_md (10 green): rdf, msd, rmsd, rmsf, clustering, dimreduce, hbonds, hbond_lifetime, dihedrals, planar_density
  • catgo_input (9): lammps, lammps_pair_styles, lammps_sequential, lammps_validate, qe, qe_templates, vasp, vasp_calc_types, vasp_presets

↩️ Skipped (already in Menu B): structure-ops edits, fetch, heterostructure, moire, nanotube, catalysis, /dos/compute, /optimize/structure.

❌ Excluded (broken / no endpoint): reticular (no backend endpoint — code lives only in a worktree); analyze:dft_input (dead route, removed).

⏳ Excluded (unverifiable — needs fixture/dep):

  • Electronic-structure bucket (bands*, cohp, dos_total, dos_dband, dos_from_dir) — session/HPC-based, no real DFT-output fixtures in repo.
  • catgo_simulate / kMC — mykmc package not importable in this env.
  • catgo_md water_orientation + cavitation — handlers correct & action retained; functional tests xfail pending a water-trajectory fixture (the available trajectory is a non-water crystal).

Tests

test_consolidated_registry.py (new): functional gate per folded action (real fixtures, content assertions), schema tests, and a non-vacuous drift-guard (every Menu A endpoint is folded or on an explicit excluded list — a new uncovered endpoint fails the test). test_claude_code_mcp.py updated from its stale 11-tool/≤300-char assertions to the 17-tool reality.

Full suite: 63 passed, 2 xfailed (test_consolidated_registry.py test_claude_code_mcp.py test_mcp_tools.py).

Notes / follow-ups

  • The live /api/mcp HTTP transport needs a backend restart to surface the 2 new tools — the dev server process predates this branch. Correctness is verified by the test suite (current source) + per-handler live-backend gates.
  • vasp_presets loads workflow.presets.vasp frozen-import-first with a file-path fallback, and catgo_server.spec now collects workflow/presets/*.py — so it works in both dev and the PyInstaller bundle (avoids the known rfc3987-class silent-disable gotcha).
  • Pre-existing bugs left out of scope (follow-up): legacy catgo_structure:add_molecule reads a nonexistent n_water_placed (should be n_water_molecules); _handle_analyze catalysis actions use the same import workflow.* pattern that's shadowed by catgo/workflow on sys.path (latent, untested).
  • Stacks logically alongside feat(mcp): expose lateral (in-plane) heterostructure via MCP #138 (both touch server_claude_code.py); rebase if needed.

🤖 Generated with Claude Code

Hello-QM and others added 14 commits May 25, 2026 23:52
Single MCP surface = consolidated tools (server_claude_code.py). Fold
Menu A-only capabilities into Menu B as actions/new tools (catgo_md,
catgo_input, catgo_simulate; +building/electronic-structure actions on
catgo_structure/catgo_analyze), repoint stdio to serve Menu B, retire the
granular declarative registry from the live path. Plugin/dynamic features
left for follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per-capability migration gate: (0) dedup pre-check — skip endpoints Menu B
already reaches and Menu A's own dupes; (1) TDD routing + live test first;
(2) fold only if both green; (3) exclude + report broken endpoints instead
of shipping non-working tools. Final set = unique AND verified. PR reports
folded / skipped-duplicate / excluded-broken.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Migration gate is a REAL functional test: drive each action through the
consolidated handler against the live backend with a real fixture
(structure/trajectory/DFT dir) and assert on result content — changed
atom count, sane g(r)/MSD, expected INCAR/&control blocks, parsed Fermi
level. Bare HTTP 200 does not pass. Capabilities with no real fixture are
unverifiable → not folded. Fake-client routing tests demoted to optional
wiring regression. Four PR result lists; parity test accommodates the
excluded/unverifiable sets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…cope

Reading backend contracts up front applied the gate before implementation:
reticular has no endpoint (worktree-only); electronic-structure bucket is
session/HPC-based with no DFT fixtures → unverifiable; analyze:dft_input
posts to a non-existent /dft-input/generate (dead) and is superseded by the
new catgo_input. Verifiable set = catgo_structure +4 building, catgo_analyze
+energy/calculators, catgo_md (12, real trajectory fixture), catgo_input (9),
catgo_simulate (2, conditional on mykmc). Migration tables updated with exact
request shapes + fixtures from recon.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bite-sized TDD plan, real-functional-test gated per capability. Phases:
0 fixtures, 1 catgo_structure building actions, 2 analyze energy/calculators
(+drop dead dft_input), 3 catgo_md (12), 4 catgo_input (9, supersedes
dft_input), 5 stdio→Menu B transport unification (plugin branches kept),
6 schema+parity drift-guard + stale-test fix, 7 verify+PR with four result
lists. ES bucket / reticular / kMC excluded per recon (no fixtures/endpoint/dep).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…) into catgo_structure

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… dead dft_input

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…fallback); expose slow_growth

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…es preserved)

Repoint the stdio transport to advertise and dispatch the consolidated
"Menu B" mega-tools (catgo_structure/fetch/workflow/analyze/view/catalysis/
system/workflow_engine/file/diagnose/quickbuild/skills/heterostructure/
nanotube/moire/md/input) so all transports (stdio/HTTP/SSE) are unified.

- list_tools() now returns Menu B Tool objects + plugin defs.
- call_tool() routes Menu B names to server_claude_code handlers first;
  granular registry kept as _GRANULAR_TOOLS for the declarative/plugin
  fallback. All plugin / catgo_create_tool / catgo_ext_* / atomate2-quacc
  import / sandbox-file branches preserved.
- Added module-level list_tools_sync() helper.
- mcp_tools/__init__.py: bind `server` to the submodule (not the Server
  instance) so `import catgo.mcp_tools.server` resolves to the module and
  exposes list_tools_sync (required for the new test; no consumer relies on
  the prior Server-object re-export).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e stale test_claude_code_mcp to 17-tool reality

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t parity, honest drift-guard, schema/contract bugs)

server_claude_code.py:
- catalysis import shadowing: load workflow.catalysis.* via frozen-import-first
  + file-path fallback (same pattern as vasp_presets); dev tree no longer fails
  with "No module named workflow.catalysis".
- passivate: preflight error when `bulk` missing (backend requires slab AND bulk)
  instead of a raw 422.
- VASP calculation_type schema: list real enum (opt|scf|freq|bader|dos|ddec|elf|
  md|slow_growth); drop nonexistent relax|band.
- add_molecule: read n_water_molecules (was nonexistent n_water_placed -> always 0).
- strain axis schema: document a|b|c (uniaxial only); drop invented x|xy.
- defect supercell: document 2x2x2 default (omitting expands cell 8x).
- catgo_md: add missing topology_format field (binary xtc/trr/dcd were unusable).
- build dispatch: (data.get("structures") or [None])[0] — no IndexError on empty.
- QE input render: only string fields become file blocks; k-grid list labeled.

transport parity (server.py + mcp_http.py + mcp_sse.py):
- extract build_full_tool_list() / dispatch_dynamic_tool(); HTTP + SSE now
  advertise and dispatch the same plugin/ext/lifecycle/import tools as stdio
  (was Menu-B-only -> "Unknown tool" over HTTP/SSE).

tests:
- drift-guard now non-vacuous: folded set derived from live dispatch tables
  (AST + regex), exact endpoint coverage (no broad family prefixes), unfolded
  adsorption/substitution/intercalation explicitly EXCLUDED with reasons.
- restore description-length cap (3000, workflow exempt <=9000) and exact
  tool-count tripwire (==17).

63 passed, 2 xfailed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Hello-QM Hello-QM closed this Jun 26, 2026
@Hello-QM
Hello-QM deleted the feat/mcp-unify-menu-b branch July 1, 2026 09:07
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