---
title: "MCP Events"
description: "Subscribe your MCP client to Bird events, such as a new email in a mailbox or an inbound SMS, and receive each one as a signed webhook on mcp.bird.com."
canonical: "https://bird.com/docs/ai/mcp-events"
---

# MCP Events

MCP Events lets an MCP client hear about what happens in Bird without polling. Your client subscribes to an event, such as an email arriving in a mailbox, and the hosted [Bird MCP server](/docs/ai/mcp-server) posts each matching event to a callback URL the client owns. The client wakes your agent with the event, and the agent acts on it with Bird's tools.

MCP Events implements the [MCP triggers and events extension](https://github.com/modelcontextprotocol/experimental-ext-triggers-events) with webhook delivery. Your MCP client handles the protocol: you connect it to `mcp.bird.com` and ask it to watch for something. ChatGPT supports it today.

## Before you start

- Connect your client to the hosted server at `https://mcp.bird.com/`, or its `/dynamic` endpoint. The `/public` endpoint and the local `bird mcp` server do not serve MCP Events.
- Sign in with an account that can manage webhooks. Each subscription needs the `webhooks:write` scope and the read scope of its event, which the client requests when you sign in.
- Use a client that supports the extension and its webhook delivery mode.

## Events you can subscribe to

| Event                            | Read scope      | Filters                                 |
| -------------------------------- | --------------- | --------------------------------------- |
| `email_mailbox.message_received` | `mailbox:read`  | `mailbox_id`, `thread_id`               |
| `email.delivered`                | `emails:read`   | `broadcast_id`                          |
| `sms.received`                   | `sms:read`      | `to`, a number of yours in E.164 format |
| `whatsapp.received`              | `whatsapp:read` | none                                    |
| `amb.received`                   | `amb:read`      | none                                    |

`events/list` returns the events your sign-in can subscribe to, each with its filters and payload schema. A filter narrows the subscription to one resource: `mailbox_id` set to `mbx_…` delivers only the mail that arrives in that mailbox. An event without filters delivers every occurrence in the workspace.

After you create a mailbox through the MCP server, the response suggests subscribing to its mail, with the event and `mailbox_id` filled in.

## How a subscription works

1. **Subscribe.** The client calls `events/subscribe` with the event, its filters, a callback URL and a signing secret of its own (`whsec_…`).
2. **Verify.** Before creating anything, we post a signed `{"type":"verification","challenge":"…"}` to the callback. The callback must answer with a `2xx` whose JSON body echoes `challenge`, within 4 seconds.
3. **Receive.** Each matching event arrives as a `POST` to the callback, signed with the client's secret.
4. **Renew.** A subscription lasts until its `refreshBefore` time, at most 24 hours and at least 5 minutes from the client's suggested `ttlMs`. Calling `events/subscribe` again with the same event, filters and callback renews it in place. A new signing secret replaces the old one once the callback verifies it, and the old one keeps signing for 5 minutes.
5. **End.** The client calls `events/unsubscribe`, or stops renewing and the subscription expires.

Subscribing again from the same sign-in with the same event, filters and callback is idempotent: it renews the subscription you have rather than creating another.

## Deliveries

Each delivery is a [Standard Webhooks](https://www.standardwebhooks.com/) request:

- `webhook-id` carries the event's ID, so the client can drop a repeat.
- `webhook-timestamp` and `webhook-signature` sign the body with the client's secret.
- `X-MCP-Subscription-Id` names the subscription, so the client can pick its secret before reading the body.

The body is `{"eventId", "name", "timestamp", "data", "cursor": null}`, where `data` is the event's payload as `events/list` describes it. We keep no replayable history, so `cursor` is always `null`.

A body is at most 256 KiB. An `amb.received` event that would be larger has its message text cut short at a character boundary and carries `body_truncated: true`; the client fetches the whole message with `amb_get`. Any other event that would exceed the limit is not sent.

A delivery that fails is retried eight times over about eight hours, so an event your agent acts on is not stale when it lands. If the callback answers `410 Gone` or `413 Content Too Large`, we drop that one event and keep the subscription. Failed deliveries never pause a subscription: it ends when its lease runs out.

## When a subscription ends

A subscription ends when the client unsubscribes, when it expires, or when someone deletes it in Bird, from the dashboard's **Webhooks** list or through the API. Deleting it stops deliveries at once, but the client is not told: while it still holds the subscription, it creates it again at its next renewal, verifying its callback again. To stop a subscription for good, remove it from the client as well.

If the sign-in behind a subscription is revoked, or loses the event's read scope, we stop delivering to it, and it expires within its lease.

## See your subscriptions

Every subscription is a webhook endpoint in your workspace. The dashboard's **Webhooks** list shows each one with its client's logo, its event and its filters, and you can delete it there. Subscriptions count toward your organization's webhook endpoint limit.

## Troubleshooting

| Error                                       | What it means                                                                                                                             | What to do                                                                                      |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `-32015` `CallbackEndpointError`            | The callback did not verify. `data.reason` is `connection_refused`, `timeout`, `tls_error`, `http_4xx`, `http_5xx` or `challenge_failed`. | Make the callback publicly reachable over HTTPS, and have it echo `challenge` within 4 seconds. |
| `-32013` with `data.limit: "subscriptions"` | The organization has no webhook endpoint left.                                                                                            | Delete an endpoint you no longer need, then subscribe again.                                    |
| `-32013` with `data.limit: "rate"`          | Too many callback verifications in a short time.                                                                                          | Wait, then retry the same request.                                                              |
| `-32012`                                    | The sign-in lacks the event's read scope or `webhooks:write`. `data.required` names the missing one.                                      | Sign in again and grant it.                                                                     |
| `-32602`                                    | A filter the event does not take, or a callback that is not HTTPS.                                                                        | Use the filters `events/list` returns.                                                          |

## Next steps

- [Route messages to your AI agent](/docs/ai/route-messages-to-an-agent) sends inbound messages to Claude Managed Agents or Grok Bot through a connector, without MCP.
- [Webhooks & events](/docs/guides/webhooks) covers signature verification and the event catalog.
- [MCP server](/docs/ai/mcp-server) lists the tools your agent acts with.

## Related resources

- [Setting up your coding agent](/learn/basics/setting-up-your-coding-agent) (video)
- [What is an MCP server, and how does an agent use one to send messages?](/explained/platform/what-is-an-mcp-server-and-how-does-an-agent-send-messages) (answer)
- [Coding agents](/ai) (product)
- [Build with AI agents](/learn/paths/agents) (course)

[Get an implementation brief](/learn/workspace?topic=agents)
