Skip to content

Commit dd82ff6

Browse files
committed
tests/interaction: add streamable-http-stateless as a connect-matrix arm
The 2025-era unofficial stateless mode (fresh transport per request, no session id, no standalone GET stream) is now a fourth connectable transport alongside in-memory, sse, and streamable-http. The factory is a partial of connect_over_streamable_http with stateless_http=True; the same shared Server instance backs every request, so no server-factory widening is needed. 41 requirements that structurally cannot run on the stateless arm are annotated with arm_exclusions scoped to this transport: 29 because the server cannot issue requests back to the client (sampling, elicitation, roots, server-to-client ping/cancel) and 12 because they need persisted session state or the standalone GET stream (client_params from initialize, cross-POST cancellation, unsolicited list-changed notifications). The connect fixture now pre-binds protocol_version into the returned factory; the value is still the single SPEC_VERSIONS entry and the factories ignore it, so this is wiring-only. 504 connect cells (411 existing + 93 stateless), all green; 100% coverage; pyright/ruff clean.
1 parent 0a5be73 commit dd82ff6

5 files changed

Lines changed: 88 additions & 14 deletions

File tree

tests/interaction/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ exercises; `SPEC_REVISION = SPEC_VERSIONS[-1]` is the newest. The `connect` fixt
143143
which intersects the admissible cells across every cited requirement — a cell survives only if
144144
**all** of the test's requirements admit it.
145145

146+
`streamable-http-stateless` is the fourth connectable transport: the 2025-era unofficial stateless
147+
mode where each request opens a fresh transport, no session id is issued, and there is no standalone
148+
GET stream. Requirements that need a server→client back-channel or persisted session state are
149+
excluded from that arm via `arm_exclusions` (reasons `server-initiated-request` and
150+
`requires-session`).
151+
146152
What admits or excludes a cell:
147153

148154
- **`added_in` / `removed_in`** gate which spec versions a requirement exists in, as a half-open

tests/interaction/_connect.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from collections.abc import AsyncIterator, Awaitable, Callable, Iterable
1111
from contextlib import AbstractAsyncContextManager, asynccontextmanager
12+
from functools import partial
1213
from typing import Any, Protocol
1314

1415
import httpx
@@ -119,10 +120,11 @@ async def connect_over_streamable_http(
119120
) -> AsyncIterator[Client]:
120121
"""Yield a Client connected to the server's streamable HTTP app, entirely in process.
121122
122-
With the defaults this is the matrix leg (stateful sessions, SSE responses); the
123-
transport-specific tests pass `stateless_http` or `json_response` to select the other
124-
server modes, and the resumability tests pass an `event_store` (with `retry_interval=0` so
125-
the client's reconnection wait is a no-op).
123+
With the defaults this is the matrix leg (stateful sessions, SSE responses); the stateless
124+
matrix arm binds `stateless_http=True` (see `connect_over_streamable_http_stateless`);
125+
transport-specific tests pass `json_response` to select the other server mode, and the
126+
resumability tests pass an `event_store` (with `retry_interval=0` so the client's
127+
reconnection wait is a no-op).
126128
"""
127129
app = server.streamable_http_app(
128130
stateless_http=stateless_http,
@@ -148,6 +150,12 @@ async def connect_over_streamable_http(
148150
yield client
149151

150152

153+
connect_over_streamable_http_stateless: Connect = partial(connect_over_streamable_http, stateless_http=True)
154+
"""The streamable-http matrix arm with the server in stateless mode (fresh transport per request,
155+
no session id, no standalone GET stream). The same shared Server instance backs every request --
156+
stateless mode does not require a server factory."""
157+
158+
151159
@asynccontextmanager
152160
async def mounted_app(
153161
server: Server | MCPServer,

0 commit comments

Comments
 (0)