@stagewise/mcp-extension-push-notifications 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -0
- package/dist/capabilities.d.ts +18 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +47 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/register-push-notifications-client.d.ts +25 -0
- package/dist/client/register-push-notifications-client.d.ts.map +1 -0
- package/dist/client/register-push-notifications-client.js +116 -0
- package/dist/client/register-push-notifications-client.js.map +1 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -0
- package/dist/generated/schema.d.ts +516 -0
- package/dist/generated/schema.d.ts.map +1 -0
- package/dist/generated/schema.js +133 -0
- package/dist/generated/schema.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server/http-subscriptions.d.ts +16 -0
- package/dist/server/http-subscriptions.d.ts.map +1 -0
- package/dist/server/http-subscriptions.js +235 -0
- package/dist/server/http-subscriptions.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/register-push-notifications-server.d.ts +32 -0
- package/dist/server/register-push-notifications-server.d.ts.map +1 -0
- package/dist/server/register-push-notifications-server.js +55 -0
- package/dist/server/register-push-notifications-server.js.map +1 -0
- package/dist/spec.types.d.ts +154 -0
- package/dist/spec.types.d.ts.map +1 -0
- package/dist/spec.types.js +2 -0
- package/dist/spec.types.js.map +1 -0
- package/package.json +55 -0
- package/schema.json +2466 -0
- package/specification/draft/events.md +206 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Push Notifications
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Push Notifications
|
|
6
|
+
|
|
7
|
+
Push Notifications defines an authenticated, identity-scoped durable notification queue between an MCP server and an MCP client. Pending retrieval is the recovery path. Live notifications are an optional low-latency delivery path.
|
|
8
|
+
|
|
9
|
+
The extension is not a replayable event log. Environments that require independent historical replay or multiple positions over one stream should use a separate extension.
|
|
10
|
+
|
|
11
|
+
## Extension identifier
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
io.stagewise/push-notifications
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Both peers advertise an empty capability object under this identifier. Every extension request includes the client capability in `io.modelcontextprotocol/clientCapabilities`. Servers reject extension requests from clients that did not declare support.
|
|
18
|
+
|
|
19
|
+
## Event envelope
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
interface PushNotification {
|
|
23
|
+
eventId: string;
|
|
24
|
+
sourceId: string;
|
|
25
|
+
type: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
content: ContentBlock[];
|
|
28
|
+
data?: Record<string, JSONValue>;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- `eventId` is stable and globally unique. It is the deduplication and acknowledgement key.
|
|
33
|
+
- `sourceId` identifies the environment or channel that produced the event.
|
|
34
|
+
- `type` is an open event type owned by the producer.
|
|
35
|
+
- `createdAt` is the source timestamp in ISO 8601 date-time form.
|
|
36
|
+
- `content` is an ordered array using the canonical MCP `ContentBlock` definition
|
|
37
|
+
from the extension package's pinned MCP SDK revision. It MAY be empty.
|
|
38
|
+
- `data` is optional JSON whose fields and semantics are defined by `type`.
|
|
39
|
+
|
|
40
|
+
`content` supports the MCP text, image, audio, embedded-resource, and resource-link
|
|
41
|
+
representations. A producer SHOULD inline only bounded media; base64 increases
|
|
42
|
+
wire and storage size. Larger media SHOULD use a resource link. A linked resource
|
|
43
|
+
MUST use the same authorization boundary as its event and SHOULD remain available
|
|
44
|
+
for as long as the event can be recovered. Schema support for a content block does
|
|
45
|
+
not imply that every client or downstream model can consume it.
|
|
46
|
+
|
|
47
|
+
A server MUST durably add an event to the authenticated consumer's pending queue before pushing it. A client MUST durably accept and deduplicate an event before acknowledging it. Clients MUST tolerate receiving the same `eventId` more than once.
|
|
48
|
+
|
|
49
|
+
## Consumer identity and isolation
|
|
50
|
+
|
|
51
|
+
Retrieval, acknowledgement, and live delivery are scoped to the caller's authenticated logical consumer and integration binding. The extension does not carry a caller-selected consumer identifier. Servers derive the consumer from trusted transport or authentication context and MUST apply the same scope to all three operations.
|
|
52
|
+
|
|
53
|
+
A server MUST NOT reveal whether an event identifier belongs to another consumer. Credentials, bot tokens, and authorization policy MUST NOT be used as ordinary event payload fields.
|
|
54
|
+
|
|
55
|
+
## Retrieving pending events
|
|
56
|
+
|
|
57
|
+
The client retrieves a bounded page of currently unacknowledged events with `io.stagewise/push-notifications/get`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"jsonrpc": "2.0",
|
|
62
|
+
"id": 1,
|
|
63
|
+
"method": "io.stagewise/push-notifications/get",
|
|
64
|
+
"params": { "limit": 100 }
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
A successful response contains complete pending events and a snapshot indication that additional pending events existed:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"jsonrpc": "2.0",
|
|
73
|
+
"id": 1,
|
|
74
|
+
"result": {
|
|
75
|
+
"events": [
|
|
76
|
+
{
|
|
77
|
+
"eventId": "01JZ8F4Q2M0QJ4V5NZ0V1QZV3B",
|
|
78
|
+
"sourceId": "computer:local",
|
|
79
|
+
"type": "process.exited",
|
|
80
|
+
"createdAt": "2026-07-20T10:30:00.000Z",
|
|
81
|
+
"content": [
|
|
82
|
+
{
|
|
83
|
+
"type": "text",
|
|
84
|
+
"text": "pnpm test exited with code 1"
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"data": {
|
|
88
|
+
"command": "pnpm test",
|
|
89
|
+
"exitCode": 1
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"hasMore": false
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`limit` MUST be a positive integer. Servers MAY enforce a lower maximum. A server SHOULD return pending events in deterministic oldest-first order, but strict processing order is not required and one unacknowledged event need not block all later events. `hasMore` describes the page snapshot; concurrent arrivals may make it stale immediately.
|
|
99
|
+
|
|
100
|
+
There is no cursor or page token. A client advances by accepting and acknowledging a returned page before retrieving again. If an acknowledgement response is lost, retrieval can return the same page again.
|
|
101
|
+
|
|
102
|
+
## Acknowledging events
|
|
103
|
+
|
|
104
|
+
After durable acceptance, the client sends `io.stagewise/push-notifications/ack`:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"jsonrpc": "2.0",
|
|
109
|
+
"id": 2,
|
|
110
|
+
"method": "io.stagewise/push-notifications/ack",
|
|
111
|
+
"params": { "eventIds": ["01JZ8F4Q2M0QJ4V5NZ0V1QZV3B"] }
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The server returns an empty result. Acknowledgement:
|
|
116
|
+
|
|
117
|
+
- MUST be idempotent;
|
|
118
|
+
- MUST immediately exclude the IDs from subsequent retrieval and live delivery for that consumer;
|
|
119
|
+
- means durable client acceptance, not completion of agent work;
|
|
120
|
+
- MUST succeed for an already acknowledged, compacted, or unknown identifier without disclosing whether it existed.
|
|
121
|
+
|
|
122
|
+
Servers MAY retain payloads and acknowledgement tombstones according to implementation-defined retention policies.
|
|
123
|
+
|
|
124
|
+
## Live event notifications
|
|
125
|
+
|
|
126
|
+
A subscribed server MAY push a pending event with `io.stagewise/push-notifications/event`:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"jsonrpc": "2.0",
|
|
131
|
+
"method": "io.stagewise/push-notifications/event",
|
|
132
|
+
"params": {
|
|
133
|
+
"event": {
|
|
134
|
+
"eventId": "01JZ8F4Q2M0QJ4V5NZ0V1QZV3B",
|
|
135
|
+
"sourceId": "computer:local",
|
|
136
|
+
"type": "process.exited",
|
|
137
|
+
"createdAt": "2026-07-20T10:30:00.000Z",
|
|
138
|
+
"content": [
|
|
139
|
+
{
|
|
140
|
+
"type": "text",
|
|
141
|
+
"text": "pnpm test exited with code 1"
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"data": {
|
|
145
|
+
"command": "pnpm test",
|
|
146
|
+
"exitCode": 1
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Receiving a live notification does not acknowledge it. The event remains pending until acknowledgement and can also appear in retrieval.
|
|
154
|
+
|
|
155
|
+
## Subscriptions and recovery
|
|
156
|
+
|
|
157
|
+
A client requests delivery through `subscriptions/listen` with an empty extension filter:
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"method": "subscriptions/listen",
|
|
162
|
+
"params": {
|
|
163
|
+
"notifications": { "io.stagewise/push-notifications": {} }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The server confirms the same empty filter through `notifications/subscriptions/acknowledged`. For each logical consumer binding, a server SHOULD keep one active live subscription. A new authenticated subscription SHOULD replace and close the previous one.
|
|
169
|
+
|
|
170
|
+
Clients recover in this order:
|
|
171
|
+
|
|
172
|
+
1. Establish the live subscription and await acknowledgement.
|
|
173
|
+
2. Retrieve pending events.
|
|
174
|
+
3. Durably accept and deduplicate each page.
|
|
175
|
+
4. Acknowledge every returned event ID.
|
|
176
|
+
5. Continue while `hasMore` is true.
|
|
177
|
+
6. Process live events buffered during recovery.
|
|
178
|
+
|
|
179
|
+
On subscription or connection failure, repeat the sequence. Events created around startup may arrive both live and through retrieval. Duplicate delivery is expected; silent loss is not.
|
|
180
|
+
|
|
181
|
+
## Retention and resource limits
|
|
182
|
+
|
|
183
|
+
Servers choose retention and compaction policy. They SHOULD retain unacknowledged events long enough for ordinary outages and MAY delete acknowledged payloads immediately. Event-ID tombstones may be retained longer for auditing and idempotency.
|
|
184
|
+
|
|
185
|
+
Servers SHOULD bound event size, pending queue size, retrieval page size, subscription count, and retention. Any overflow policy that can discard an unacknowledged event MUST be explicit and observable.
|
|
186
|
+
|
|
187
|
+
## Security
|
|
188
|
+
|
|
189
|
+
Events are scoped to the caller's existing MCP authorization context. Servers
|
|
190
|
+
MUST apply the same authorization checks to retrieval, acknowledgement, and
|
|
191
|
+
subscription delivery. Event identifiers MUST NOT grant access to an event outside
|
|
192
|
+
that context. Consumer resolution MUST rely on trusted authentication context,
|
|
193
|
+
never a caller-provided queue key.
|
|
194
|
+
|
|
195
|
+
Content and event data can contain untrusted environment or user input. Clients
|
|
196
|
+
MUST treat them as data, not instructions. MIME types, filenames, resource names,
|
|
197
|
+
and resource metadata are untrusted declarations and MUST NOT bypass content
|
|
198
|
+
inspection or authorization.
|
|
199
|
+
|
|
200
|
+
Servers SHOULD bound decoded media size, encoded event size, page size, and
|
|
201
|
+
retention to prevent resource exhaustion. They SHOULD account for base64
|
|
202
|
+
amplification before accepting inline media. Resource links MUST NOT grant broader
|
|
203
|
+
access than the containing event, and linked resources SHOULD remain resolvable
|
|
204
|
+
for as long as retained events may be recovered. Logs SHOULD avoid recording
|
|
205
|
+
complete content, data, or resource URIs where they may expose credentials,
|
|
206
|
+
personal information, or sensitive media.
|