HarperFast / HarperFast/harper
MCP 2026-07-28 "modern" era: stateless protocol support (dual-era server)
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
Following up on #465 ([comment](https://github.com/HarperFast/harper/issues/465#issuecomment-4572686284)) — *"Are we tracking the 2026-07-28-release-candidate?"* (linked to the stateless-protocol section). That question was never converted into a tracked item when #465 closed — this is it. It's the core-transport counterpart to the OAuth-side tracker (HarperFast/oauth#100).
**TL;DR:** the 2026-07-28 revision is an architectural pivot, not an incremental bump — but backward compatibility is explicit, so **nothing breaks on July 28**. Core today is a spec-compliant **2025-06-18 ("legacy")** server; the new revision is **"modern"** (stateless, no handshake). Adopting it means becoming a **dual-era** server. Not urgent, but it should be tracked and it affects #1349 sequencing.
## What changed (verified against the draft spec)
The RC redefines the transport model. Terminology from the spec:
- **Legacy** (≤2025-11-25): a session established via an `initialize` handshake. ← what core implements today (2025-06-18, backcompat 2025-03-26).
- **Modern** (2026-07-28+): protocol version, client identity, and capabilities travel as per-request `_meta.io.modelcontextprotocol/*` (mirrored into HTTP headers); requests are served **statelessly**.
Key changes (`draft/basic/lifecycle` + `draft/basic/transports`):
1. **No negotiation handshake.** *"There is no negotiation handshake. Every request carries its protocol version, and the server accepts or rejects each request independently."* → `initialize` / `notifications/initialized` is legacy-only.
2. **Stateless — no `Mcp-Session-Id`.** *"A request carrying modern per-request `_meta` is served statelessly."* Sessions are a legacy concept.
3. **Servers no longer initiate JSON-RPC requests.** *"servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses."* Sampling / elicitation / roots and the Tasks API become negotiated **extensions** (`capabilities.extensions`), not core message patterns.
4. **`server/discover` is now MUST-implement.**
5. New **`UnsupportedProtocolVersionError` (`-32022`)** for version mismatch.
## Impact on core (`components/mcp/`)
Everything today is legacy-era and correct for 2025-06-18: `lifecycle.ts` (initialize/initialized), `session.ts` / `sessionRegistry.ts` (Mcp-Session-Id), `transport.ts` (MCP-Protocol-Version header + session lookup).
To support modern, core becomes **dual-era** — the spec blesses this: *"A dual-era server MAY serve both eras concurrently on the same endpoint."*
- Serve legacy when a request opens with `initialize`; serve modern (statelessly) when a request carries modern `_meta`.
- Implement `server/discover`.
- Derive version/identity/capabilities from per-request `_meta` on the modern path (a per-request context object replacing the persisted session).
- Map Tasks + server-initiated flows onto the extension mechanism.
**Nothing breaks July 28:** deployed clients speak legacy (2025-06-18 / 2025-03-26) and a legacy server keeps serving them. Only modern-*only* clients would fail — pressure builds gradually as clients adopt modern.
## Tension with #1349 (resolve before Phase 4)
#1349 (the committed protocol-surface roadmap) is scoped entirely to 2025-06-18, and its heaviest planned work targets what modern restructures:
- **§3.7 / Phase 4 (server-initiated requests: sampling / elicitation / roots)** — modern core *removes* that message direction; it becomes an extension. Building it now as core JSON-RPC is building on legacy semantics.
- **Session-state machinery** (client-capabilities on `McpSessionRecord`, the pending-request registry, durable subscription state in `mcp_session`) — modern is stateless per-request; subscriptions / SSE need rethinking under it.
Not a reason to stop #1349 — the legacy surface is what clients use *today* — but Phase 4's effort and sequencing should be weighed against this before it starts.
## Scope of this issue
Tracking + design context for the modern era; not committing to a delivery date. Next steps when prioritized:
1. Re-confirm each item against the final (post-RC) spec text — RC→stable diffs are usually small but nonzero.
2. Decide the dual-era architecture (shared dispatch; per-request context replacing the session object on the modern path).
3. File sub-issues for `server/discover`, the modern stateless transport path, and the extension mappings.
## Related
- Origin: #465 ([comment](https://github.com/HarperFast/harper/issues/465#issuecomment-4572686284))
- Roadmap it intersects: #1349
- OAuth counterpart: HarperFast/oauth#100 (RFC 9207 `iss` piece shipping now in oauth#149 / oauth#150)
- Spec: [RC blog](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/) · [draft: versioning](https://modelcontextprotocol.io/specification/draft/basic/versioning) · [draft: transports](https://modelcontextprotocol.io/specification/draft/basic/transports)
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor guide
Research direction
Start with components/mcp/lifecycle.ts, session.ts, sessionRegistry.ts, and transport.ts, then compare the draft versioning and transports specifications with the current 2025-06-18 behavior. The issue is done when the dual-era architecture is decided and sub-issues are filed for server/discover, the modern stateless transport path, and extension mappings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nodejs
- Domain
- api, backend, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100