Repository navigation
Description
Phase 1 of design #1414 (cold-restart upstream HTTP session resume). Design doc: files/designs/code-mcpx-cold-restart-session-resume.md in the keep-the-four-repos-healthy goal workspace.
Scope
Persist the resumable half of each legacy streamable-HTTP upstream session in the mcpx daemon state directory and restore it on cold start, reusing the takeover restore path:
- New versioned state file next to
sessions.json, written/read with theinternal/daemon/sessions.godiscipline: atomic tmp+rename,defaults.PrivateMode, version envelope, ignore-and-log on version mismatch or corruption. - Record per pool instance: instance key (server name + pool scope key), upstream URL, config fingerprint (hash over the session-defining config fields + header/auth names — never values),
SessionID,Negotiated, the fullmcpclient.Sessionprotocol state (as returned byClient.SessionState()),savedAt. - The record type has no field for headers or resolved secret values — that absence is the security invariant (handoff headers travel over the takeover socket only; see
HTTPHandoffcomment ininternal/mcpclient/http.go). On restore, headers are re-derived from live config via the existinghttpOptions()/resolveAuth()path. - Save triggers: successful legacy
initialize(session established) and any response that installs a newMcp-Session-Id(internal/mcpclient/http.go:156). Save failure: log, non-fatal — the daemon behaves exactly as today. - Restore: at pool connect, if a record exists and its fingerprint matches the live config, seed the transport with
ht.Resume(...)and build the client withmcpclient.Resume(...)— the identical calls the takeover path makes (internal/pool/handoff.go:238,326). No parallel resume implementation. - Fingerprint mismatch → record discarded, fresh initialize, no error surfaced.
- Scope limits: legacy-era streamable HTTP only. Modern era (no sessions) and legacy SSE (session lives in the GET stream) are untouched. Takeover behaviour unchanged. The standalone GET stream is re-established on resume exactly as takeover re-establishes it — parity with takeover is the bar.
Out of scope (Phase 2 / Phase 3 of #1414): 404/401 expiry fallback and retry, record removal on config removal, graceful-shutdown DELETE semantics, TTL, dashboard visibility.
Acceptance
- Defining test passes: daemon against a test HTTP upstream → legacy session established → daemon killed with SIGKILL → daemon restarted → first call succeeds; the upstream saw no second
initialize; the request carried the originalMcp-Session-Id. - Fingerprint-mismatch record is ignored and a fresh initialize happens (test).
- Corrupt / version-mismatched state file is ignored and logged; daemon starts and operates normally (test).
- No test or code path writes a resolved header/secret value into the state file (record type has no such field; assert in test by scanning the written file for a sentinel secret value).
- Takeover tests and the full suite pass:
cd pkgs/mcpx && go test ./....
agent-note:v1 — filed by the repo design architect (dedicated code job, pass 2, 2026-10-27) as a sub-issue of design #1414. Filed as task/triage: triage confirms scope against current main and enqueues the implementation packet; do not implement in the triage task. The direction decision sits with Drew on #1414 (user/review) — triage may proceed, implementation start should respect that decision.
Activity
developing-today commentedon Oct 27, 2026
CODE-505
dezren39 commentedon Oct 27, 2026
Intake review
Fleet-monitor intake pass (2026-10-27). Phase 1 of design #1414 (which carries
user/review— the direction decision is Drew's there; this intake does not pre-empt it). Related: #1416 (Phase 2, expiry fallback), #1414 (design). The body already carries a full## Acceptancesection, so no body edit; labels were already normalized by the filer (kind/feature, priority/normal, effort/l, app/mcpx, source/design-architect) — I added only meta/enriched.Notes / risks: the security invariant is structural — the persisted record type must have no field capable of holding a resolved header/secret value, and the acceptance test scanning the written file for a sentinel secret is the right proof. Suggested approach: reuse the takeover restore calls exactly as scoped (
ht.Resume/mcpclient.Resume); no parallel resume path.dezren39 commentedon Oct 27, 2026
🤖 Agent note · picked up
53 remaining items
dezren39 commentedon Nov 4, 2026
Resumed by repo queue worker lane code-u for task 1483: PR #5455 at head 9c8b465 (lane code-v parked it for CI + Codex re-review after fixing both Codex P2 findings at the previous head, threads replied). Fresh state: no new Codex findings on the current head, only check run is CodeRabbit (neutral/skipping) — this repo runs CI on main, so re-verifying the targeted mcpx suites on the laptop at this head, then merging per standing criteria if green.
Merge pull request #5455 from developing-today/queue/1483-1415-mcpx-p…
dezren39 commentedon Nov 4, 2026
Done (task 1483, lane code-u resume): PR #5455 merged at 7cd293e. Resume verification at head 9c8b465: laptop
go testfor pkgs/mcpx internal/pool, internal/mcpclient, and internal/daemon all pass; both Codex P2 findings from the previous head were fixed in the PR with thread replies and no new Codex findings exist on the merged head; the only PR check run was CodeRabbit (neutral) — this repo runs CI on main. Phase 2 (expiry fallback / record hygiene) remains issue #1416, already separately queued.