> ## Documentation Index
> Fetch the complete documentation index at: https://chatbase.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Events

> Let ChatGPT and other MCP clients react when a ticket is created, a conversation escalates, a customer replies or a phone call ends.

MCP Events let an AI assistant connected to the [Chatbase MCP server](https://chatbase.co/docs/developer-guides/mcp.md) react to what happens on your AI agents, without anyone asking it to check. You describe once what to watch for and what to do, and the assistant runs that task every time it happens.

> [!NOTE]
>
> MCP Events is a very new feature built on a draft extension to the Model Context Protocol. Client support is still arriving and may change as the specification settles.

## Supported clients

| Client | Support |
| - | - |
| ChatGPT | Work chats on ChatGPT web, and in the desktop app with **Cloud** selected |
| ChatGPT dots | Supported by ChatGPT, but a run currently starts without the event's details. Use Work chats until this is fixed. |
| Your own agent | Any client that implements the events extension, such as the [Vercel AI SDK](https://ai-sdk.dev/docs/ai-sdk-core/mcp-events). See [Build your own client](#build-your-own-client). |

Other MCP clients will receive events as they add support for the extension.

## Use it in ChatGPT

**1. Connect Chatbase**

Add the Chatbase connector to ChatGPT and approve access, as described in [MCP Server](https://chatbase.co/docs/developer-guides/mcp.md#claude-and-chatgpt).

**2. Describe the trigger and the task**

In a Work chat, name the AI agent, what to watch for and what to do. For example: *"Whenever a new ticket is created on Acme Support, summarize it, suggest a priority and draft a first reply."*

**3. Let it run**

ChatGPT subscribes to the event and runs the task each time it happens.

### Ideas

* **Triage new tickets:** summarize each new ticket, suggest a priority and draft a first reply.
* **Draft replies:** when a customer replies on a ticket, draft an answer from the full thread.
* **Close knowledge gaps:** when the AI agent hands a conversation to a human, explain what it could not answer so you can add the missing source.
* **Brief the human:** when a conversation escalates, give the person taking over a short summary before they reply.
* **Log calls:** after each phone call, write a summary and the follow-ups.
* **Spot trends:** collect the week's escalations and group them by reason.

## Events

Every event is scoped to one AI agent. A delivery carries ids only, never message text, names, emails or phone numbers. The assistant reads the details with the tool named below, using your permissions.

| Event | Sent when | Read the details with | Permission |
| - | - | - | - |
| `chatbase.ticket.created` | A Helpdesk ticket is created, or the AI agent files one on a connected platform such as Zendesk | `chatbase_get_ticket` | `helpdesk_tickets:read` |
| `chatbase.conversation.escalated` | The AI agent hands a conversation to a human through its ticket or live chat action | `chatbase_export_conversations` | `chatlogs:export` |
| `chatbase.ticket.message_received` | A customer replies on an existing ticket | `chatbase_list_ticket_messages` | `helpdesk_tickets:read` |
| `chatbase.conversation.deescalated` | A conversation a human had taken over goes back to the AI agent | `chatbase_export_conversations` | `chatlogs:export` |
| `chatbase.phone_call.ended` | A phone call with the AI agent ends | `chatbase_export_conversations` | `chatlogs:export` |

> [accordion] chatbase.ticket.created
>
> Sent for ordinary tickets from any channel, and for tickets the AI agent or a connected tool creates. Not sent for live chat or Outbound campaign tickets, or for tickets created directly inside a third-party platform.
>
> Payload: `agentId`, `ticketNumber`, `channel`, `platform`, `conversationId`, `escalatedConversation`. For a ticket on another platform, `ticketNumber` and `channel` are null and `platform` names it, for example `zendesk`. `escalatedConversation` is true when creating the ticket also handed the conversation to a human.

> [accordion] chatbase.conversation.escalated
>
> Sent only when the AI agent itself decides to hand off. Not sent when a human takes over from the dashboard, or when a platform such as Zendesk takes control.
>
> Payload: `agentId`, `conversationId`, `reason` (`ticket` or `live_chat`), `ticketNumber`. `ticketNumber` is null when the handoff went to a third-party platform.

> [accordion] chatbase.ticket.message\_received
>
> Sent for customer replies on ordinary and Outbound campaign tickets, including automatic replies such as out-of-office emails. Not sent for the first message of a ticket, replies from your team, internal notes, or messages during a live chat with a human. On the Chat Bubble, WhatsApp, Messenger and Instagram, once a ticket is closed and the conversation is back with the AI agent, the customer's next message goes to the AI agent instead.
>
> Payload: `agentId`, `ticketNumber`, `messageId`.

> [accordion] chatbase.conversation.deescalated
>
> Sent once per handback: the conversation's last open ticket was closed, or a live chat on another platform ended. Also sent when a human had taken over from the dashboard, so it can arrive without an earlier escalated event.
>
> Payload: `agentId`, `conversationId`.

> [accordion] chatbase.phone\_call.ended
>
> Sent once per real phone call, never for voice chat in a web widget.
>
> Payload: `agentId`, `conversationId`, `durationSeconds`.

> [!NOTE]
>
> If a client subscribes to both `chatbase.ticket.created` and `chatbase.conversation.escalated`, a ticket the AI agent creates to hand over a conversation arrives only as `chatbase.conversation.escalated`, which carries the `ticketNumber`. The client never receives both for one ticket.

### Good to know

* Conversations in the Playground, Actions and Q\&A never send events. Test from a real channel such as the Chat Bubble, email or WhatsApp.
* Actions an assistant takes through the MCP tools also send events. For example, creating a ticket with `chatbase_create_ticket` sends `chatbase.ticket.created`.
* Revoking an app under **Settings → General → Connected apps** ends all its subscriptions immediately.
* If your role loses a permission an event needs, deliveries for that event stop.

## Build your own client

The server implements the webhook delivery mode of the [MCP Triggers & Events draft](https://github.com/modelcontextprotocol/experimental-ext-triggers-events). Clients call three JSON-RPC methods on `https://mcp.chatbase.co/api/mcp`, using the same OAuth connection as the tools.

| Method | Purpose |
| - | - |
| `events/list` | Lists the events above with their input and payload schemas |
| `events/subscribe` | Starts or renews a subscription |
| `events/unsubscribe` | Ends a subscription |

### Subscribe

Send the event name, `arguments` with the `agentId`, and a `delivery` object with `mode: "webhook"`, an `https` `url` and a `secret` you generate: `whsec_` followed by 24 to 64 random bytes, base64-encoded.

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "events/subscribe",
  "params": {
    "name": "chatbase.ticket.created",
    "arguments": { "agentId": "<agentId>" },
    "delivery": {
      "mode": "webhook",
      "url": "https://example.com/chatbase-events",
      "secret": "whsec_<base64>"
    }
  }
}
```

The first time you subscribe a URL, Chatbase POSTs `{"type":"verification","challenge":"..."}` to it. Respond within 5 seconds with a `2xx` and `{"challenge":"..."}` echoing the same value.

* **Lease:** the response includes `refreshBefore`. Call `events/subscribe` again with the same parameters before then to renew. The lease is 1 minute to 24 hours, 24 hours by default. Send `ttlMs: null` for a subscription that lasts until the connection is revoked or expires, and the response returns `refreshBefore: null`.
* **Limits:** 25 live subscriptions per connection. Repeating a subscribe with the same event, arguments and URL renews it rather than creating another.
* **URLs:** `https` only, on a public address. Redirects are not followed.

### Deliveries

Each event is a POST signed with [Standard Webhooks](https://www.standardwebhooks.com) headers (`webhook-id`, `webhook-timestamp`, `webhook-signature`), using your secret. Verify the signature before trusting the body.

```json theme={null}
{
  "eventId": "evt_...",
  "name": "chatbase.ticket.created",
  "timestamp": "2026-11-05T10:00:00.000Z",
  "data": {
    "agentId": "<agentId>",
    "ticketNumber": 1042,
    "channel": "email",
    "platform": null,
    "conversationId": null,
    "escalatedConversation": false
  },
  "cursor": null
}
```

| Your response | What Chatbase does |
| - | - |
| `2xx` within 10 seconds | Marks the event delivered |
| `410 Gone` | Ends the subscription |
| `413` | Drops that event |
| Anything else, or no response | Retries with backoff, up to 6 times, then drops the event |

Delivery is at least once and can arrive out of order. Deduplicate on `eventId`, and read the record with the tool rather than acting on the payload alone.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.