Skip to content

Layer 2: auto-wire mcp_serve as worker-session MCP server (no operator config required) #82

@PowerCreek

Description

@PowerCreek

Follow-up to #80. Layer 1 (packaging) merged in #81mcp_serve.py now ships in the wheel. Layer 2 closes the runtime gap: even with mcp_serve packaged, no auto-start path exists for a worker to actually consume its tools.

Current state (operator-side, undocumented)

For a worker to access G2/G3/G4 MCP tools today:

  1. Operator manually runs hermes mcp serve & in background
  2. Operator manually writes ~/.hermes/profiles/<profile>/.mcp.json referencing that server's transport
  3. Worker session's MCP client connects on boot

None of this auto-happens. Polynomial-explorer worker boots with zero MCP tools accessible. The G2/G3/G4 plugin loads (post-#79 register fix) and the MCP tools are registered server-side (post-#81 packaging fix) — but no server is running + no .mcp.json points at one, so the worker MCP client has nothing to connect to.

Proposed fix (stdio transport, zero operator config)

MCP supports stdio transport where the client spawns the server as a subprocess + talks via stdin/stdout. No port allocation, no lifecycle daemon, no orphaned processes — when the worker exits, the subprocess exits.

Concrete plan:

  1. Verify mcp_serve.run_mcp_server supports --transport stdio (FastMCP default; should already work — confirm in the impl).
  2. Add stdio invocation entry: a top-level python -m mcp_serve command (or hermes mcp serve --stdio) that runs the server in stdio mode and exits cleanly when stdin closes.
  3. Auto-write .mcp.json at session boot in agent_init.py (or equivalent init hook):
    • Detect if any plugin manifests declare MCP tools (i.e., the devagentic-mutations, hermes-github, devagentic-lane-h plugins are loaded post-fix(plugins): add register(ctx) to G1/G2/G3/G4 — loader was silently skipping (closes #78) #79).
    • If yes AND .mcp.json doesn't already reference a hermes-internal server: write/merge an entry like:
      {
        "servers": [
          {
            "name": "hermes-internal",
            "command": "python",
            "args": ["-m", "mcp_serve", "--stdio"]
          }
        ]
      }
    • Use the same HERMES_HOME / .mcp.json pattern as existing MCP client config.
    • Idempotent: skip rewrite if the entry already exists.
  4. Worker MCP client picks it up at boot (existing behavior of tools/mcp_tool.py).

Acceptance

  • Fresh worker session with no operator-side .mcp.json writes one auto-referencing local mcp_serve via stdio.
  • Worker hermes mcp status (or equivalent) shows hermes-internal connected.
  • Worker can invoke G2/G3/G4 tools (e.g. grafted_context_fetch) without operator config.
  • Existing .mcp.json files with other servers are NOT clobbered — entries merge.
  • Disable knob (env var HERMES_DISABLE_INTERNAL_MCP=1) for operators who want a different MCP server topology.

Why this is the right shape

  • stdio removes port-allocation + daemon-lifecycle complexity. Subprocess dies with the worker; no orphans.
  • Auto-detect from loaded plugins means new MCP-only plugins shipped later (G2b/G2c/G2d / G4 extensions) auto-surface without operator changes.
  • Merge-don't-clobber preserves existing MCP server config (Linear, Notion, etc. that operators may already have).
  • Disable knob for operators with custom MCP server topology.

Out of scope

  • Sidecar HTTP/SSE transport for mcp_serve (heavier; needs port management + auth on the localhost surface). Future enhancement; stdio covers 100% of single-session worker use cases.
  • Restart-on-crash for the spawned subprocess (worker session itself will detect MCP disconnection + retry via existing MCP client logic).

Severity

Final piece of the post-G1-G4 deploy chain. After this lands + container rebuild + worker spawn, polynomial-explorer should have full tool access end-to-end with zero operator wiring.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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