Skip to main content
MCP Events is a draft from the MCP Triggers & Events working group, not part of the MCP specification yet. The feature is experimental and may change with the draft. ChatGPT is the only host that supports it today, through webhooks, in Work chats.
Tools only run when the model calls them. Events go the other way: the user asks ChatGPT to watch for something (“tell me when someone comments on this doc, and draft a reply”), ChatGPT subscribes to one of your event types with a callback URL, and every time a matching event is POSTed to that URL, ChatGPT runs the user’s instructions in that chat. registerEvent handles the subscription side of the protocol. Skybridge lists your event types, checks who is subscribing and with which arguments, verifies the callback URL, and then hands the subscription to your onSubscribe hook. Delivering the events is up to whatever already knows when they happen, usually your backend’s webhook system. deliverEvent does the delivery for you when that system runs on Node.

Example

A document app lets users subscribe to new comments on one document. Its backend already sends webhooks, so onSubscribe registers ChatGPT’s callback there.

Parameters

config

hooks

subscription carries:

Refreshes

Subscriptions are short-lived. The events/subscribe response tells the host to subscribe again before expiresAt, and the host keeps the subscription alive by sending the same request again. Skybridge keeps no state, so a refresh looks exactly like a first subscribe: onSubscribe runs again with the same subscription.id and a later expiresAt, and possibly a new secret. Write onSubscribe as an upsert keyed on subscription.id: create the webhook the first time you see the id, then update its expiresAt and secret. If your webhook system can’t expire webhooks, store expiresAt next to the webhook and stop delivering once it has passed. deliverEvent already refuses to post to an expired subscription. extra is the same as in a registerTool handler: extra.http.authInfo tells you who is subscribing. Returns the server, so calls chain.

deliverEvent

POSTs one event to a subscription the way MCP Events expects: the event envelope, Standard Webhooks signature headers and a 10 second deadline. Outside development it refuses to connect to private addresses. Pass the upstream’s own identifier as id so the host can drop duplicates, and reuse it when retrying. Pass secret as an array to sign with several secrets during a rotation. A subscription past its expiresAt is not posted to and returns { ok: false, reason: "expired", retryable: false }. Otherwise it makes one attempt and returns { ok: true } or { ok: false, reason, retryable, status }, where status is the HTTP status when the host answered. A 410 or 413 is not retryable. Retrying is up to you.

How it works

  • Subscribing requires a signed-in user: set oauth.
  • Callback URLs must be https and resolve to public addresses. Unless NODE_ENV is production, http and local addresses are allowed so you can test with a local receiver. skybridge start sets NODE_ENV=production; set it yourself if you run the server another way.
  • Subscriptions last 30 minutes unless the host asks for another lifetime, at most 24 hours.
  • Payloads are capped at 256 KiB. Send a summary and let the model fetch the rest with a tool.
  • Events are not replayed: an event sent while a subscription has lapsed is lost.

registerTool

Tools the model calls, and the extra they receive

McpServer

Every method of the server