Skip to content

feat(mcp)!: HTTP canonical transport — init registers HTTP + keepalive daemon, demote stdio (v0.10.0)#464

Merged
jamestexas merged 2 commits into
mainfrom
feat/mcp-transport-http-canonical
Jun 27, 2026
Merged

feat(mcp)!: HTTP canonical transport — init registers HTTP + keepalive daemon, demote stdio (v0.10.0)#464
jamestexas merged 2 commits into
mainfrom
feat/mcp-transport-http-canonical

Conversation

@jamestexas

Copy link
Copy Markdown
Contributor

Breaking change → v0.10.0. Finishes the half-done stdio→HTTP migration. See ADR-0022.

The mess this fixes

mache serve defaulted to HTTP, but the migration never finished:

  • mache init registered a stdio entry running bare mache serve — which now starts an HTTP listener and never speaks JSON-RPC on stdout (no stdin autodetect). So the documented onboarding produced a non-working registration; only the manual claude mcp add --transport http … worked.
  • Nothing kept the HTTP daemon alive → connection refused until you ran mache serve in a spare terminal.

What changed (3 beads)

  • mache-609f70mache init registers the shared HTTP endpoint http://localhost:7532/mcp (Claude CLI --transport http + {"type":"http","url":…} for .claude/mcp.json, Cursor, Windsurf, Gemini, Zed, VS Code). No stdio command, no per-client binary path.
  • mache-605d08 (achievable slice)mache init --global installs a per-user keepalive supervisor (launchd plist / systemd --user unit) running mache serve --http localhost:7532, so the endpoint is answerable without babysitting. Supervisor load is test-gated (daemonAgentAutoload); plist/unit generation is unit-tested.
  • mache-60dc86--stdio kept as an explicit CI/sandbox/headless escape hatch, never registered; reframed in serve --help, README, ARCHITECTURE. ADR-0022 + version bump 0.9.0 → 0.10.0 (melange + server.json regenerated).

Why HTTP-canonical is sound (not a hack)

One daemon serves every project, routing per session via the MCP roots protocol (serve_registry.go::resolveSessionListRoots), plus hosted (?repo=) + repo-clone modes.

Tests

  • go test ./cmd/ green (full package). New daemon_agent_test.go covers plist/unit generation + file-write (load side-effect gated off). config_test/init_test updated to assert the HTTP contract (type:http+url, no command/serve).
  • go vet + golangci-lint clean.

Explicitly NOT in this PR (tracked)

On-demand socket activation (spawn-on-connect) and the ~/.mache daemon-reliability hardening (stale state, singleton-socket clobber) stay in mache-605d08 / mache-823d91 (decade mcp-transport-canonical). This PR ships canonicalization + a keepalive supervisor, not the full on-demand lifecycle.

🤖 Generated with Claude Code

…TTP + keepalive daemon, demote stdio

Finish the half-done stdio→HTTP migration (ADR-0022). Breaking → v0.10.0.

- mache init now registers the shared Streamable HTTP endpoint
  (http://localhost:7532/mcp) for Claude Code (CLI + .claude/mcp.json) and
  all detected editors — never a stdio command that (post-default-flip)
  actually starts an HTTP listener. (mache-609f70)
- mache init --global installs a per-user keepalive supervisor (launchd on
  macOS, systemd --user on Linux) running 'mache serve --http', so the
  registered endpoint is answerable without babysitting 'mache serve'. The
  load step is test-gated (daemonAgentAutoload). (mache-605d08, achievable slice)
- --stdio kept as an explicit CI/sandbox/headless escape hatch, never
  registered; reframed in serve --help, README, ARCHITECTURE. (mache-60dc86)
- ADR-0022 records the decision; version → 0.10.0 (melange + server.json regen).

On-demand socket activation + ~/.mache daemon-reliability hardening remain in
mache-605d08 / mache-823d91 (decade mcp-transport-canonical).
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

find_smells (advisory)

Scoped to files changed in this PR. Rules below run on the standalone (no-LLO) cross-ref tables; _ast rules (cyclomatic_complexity, long_function, long_file, magic_int_in_comparison) are not exercised here.

dead_code — 1 finding(s) in changed files
Source Node Metric
cmd/config.go cmd/functions/registerClaudeCodeCLIImpl 0
fan_out_skew — 3 finding(s) in changed files
Source Node Metric
cmd/serve.go cmd/functions/runServe/source 62
cmd/serve.go cmd/functions/buildServeGraph/source 39
cmd/serve.go cmd/functions/buildMaybeMultiGraph/source 22

Rules: the registry is cmd/smell_rules.go (source of truth); see the authoring guide to add one. Advisory only — these are heuristics, not gates.

… P2)

The launchd plist and systemd unit interpolated the binary/log paths raw.
os.Executable() can resolve under a path with spaces (e.g. an app bundle
'/Applications/Mache Tools/mache') or — theoretically — XML-significant
chars, producing a malformed supervisor file.

- plist: dynamic values go through encoding/xml.EscapeText (xmlText).
- systemd: ExecStart path is double-quoted with \ / " escaping (systemdQuote)
  so a spaced path is one argument, not whitespace-split.

Tests: plist render with '/Applications/Mache & Tools/<m>ache' is asserted to
be valid XML end-to-end (xml.Decoder) with metachars escaped; systemd unit
quotes a spaced path.
@jamestexas jamestexas merged commit d190201 into main Jun 27, 2026
15 checks passed
@jamestexas jamestexas deleted the feat/mcp-transport-http-canonical branch June 27, 2026 01:59
jamestexas added a commit that referenced this pull request Jul 2, 2026
…1, mache-89e322) (#466)

* [mache-89e322] docs: add frontmatter to smell-debt-baseline — fix docs:lint on main

docs:lint requires covers-version + last-verified frontmatter on every
top-level docs/*.md; this dated snapshot shipped without it and reddened
the gate on main. Add minimal valid frontmatter (covers-version v0.8.0 to
match ARCHITECTURE.md / latest CHANGELOG, last-verified = measurement date).

* [mache-823d91] docs: point HTTP-daemon gotcha at `mache init --global` supervisor

The keepalive supervisor shipped in v0.10.0 (#464): `mache init --global`
installs a launchd LaunchAgent (macOS) or systemd --user unit (Linux) that
starts + keepalives the shared HTTP daemon. GETTING-STARTED still told users
it was unbuilt and "tracked in mache-823d91". Update the connection-refused
gotcha to point at the shipped one-command fix.

* [mache-823d91] docs: "keeps it alive" not "keepalives" (Copilot review nit)

Copilot flagged "keepalives" as jargon/incorrect verb form in user-facing
docs. Use the standard phrasing.
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