client
The client side of MCP Events (SEP-3415): Events, a Client extension.
async with Client(url, extensions=[Events()]) as client:
events = client.extension(Events)
async for batch in events.watch("incident.created", {"service": "billing"}, cursor=load_cursor()):
for event in batch.events:
handle(event)
save_cursor(batch.cursor)
Events
Bases: ClientExtension
Register with Client(extensions=[Events()]), then use client.extension(Events).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_poll_interval
|
timedelta
|
The shortest wait between polls, whatever the server asks for, so a misbehaving server cannot drive a tight loop. |
timedelta(seconds=1)
|
Source code in src/mcp/experimental/events/client.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
bind
bind(session: ClientSession) -> EventsClient
Return the events verbs bound to session.
Source code in src/mcp/experimental/events/client.py
59 60 61 | |
EventsClient
The events verbs bound to one connected session. Obtain it from client.extension(Events).
Source code in src/mcp/experimental/events/client.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
list
async
list() -> list[EventDescriptor]
Return every event type the server offers, following pagination.
Source code in src/mcp/experimental/events/client.py
71 72 73 74 75 76 77 78 79 80 | |
poll
async
poll(
name: str,
arguments: dict[str, Any] | None = None,
*,
cursor: str | None = None,
max_age: timedelta | None = None,
max_events: int | None = None
) -> PollEventsResult
Read the events after cursor once. A None cursor returns no events, only the current position.
Source code in src/mcp/experimental/events/client.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
watch
async
watch(
name: str,
arguments: dict[str, Any] | None = None,
*,
cursor: str | None = None
) -> AsyncGenerator[PollEventsResult, None]
Poll forever, yielding every batch, including empty ones.
Persist batch.cursor after handling a batch, and pass it back after a restart
to resume: delivery is at-least-once, so deduplicate on event_id. Empty batches
still move the cursor, which keeps it inside the upstream's retention window.
Source code in src/mcp/experimental/events/client.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | |
subscribe
async
subscribe(
name: str,
arguments: dict[str, Any] | None = None,
*,
url: str,
secret: str,
cursor: str | None = None,
ttl: timedelta | None = None
) -> AsyncIterator[SubscribeEventsResult]
Hold a webhook subscription: events are POSTed to url, signed with secret.
The subscription is refreshed in the background before it expires, and removed on exit.
Receive the deliveries with mcp.experimental.events.receiver.WebhookReceiver.
Raises:
| Type | Description |
|---|---|
MCPError
|
The server refused the subscription, e.g. because |
Source code in src/mcp/experimental/events/client.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |