Repository navigation
Triggers and Events extension: client conformance scenarios #540
Description
#521 adds server conformance for the Events extension and nothing for clients. The server side is already large, so as agreed in the #521 review, client scenarios will come in a follow-up PR. This issue tracks that work.
What's in scope
On #521, src/seps/sep-9999.yaml excludes eight client obligations with the reason "needs a client-conformance scenario set". These are the rows I want to grade:
| Requirement | Keyword |
|---|---|
Re-call events/list to refresh the event type registry |
SHOULD |
Poll again immediately when hasMore is true, ignoring nextPollMs |
SHOULD |
| Apply a configurable poll floor, default 1000 ms | SHOULD |
Don't apply the default request timeout to events/stream; reconnect with the cursor after two heartbeat intervals of silence |
SHOULD |
Re-call events/subscribe before refreshBefore |
MUST |
| Re-subscribe occasionally even when granted no expiry | SHOULD |
Never persist or replay a cursor: null; resume with null |
MUST |
Treat truncated: true as a gap and persist the fresh cursor |
SHOULD |
Four more stay excluded because nothing on the wire shows them: CSPRNG secret generation, sanitizing payloads before an LLM sees them, policy evaluation between receipt and action, and the SDK telling the application about a termination. I'm also leaving out the receiver obligations (signature verification, the timestamp window, dedup on webhook-id) for now. The harness plays the receiver in the server suite, and grading the client as a receiver would widen this first pass quite a bit.
Proposed shape
Splitting it by delivery mode, the same way the server scenarios are split, since a client can support poll without push. That gives two or three scenarios. Each runs a mock server and grades what the client sends, like mrtr-client.ts and skills/ do.
| Scenario | Mock server does | Grades |
|---|---|---|
| poll client | answers hasMore: true with a large nextPollMs, then nextPollMs: 0, then truncated: true with a fresh cursor, then an event type with cursor: null, then sends list_changed |
drain on hasMore, poll floor, fresh cursor after truncated, no null-cursor replay, re-list |
| push client | heartbeats quickly, then goes silent without closing the stream | no default timeout on events/stream, reconnect with cursor, null cursor on reconnect |
| webhook client | grants a 3 s refreshBefore |
re-subscribe before refreshBefore, secret replaced on refresh |
That comes to 8–10 checks, and every scenario fits the default 30 s timeout. "Re-subscribe occasionally" has no finite window to observe it in, so it stays excluded.
Implementations to run against
everything-client.tsgets a hand-written events client over raw JSON-RPC, the way the MRTR scenario does it, because the TypeScript SDK has no events client yet. It switches to the SDK if the TypeScript SDK proposal (linked below) lands.- mcpkit's Go client (
experimental/ext/events/clients/go, with a Python client alongside) already does push streams and webhook subscribe with a refresh loop. It needs a poll loop before it's run here, plus a fix for its webhook signature key derivation, which the server suite on feat(sep-3415): Conformance suite for triggers and events #521 found to be non-conformant. - Each scenario gets a deliberately broken client in
examples/clients/typescript/, with a vitest case asserting the check goes red.
Open question for the extension authors
The dead-stream rule says "more than twice the heartbeat interval", but the server never tells the client what the interval is. The only guidance is that servers SHOULD heartbeat at least every 30 s. A client that assumes 30 s needs a window over 60 s before it reconnects. A client that infers the interval from the heartbeats it sees can be tested in a few seconds against a fast mock. Until the document says which, I'd grade this row as a WARNING with a long window, or leave it out. I'll raise it in experimental-ext-triggers-events.
Related
- feat(sep-3415): Conformance suite for triggers and events #521: server conformance for the Events extension
- TypeScript SDK proposal for an experimental events module
Activity
panyam commentedon Oct 2, 2026
@pja-ant FYI