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 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAuBtF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAOvE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,QAAQ,GAAG,MAAiB,GACtC,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,QAAQ,GAAG,MAAiB,GACtC,OAAO,CAOT;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateSubscriptionId = generateSubscriptionId;
7
+ exports.generateWebhookUrl = generateWebhookUrl;
8
+ exports.parseUriTemplate = parseUriTemplate;
9
+ exports.matchUriTemplate = matchUriTemplate;
10
+ exports.createHmacSignature = createHmacSignature;
11
+ exports.verifyHmacSignature = verifyHmacSignature;
12
+ exports.sleep = sleep;
13
+ exports.calculateBackoff = calculateBackoff;
14
+ exports.sanitizeUrl = sanitizeUrl;
15
+ exports.extractErrorMessage = extractErrorMessage;
16
+ exports.isValidUrl = isValidUrl;
17
+ exports.isHttpsUrl = isHttpsUrl;
18
+ const crypto_1 = __importDefault(require("crypto"));
19
+ const nanoid_1 = require("nanoid");
20
+ /**
21
+ * Generate a unique subscription ID
22
+ */
23
+ function generateSubscriptionId() {
24
+ return `sub_${(0, nanoid_1.nanoid)(16)}`;
25
+ }
26
+ /**
27
+ * Generate webhook URL for third-party services
28
+ */
29
+ function generateWebhookUrl(publicUrl, subscriptionId) {
30
+ const baseUrl = publicUrl.endsWith('/') ? publicUrl.slice(0, -1) : publicUrl;
31
+ return `${baseUrl}/webhooks/incoming/${subscriptionId}`;
32
+ }
33
+ /**
34
+ * Parse URI template
35
+ * Example: parseUriTemplate('github://repo/{owner}/{repo}', 'github://repo/octocat/hello')
36
+ * Returns: { owner: 'octocat', repo: 'hello' }
37
+ */
38
+ function parseUriTemplate(template, uri) {
39
+ const templateParts = template.split('/');
40
+ const uriParts = uri.split('/');
41
+ if (templateParts.length !== uriParts.length) {
42
+ throw new Error(`URI ${uri} does not match template ${template}`);
43
+ }
44
+ const params = {};
45
+ for (let i = 0; i < templateParts.length; i++) {
46
+ const templatePart = templateParts[i];
47
+ const uriPart = uriParts[i];
48
+ if (templatePart.startsWith('{') && templatePart.endsWith('}')) {
49
+ const paramName = templatePart.slice(1, -1);
50
+ params[paramName] = uriPart;
51
+ }
52
+ else if (templatePart !== uriPart) {
53
+ throw new Error(`URI ${uri} does not match template ${template}`);
54
+ }
55
+ }
56
+ return params;
57
+ }
58
+ /**
59
+ * Match URI against template
60
+ */
61
+ function matchUriTemplate(template, uri) {
62
+ try {
63
+ parseUriTemplate(template, uri);
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ /**
71
+ * Create HMAC signature
72
+ */
73
+ function createHmacSignature(payload, secret, algorithm = 'sha256') {
74
+ const hmac = crypto_1.default.createHmac(algorithm, secret);
75
+ const data = typeof payload === 'string' ? payload : JSON.stringify(payload);
76
+ hmac.update(data);
77
+ return `${algorithm}=${hmac.digest('hex')}`;
78
+ }
79
+ /**
80
+ * Verify HMAC signature (timing-safe comparison)
81
+ */
82
+ function verifyHmacSignature(payload, signature, secret, algorithm = 'sha256') {
83
+ try {
84
+ const expected = createHmacSignature(payload, secret, algorithm);
85
+ return crypto_1.default.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
91
+ /**
92
+ * Sleep utility for retry delays
93
+ */
94
+ function sleep(ms) {
95
+ return new Promise((resolve) => setTimeout(resolve, ms));
96
+ }
97
+ /**
98
+ * Exponential backoff calculator
99
+ */
100
+ function calculateBackoff(attempt, baseDelay) {
101
+ return baseDelay * Math.pow(2, attempt);
102
+ }
103
+ /**
104
+ * Sanitize URL for logging (remove sensitive query params)
105
+ */
106
+ function sanitizeUrl(url) {
107
+ try {
108
+ const urlObj = new URL(url);
109
+ urlObj.searchParams.delete('token');
110
+ urlObj.searchParams.delete('secret');
111
+ urlObj.searchParams.delete('api_key');
112
+ return urlObj.toString();
113
+ }
114
+ catch {
115
+ return url;
116
+ }
117
+ }
118
+ /**
119
+ * Extract error message safely
120
+ */
121
+ function extractErrorMessage(error) {
122
+ if (error instanceof Error) {
123
+ return error.message;
124
+ }
125
+ if (typeof error === 'string') {
126
+ return error;
127
+ }
128
+ return 'Unknown error';
129
+ }
130
+ /**
131
+ * Validate URL format
132
+ */
133
+ function isValidUrl(url) {
134
+ try {
135
+ new URL(url);
136
+ return true;
137
+ }
138
+ catch {
139
+ return false;
140
+ }
141
+ }
142
+ /**
143
+ * Validate HTTPS URL
144
+ */
145
+ function isHttpsUrl(url) {
146
+ try {
147
+ const urlObj = new URL(url);
148
+ return urlObj.protocol === 'https:';
149
+ }
150
+ catch {
151
+ return false;
152
+ }
153
+ }
154
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { WebhookConfig, StoredSubscription, ResourceDefinition, WebhookChangeInfo, Logger } from '../types';
2
+ export declare class WebhookManager {
3
+ private config;
4
+ private resources;
5
+ private logger?;
6
+ private readonly timeout;
7
+ private readonly retries;
8
+ private readonly retryDelay;
9
+ constructor(config: WebhookConfig | undefined, resources: ResourceDefinition[], logger?: Logger | undefined);
10
+ /**
11
+ * Process incoming webhook from third-party service
12
+ */
13
+ processIncomingWebhook(subscriptionId: string, payload: any, headers: Record<string, string>, subscription: StoredSubscription): Promise<WebhookChangeInfo | null>;
14
+ /**
15
+ * Send notification to client webhook in standard MCP format
16
+ */
17
+ notifyClient(subscription: StoredSubscription, changeInfo: WebhookChangeInfo): Promise<void>;
18
+ /**
19
+ * Call webhook URL
20
+ */
21
+ private callWebhook;
22
+ /**
23
+ * Find resource by name
24
+ */
25
+ private findResourceByName;
26
+ }
27
+ //# sourceMappingURL=WebhookManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebhookManager.d.ts","sourceRoot":"","sources":["../../src/webhooks/WebhookManager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,MAAM,EACP,MAAM,UAAU,CAAC;AAIlB,qBAAa,cAAc;IAMvB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM,CAAC;IAPjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAG1B,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,SAAS,EAAE,kBAAkB,EAAE,EAC/B,MAAM,CAAC,EAAE,MAAM,YAAA;IAOzB;;OAEG;IACG,sBAAsB,CAC1B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAgDpC;;OAEG;IACG,YAAY,CAChB,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,iBAAiB,GAC5B,OAAO,CAAC,IAAI,CAAC;IAsFhB;;OAEG;YACW,WAAW;IA+CzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAG3B"}
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebhookManager = void 0;
4
+ const errors_1 = require("../errors");
5
+ const utils_1 = require("../utils");
6
+ class WebhookManager {
7
+ constructor(config, resources, logger) {
8
+ this.config = config;
9
+ this.resources = resources;
10
+ this.logger = logger;
11
+ this.timeout = config?.outgoing?.timeout ?? 5000;
12
+ this.retries = config?.outgoing?.retries ?? 3;
13
+ this.retryDelay = config?.outgoing?.retryDelay ?? 1000;
14
+ }
15
+ /**
16
+ * Process incoming webhook from third-party service
17
+ */
18
+ async processIncomingWebhook(subscriptionId, payload, headers, subscription) {
19
+ this.logger?.debug('Processing incoming webhook', {
20
+ subscriptionId,
21
+ resourceType: subscription.resourceType,
22
+ });
23
+ // Find resource definition
24
+ const resource = this.findResourceByName(subscription.resourceType);
25
+ if (!resource?.subscription) {
26
+ throw new errors_1.WebhookError('Resource subscription handler not found');
27
+ }
28
+ // Verify signature if configured
29
+ if (this.config?.verifyIncomingSignature) {
30
+ const signature = headers['x-hub-signature-256'] || headers['x-signature'];
31
+ if (signature && this.config.incomingSecret) {
32
+ const isValid = this.config.verifyIncomingSignature(payload, signature, this.config.incomingSecret);
33
+ if (!isValid) {
34
+ this.logger?.warn('Invalid webhook signature', { subscriptionId });
35
+ throw new errors_1.WebhookError('Invalid webhook signature');
36
+ }
37
+ }
38
+ }
39
+ try {
40
+ // Call resource's onWebhook handler
41
+ const changeInfo = await resource.subscription.onWebhook(subscriptionId, payload, headers);
42
+ this.logger?.debug('Webhook processed', {
43
+ subscriptionId,
44
+ changeType: changeInfo?.changeType,
45
+ });
46
+ return changeInfo;
47
+ }
48
+ catch (error) {
49
+ this.logger?.error('Failed to process webhook', {
50
+ subscriptionId,
51
+ error: (0, utils_1.extractErrorMessage)(error),
52
+ });
53
+ throw new errors_1.WebhookError('Failed to process webhook', { cause: error });
54
+ }
55
+ }
56
+ /**
57
+ * Send notification to client webhook in standard MCP format
58
+ */
59
+ async notifyClient(subscription, changeInfo) {
60
+ // Standard MCP notification format
61
+ const payload = {
62
+ jsonrpc: '2.0',
63
+ method: 'notifications/resources/updated',
64
+ params: {
65
+ uri: changeInfo.resourceUri,
66
+ title: changeInfo.data?.title,
67
+ _meta: {
68
+ changeType: changeInfo.changeType,
69
+ subscriptionId: subscription.uri,
70
+ timestamp: new Date().toISOString(),
71
+ ...changeInfo.data
72
+ }
73
+ }
74
+ };
75
+ this.logger?.info('Notifying client (MCP format)', {
76
+ url: subscription.clientCallbackUrl,
77
+ uri: changeInfo.resourceUri,
78
+ changeType: changeInfo.changeType,
79
+ });
80
+ // Sign payload if secret is provided
81
+ let signature;
82
+ if (subscription.clientCallbackSecret && this.config?.outgoing?.signPayload) {
83
+ signature = this.config.outgoing.signPayload(payload, subscription.clientCallbackSecret);
84
+ }
85
+ // Call before hook
86
+ this.config?.outgoing?.onBeforeCall?.(subscription.clientCallbackUrl, payload);
87
+ // Attempt delivery with retries
88
+ let lastError;
89
+ for (let attempt = 0; attempt < this.retries; attempt++) {
90
+ try {
91
+ const response = await this.callWebhook(subscription.clientCallbackUrl, payload, signature);
92
+ // Call after hook
93
+ this.config?.outgoing?.onAfterCall?.(subscription.clientCallbackUrl, response);
94
+ this.logger?.info('Client notified successfully (MCP format)', {
95
+ url: subscription.clientCallbackUrl,
96
+ attempt: attempt + 1,
97
+ });
98
+ return; // Success
99
+ }
100
+ catch (error) {
101
+ lastError = error instanceof Error ? error : new Error(String(error));
102
+ this.logger?.warn('Webhook delivery failed', {
103
+ url: subscription.clientCallbackUrl,
104
+ attempt: attempt + 1,
105
+ error: (0, utils_1.extractErrorMessage)(error),
106
+ });
107
+ // Don't retry on client errors (4xx)
108
+ if (error instanceof Error && 'status' in error) {
109
+ const status = error.status;
110
+ if (status >= 400 && status < 500) {
111
+ throw new errors_1.WebhookError('Client error, not retrying', { status });
112
+ }
113
+ }
114
+ // Wait before retry (exponential backoff)
115
+ if (attempt < this.retries - 1) {
116
+ const delay = (0, utils_1.calculateBackoff)(attempt, this.retryDelay);
117
+ await (0, utils_1.sleep)(delay);
118
+ }
119
+ }
120
+ }
121
+ // All retries failed
122
+ this.config?.outgoing?.onAfterCall?.(subscription.clientCallbackUrl, null, lastError);
123
+ throw new errors_1.WebhookError('Failed to notify client after all retries', {
124
+ attempts: this.retries,
125
+ lastError: (0, utils_1.extractErrorMessage)(lastError),
126
+ });
127
+ }
128
+ /**
129
+ * Call webhook URL
130
+ */
131
+ async callWebhook(url, payload, signature) {
132
+ const controller = new AbortController();
133
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
134
+ try {
135
+ const headers = {
136
+ 'Content-Type': 'application/json',
137
+ };
138
+ if (signature) {
139
+ headers['X-MCP-Signature'] = signature;
140
+ }
141
+ const response = await fetch(url, {
142
+ method: 'POST',
143
+ headers,
144
+ body: JSON.stringify(payload),
145
+ signal: controller.signal,
146
+ });
147
+ clearTimeout(timeoutId);
148
+ if (!response.ok) {
149
+ const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
150
+ error.status = response.status;
151
+ throw error;
152
+ }
153
+ return {
154
+ ok: true,
155
+ status: response.status,
156
+ };
157
+ }
158
+ catch (error) {
159
+ clearTimeout(timeoutId);
160
+ if (error instanceof Error && error.name === 'AbortError') {
161
+ throw new Error(`Request timeout after ${this.timeout}ms`);
162
+ }
163
+ throw error;
164
+ }
165
+ }
166
+ /**
167
+ * Find resource by name
168
+ */
169
+ findResourceByName(name) {
170
+ return this.resources.find((r) => r.name === name);
171
+ }
172
+ }
173
+ exports.WebhookManager = WebhookManager;
174
+ //# sourceMappingURL=WebhookManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebhookManager.js","sourceRoot":"","sources":["../../src/webhooks/WebhookManager.ts"],"names":[],"mappings":"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"}