refactor(mcp): unify MCP onto consolidated registry + fold verified Menu A capabilities - #142
Closed
Hello-QM wants to merge 14 commits into
Closed
refactor(mcp): unify MCP onto consolidated registry + fold verified Menu A capabilities#142Hello-QM wants to merge 14 commits into
Hello-QM wants to merge 14 commits into
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_layercatgo_analyze+2:energy,calculators(and removed the deaddft_input— it POSTed to/dft-input/generate, which does not exist)catgo_md— 12 trajectory analyses (table-driven; base64trajectory_b64+format)catgo_input— LAMMPS/QE/VASP input generation + presets (supersedes the deaddft_input)server.pynow 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_layercatgo_analyze: energy (real MACE single-point), calculatorscatgo_md(10 green): rdf, msd, rmsd, rmsf, clustering, dimreduce, hbonds, hbond_lifetime, dihedrals, planar_densitycatgo_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):
bands*,cohp,dos_total,dos_dband,dos_from_dir) — session/HPC-based, no real DFT-output fixtures in repo.catgo_simulate/ kMC —mykmcpackage not importable in this env.catgo_mdwater_orientation+cavitation— handlers correct & action retained; functional testsxfailpending 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.pyupdated 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
/api/mcpHTTP 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_presetsloadsworkflow.presets.vaspfrozen-import-first with a file-path fallback, andcatgo_server.specnow collectsworkflow/presets/*.py— so it works in both dev and the PyInstaller bundle (avoids the known rfc3987-class silent-disable gotcha).catgo_structure:add_moleculereads a nonexistentn_water_placed(should ben_water_molecules);_handle_analyzecatalysis actions use the sameimport workflow.*pattern that's shadowed bycatgo/workflowon sys.path (latent, untested).server_claude_code.py); rebase if needed.🤖 Generated with Claude Code