Repository navigation
Demo: receive MCP Events with Event Gateway as a forward proxy - #23
Merged
Merged
Conversation
An MCP server (protocol 2026-07-28, MCP SDK v2) that offers incident.created in webhook delivery mode, following OpenAI's MCP Events profile. It plays the part of any third-party MCP server in the demo. - events/list, events/subscribe (verification challenge before activation, TTL grants, dual-signing on secret rotation) and events/unsubscribe. - Standard Webhooks signing on every attempt, bounded retries, no retry on 410 or 413. - npm run emit opens an incident, with options to send a duplicate or a badly signed delivery. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… forward proxy The agent owns its proxy: per subscription it creates an MCP Events source holding a fresh whsec_ secret and a connection with a deduplicate rule on headers.webhook-id and a retry rule, subscribes with the source URL, refreshes before refreshBefore, and on exit unsubscribes and deletes both. - CLI mode (default locally) delivers through hookdeck listen, supervised with its own CLI config under run/. - HTTP mode (AGENT_PUBLIC_URL set) delivers to the agent's public endpoint, which checks x-hookdeck-signature. - The endpoint re-checks the MCP server's signature without the 5-minute window, handles each eventId once and ignores verification bodies. - npm run agent:status, agent:fail and teardown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
npm run scenarios checks the subscription, a delivery, a duplicate, a bad signature, the agent down then back and, when deployed, a forged request, and prints pass or fail with evidence. 6 of 6 passed against the deployed services. One image serves both services; fly.sender.toml and fly.agent.toml run them as always-on single machines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- docs/PLAN.md: the proposal, background on SEP-3415's forward proxy, who does what, status, verified results and remaining work. - README.md and AGENTS.md for running and continuing the demo. - hookdeck/mcp-events-outpost: a stub linking the sending-side demo. - Repo README rows for both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rt and on reconnect - recover.ts: retry CLI_DISCONNECTED requests scoped to the agent's connection (retry, not replay), retry events that settled as FAILED unless the agent answered 4xx, and leave queued or scheduled events to Event Gateway. Repeats every 60 s for up to 5 minutes. - --keep leaves the subscription and endpoint in place on exit; the next start picks the endpoint up (secret read back with include=config.auth), re-subscribes and recovers. - /demo/listen and npm run agent:listen stop, kill or start listen. - Two CLI scenarios: listen stopped cleanly, and listen killed. - Match the agent's resource names exactly (<prefix>-<8 hex>). The prefix match let a local agent delete the deployed agent's source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Correct the Phase 2 CLI cases from measurements with hookdeck-cli 3.1.0: a crash doesn't hold events as pending, pausing doesn't cover a clean stop, and recovery uses request retry. Record the 75 s hold as not reproduced, and add the recovery results to the status table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… server The agent subscribed to order.created on the Outpost demo's server with only env changes: filtering by Outpost, a 503 retried by Event Gateway, and a clean listen stop recovered by request retry all behaved as with the stand-in sender. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the WIP banner with a status line, and add how Event Gateway covers SEP-3415's receiver duties, what's verified across local, deployed and the Outpost demo as sender, what isn't (servers that follow SEP-3415's capability location and error codes, rotation, CLI-mode refresh), and the 200 answer to a badly signed delivery as a known limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d the server The flowcharts ranked the MCP server between the agent and Event Gateway, because the agent has edges to both. Sequence diagrams keep the declared order (agent, proxy, server) and show the steps in time order. The README steps now separate answering the challenge from storing and verifying events, and say Event Gateway answers 200 once stored and verifies after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
evdock's daemon receives through an MCP Events source and hookdeck listen with one small change (a supplied secret, --secret-env). Delivery, dedup, bad signatures and refresh work; a delivery held over 5 minutes fails evdock's timestamp check with 401, which the retry rule then repeats. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…enge only The evdock spike options assumed a proxy that checks freshness on receipt. Event Gateway doesn't yet for deliveries, so say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The demo is Event Gateway in the role SEP-3415 calls a forward proxy, so the directory now uses that term. The Fly app names are kept as they are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ness gap Known limits now cover the code an MCP client needs to set up the proxy, the project API key the agent holds, one source per subscription, and that nothing rejects a stale event. The CLI path is described as local development. Field report drafts stay out of the repo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plan now says the demo is done, with the deployed scenarios passing again on 2026-10-14. The working group notes stay as notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…retry The clean-stop scenario read the agent's recovery record as soon as the event was handled. A recovery pass records its retries when it finishes, and the retried event can be delivered first, so the check could fail on a correct run. It now waits for the record. Re-verified on 2026-10-14: 7 of 7 locally, including a fresh subscribe and a refresh in CLI mode, and 6 of 6 deployed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
leggetter
marked this pull request as ready for review
October 14, 2026 15:49
…P note Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A demo of Hookdeck Event Gateway acting as the forward proxy that MCP Events (SEP-3415, a draft MCP extension) describes for webhook delivery, in
hookdeck/mcp-events-forward-proxy/. Verified against a dedicated Event Gateway test project, last on 2026-10-14 after Event Gateway's MCP Events handshake changes: 7 of 7 scenarios locally and 6 of 6 deployed.src/sender/): an MCP server offeringincident.createdin webhook mode, standing in for any third-party MCP server.src/agent/): an MCP client that owns its proxy. Per subscription it creates anMCP Eventssource with a freshwhsec_secret and a connection (dedup onheaders.webhook-id, retries), subscribes with the source URL, refreshes, and cleans up on exit.hookdeck listen(no public URL), and deployed over HTTP to the agent's endpoint, which checksx-hookdeck-signature.listenwas down (src/agent/recover.ts): on start and on reconnect, the agent retriesCLI_DISCONNECTEDrequests and settledFAILEDevents, and leaves anything queued or scheduled to Event Gateway. With--keep, a restarted agent picks up its existing source and subscription.npm run scenarios: runs the scenarios and prints pass or fail with evidence: 7 locally (CLI), 6 deployed (HTTP). The deployed agent was last deployed on 2026-10-08; no later commit changes how the agent or sender behaves (only the MCP client's name).503retried by Event Gateway, and a cleanlistenstop recovered.MCP Eventssource andhookdeck listenwith one small evdock change (a supplied secret); deliveries held over 5 minutes fail its timestamp check. Results indocs/PLAN.md(Phase 3).hookdeck/mcp-events-outpoststub linking the sending-side demo, and rows for both in the repo README.mcp-events-receive-*, from the demo's earlier name; a comment in eachfly.*.tomlsays so.Verified results
First run 2026-10-08; the rows
npm run scenarioscovers re-run 2026-10-14. The rows marked by hand in the README weren't re-run.webhook-id, re-signed)VERIFICATION_FAILED, never delivered; sender saw200503, then recovers200401refreshBeforedeliveryStatus; one subscription kept for over 6 dayslisten, deletes source and connectionlistenstopped cleanly, then backCLI_DISCONNECTED; recovery retried the request; handled oncelistenkilled, back after 30 slistenkilled until retries ran outFAILED; recovery retried it; handled once--keep, events sent, restarted🤖 Generated with Claude Code