Bug (two layers)
Layer 1: packaging (immediate fix)
mcp_serve.py lives at repo root but is not in [tool.setuptools] py-modules:
py-modules = ["run_agent", "model_tools", "toolsets", "batch_runner",
"trajectory_compressor", "toolset_distributions", "cli",
"hermes_bootstrap", "hermes_constants", "hermes_state",
"hermes_time", "hermes_logging", "utils"]
Setuptools' packages.find only picks up Python PACKAGES (dirs with __init__.py), not top-level modules. So mcp_serve.py is silently dropped from the wheel.
`find /home/duplex/.local -name mcp_serve.py` returns nothing → `from mcp_serve import run_mcp_server` (called in hermes_cli/mcp_config.py:748) raises ImportError at runtime → no MCP server can be started from the installed wheel.
Audit of root-level .py files vs py-modules list:
- MISSING:
mcp_serve.py, mini_swe_runner.py
- (
setup.py correctly absent — it's a build-time script, not runtime)
Layer 2: runtime invocation (deeper gap)
Even with mcp_serve.py shipped, the MCP server doesn't auto-start when a worker session spawns. The architecture today:
mcp_serve.py = MCP server (registers G2/G3/G4 tools via _register_X_tools from create_mcp_server()).
tools/mcp_tool.py = MCP client (worker uses this to connect to running MCP servers per .mcp.json config).
hermes_cli/mcp_config.py::run_mcp_server = the function that actually starts the server, but it's only invoked from the hermes mcp serve subcommand.
So for a worker to access grafted_context_fetch / silo_query / confer_run / file_issue / lane_h_*:
- Operator must explicitly start mcp_serve in background (
hermes mcp serve & or similar)
- Worker's
.mcp.json must reference that server endpoint
- Worker session must successfully MCP-client-connect
None of this auto-happens for the polynomial-explorer (or any vertical) worker today. Operator-side wiring is undocumented and undelivered.
Fix scope for this PR
Layer 1 (immediate): add mcp_serve + mini_swe_runner to py-modules in pyproject.toml. Packaging-contract test asserts both are listed AND verify the wheel contains them.
Layer 2 (follow-up): out of scope for this PR — needs its own design surface. Options:
- Auto-start mcp_serve as a sidecar when a hermes worker session boots
- Auto-write
.mcp.json referencing localhost mcp_serve when worker config detects MCP-only plugins
- Document operator-side wiring in plugin READMEs (current state — undelivered)
Filing a separate issue tracking layer 2 once this PR lands.
Acceptance (Layer 1)
mcp_serve.py + mini_swe_runner.py listed in py-modules.
- Built wheel contains both modules at top level.
- Packaging-contract test asserts both are in py-modules AND in-tree files exist (catches future regression where a new root-level module is added but not listed).
Severity
Critical for the post-#77 + #78 deploy chain. Without this, the loader register()s work (#78) but the MCP tools they reference can't actually be served from the install.
Combined deploy chain (updated)
| # |
PR |
Status |
What it fixes |
| 1 |
devagentic#222 |
merged |
/graphql on port 6071 |
| 2 |
hermes-agent#77 |
merged |
plugin.yaml ships in wheel |
| 3 |
hermes-agent#79 |
open |
register(ctx) in plugin __init__.py |
| 4 |
hermes-agent#NN (this) |
filed |
mcp_serve.py ships in wheel |
| 5 |
follow-up |
not filed yet |
mcp_serve auto-start / mcp.json wiring |
Bug (two layers)
Layer 1: packaging (immediate fix)
mcp_serve.pylives at repo root but is not in[tool.setuptools]py-modules:Setuptools'
packages.findonly picks up Python PACKAGES (dirs with__init__.py), not top-level modules. Somcp_serve.pyis silently dropped from the wheel.`find /home/duplex/.local -name mcp_serve.py` returns nothing → `from mcp_serve import run_mcp_server` (called in
hermes_cli/mcp_config.py:748) raises ImportError at runtime → no MCP server can be started from the installed wheel.Audit of root-level
.pyfiles vs py-modules list:mcp_serve.py,mini_swe_runner.pysetup.pycorrectly absent — it's a build-time script, not runtime)Layer 2: runtime invocation (deeper gap)
Even with mcp_serve.py shipped, the MCP server doesn't auto-start when a worker session spawns. The architecture today:
mcp_serve.py= MCP server (registers G2/G3/G4 tools via_register_X_toolsfromcreate_mcp_server()).tools/mcp_tool.py= MCP client (worker uses this to connect to running MCP servers per.mcp.jsonconfig).hermes_cli/mcp_config.py::run_mcp_server= the function that actually starts the server, but it's only invoked from thehermes mcp servesubcommand.So for a worker to access grafted_context_fetch / silo_query / confer_run / file_issue / lane_h_*:
hermes mcp serve &or similar).mcp.jsonmust reference that server endpointNone of this auto-happens for the polynomial-explorer (or any vertical) worker today. Operator-side wiring is undocumented and undelivered.
Fix scope for this PR
Layer 1 (immediate): add
mcp_serve+mini_swe_runnertopy-modulesinpyproject.toml. Packaging-contract test asserts both are listed AND verify the wheel contains them.Layer 2 (follow-up): out of scope for this PR — needs its own design surface. Options:
.mcp.jsonreferencing localhost mcp_serve when worker config detects MCP-only pluginsFiling a separate issue tracking layer 2 once this PR lands.
Acceptance (Layer 1)
mcp_serve.py+mini_swe_runner.pylisted inpy-modules.Severity
Critical for the post-#77 + #78 deploy chain. Without this, the loader register()s work (#78) but the MCP tools they reference can't actually be served from the install.
Combined deploy chain (updated)
/graphqlon port 6071register(ctx)in plugin__init__.pymcp_serve.pyships in wheel