MCP Events
Subscribe a ZyberDesk OAuth ChatGPT MCP connector to verified, signed callbacks for authorized events.
MCP Events
MCP Events deliver selected ZyberDesk changes to an HTTPS callback. The event catalog is scoped to the OAuth caller's team and granted scopes. Event delivery uses the existing ChatGPT Streamable HTTP server; it is separate from the broad team MCP endpoint.
Warning
MCP Events are rollout-gated and disabled by default. A server exposes event discovery and methods only after its operator enables MCP_EVENTS_ENABLED and completes that environment's database, worker, callback-egress, and authenticated pilot checks. Contact your administrator for availability; the public endpoint alone does not mean Events are enabled.
Connect in ChatGPT
Use the configured ZyberDesk connector in ChatGPT Work on the web, or in ChatGPT Desktop with Work and Cloud enabled. After the Events rollout is enabled for your environment, rescan or refresh the connector so ChatGPT discovers the Events capability. Then ask ChatGPT to watch a ticket and describe what to do when a customer replies, for example: “Watch ticket ticket_123 for new customer replies and summarize each reply for me.” ChatGPT supplies the callback URL and secret during subscription setup; use only the callback it provides.
Endpoint and transport
Use the OAuth-only ChatGPT endpoint:
https://www.zyberdesk.com/api/chatgpt/mcp/mcp
Send MCP requests with Content-Type: application/json and Accept: application/json, text/event-stream. The server can return either a JSON response or an SSE-framed Streamable HTTP response. After initialization, send the negotiated protocol version in the MCP-Protocol-Version header. When Events are enabled, discovery advertises protocol version 2026-07-28 and the events capability.
Events are available through these methods:
events/listreturns the event definitions granted to the OAuth caller.events/subscribeverifies an HTTPS callback and creates or refreshes a subscription.events/unsubscribeidempotently revokes the matching subscription.
There is no subscriptions/list method and MCP Events v1 has no replay or catch-up cursor. The separate team endpoint, POST /api/mcp, retains its broad team tool registry and does not expose this ChatGPT Events adapter.
Event catalog
The catalog only returns event types authorized for the connected OAuth grant. Optional filters and payloads are:
| Event | Required scopes | Optional filter | Payload in data |
|---|---|---|---|
contacts.created | mcp:read, contacts:read | contactId | { "contactId": "..." } |
contacts.updated | mcp:read, contacts:read | contactId | { "contactId": "..." } |
customer.replied | mcp:read, tickets:read | ticketId | { "ticketId": "...", "replyId": "..." } |
Contact updates cover stored profile fields. Activity-only timestamp changes, soft-delete-only changes, and account, business, or assignment relation changes are excluded.
customer.replied
customer.replied is visible to callers with both mcp:read and tickets:read. You can filter a subscription to one ticket with the optional ticketId argument (1–256 characters):
{
"jsonrpc": "2.0",
"id": 1,
"method": "events/subscribe",
"params": {
"name": "customer.replied",
"arguments": { "ticketId": "ticket_123" },
"ttlMs": 86400000,
"delivery": {
"mode": "webhook",
"url": "https://hooks.example.com/zyberdesk",
"secret": "whsec_<base64-encoded-random-secret>"
}
}
}
Omit arguments to receive replies for all tickets the caller is authorized to read. ticketId is camelCase in the subscription filter and event payload. The event contains IDs only:
{
"eventId": "b65f8b0e-1dd3-4ea4-9f6e-68bc866875fb",
"name": "customer.replied",
"timestamp": "2026-10-06T10:20:30.000Z",
"data": { "ticketId": "ticket_123", "replyId": "reply_456" },
"cursor": null
}
The timestamp is when the reply row was persisted. The payload does not include reply text. Use the get_ticket_reply MCP tool to read a reply the caller is authorized to access:
{
"name": "get_ticket_reply",
"arguments": {
"ticket_id": "ticket_123",
"reply_id": "reply_456"
}
}
The event's camelCase ticketId and replyId map to the tool's snake_case ticket_id and reply_id arguments. These are internal ticket and reply IDs; pass the values from the event directly rather than a provider's display ID. The tool requires tickets:read, returns reply.body_text as plain text capped at 12,000 characters, and returns reply.created_at, reply.platform, and reply.truncated so callers can tell when text was shortened.
Source coverage
The Help Scout source contract captures a reply only from a convo.customer.reply.created callback with a verified raw-body HMAC, an explicitly enabled same-platform connection, and exactly one matching provider thread. The callback customer ID and preview must match the provider snapshot, and the callback modification time must match the thread's creation time at whole-second precision; normalized previews match exactly, except that a provider preview ending in an ellipsis may match an exact prefix. The resolver checks every page, up to eight, and requires page metadata to stay complete and consistent. Missing configuration, unavailable or incomplete provider evidence, changing page metadata, more than eight pages, or an unmatched or ambiguous thread leaves MCP capture off while ordinary ticket ingestion can still succeed. With a configured secret, an invalid raw-body signature is rejected with HTTP 401. A suppressed reply creates no MCP Events row and is not retried or replayed into MCP Events. Incremental Gmail history ingestion also qualifies when a customer message is appended to an existing ticket. A recovered incremental Gmail history entry can qualify after a missed wake-up. Initial ticket descriptions, bulk historical imports and backfills, staff outbound replies, private notes, and deleted rows are excluded. Freshdesk and Zendesk reply capture is not currently part of this event contract.
Events have no replay in v1. A subscription receives eligible replies at or after its database-stored activation timestamp; creating a subscription does not send historical replies.
Callback requirements
Use an HTTPS URL on port 443 that your receiver controls. ChatGPT supplies the callback URL and a whsec_ secret during connector subscription setup. For other compatible clients, supply a secret containing valid base64 for 24–64 random bytes. Keep the secret private and out of logs. Before activating a subscription, the server sends a signed verification challenge; the receiver must return the exact challenge in a successful response.
Event deliveries use Standard Webhooks-compatible signatures and these headers:
| Header | Purpose |
|---|---|
webhook-id | Stable event ID, reused across delivery retries |
webhook-timestamp | Timestamp used to sign this delivery attempt |
webhook-signature | Signature(s) for the serialized request body |
X-MCP-Subscription-Id | Subscription associated with this delivery |
Deduplicate deliveries by webhook-id. The server retries network failures and HTTP 408, 425, 429, and 5xx responses for up to eight attempts total (one initial attempt and up to seven retries). Backoff starts at five seconds, grows exponentially with jitter, and is capped at 15 minutes; a valid Retry-After value is honored up to the same cap. HTTP 410 and 413 responses are terminal. Event outbox rows are retained for 30 days from occurrence; completed, terminal, or cancelled delivery and attempt records are retained for 90 days after completion. Delivery-attempt status is operator-only in v1; MCP has no subscriber-facing method to inspect delivery attempts. The subscription response includes refreshBefore; refresh before that time to keep receiving events. Set ttlMs to request a shorter finite lifetime; if omitted, the server applies its configured finite default.
When an event is unavailable, check whether Events are enabled on the environment, whether the OAuth grant includes the required scopes, and whether the callback remains verified and the subscription has not expired. A disabled server omits the Events capability from discovery and rejects Events methods.