Skip to content

[factory] hookgres/mcp-events: MCP Events webhook delivery (SEP-3415) — pr-open - #61

Open
NickolasBenakis wants to merge 2 commits into
factory/mcp-events-1from
factory/mcp-events-2
Open

NickolasBenakis wants to merge 2 commits into
factory/mcp-events-1from
factory/mcp-events-2

Conversation

@NickolasBenakis

Copy link
Copy Markdown
Owner

Adds hookgres/mcp-events: the server side of webhook delivery for MCP Events (SEP-3415, draft). Stacked on #60.

  • handle() answers events/list, events/subscribe and events/unsubscribe. Poll and push answer Unsupported.
  • Subscribe checks that a principal is set, the URL is https, the secret is a valid whsec_ and the event name is known. The subscription id is derived from (principal, url, name, arguments).
  • The endpoint is verified with a signed verification challenge, cached per (principal, url) and rate-limited per host, or with an allowlist (verify).
  • Refresh: TTL grant and clamp, secret rotation that dual-signs for 5 minutes, deliveryStatus.
  • emit(name, data, { client }) queues one message per matching subscription, inside the caller's transaction if one is passed. Delivery is Hookgres: Standard Webhooks signatures, X-MCP-Subscription-Id, 5 attempts over about 8 minutes, 410/413 final, no redirects, private addresses blocked at delivery time.
  • Guide: docs/guides/mcp-events.md, including what isn't covered yet (cursor replay, gap/terminated envelopes, inputSchema validation).

Verification

  • pnpm typecheck, pnpm lint, pnpm test: 364 tests pass, 17 of them in test/mcp-events.test.ts.
  • The concurrent-subscribe test fails 3 of 3 runs without the advisory lock (3 endpoints) and passes with it.
  • Passes all 36 sender checks in the conformance PR, including delivery after a SIGKILL and restart.

Decision Log

  • Each subscription is a Hookgres endpoint in its own schema (hookgres_mcp_events), with the subscription id as tenantId, so webhook-id is unique per subscription.
  • Endpoint auto-disable is off (disableEndpointAfterMs: null): disabling fails queued deliveries, while the SEP's suspension pauses them. TTL expiry does the cleanup.
  • The hookgres passthrough excludes fetch, because a custom fetch would turn off delivery-time address checks.
  • Review fixes: an advisory lock per subscription key, a bounded challenge read, a per-host verification limit, a 4 KB cap on arguments, and deleteExpired() going through deleteEndpoint.

Follow-ups

  • Cursor watermarks for durable upstreams, gap and terminated envelopes.
  • inputSchema validation of arguments.

🤖 Generated with Claude Code

NickolasBenakis and others added 2 commits November 13, 2026 23:23
Handles events/list, events/subscribe and events/unsubscribe for webhook
mode, verifies callback endpoints with a signed challenge, and emit()
queues an event per matching subscription inside the caller's transaction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-limit

Fixes from review: an advisory lock stops concurrent subscribes from
creating duplicate endpoints and unsubscribe removes all of them; the
fetch passthrough is no longer allowed (it would skip delivery-time
address checks); the challenge response is read with a size cap;
verification POSTs are rate-limited per host; arguments are capped at
4 KB; deleteExpired uses deleteEndpoint; deliveryStatus.active reflects
suspension; invalid callback addresses map to InvalidParams.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hookgres Ready Ready Preview Nov 13, 2026 9:30pm UTC

@NickolasBenakis NickolasBenakis changed the title [factory] hookgres/mcp-events: MCP Events webhook delivery (SEP-3415) — in-review [factory] hookgres/mcp-events: MCP Events webhook delivery (SEP-3415) — pr-open Nov 13, 2026
@NickolasBenakis
NickolasBenakis marked this pull request as ready for review November 13, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant