mcp-http-webhook 1.0.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.
Files changed (80) hide show
  1. package/.eslintrc.json +16 -0
  2. package/.prettierrc.json +8 -0
  3. package/ARCHITECTURE.md +269 -0
  4. package/CONTRIBUTING.md +136 -0
  5. package/GETTING_STARTED.md +310 -0
  6. package/IMPLEMENTATION.md +294 -0
  7. package/LICENSE +21 -0
  8. package/MIGRATION_TO_SDK.md +263 -0
  9. package/README.md +496 -0
  10. package/SDK_INTEGRATION_COMPLETE.md +300 -0
  11. package/STANDARD_SUBSCRIPTIONS.md +268 -0
  12. package/STANDARD_SUBSCRIPTIONS_COMPLETE.md +309 -0
  13. package/SUMMARY.md +272 -0
  14. package/Spec.md +2778 -0
  15. package/dist/errors/index.d.ts +52 -0
  16. package/dist/errors/index.d.ts.map +1 -0
  17. package/dist/errors/index.js +81 -0
  18. package/dist/errors/index.js.map +1 -0
  19. package/dist/index.d.ts +9 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +37 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/protocol/ProtocolHandler.d.ts +37 -0
  24. package/dist/protocol/ProtocolHandler.d.ts.map +1 -0
  25. package/dist/protocol/ProtocolHandler.js +172 -0
  26. package/dist/protocol/ProtocolHandler.js.map +1 -0
  27. package/dist/server.d.ts +6 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +502 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/stores/InMemoryStore.d.ts +27 -0
  32. package/dist/stores/InMemoryStore.d.ts.map +1 -0
  33. package/dist/stores/InMemoryStore.js +73 -0
  34. package/dist/stores/InMemoryStore.js.map +1 -0
  35. package/dist/stores/RedisStore.d.ts +18 -0
  36. package/dist/stores/RedisStore.d.ts.map +1 -0
  37. package/dist/stores/RedisStore.js +45 -0
  38. package/dist/stores/RedisStore.js.map +1 -0
  39. package/dist/stores/index.d.ts +3 -0
  40. package/dist/stores/index.d.ts.map +1 -0
  41. package/dist/stores/index.js +9 -0
  42. package/dist/stores/index.js.map +1 -0
  43. package/dist/subscriptions/SubscriptionManager.d.ts +49 -0
  44. package/dist/subscriptions/SubscriptionManager.d.ts.map +1 -0
  45. package/dist/subscriptions/SubscriptionManager.js +181 -0
  46. package/dist/subscriptions/SubscriptionManager.js.map +1 -0
  47. package/dist/types/index.d.ts +271 -0
  48. package/dist/types/index.d.ts.map +1 -0
  49. package/dist/types/index.js +16 -0
  50. package/dist/types/index.js.map +1 -0
  51. package/dist/utils/index.d.ts +51 -0
  52. package/dist/utils/index.d.ts.map +1 -0
  53. package/dist/utils/index.js +154 -0
  54. package/dist/utils/index.js.map +1 -0
  55. package/dist/webhooks/WebhookManager.d.ts +27 -0
  56. package/dist/webhooks/WebhookManager.d.ts.map +1 -0
  57. package/dist/webhooks/WebhookManager.js +174 -0
  58. package/dist/webhooks/WebhookManager.js.map +1 -0
  59. package/examples/GITHUB_LIVE_EXAMPLE.md +308 -0
  60. package/examples/GITHUB_LIVE_SETUP.md +253 -0
  61. package/examples/QUICKSTART.md +130 -0
  62. package/examples/basic-setup.ts +142 -0
  63. package/examples/github-server-live.ts +690 -0
  64. package/examples/github-server.ts +223 -0
  65. package/examples/google-drive-server-live.ts +773 -0
  66. package/examples/start-github-live.sh +53 -0
  67. package/jest.config.js +20 -0
  68. package/package.json +58 -0
  69. package/src/errors/index.ts +81 -0
  70. package/src/index.ts +19 -0
  71. package/src/server.ts +595 -0
  72. package/src/stores/InMemoryStore.ts +87 -0
  73. package/src/stores/RedisStore.ts +51 -0
  74. package/src/stores/index.ts +2 -0
  75. package/src/subscriptions/SubscriptionManager.ts +240 -0
  76. package/src/types/index.ts +341 -0
  77. package/src/utils/index.ts +156 -0
  78. package/src/webhooks/WebhookManager.ts +230 -0
  79. package/test-sdk-integration.sh +157 -0
  80. package/tsconfig.json +21 -0
