mcp-http-webhook 1.0.29 β†’ 1.0.30

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.
@@ -1,268 +0,0 @@
1
- # Standard MCP Subscriptions with Webhook Support
2
-
3
- This library now supports **standard MCP `resources/subscribe`** with webhook callbacks, eliminating the need for custom endpoints!
4
-
5
- ## 🎯 Two Ways to Subscribe
6
-
7
- ### Method 1: Standard MCP Subscribe (Recommended) βœ…
8
-
9
- Use the standard `resources/subscribe` method with webhook URL in `_meta`:
10
-
11
- ```bash
12
- curl -X POST http://localhost:3000/mcp \
13
- -H "Content-Type: application/json" \
14
- -d '{
15
- "jsonrpc": "2.0",
16
- "id": 1,
17
- "method": "resources/subscribe",
18
- "params": {
19
- "uri": "github://repo/owner/repo/issues",
20
- "_meta": {
21
- "webhookUrl": "https://your-app.com/webhooks/mcp",
22
- "webhookSecret": "your-secret-123"
23
- }
24
- }
25
- }'
26
- ```
27
-
28
- **Response:**
29
- ```json
30
- {
31
- "jsonrpc": "2.0",
32
- "id": 1,
33
- "result": {
34
- "subscriptionId": "sub_abc123xyz",
35
- "_meta": {
36
- "subscriptionId": "sub_abc123xyz",
37
- "webhookEnabled": true
38
- }
39
- }
40
- }
41
- ```
42
-
43
- ### Method 2: Legacy Custom Endpoint (Still Supported)
44
-
45
- ```bash
46
- curl -X POST http://localhost:3000/mcp/resources/subscribe \
47
- -H "Content-Type: application/json" \
48
- -d '{
49
- "uri": "github://repo/owner/repo/issues",
50
- "callbackUrl": "https://your-app.com/webhooks/mcp",
51
- "callbackSecret": "your-secret-123"
52
- }'
53
- ```
54
-
55
- ## πŸ“¬ Webhook Notifications (Standard MCP Format)
56
-
57
- When a resource changes, your webhook URL receives a **standard MCP notification**:
58
-
59
- ```json
60
- {
61
- "jsonrpc": "2.0",
62
- "method": "notifications/resources/updated",
63
- "params": {
64
- "uri": "github://repo/owner/repo/issues",
65
- "title": "Repository Issues Updated",
66
- "_meta": {
67
- "changeType": "created",
68
- "subscriptionId": "sub_abc123xyz",
69
- "timestamp": "2025-10-14T13:30:00Z",
70
- "issue": {
71
- "number": 42,
72
- "title": "New feature request",
73
- "state": "open"
74
- }
75
- }
76
- }
77
- }
78
- ```
79
-
80
- ## πŸ”„ Full Workflow Example
81
-
82
- ### 1. Subscribe to Resource
83
-
84
- ```typescript
85
- // Using standard MCP client
86
- const response = await mcpClient.request({
87
- method: 'resources/subscribe',
88
- params: {
89
- uri: 'github://repo/surajbhan/test/issues',
90
- _meta: {
91
- webhookUrl: 'https://my-app.com/mcp/notifications',
92
- webhookSecret: 'my-secret-key'
93
- }
94
- }
95
- });
96
-
97
- console.log('Subscription ID:', response._meta.subscriptionId);
98
- ```
99
-
100
- ### 2. Receive Notifications
101
-
102
- ```typescript
103
- // Your webhook endpoint
104
- app.post('/mcp/notifications', (req, res) => {
105
- const notification = req.body;
106
-
107
- if (notification.method === 'notifications/resources/updated') {
108
- const { uri, title, _meta } = notification.params;
109
-
110
- console.log('Resource updated:', uri);
111
- console.log('Change type:', _meta.changeType); // 'created', 'updated', or 'deleted'
112
- console.log('Details:', _meta);
113
-
114
- // Handle the update
115
- handleResourceUpdate(uri, _meta);
116
- }
117
-
118
- res.status(200).send('OK');
119
- });
120
- ```
121
-
122
- ### 3. Unsubscribe
123
-
124
- ```typescript
125
- // Standard MCP unsubscribe
126
- await mcpClient.request({
127
- method: 'resources/unsubscribe',
128
- params: {
129
- uri: 'github://repo/surajbhan/test/issues',
130
- _meta: {
131
- subscriptionId: 'sub_abc123xyz'
132
- }
133
- }
134
- });
135
- ```
136
-
137
- ## πŸ” Webhook Security
138
-
139
- ### Signature Verification
140
-
141
- All webhook notifications include a signature header for verification:
142
-
143
- ```typescript
144
- import crypto from 'crypto';
145
-
146
- function verifyWebhookSignature(
147
- payload: any,
148
- signature: string,
149
- secret: string
150
- ): boolean {
151
- const hmac = crypto.createHmac('sha256', secret);
152
- hmac.update(JSON.stringify(payload));
153
- const expected = `sha256=${hmac.digest('hex')}`;
154
-
155
- return crypto.timingSafeEqual(
156
- Buffer.from(signature),
157
- Buffer.from(expected)
158
- );
159
- }
160
-
161
- // In your webhook handler
162
- app.post('/mcp/notifications', (req, res) => {
163
- const signature = req.headers['x-webhook-signature'];
164
- const isValid = verifyWebhookSignature(
165
- req.body,
166
- signature,
167
- 'my-secret-key'
168
- );
169
-
170
- if (!isValid) {
171
- return res.status(401).send('Invalid signature');
172
- }
173
-
174
- // Process notification...
175
- });
176
- ```
177
-
178
- ## 🎨 MCP Inspector Integration
179
-
180
- The standard subscribe method works seamlessly with MCP Inspector:
181
-
182
- 1. Open MCP Inspector: `npx @modelcontextprotocol/inspector http://localhost:3000/mcp`
183
- 2. List resources
184
- 3. Click "Subscribe" on a resource
185
- 4. **NEW**: Inspector can pass webhook URL via `_meta`
186
-
187
- ## πŸ“Š Comparison
188
-
189
- | Feature | Standard MCP Subscribe | Legacy Endpoint |
190
- |---------|----------------------|-----------------|
191
- | **Endpoint** | `POST /mcp` | `POST /mcp/resources/subscribe` |
192
- | **Method** | `resources/subscribe` | N/A (direct POST) |
193
- | **Webhook URL** | `params._meta.webhookUrl` | `params.callbackUrl` |
194
- | **MCP Compliant** | βœ… Yes | ❌ No (custom extension) |
195
- | **Inspector Compatible** | βœ… Yes | ⚠️ Partial |
196
- | **Notification Format** | `notifications/resources/updated` | Custom |
197
- | **Recommended** | βœ… **Use this** | ⚠️ Legacy support |
198
-
199
- ## πŸš€ Quick Start
200
-
201
- ### For MCP Clients
202
-
203
- ```typescript
204
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
205
-
206
- const client = new Client({
207
- name: 'my-app',
208
- version: '1.0.0'
209
- });
210
-
211
- // Connect to MCP server
212
- await client.connect(transport);
213
-
214
- // Subscribe with webhook
215
- const subscription = await client.request({
216
- method: 'resources/subscribe',
217
- params: {
218
- uri: 'github://repo/owner/repo/issues',
219
- _meta: {
220
- webhookUrl: 'https://my-app.com/webhooks/mcp',
221
- webhookSecret: 'secret123'
222
- }
223
- }
224
- });
225
-
226
- console.log('Subscribed:', subscription._meta.subscriptionId);
227
- ```
228
-
229
- ### For HTTP Clients
230
-
231
- ```bash
232
- # Subscribe
233
- curl -X POST http://localhost:3000/mcp \
234
- -H "Content-Type: application/json" \
235
- -d '{
236
- "jsonrpc": "2.0",
237
- "id": 1,
238
- "method": "resources/subscribe",
239
- "params": {
240
- "uri": "github://repo/owner/repo/issues",
241
- "_meta": {
242
- "webhookUrl": "https://webhook.site/your-unique-url",
243
- "webhookSecret": "test123"
244
- }
245
- }
246
- }'
247
-
248
- # Watch webhook.site for notifications!
249
- ```
250
-
251
- ## 🎯 Benefits
252
-
253
- 1. **βœ… Standard Compliant**: Works with all MCP clients
254
- 2. **πŸ”Œ Universal**: No custom endpoints needed
255
- 3. **πŸ“‘ Webhook-based**: No SSE connection required
256
- 4. **πŸ”’ Secure**: Built-in signature verification
257
- 5. **🎨 Inspector Ready**: Full MCP Inspector support
258
- 6. **πŸ“š Spec Aligned**: Follows MCP 2025-06-18 specification
259
-
260
- ## πŸ“– Learn More
261
-
262
- - **MCP Spec**: https://modelcontextprotocol.io/specification/2025-06-18/server/resources#subscriptions
263
- - **Full Example**: See `examples/github-server-live.ts`
264
- - **Architecture**: See `ARCHITECTURE.md`
265
-
266
- ---
267
-
268
- **πŸŽ‰ Now you have standard MCP subscriptions with webhook support!**
@@ -1,309 +0,0 @@
1
- # βœ… Standard MCP Subscriptions Implementation Complete
2
-
3
- ## 🎯 What Was Implemented
4
-
5
- Successfully integrated **standard MCP `resources/subscribe`** with webhook callback support, making the library fully MCP-compliant while preserving all webhook functionality.
6
-
7
- ## πŸ”„ How It Works
8
-
9
- ### Before (Custom Endpoint)
10
- ```bash
11
- POST /mcp/resources/subscribe
12
- {
13
- "uri": "github://repo/owner/repo/issues",
14
- "callbackUrl": "https://client.com/webhook",
15
- "callbackSecret": "secret"
16
- }
17
- ```
18
-
19
- ### After (Standard MCP) βœ…
20
- ```bash
21
- POST /mcp
22
- {
23
- "jsonrpc": "2.0",
24
- "method": "resources/subscribe",
25
- "params": {
26
- "uri": "github://repo/owner/repo/issues",
27
- "_meta": {
28
- "webhookUrl": "https://client.com/webhook",
29
- "webhookSecret": "secret"
30
- }
31
- }
32
- }
33
- ```
34
-
35
- ## πŸ“‹ Key Changes
36
-
37
- ### 1. Server Intercepts Standard MCP Subscribe
38
-
39
- In `src/server.ts`, the main `/mcp` endpoint now intercepts `resources/subscribe`:
40
-
41
- ```typescript
42
- // Intercept resources/subscribe to support webhook callbacks
43
- if (req.body.method === 'resources/subscribe') {
44
- const webhookUrl = req.body.params?._meta?.webhookUrl;
45
-
46
- if (webhookUrl) {
47
- // Handle webhook-based subscription
48
- const result = await subscriptionManager.createSubscription({
49
- uri,
50
- clientCallbackUrl: webhookUrl,
51
- clientCallbackSecret: webhookSecret,
52
- context,
53
- });
54
-
55
- // Return standard MCP response
56
- return res.json({
57
- jsonrpc: '2.0',
58
- id: req.body.id,
59
- result: {
60
- ...result,
61
- _meta: { subscriptionId: result.subscriptionId, webhookEnabled: true }
62
- }
63
- });
64
- }
65
- }
66
- ```
67
-
68
- ### 2. Standard MCP Notification Format
69
-
70
- Updated `src/webhooks/WebhookManager.ts` to send notifications in standard MCP format:
71
-
72
- ```typescript
73
- // Standard MCP notification
74
- const payload = {
75
- jsonrpc: '2.0',
76
- method: 'notifications/resources/updated',
77
- params: {
78
- uri: changeInfo.resourceUri,
79
- title: changeInfo.data?.title,
80
- _meta: {
81
- changeType: changeInfo.changeType,
82
- subscriptionId: subscription.uri,
83
- timestamp: new Date().toISOString(),
84
- ...changeInfo.data
85
- }
86
- }
87
- };
88
- ```
89
-
90
- ### 3. Both Methods Supported
91
-
92
- - βœ… **Standard MCP**: `POST /mcp` with `resources/subscribe` method
93
- - βœ… **Legacy Custom**: `POST /mcp/resources/subscribe` (backward compatible)
94
-
95
- ## πŸŽ‰ Benefits
96
-
97
- ### 1. MCP Compliance
98
- - βœ… Follows MCP specification 2025-06-18
99
- - βœ… Works with all standard MCP clients
100
- - βœ… Compatible with MCP Inspector
101
- - βœ… Uses `notifications/resources/updated` format
102
-
103
- ### 2. Webhook-Based (Not SSE)
104
- - βœ… No persistent connection required
105
- - βœ… Client provides webhook URL in `_meta`
106
- - βœ… Server sends HTTP POST to client webhook
107
- - βœ… Fully stateless and scalable
108
-
109
- ### 3. Backward Compatible
110
- - βœ… Custom endpoints still work (`/mcp/resources/subscribe`)
111
- - βœ… Existing integrations unaffected
112
- - βœ… Gradual migration path
113
-
114
- ## πŸ“š Usage Examples
115
-
116
- ### Example 1: Subscribe via Standard MCP
117
-
118
- ```typescript
119
- // MCP Client
120
- const response = await client.request({
121
- method: 'resources/subscribe',
122
- params: {
123
- uri: 'github://repo/owner/repo/issues',
124
- _meta: {
125
- webhookUrl: 'https://my-app.com/mcp/notifications',
126
- webhookSecret: 'secret123'
127
- }
128
- }
129
- });
130
-
131
- // Response
132
- {
133
- subscriptionId: 'sub_abc123',
134
- _meta: {
135
- subscriptionId: 'sub_abc123',
136
- webhookEnabled: true
137
- }
138
- }
139
- ```
140
-
141
- ### Example 2: Receive Notifications
142
-
143
- ```typescript
144
- // Your webhook endpoint
145
- app.post('/mcp/notifications', (req, res) => {
146
- const notification = req.body;
147
-
148
- // Standard MCP notification
149
- if (notification.method === 'notifications/resources/updated') {
150
- console.log('Resource:', notification.params.uri);
151
- console.log('Change:', notification.params._meta.changeType);
152
- console.log('Data:', notification.params._meta);
153
- }
154
-
155
- res.send('OK');
156
- });
157
- ```
158
-
159
- ### Example 3: Unsubscribe
160
-
161
- ```typescript
162
- await client.request({
163
- method: 'resources/unsubscribe',
164
- params: {
165
- uri: 'github://repo/owner/repo/issues',
166
- _meta: {
167
- subscriptionId: 'sub_abc123'
168
- }
169
- }
170
- });
171
- ```
172
-
173
- ## πŸ§ͺ Testing
174
-
175
- ### Test with curl
176
-
177
- ```bash
178
- # 1. Subscribe
179
- curl -X POST http://localhost:3000/mcp \
180
- -H "Content-Type: application/json" \
181
- -d '{
182
- "jsonrpc": "2.0",
183
- "id": 1,
184
- "method": "resources/subscribe",
185
- "params": {
186
- "uri": "github://repo/surajbhan/test/issues",
187
- "_meta": {
188
- "webhookUrl": "https://webhook.site/unique-url",
189
- "webhookSecret": "test123"
190
- }
191
- }
192
- }'
193
-
194
- # 2. Create issue (triggers webhook)
195
- # Go to GitHub and create an issue
196
-
197
- # 3. Check webhook.site for notification!
198
- ```
199
-
200
- ### Test with MCP Inspector
201
-
202
- ```bash
203
- npx @modelcontextprotocol/inspector http://localhost:3000/mcp
204
- ```
205
-
206
- 1. List resources
207
- 2. Subscribe to a resource
208
- 3. Provide webhook URL in metadata
209
- 4. Trigger resource change
210
- 5. See notification arrive!
211
-
212
- ## πŸ“Š Notification Flow
213
-
214
- ```
215
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
216
- β”‚ Client β”‚
217
- β”‚ (Your App) β”‚
218
- β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
219
- β”‚
220
- β”‚ 1. POST /mcp
221
- β”‚ method: resources/subscribe
222
- β”‚ params._meta.webhookUrl: "https://client.com/webhook"
223
- β”‚
224
- β–Ό
225
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
226
- β”‚ MCP Server β”‚
227
- β”‚ (This Library) β”‚
228
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
229
- β”‚
230
- β”‚ 2. Create subscription
231
- β”‚ Setup GitHub webhook
232
- β”‚
233
- β–Ό
234
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
235
- β”‚ GitHub β”‚
236
- β”‚ (3rd Party) β”‚
237
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
238
- β”‚
239
- β”‚ 3. Issue created
240
- β”‚ POST /webhooks/incoming/sub_123
241
- β”‚
242
- β–Ό
243
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
244
- β”‚ MCP Server β”‚
245
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
246
- β”‚
247
- β”‚ 4. Send MCP notification
248
- β”‚ POST https://client.com/webhook
249
- β”‚ {
250
- β”‚ "jsonrpc": "2.0",
251
- β”‚ "method": "notifications/resources/updated",
252
- β”‚ "params": { ... }
253
- β”‚ }
254
- β”‚
255
- β–Ό
256
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
257
- β”‚ Client β”‚
258
- β”‚ Receives β”‚
259
- β”‚Notification β”‚
260
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
261
- ```
262
-
263
- ## πŸ” Security
264
-
265
- ### Signature Verification
266
-
267
- All notifications include HMAC signature:
268
-
269
- ```typescript
270
- const signature = headers['x-webhook-signature'];
271
- // Format: "sha256=<hmac_hex>"
272
-
273
- const hmac = crypto.createHmac('sha256', secret);
274
- hmac.update(JSON.stringify(payload));
275
- const expected = `sha256=${hmac.digest('hex')}`;
276
-
277
- if (signature !== expected) {
278
- throw new Error('Invalid signature');
279
- }
280
- ```
281
-
282
- ## πŸ“– Documentation
283
-
284
- - **Standard Subscriptions Guide**: `STANDARD_SUBSCRIPTIONS.md`
285
- - **GitHub Live Example**: `examples/github-server-live.ts`
286
- - **MCP Specification**: https://modelcontextprotocol.io/specification/2025-06-18/server/resources#subscriptions
287
-
288
- ## βœ… Checklist
289
-
290
- - [x] Standard `resources/subscribe` intercept
291
- - [x] Webhook URL via `_meta` parameter
292
- - [x] Standard MCP notification format (`notifications/resources/updated`)
293
- - [x] Backward compatible with custom endpoints
294
- - [x] Signature verification
295
- - [x] Retry logic with exponential backoff
296
- - [x] MCP Inspector compatible
297
- - [x] Documentation and examples
298
- - [x] Live GitHub integration tested
299
-
300
- ## πŸš€ Result
301
-
302
- You now have:
303
- 1. βœ… **Standard MCP compliance** - works with all MCP clients
304
- 2. βœ… **Webhook-based subscriptions** - no SSE needed
305
- 3. βœ… **Third-party integration** - GitHub, Slack, etc.
306
- 4. βœ… **Backward compatible** - existing code still works
307
- 5. βœ… **Production ready** - retry, security, monitoring
308
-
309
- **The best of both worlds: Standard MCP + Webhook Power! πŸŽ‰**