Skip to content

Commit a79f95f

Browse files
committed
Add roadmap for 2026-07-28 spec support
1 parent 64aa6f5 commit a79f95f

2 files changed

Lines changed: 189 additions & 35 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,17 @@ This file was introduced during the v1.7.x series. Structured entries below cove
1414
**v1.6.0 and later**; earlier releases can be reviewed via the
1515
[Git tag history](https://github.com/logiscape/mcp-sdk-php/tags).
1616

17-
## [Unreleased]
17+
## [1.7.2]
1818

1919
### Added
2020

21+
- Published a day-one support roadmap for the MCP `2026-07-28` "stateless core"
22+
spec revision (RC locked 2026-05-21). Adoption is additive and
23+
version-negotiated — the new stateless paths run only for clients that
24+
negotiate `2026-07-28`, leaving `2024-11-05``2025-11-25` core flows untouched.
25+
The experimental Tasks primitive will be replaced cleanly with the SEP-2663
26+
extension. See [ROADMAP.md](ROADMAP.md). No protocol changes ship in this entry;
27+
this records the planned direction only.
2128
- Client side documentation guide
2229
- `ClientSession::onListRoots()` and `Client::onListRoots()` register a
2330
`roots/list` handler and advertise the `roots` capability in the

ROADMAP.md

Lines changed: 181 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Group assigns tiers.
3939
| SEP-1730 criterion | Target (Tier 1) | Current state |
4040
| --------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
4141
| Conformance pass rate | 100% | **100%** of applicable required tests on suite `v0.1.16`. Three known failures, all in optional MCP Extensions (documented in baseline). |
42-
| New protocol features | Before spec release | `2025-11-25` supported; back-compat for `2024-11-05`, `2025-03-26`, `2025-06-18`. |
42+
| New protocol features | Before spec release | `2025-11-25` supported; back-compat for `2024-11-05`, `2025-03-26`, `2025-06-18`. Day-one work for the `2026-07-28` RC is in progress ahead of final release (see below). |
4343
| Issue triage | 2 business days | Best-effort; see response-time section below. |
4444
| Critical bug resolution | 7 days | Best-effort, typically weeks not days for non-trivial fixes. |
4545
| Stable release | Required, clear versioning | Met. Currently `v1.7.0`, semver-tagged since `v1.0.0`. |
@@ -82,6 +82,141 @@ will — the arithmetic changes.
8282
- **Expand `conformance/everything-server.php` and `everything-client.php`**
8383
to cover new tools, prompts, and resources as the official suite grows.
8484

85+
### Day-one support for the 2026-07-28 spec revision
86+
87+
The [`2026-07-28` Release Candidate](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/)
88+
(locked 2026-05-21; final spec 2026-07-28) is the largest revision since launch —
89+
a **stateless core** that drops the connection handshake and the protocol-level
90+
session. In line with guiding principle #1 and the SEP-1730 expectation that
91+
SDKs implement new features before the revision ships, our target is a clean
92+
conformance run within the RC-to-final window. Neither the official Python SDK
93+
(latest `2025-11-25`, set in v1.23.1) nor the TypeScript SDK (v2 pre-alpha) has
94+
published `2026-07-28` support yet — though the Python SDK is explicitly
95+
architecting its in-progress v2 around exactly this transport-changing revision
96+
(see the release-vehicle note below).
97+
98+
**Strategy: additive and version-negotiated.** `2026-07-28` becomes a negotiable
99+
protocol version; the new stateless code paths run **only** when a client speaks
100+
that revision. The existing handshake-and-session paths for `2024-11-05`
101+
`2025-11-25` stay untouched, so no existing client or server breaks (guiding
102+
principle #4). Mechanically this reuses the gating the SDK already has — a new
103+
entry in `Version::SUPPORTED_PROTOCOL_VERSIONS` / `LATEST_PROTOCOL_VERSION` and
104+
`FEATURE_VERSIONS` (`src/Shared/Version.php`), feature checks via
105+
`ServerSession::clientSupportsFeature()` / `ClientSession::supportsFeature()`,
106+
and backward shaping via `ServerSession::adaptResponseForClient()`. The new
107+
wrinkle is dual-era interoperability. The spec lets a server support both eras at
108+
once and defines how each side detects which it is talking to, so back-compat is
109+
achievable additively in both directions:
110+
111+
- **Server side.** A legacy client opens with an `initialize` request; a modern
112+
client instead sends ordinary requests that carry the negotiated version in the
113+
`MCP-Protocol-Version` HTTP header with matching `_meta`. The server keys off
114+
that per-request version metadata (and the `initialize` method for legacy) —
115+
*not* the session id. Under `2026-07-28` the `Mcp-Session-Id` header is removed
116+
and ignored rather than used as a routing or mode signal.
117+
- **Client side.** We follow the spec's documented detection rather than guessing.
118+
Over HTTP: send a modern request first and, on a `400`, inspect the body —
119+
because a `400` is also returned for `UnsupportedProtocolVersionError`,
120+
missing-capability, and header-validation failures, the status alone is not a
121+
legacy signal. A recognized modern JSON-RPC error (e.g.
122+
`UnsupportedProtocolVersionError`) means the server is modern (retry with one of
123+
its advertised versions; do **not** fall back), whereas an empty or
124+
unrecognized body means fall back to `initialize` and continue legacy. Over
125+
stdio (no per-request status code): probe `server/discover` with the preferred
126+
version in `_meta`, fall back to the legacy handshake on `Method not found`
127+
(`-32601`), and on `UnsupportedProtocolVersionError` use one of the server's
128+
advertised versions instead of falling back.
129+
130+
What we intend to implement (intentions, not final API shapes — the same caveat
131+
the Medium-term section carries; several of these SEPs are still settling):
132+
133+
- **Stateless core.**
134+
- **SEP-2575** — remove the `initialize`/`initialized` handshake; carry
135+
protocol version, client info, and capabilities in `_meta` on every request,
136+
and answer the new `server/discover` method on demand (reusing
137+
`Server::getCapabilities()`).
138+
- **SEP-2567** — remove the protocol-level session: under `2026-07-28` the
139+
SDK stops emitting and stops honouring the `Mcp-Session-Id` header (legacy
140+
revisions keep it), so any request can land on any instance.
141+
- **SEP-2243** — read and validate the request-metadata headers so gateways can
142+
route without inspecting the body: `Mcp-Method` on **all** requests and
143+
notifications, and `Mcp-Name` only on the name/uri-bearing methods
144+
(`tools/call`, `resources/read`, `prompts/get`; the Tasks extension reuses it
145+
for the task id). A header whose value disagrees with the body, or a missing
146+
required header, is rejected `400` with a `HeaderMismatch` / `-32001` error.
147+
(The mandatory per-request `MCP-Protocol-Version` header and its
148+
must-match-`_meta` rule are defined by SEP-2575 above; SEP-2243 supplies the
149+
`-32001` enforcement, which also covers a version-header/`_meta` mismatch.)
150+
Also support the `x-mcp-header` schema annotation that mirrors designated tool
151+
parameters into `Mcp-Param-*` headers (clients MUST emit them; whether those
152+
headers survive network intermediaries and shared-hosting `.htaccess` is a
153+
deployment concern, not something the spec obliges intermediaries to do).
154+
- **SEP-2549** — emit `ttlMs` / `cacheScope` on list and resource-read results
155+
(HTTP `Cache-Control` semantics).
156+
- **SEP-2322** — the multi-round-trip request mechanism: sampling, elicitation,
157+
and roots become `InputRequiredResult` exchanges (`inputRequests` /
158+
`requestState` / `inputResponses`) instead of server-initiated requests. (Two
159+
related removals live in adjacent SEPs: SEP-2575 removes the standalone GET
160+
SSE stream, replacing it with `subscriptions/listen`, and SEP-2260 restricts
161+
that channel to server→client *notifications* only — no independent
162+
server-initiated *requests*.) Request-scoped SSE response streams
163+
(request-related notifications then the final response) and long-lived
164+
`subscriptions/listen` streams for change notifications remain; `Last-Event-ID`
165+
resumption does not.
166+
- **SEP-2106** — accept JSON Schema 2020-12 keywords (composition, conditionals,
167+
`$ref`) in tool schemas, with the spec's constraints: `inputSchema` still
168+
requires a root `type: "object"`, `outputSchema` is unrestricted, and
169+
`structuredContent` may be any JSON value conforming to it. **SEP-2164**
170+
change the missing-resource error from `-32002` to `-32602`.
171+
- **Authorization.** SEP-2468 (`iss` validation, RFC 9207), SEP-837
172+
(`application_type` on registration), SEP-2352 (credential binding), SEP-2207
173+
(refresh-token flow), SEP-2350 (scope accumulation), and SEP-2351
174+
(`.well-known` discovery). These drop into the existing `Client/Auth/` and
175+
`Server/Auth/` framework rather than needing a new abstraction.
176+
- **Governance.** Adopt the SEP-2596 / SEP-2577 feature-lifecycle states (Active
177+
/ Deprecated / Removed, 12-month minimum) for the now-deprecated Roots,
178+
Sampling, and Logging features — deprecated, not removed — and track the
179+
SEP-2484 requirement that Standards-Track SEPs ship matching conformance
180+
scenarios.
181+
- **Tasks extension (SEP-2663).** A **breaking redesign** of the experimental
182+
Tasks primitive already in the tree: `tasks/get` / `tasks/update` /
183+
`tasks/cancel`, the task handle returned from `tools/call`, and **removal of
184+
`tasks/list`** (which cannot be scoped without sessions). Because the existing
185+
Tasks surface is pre-release, we redesign it cleanly — gated to `2026-07-28`,
186+
no deprecation shims — and keep the file-based store for shared-hosting
187+
compatibility.
188+
189+
**cPanel/Apache compatibility (guiding principle #3).** On balance this revision
190+
helps shared hosting: dropping sticky sessions and shared session stores, and
191+
turning sampling/elicitation into `InputRequiredResult` round-trips instead of
192+
server-initiated requests over an open stream, removes the most fragile pieces
193+
documented in [`docs/compatibility.md`](docs/compatibility.md). It is not a
194+
clean break from SSE, though — request-scoped SSE responses and opt-in
195+
`subscriptions/listen` streams remain long-lived, so the existing SSE
196+
shared-hosting guidance still applies to those. The items that need attention
197+
rather than a hard requirement are narrow: the request-metadata headers
198+
(`Mcp-Method`, `Mcp-Name`, `MCP-Protocol-Version`, and any `Mcp-Param-*`) must
199+
survive `.htaccess` and any proxy — the same class of forwarding concern we
200+
already document for `Authorization` — and the MCP Apps extension renders
201+
host-side, so the server emits the resource and must not fatal where a host can't
202+
display it. Core features (tools, prompts, resources, `server/discover`) remain a
203+
must-work-everywhere commitment.
204+
205+
**Release vehicle — undecided, pending v2 linkage.** Per CONTRIBUTING's
206+
versioning policy, additive new-revision support qualifies on its own as a
207+
**minor** (`v1.X`) bump, while the major (`v2`) is reserved for "when the official
208+
MCP SDKs cut a `v2`." The signal here points toward linkage, not against it: the
209+
Python SDK's v1.25.0 release note states its v2 plan "relies on the next upcoming
210+
spec release which will heavily change how the transport layer works, which in
211+
turn will guide a lot of how we architect v2" — i.e. the official v2 is being
212+
designed around exactly this transport-changing revision. That makes it plausible
213+
the ecosystem `v2` and `2026-07-28` arrive together, which under our governance
214+
rule would have us cut our own `v2` to match. **Action item:** confirm with
215+
upstream whether the official SDKs are in fact tying their `v2` release to
216+
`2026-07-28` before choosing the vehicle. If they are, we align our `v2` with it;
217+
if the revision lands ahead of any `v2`, we ship it additively as a minor in the
218+
meantime.
219+
85220
### Medium-term
86221

87222
Items in this section are directions we intend to explore ahead of a formal
@@ -97,18 +232,19 @@ the SEP is stable.
97232
[SUPPORT.md](SUPPORT.md) once enough trusted contributors are on board to
98233
sustain them. See [GOVERNANCE.md](GOVERNANCE.md) for the path to becoming
99234
one.
100-
- **Graduate the Tasks primitive (SEP-1686).** An experimental implementation
101-
is already in the tree — `Mcp\Server\TaskManager` with file-based storage
102-
(chosen for cPanel/Apache compatibility), the `McpServer::enableTasks()`
103-
wiring for `tasks/get` / `tasks/list` / `tasks/cancel` / `tasks/result`,
104-
client-side `getTask()` / `listTasks()` / `cancelTask()` methods, and a
105-
full state-transition validator. The remaining work tracks the pieces that
106-
are still moving upstream: richer retry semantics, configurable
107-
result-expiry policies beyond the current TTL, and closing the
108-
task-augmented-request gap explicitly marked in
109-
`Server/Elicitation/ElicitationContext::url()` (and the equivalent
110-
sampling path). Graduation out of "experimental" waits for spec stability
111-
in the official SDKs.
235+
- **Graduate the Tasks primitive.** An experimental implementation is already
236+
in the tree — `Mcp\Server\TaskManager` with file-based storage (chosen for
237+
cPanel/Apache compatibility), the `McpServer::enableTasks()` wiring for
238+
`tasks/get` / `tasks/list` / `tasks/cancel` / `tasks/result`, client-side
239+
`getTask()` / `listTasks()` / `cancelTask()` methods, and a full
240+
state-transition validator. As of the `2026-07-28` RC, Tasks has moved from a
241+
core primitive (formerly tracked here as SEP-1686) to the **SEP-2663
242+
extension** with a stateless redesign — notably dropping `tasks/list`. That
243+
redesign is now tracked in the day-one subsection above; this bullet remains
244+
only for the still-moving pieces (richer retry semantics, configurable
245+
result-expiry beyond the current TTL, and the task-augmented-request gap
246+
marked in `Server/Elicitation/ElicitationContext::url()` and the equivalent
247+
sampling path).
112248
- **Finish task-augmented elicitation and sampling.** Form-mode and URL-mode
113249
elicitation are already wired on both sides of the wire, and
114250
`sampling/createMessage` already accepts `tools` / `toolChoice` under the
@@ -126,20 +262,26 @@ the SEP is stable.
126262
independent item.
127263
- **Shared session store for clustered HTTP deployments.** The
128264
`SessionStoreInterface` seam already accepts pluggable implementations;
129-
file-based and in-memory stores ship in-box. Horizontal-scaling
130-
friendliness is primarily about publishing a reference shared-store
131-
implementation (likely a PSR-6 or PSR-16 adapter, so users can pick
132-
Redis/Memcached/APCu without the SDK taking a hard dependency) and
133-
documenting the seam so that the forthcoming stateless transport work
134-
from the Transports WG does not force API churn.
135-
- **MCP Server Cards (SEP-2127).** OAuth `.well-known` endpoints are already
136-
served by the HTTP runner; the MCP Server Card `.well-known` endpoint is not.
137-
SEP-2127 is the current active draft for pre-connection discovery, replacing
138-
the earlier SEP-1649 discussion and aligning with the 2026 roadmap's
139-
transport-scalability priority. The SDK's role is a thin endpoint on
140-
`HttpServerRunner` plus helpers for generating the document; this is a natural
141-
fit for shared hosting, and we plan to ship it behind a config flag once the
142-
path and schema stop moving.
265+
file-based and in-memory stores ship in-box. The stateless transport work
266+
once described here as "forthcoming from the Transports WG" is now concrete in
267+
the `2026-07-28` RC (SEP-2567 removes the protocol-level session, SEP-2575
268+
removes the handshake), which makes a shared session store **optional** rather
269+
than a horizontal-scaling prerequisite under the new revision. The remaining
270+
value is for clients still on `2024-11-05``2025-11-25`: publishing a reference
271+
shared-store implementation (likely a PSR-6 or PSR-16 adapter, so users can
272+
pick Redis/Memcached/APCu without the SDK taking a hard dependency) and keeping
273+
the seam stable so the additive stateless paths above do not force API churn.
274+
- **Pre-connection discovery: Server Cards (SEP-2127) vs. `server/discover`
275+
(SEP-2575).** OAuth `.well-known` endpoints are already served by the HTTP
276+
runner; a discovery surface for capabilities is not. Two mechanisms now
277+
overlap here: the SEP-2127 Server Card `.well-known` document (a static,
278+
pre-connection descriptor) and the `2026-07-28` `server/discover` RPC method
279+
(an on-demand, cacheable capability fetch that replaces what the handshake
280+
used to provide). `server/discover` is the priority because it is part of
281+
day-one revision support (tracked above); a Server Card endpoint remains a
282+
complementary, lower-priority addition. Both are thin endpoints on
283+
`HttpServerRunner` and natural fits for shared hosting, shipped behind a config
284+
flag once the paths and schemas stop moving.
143285
- **Close remaining OAuth-spec alignment gaps.** The client-side already
144286
has `ClientIdMetadataDocument` (CIMD / SEP-991), a PKCE implementation,
145287
Protected-Resource and Authorization-Server metadata discovery, and
@@ -158,14 +300,19 @@ requirement, or because adoption depends on demand from this SDK's users
158300
(primarily PHP developers deploying on shared hosting). We would rather wait
159301
than put users on a breaking-API treadmill.
160302

161-
- **MCP Apps extension (`ui://` resources).** The
303+
- **MCP Apps extension (`ui://` resources, SEP-1865).** The
162304
[ext-apps](https://github.com/modelcontextprotocol/ext-apps) repository
163-
shipped its first stable spec revision in early 2026. Nothing in the
164-
current `McpServer::resource()` API prevents serving a `ui://` resource
165-
today — the question is whether a first-class helper (e.g. `->ui(...)`
166-
that bundles the MIME type, size-bound checks, and tool-metadata
167-
conventions) is worth adding. We will evaluate once the extension sees
168-
traction in the MCP hosts PHP developers actually target.
305+
shipped its first stable spec revision in early 2026, and the `2026-07-28`
306+
extensions framework (SEP-2133) formalises it as an independently versioned
307+
extension. It is explicitly **follow-on, not part of day-one revision
308+
support** (see the day-one subsection): the UI renders host-side in a sandboxed
309+
iframe, so the SDK's role is server-side emission only. Nothing in the current
310+
`McpServer::resource()` API prevents serving a `ui://` resource today — the
311+
question is whether a first-class helper (e.g. `->ui(...)` that bundles the
312+
MIME type, size-bound checks, and tool-metadata conventions) is worth adding,
313+
and the server must degrade gracefully where a host cannot display it. We will
314+
evaluate once the extension sees traction in the MCP hosts PHP developers
315+
actually target.
169316
- **Advanced OAuth profiles: DPoP and Workload Identity Federation.**
170317
SEP-1932 (DPoP, sender-constrained tokens per RFC 9449) and SEP-1933
171318
(Workload Identity Federation) are both in review and aimed primarily at

0 commit comments

Comments
 (0)