@@ -0,0 +1,223 @@
1
+ import { createMCPServer } from '../src';
2
+ import { InMemoryStore } from '../src/stores';
3
+ import crypto from 'crypto';
4
+
5
+ /**
6
+ * GitHub MCP Server Example
7
+ * Demonstrates webhook-based subscriptions
8
+ */
9
+
10
+ const store = new InMemoryStore();
11
+
12
+ const server = createMCPServer({
13
+ name: 'github-mcp',
14
+ version: '1.0.0',
15
+ publicUrl: process.env.PUBLIC_URL || 'https://mcp.example.com',
16
+ port: 3000,
17
+ store,
18
+
19
+ tools: [
20
+ {
21
+ name: 'create_issue',
22
+ description: 'Create a GitHub issue',
23
+ inputSchema: {
24
+ type: 'object',
25
+ properties: {
26
+ owner: { type: 'string', description: 'Repository owner' },
27
+ repo: { type: 'string', description: 'Repository name' },
28
+ title: { type: 'string', description: 'Issue title' },
29
+ body: { type: 'string', description: 'Issue body' },
30
+ },
31
+ required: ['owner', 'repo', 'title'],
32
+ },
33
+ handler: async (input, context) => {
34
+ // Simulate GitHub API call
35
+ console.log('Creating issue:', input);
36
+
37
+ return {
38
+ issue: {
39
+ number: 42,
40
+ title: input.title,
41
+ state: 'open',
42
+ html_url: `https://github.com/${input.owner}/${input.repo}/issues/42`,
43
+ },
44
+ };
45
+ },
46
+ },
47
+ ],
48
+
49
+ resources: [
50
+ {
51
+ uri: 'github://repo/{owner}/{repo}/issues',
52
+ name: 'GitHub Repository Issues',
53
+ description: 'All issues in a GitHub repository',
54
+ mimeType: 'application/json',
55
+
56
+ read: async (uri, context) => {
57
+ const parts = uri.split('/');
58
+ const owner = parts[3];
59
+ const repo = parts[4];
60
+
61
+ console.log(`Reading issues for ${owner}/${repo}`);
62
+
63
+ // Simulate GitHub API call
64
+ return {
65
+ contents: [
66
+ {
67
+ number: 1,
68
+ title: 'Example issue',
69
+ state: 'open',
70
+ },
71
+ ],
72
+ };
73
+ },
74
+
75
+ list: async (context) => {
76
+ return [
77
+ {
78
+ uri: 'github://repo/octocat/hello-world/issues',
79
+ name: 'octocat/hello-world Issues',
80
+ description: 'Issues for hello-world repository',
81
+ },
82
+ ];
83
+ },
84
+
85
+ subscription: {
86
+ onSubscribe: async (uri, subscriptionId, thirdPartyWebhookUrl, context) => {
87
+ console.log('Subscribing to:', uri);
88
+ console.log('Third-party webhook URL:', thirdPartyWebhookUrl);
89
+
90
+ // In production, this would:
91
+ // 1. Call GitHub API to create webhook
92
+ // 2. Store webhook ID
93
+ // Example:
94
+ // const webhook = await octokit.repos.createWebhook({
95
+ // owner,
96
+ // repo,
97
+ // config: {
98
+ // url: thirdPartyWebhookUrl,
99
+ // content_type: 'json',
100
+ // secret: process.env.GITHUB_WEBHOOK_SECRET
101
+ // },
102
+ // events: ['issues']
103
+ // });
104
+
105
+ return {
106
+ thirdPartyWebhookId: 'webhook_123',
107
+ metadata: {
108
+ owner: 'octocat',
109
+ repo: 'hello-world',
110
+ },
111
+ };
112
+ },
113
+
114
+ onUnsubscribe: async (uri, subscriptionId, storedData, context) => {
115
+ console.log('Unsubscribing from:', uri);
116
+ console.log('Removing webhook:', storedData.thirdPartyWebhookId);
117
+
118
+ // In production, this would:
119
+ // await octokit.repos.deleteWebhook({
120
+ // owner,
121
+ // repo,
122
+ // hook_id: storedData.thirdPartyWebhookId
123
+ // });
124
+ },
125
+
126
+ onWebhook: async (subscriptionId, payload, headers) => {
127
+ console.log('Received GitHub webhook:', subscriptionId);
128
+
129
+ // Verify signature
130
+ const signature = headers['x-hub-signature-256'];
131
+ if (signature) {
132
+ // Verification logic here
133
+ }
134
+
135
+ const event = headers['x-github-event'];
136
+
137
+ if (event === 'issues') {
138
+ const { action, issue, repository } = payload;
139
+
140
+ if (['opened', 'edited', 'closed'].includes(action)) {
141
+ return {
142
+ resourceUri: `github://repo/${repository.owner.login}/${repository.name}/issues`,
143
+ changeType: action === 'opened' ? 'created' : action === 'closed' ? 'deleted' : 'updated',
144
+ data: {
145
+ issueNumber: issue.number,
146
+ title: issue.title,
147
+ state: issue.state,
148
+ action,
149
+ },
150
+ };
151
+ }
152
+ }
153
+
154
+ return null;
155
+ },
156
+ },
157
+ },
158
+ ],
159
+
160
+ webhooks: {
161
+ incomingPath: '/webhooks/incoming',
162
+ incomingSecret: process.env.GITHUB_WEBHOOK_SECRET,
163
+
164
+ verifyIncomingSignature: (payload, signature, secret) => {
165
+ const hmac = crypto.createHmac('sha256', secret);
166
+ hmac.update(JSON.stringify(payload));
167
+ const expected = `sha256=${hmac.digest('hex')}`;
168
+ return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
169
+ },
170
+
171
+ outgoing: {
172
+ timeout: 5000,
173
+ retries: 3,
174
+ retryDelay: 1000,
175
+
176
+ signPayload: (payload, secret) => {
177
+ const hmac = crypto.createHmac('sha256', secret);
178
+ hmac.update(JSON.stringify(payload));
179
+ return `sha256=${hmac.digest('hex')}`;
180
+ },
181
+ },
182
+ },
183
+
184
+ authenticate: async (req) => {
185
+ const token = req.headers.authorization?.replace('Bearer ', '');
186
+ if (!token) {
187
+ throw new Error('Missing authorization token');
188
+ }
189
+
190
+ // In production, verify JWT token
191
+ return {
192
+ userId: 'user-123',
193
+ githubToken: token,
194
+ };
195
+ },
196
+
197
+ logLevel: 'debug',
198
+ });
199
+
200
+ server.start().then(() => {
201
+ console.log('GitHub MCP Server running!');
202
+ console.log('');
203
+ console.log('Subscribe to issues:');
204
+ console.log('POST http://localhost:3000/mcp/resources/subscribe');
205
+ console.log(' Body:');
206
+ console.log(' {');
207
+ console.log(' "method": "resources/subscribe",');
208
+ console.log(' "params": {');
209
+ console.log(' "uri": "github://repo/octocat/hello-world/issues",');
210
+ console.log(' "callbackUrl": "https://client.example.com/webhook",');
211
+ console.log(' "callbackSecret": "client-secret"');
212
+ console.log(' }');
213
+ console.log(' }');
214
+ console.log('');
215
+ console.log('Webhook endpoint:');
216
+ console.log(`${process.env.PUBLIC_URL}/webhooks/incoming/{subscriptionId}`);
217
+ });
218
+
219
+ process.on('SIGTERM', async () => {
220
+ await server.stop();
221
+ store.destroy();
222
+ process.exit(0);
223
+ });