An agent that polls a tool gets an error when something breaks; an agent that subscribes to events gets silence, and silence is also what a quiet week looks like. At DevDay on 29 September 2026 OpenAI shipped plugin automations against MCP Events — a design sketch that still carries no SEP number and lives in a repository whose README calls its contents "exploratory and do not represent official MCP specifications or recommendations" — and the parts of that draft its integration does not consume are precisely the two envelopes that tell a client its stream ended rather than emptied. The draft defines them. It makes neither mandatory. That is the whole problem with event-driven agents in one design decision.
At a glance
Four ways an event stream goes quiet, and who is supposed to tell you which one happened.
| Cause | Signal in the draft | Strength | In the shipped integration |
|---|---|---|---|
| Subscriber's access revoked | notifications/events/terminated |
Re-check is a SHOULD | Not consumed |
| Server restart drops the buffer | {"type":"gap"} envelope |
At-most-once for emit-only types | Not consumed |
| Callback unreachable | deliveryStatus on refresh |
Visible only at the next refresh | Refresh exists |
| Genuinely nothing happened | — none needed — | — | Indistinguishable from the above |
What shipped, and what it shipped against
MCP Events is a Triggers and Events Working Group document — leads Clare Liguori of AWS and Peter Alexander of Anthropic — whose charter was merged on 25 March 2026 and whose single deliverable, "SEP: Events in MCP v1 RFC", still reads Ideating with a target date of "End April" that has not been revised since. The design sketch itself is dated 19 February 2026 and marked "Draft proposal". There is no SEP file for it in the specification repository's seps/ directory, and the incubation repo carries the experimental- prefix rather than the ext- prefix that marks an official MCP extension. The August roadmap lists server-initiated events as current work and asks for a composition review across the Agents, Transports and Triggers groups — which is to say the primitive is not finished and its interaction with Tasks is an open question.
OpenAI's own announcement wording is careful and correct: support for "the proposed MCP Events specification". The availability line is not careful in the same way — all plans. So a proposal with no SEP acquired, in one afternoon, the largest client implementation it will ever have, and the working group that owns it meets weekly on a thirty-minute cadence.
This is not an argument that OpenAI should have waited. Specs without implementations do not converge either, and the integration faithfully implements the webhook half. It is an argument about what happens next: the optional parts of a draft, once a dominant client has skipped them, stop being optional in the direction you would hope.
Three delivery modes, and the load-bearing sentence is "none is mandatory"
The draft specifies poll (events/poll), push (events/stream) and webhook (events/subscribe), advertised per event type, and it is explicit about the cost: "This goes against MCP's usual stance of offering one way to do a thing, and the cost is real: roughly 3× spec and SDK surface." None of the three is required of a server.
Optionality at the mode level has a direct consequence for anyone building a server: conformance is not interoperability. A server that implements only poll and a client that implements only webhook can both be correct and still have nothing to say to each other. Today that resolves to a de facto requirement — implement webhook, because that is what the largest client speaks, which also means persistent subscription storage and an outbound HTTPS path from your server, neither of which a tools-only MCP server needed.
Note which way the authorisation runs. Webhook subscriptions must be made by an authenticated principal — a server must reject an unauthenticated events/subscribe with -32012 Forbidden — and the subscription key is (principal, delivery.url, name, arguments). The client supplies the signing secret. Poll and push, by contrast, are available to unauthenticated servers. So the mode choice is also a choice about whether there is a principal behind the stream at all.
Silence is the failure mode, and the draft knows it
The draft's own summary states the point plainly: events let a client subscribe and "have the agent react when they occur, without the user being present". Nobody is waiting on the result, so nobody notices its absence. Four things then produce an empty stream.
The first is revocation. Authorisation is checked at subscribe time as a MUST; after that, "the server SHOULD periodically re-verify permissions", and when access is lost the subscription is terminated and a terminated envelope carries -32012 Forbidden with a reason. Note the modal verbs: the initial check is required, the ongoing check is advisory, and the notification is a message your client has to be listening for. A client that ignores it learns at its next refresh, because events/subscribe doubles as the refresh call — and the draft lets a server grant refreshBefore: null, meaning no expiry, at which point the SDK's refresh loop "drops to an occasional health-check cadence". Your agent's belief that it is still subscribed is only ever as fresh as its last refresh, and the draft permits that interval to be very long.
The second is a restart. Guarantees are at-least-once only "when the cursor is backed by a durable upstream"; for emit-only event types the draft is blunt — "at-most-once across server restarts — the in-memory buffer and its cursors do not survive". The third is delivery failure: webhook retries are independent per event, so arrivals reorder, and the client's view of failure is the deliveryStatus field it reads at the next refresh. The fourth is that nothing happened.
And the draft is honest about the floor: "This design intentionally does not provide protocol-level guarantees around event ordering, exactly-once delivery, or transactional consistency. There are no logical clocks, sequence numbers, or cross-subscription ordering constraints." Exactly-once requires application-level deduplication on eventId. That is a defensible choice — Stripe, GitHub and Shopify all ship it — but it lands on a consumer that is an agent loop, which is the least idempotent component in anybody's stack. A duplicate webhook does not re-render a page; it re-runs a plan.
There is already a field report of exactly this class of blindness in the incubation repo, filed on 24 August 2026 against long-polling: a 30-day pilot, 74 successful calls, median 45.9 seconds and p95 241.7 seconds, with 22 of them past 60 seconds. The author's stated show-stopper is one sentence — "Client abandonment is invisible. All 22 calls past 60 s were recorded ok." The server could not tell that nobody was listening any more. That is the same problem as the four silences, arriving from the other end.
The webhook plumbing is the part they got right
It is worth being precise about where the criticism does and does not apply, because the security engineering in this draft is better than the discourse around server-initiated events would suggest. Compared with A2A's push notifications — the nearest prior art, where an agent POSTs task updates to a client-provided webhook with credentials from a configured authentication field — MCP Events is stricter on every axis.
The callback URL must be https — a MUST, where A2A says SHOULD. Delivery carries a Standard Webhooks HMAC signature with a client-supplied whsec_ secret, so the server never mints the credential that authenticates its own deliveries. There is a mandatory endpoint-verification handshake before delivery activates, cached per (principal, url), specifically to stop a subscription being used as a reflection or amplification primitive against a third party — A2A specifies no equivalent. Replay is bounded by a webhook-timestamp freshness window the draft puts at five minutes, plus eventId deduplication and a single-use nonce. SSRF defence is delivery-time IP validation against the IANA special-purpose registries, connecting to the validated IP with the original Host and SNI, and no redirects.
The draft also closes the door the obvious way on the question everyone asks first. Event receipt "does NOT constitute authorization to act" — the agent's response goes through normal MCP authorisation — and payloads are "untrusted data with the same injection considerations as tool results". There is deliberately no token pass-through, no client-credentials grant and no OIDC identity token on a tenant's behalf. Whatever you think about event-driven agents, the people writing this have read the threat model.
Which is what makes the omission interesting. The hard security problems got MUSTs. The problem of telling a client that its stream ended got an optional envelope, and optional envelopes do not get implemented, because nobody files a bug about an event that never arrived.
What to change this week
If you are building an MCP server that will carry events, or wiring an agent to consume them:
- Treat absence as an alertable condition, not a quiet state. Record an expected-arrival rate per subscription and alarm when the stream goes flat for longer than that rate predicts. This is the same discipline as watching for absence in scheduled and triggered agents, and it is the only thing that works regardless of which envelopes your client consumes.
- Re-verify at delivery time even though it is a SHOULD. If you are the server, check the principal's permission on the way out, not only at subscribe. The alternative is delivering a Slack channel's messages to an agent whose user left the channel in March.
- Make the event handler idempotent on
eventIdbefore you ship it. Not after the first duplicate. The draft hands you at-least-once at best and at-most-once for emit-only types; both of those break an agent loop in ways a web backend absorbs silently — idempotency and retries. - Bound what an event may cause. A trigger with no requester in the room is the configuration with the widest gap between intent and effect, so cap spend, scope writes, and keep reversibility in the path. Blast radius, and ambient authority for where the extra reach comes from.
- Pin the protocol version and expect it to move. The integration requires
2026-07-28; the events surface itself is pre-SEP and the working group meets weekly. Write the version into your server's contract tests rather than your memory — the 2026-07-28 revision, and protocol revisions and deprecation windows. - Log the subscription as a grant. It is derived from a permission check that happened once, it refreshes itself, and it can outlive the project that asked for it. Put it in the registry next to the credentials — access reviews for agent credentials.
FAQ
Is MCP Events part of the MCP specification?
No. As of 1 October 2026 there is no SEP file for it in the specification repository, the working group's charter lists its RFC as "Ideating", the design sketch is marked "Draft proposal", and the incubation repository's README states that its contents "are exploratory and do not represent official MCP specifications or recommendations". OpenAI's own wording — "the proposed MCP Events specification" — is accurate.
Does a revoked permission keep delivering events?
Not if the server behaves as the draft intends: it terminates the subscription when it detects the loss. The gap is on the client's side of the boundary. The delivery-time re-verification is a SHOULD rather than a MUST, and the notification that the subscription ended is an envelope a client has to consume — so the realistic failure is an agent that believes it is still watching something and is not, for however long its refresh interval is.
Why does webhook-only matter if webhook works?
Because it changes what an MCP server is. Tools-only servers answer requests; a webhook publisher needs persistent subscription storage, an outbound HTTPS path, signature generation and a verification handshake. That is a stateful service with a delivery SLA, which is a different operational commitment from the one most MCP servers were built under — MCP ops in production.
How is this different from A2A push notifications?
A2A notifies about a task the client itself created, so there is always a prior user action behind the stream. MCP Events subscribes to an upstream third-party system with, in the draft's own words, the user not present. The webhook mechanics are similar and MCP's are stricter; the new risk is the missing requester, not the transport.
Should I wait for the SEP before building against it?
Build the server if the use case is real — the webhook surface is small and the hardening requirements are clear. Do not build business logic that assumes ordering, exactly-once delivery or a reliable termination signal, because the draft explicitly declines to provide the first two and makes the third optional. Those are the parts most likely to change, and the parts your correctness should not depend on either way.
Further reading
On this wiki:
- Scheduled & Triggered Agents — the three defaults that invert when the user is gone.
- The 2026-07-28 MCP Revision — the protocol version this integration requires.
- MCP Ops in Production — what running a stateful MCP server actually costs.
- Idempotency, Retries & Side-Effect Safety — why at-least-once lands hardest on an agent loop.
- A2A v1 — the nearest prior art for server-initiated delivery.
Sources:
- MCP Events — Design Sketch, 19 February 2026, the source of every quoted requirement here.
- Triggers & Events incubation repository, including the "exploratory" disclaimer and the long-polling field report.
- Triggers and Events working-group charter, with the "Ideating" deliverable status.
- A2A specification, §4.3.3 and §13.2 on push-notification authentication.