paygate-mcp 0.6.0 → 0.8.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 +177 -33
- package/dist/cli.d.ts +1 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +76 -39
- package/dist/cli.js.map +1 -1
- package/dist/gate.d.ts +30 -2
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +122 -17
- package/dist/gate.js.map +1 -1
- package/dist/http-proxy.d.ts.map +1 -1
- package/dist/http-proxy.js +13 -2
- package/dist/http-proxy.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +27 -5
- package/dist/proxy.js.map +1 -1
- package/dist/rate-limiter.d.ts +9 -0
- package/dist/rate-limiter.d.ts.map +1 -1
- package/dist/rate-limiter.js +36 -0
- package/dist/rate-limiter.js.map +1 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +137 -33
- package/dist/server.js.map +1 -1
- package/dist/store.d.ts +35 -38
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +92 -108
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +12 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/dist/webhook.d.ts +21 -0
- package/dist/webhook.d.ts.map +1 -0
- package/dist/webhook.js +89 -0
- package/dist/webhook.js.map +1 -0
- package/package.json +1 -1
package/dist/store.js
CHANGED
|
@@ -16,10 +16,6 @@ const path_1 = require("path");
|
|
|
16
16
|
class KeyStore {
|
|
17
17
|
keys = new Map();
|
|
18
18
|
statePath;
|
|
19
|
-
/** Daily spend tracking per key. Key → SpendingWindow */
|
|
20
|
-
dailySpend = new Map();
|
|
21
|
-
/** Monthly spend tracking per key. Key → SpendingWindow */
|
|
22
|
-
monthlySpend = new Map();
|
|
23
19
|
constructor(statePath) {
|
|
24
20
|
this.statePath = statePath || null;
|
|
25
21
|
if (this.statePath) {
|
|
@@ -39,10 +35,21 @@ class KeyStore {
|
|
|
39
35
|
sanitizeName(name) {
|
|
40
36
|
return String(name).trim().slice(0, 200);
|
|
41
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Sanitize and validate tool list for ACL. Max 100 entries, trimmed.
|
|
40
|
+
*/
|
|
41
|
+
sanitizeToolList(tools) {
|
|
42
|
+
if (!tools || !Array.isArray(tools))
|
|
43
|
+
return [];
|
|
44
|
+
return tools
|
|
45
|
+
.filter(t => typeof t === 'string' && t.trim().length > 0)
|
|
46
|
+
.map(t => t.trim())
|
|
47
|
+
.slice(0, 100);
|
|
48
|
+
}
|
|
42
49
|
/**
|
|
43
50
|
* Create a new API key with initial credits.
|
|
44
51
|
*/
|
|
45
|
-
createKey(name, initialCredits) {
|
|
52
|
+
createKey(name, initialCredits, options) {
|
|
46
53
|
const key = `pg_${(0, crypto_1.randomBytes)(24).toString('hex')}`;
|
|
47
54
|
const record = {
|
|
48
55
|
key,
|
|
@@ -53,20 +60,52 @@ class KeyStore {
|
|
|
53
60
|
createdAt: new Date().toISOString(),
|
|
54
61
|
lastUsedAt: null,
|
|
55
62
|
active: true,
|
|
63
|
+
spendingLimit: 0,
|
|
64
|
+
allowedTools: this.sanitizeToolList(options?.allowedTools),
|
|
65
|
+
deniedTools: this.sanitizeToolList(options?.deniedTools),
|
|
66
|
+
expiresAt: options?.expiresAt || null,
|
|
56
67
|
};
|
|
57
68
|
this.keys.set(key, record);
|
|
58
69
|
this.save();
|
|
59
70
|
return record;
|
|
60
71
|
}
|
|
61
72
|
/**
|
|
62
|
-
* Look up an API key. Returns null if not found or
|
|
73
|
+
* Look up an API key. Returns null if not found, inactive, or expired.
|
|
63
74
|
*/
|
|
64
75
|
getKey(key) {
|
|
65
76
|
const record = this.keys.get(key);
|
|
66
77
|
if (!record || !record.active)
|
|
67
78
|
return null;
|
|
79
|
+
// Check expiry
|
|
80
|
+
if (record.expiresAt) {
|
|
81
|
+
const expiresAt = new Date(record.expiresAt).getTime();
|
|
82
|
+
if (!isNaN(expiresAt) && Date.now() >= expiresAt) {
|
|
83
|
+
return null; // Expired
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return record;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Look up key without expiry check (for admin operations on expired keys).
|
|
90
|
+
*/
|
|
91
|
+
getKeyRaw(key) {
|
|
92
|
+
const record = this.keys.get(key);
|
|
93
|
+
if (!record)
|
|
94
|
+
return null;
|
|
68
95
|
return record;
|
|
69
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Check if a key is expired (not inactive, specifically expired).
|
|
99
|
+
*/
|
|
100
|
+
isExpired(key) {
|
|
101
|
+
const record = this.keys.get(key);
|
|
102
|
+
if (!record)
|
|
103
|
+
return false;
|
|
104
|
+
if (!record.expiresAt)
|
|
105
|
+
return false;
|
|
106
|
+
const expiresAt = new Date(record.expiresAt).getTime();
|
|
107
|
+
return !isNaN(expiresAt) && Date.now() >= expiresAt;
|
|
108
|
+
}
|
|
70
109
|
/**
|
|
71
110
|
* Check if key has enough credits. Does NOT deduct.
|
|
72
111
|
*/
|
|
@@ -105,6 +144,33 @@ class KeyStore {
|
|
|
105
144
|
this.save();
|
|
106
145
|
return true;
|
|
107
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Set tool ACL for a key. allowedTools = whitelist, deniedTools = blacklist.
|
|
149
|
+
*/
|
|
150
|
+
setAcl(key, allowedTools, deniedTools) {
|
|
151
|
+
const record = this.getKey(key);
|
|
152
|
+
if (!record)
|
|
153
|
+
return false;
|
|
154
|
+
if (allowedTools !== undefined) {
|
|
155
|
+
record.allowedTools = this.sanitizeToolList(allowedTools);
|
|
156
|
+
}
|
|
157
|
+
if (deniedTools !== undefined) {
|
|
158
|
+
record.deniedTools = this.sanitizeToolList(deniedTools);
|
|
159
|
+
}
|
|
160
|
+
this.save();
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Set expiry for a key. Null = never expires.
|
|
165
|
+
*/
|
|
166
|
+
setExpiry(key, expiresAt) {
|
|
167
|
+
const record = this.getKeyRaw(key);
|
|
168
|
+
if (!record)
|
|
169
|
+
return false;
|
|
170
|
+
record.expiresAt = expiresAt;
|
|
171
|
+
this.save();
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
108
174
|
/**
|
|
109
175
|
* Revoke an API key.
|
|
110
176
|
*/
|
|
@@ -117,13 +183,17 @@ class KeyStore {
|
|
|
117
183
|
return true;
|
|
118
184
|
}
|
|
119
185
|
/**
|
|
120
|
-
* List all keys (with key values masked).
|
|
186
|
+
* List all keys (with key values masked). Includes expiry status.
|
|
121
187
|
*/
|
|
122
188
|
listKeys() {
|
|
123
189
|
const result = [];
|
|
124
190
|
for (const record of this.keys.values()) {
|
|
125
191
|
const { key, ...rest } = record;
|
|
126
|
-
result.push({
|
|
192
|
+
result.push({
|
|
193
|
+
...rest,
|
|
194
|
+
keyPrefix: key.slice(0, 10) + '...',
|
|
195
|
+
expired: this.isExpired(key),
|
|
196
|
+
});
|
|
127
197
|
}
|
|
128
198
|
return result;
|
|
129
199
|
}
|
|
@@ -141,7 +211,7 @@ class KeyStore {
|
|
|
141
211
|
/**
|
|
142
212
|
* Import a key directly (for config file loading).
|
|
143
213
|
*/
|
|
144
|
-
importKey(key, name, credits) {
|
|
214
|
+
importKey(key, name, credits, options) {
|
|
145
215
|
const record = {
|
|
146
216
|
key,
|
|
147
217
|
name: this.sanitizeName(name),
|
|
@@ -151,110 +221,15 @@ class KeyStore {
|
|
|
151
221
|
createdAt: new Date().toISOString(),
|
|
152
222
|
lastUsedAt: null,
|
|
153
223
|
active: true,
|
|
224
|
+
spendingLimit: 0,
|
|
225
|
+
allowedTools: this.sanitizeToolList(options?.allowedTools),
|
|
226
|
+
deniedTools: this.sanitizeToolList(options?.deniedTools),
|
|
227
|
+
expiresAt: options?.expiresAt || null,
|
|
154
228
|
};
|
|
155
229
|
this.keys.set(key, record);
|
|
156
230
|
this.save();
|
|
157
231
|
return record;
|
|
158
232
|
}
|
|
159
|
-
// ─── Spending Limits ────────────────────────────────────────────────────────────
|
|
160
|
-
/**
|
|
161
|
-
* Set spending limits for a key.
|
|
162
|
-
*/
|
|
163
|
-
setSpendingLimits(key, limits) {
|
|
164
|
-
const record = this.keys.get(key);
|
|
165
|
-
if (!record)
|
|
166
|
-
return false;
|
|
167
|
-
record.spendingLimits = {
|
|
168
|
-
dailyCredits: Math.max(0, Math.floor(limits.dailyCredits)),
|
|
169
|
-
monthlyCredits: Math.max(0, Math.floor(limits.monthlyCredits)),
|
|
170
|
-
};
|
|
171
|
-
this.save();
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Get spending limits for a key. Returns null if key not found.
|
|
176
|
-
*/
|
|
177
|
-
getSpendingLimits(key) {
|
|
178
|
-
const record = this.getKey(key);
|
|
179
|
-
if (!record)
|
|
180
|
-
return null;
|
|
181
|
-
return record.spendingLimits || null;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Check if a spend of `amount` would exceed daily or monthly limits.
|
|
185
|
-
* Returns { allowed: true } or { allowed: false, reason: string }.
|
|
186
|
-
*/
|
|
187
|
-
checkSpendingLimits(key, amount) {
|
|
188
|
-
const record = this.getKey(key);
|
|
189
|
-
if (!record || !record.spendingLimits)
|
|
190
|
-
return { allowed: true };
|
|
191
|
-
const limits = record.spendingLimits;
|
|
192
|
-
const now = new Date();
|
|
193
|
-
const dayKey = now.toISOString().slice(0, 10); // "2025-06-15"
|
|
194
|
-
const monthKey = now.toISOString().slice(0, 7); // "2025-06"
|
|
195
|
-
// Check daily limit
|
|
196
|
-
if (limits.dailyCredits > 0) {
|
|
197
|
-
const daily = this.dailySpend.get(key);
|
|
198
|
-
const currentDailySpend = (daily && daily.window === dayKey) ? daily.spent : 0;
|
|
199
|
-
if (currentDailySpend + amount > limits.dailyCredits) {
|
|
200
|
-
return {
|
|
201
|
-
allowed: false,
|
|
202
|
-
reason: `daily_limit_exceeded: spent ${currentDailySpend}/${limits.dailyCredits} today`,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
// Check monthly limit
|
|
207
|
-
if (limits.monthlyCredits > 0) {
|
|
208
|
-
const monthly = this.monthlySpend.get(key);
|
|
209
|
-
const currentMonthlySpend = (monthly && monthly.window === monthKey) ? monthly.spent : 0;
|
|
210
|
-
if (currentMonthlySpend + amount > limits.monthlyCredits) {
|
|
211
|
-
return {
|
|
212
|
-
allowed: false,
|
|
213
|
-
reason: `monthly_limit_exceeded: spent ${currentMonthlySpend}/${limits.monthlyCredits} this month`,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return { allowed: true };
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Record spending against daily and monthly windows.
|
|
221
|
-
* Called after a successful tool call deduction.
|
|
222
|
-
*/
|
|
223
|
-
recordSpending(key, amount) {
|
|
224
|
-
const now = new Date();
|
|
225
|
-
const dayKey = now.toISOString().slice(0, 10);
|
|
226
|
-
const monthKey = now.toISOString().slice(0, 7);
|
|
227
|
-
// Update daily
|
|
228
|
-
const daily = this.dailySpend.get(key);
|
|
229
|
-
if (daily && daily.window === dayKey) {
|
|
230
|
-
daily.spent += amount;
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
this.dailySpend.set(key, { window: dayKey, spent: amount });
|
|
234
|
-
}
|
|
235
|
-
// Update monthly
|
|
236
|
-
const monthly = this.monthlySpend.get(key);
|
|
237
|
-
if (monthly && monthly.window === monthKey) {
|
|
238
|
-
monthly.spent += amount;
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
this.monthlySpend.set(key, { window: monthKey, spent: amount });
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Get current daily and monthly spend for a key.
|
|
246
|
-
*/
|
|
247
|
-
getSpending(key) {
|
|
248
|
-
const now = new Date();
|
|
249
|
-
const dayKey = now.toISOString().slice(0, 10);
|
|
250
|
-
const monthKey = now.toISOString().slice(0, 7);
|
|
251
|
-
const daily = this.dailySpend.get(key);
|
|
252
|
-
const monthly = this.monthlySpend.get(key);
|
|
253
|
-
return {
|
|
254
|
-
daily: (daily && daily.window === dayKey) ? daily.spent : 0,
|
|
255
|
-
monthly: (monthly && monthly.window === monthKey) ? monthly.spent : 0,
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
233
|
// ─── Persistence ──────────────────────────────────────────────────────────────
|
|
259
234
|
/**
|
|
260
235
|
* Save state to disk (atomic: write tmp, then rename).
|
|
@@ -291,6 +266,15 @@ class KeyStore {
|
|
|
291
266
|
}
|
|
292
267
|
for (const [key, record] of data) {
|
|
293
268
|
if (key && record && typeof record.key === 'string') {
|
|
269
|
+
// Backfill fields for old state files
|
|
270
|
+
if (record.spendingLimit === undefined)
|
|
271
|
+
record.spendingLimit = 0;
|
|
272
|
+
if (!Array.isArray(record.allowedTools))
|
|
273
|
+
record.allowedTools = [];
|
|
274
|
+
if (!Array.isArray(record.deniedTools))
|
|
275
|
+
record.deniedTools = [];
|
|
276
|
+
if (record.expiresAt === undefined)
|
|
277
|
+
record.expiresAt = null;
|
|
294
278
|
this.keys.set(key, record);
|
|
295
279
|
}
|
|
296
280
|
}
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,mCAAqC;AACrC,2BAAoF;AACpF,+BAAqC;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -52,14 +52,12 @@ export interface PayGateConfig {
|
|
|
52
52
|
freeMethods: string[];
|
|
53
53
|
/** Whether to log all calls (shadow mode) without enforcing payment */
|
|
54
54
|
shadowMode: boolean;
|
|
55
|
+
/** Webhook URL to POST usage events to. Null = disabled. */
|
|
56
|
+
webhookUrl: string | null;
|
|
57
|
+
/** Refund credits when downstream tool call fails. Default: false. */
|
|
58
|
+
refundOnFailure: boolean;
|
|
55
59
|
}
|
|
56
60
|
export declare const DEFAULT_CONFIG: PayGateConfig;
|
|
57
|
-
export interface SpendingLimits {
|
|
58
|
-
/** Max credits per calendar day (UTC). 0 = unlimited. */
|
|
59
|
-
dailyCredits: number;
|
|
60
|
-
/** Max credits per calendar month (UTC). 0 = unlimited. */
|
|
61
|
-
monthlyCredits: number;
|
|
62
|
-
}
|
|
63
61
|
export interface ApiKeyRecord {
|
|
64
62
|
key: string;
|
|
65
63
|
name: string;
|
|
@@ -69,8 +67,14 @@ export interface ApiKeyRecord {
|
|
|
69
67
|
createdAt: string;
|
|
70
68
|
lastUsedAt: string | null;
|
|
71
69
|
active: boolean;
|
|
72
|
-
/**
|
|
73
|
-
|
|
70
|
+
/** Max total credits this key can ever spend. 0 = unlimited. */
|
|
71
|
+
spendingLimit: number;
|
|
72
|
+
/** Whitelist: only these tools are accessible. Empty array = all tools allowed. */
|
|
73
|
+
allowedTools: string[];
|
|
74
|
+
/** Blacklist: these tools are always denied. Applied after allowedTools filter. */
|
|
75
|
+
deniedTools: string[];
|
|
76
|
+
/** ISO date string when this key expires. Null = never expires. */
|
|
77
|
+
expiresAt: string | null;
|
|
74
78
|
}
|
|
75
79
|
export interface UsageEvent {
|
|
76
80
|
timestamp: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAID,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC,gEAAgE;IAChE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uEAAuE;IACvE,UAAU,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAID,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC,gEAAgE;IAChE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uEAAuE;IACvE,UAAU,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,sEAAsE;IACtE,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,cAAc,EAAE,aAY5B,CAAC;AAIF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mFAAmF;IACnF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAID,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAID,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B"}
|
package/dist/types.js
CHANGED
|
@@ -14,5 +14,7 @@ exports.DEFAULT_CONFIG = {
|
|
|
14
14
|
globalRateLimitPerMin: 60,
|
|
15
15
|
freeMethods: ['initialize', 'initialized', 'ping', 'notifications/initialized', 'tools/list', 'resources/list', 'prompts/list'],
|
|
16
16
|
shadowMode: false,
|
|
17
|
+
webhookUrl: null,
|
|
18
|
+
refundOnFailure: false,
|
|
17
19
|
};
|
|
18
20
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG;;;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAuEU,QAAA,cAAc,GAAkB;IAC3C,IAAI,EAAE,oBAAoB;IAC1B,aAAa,EAAE,EAAE;IACjB,UAAU,EAAE,EAAE;IACd,IAAI,EAAE,IAAI;IACV,qBAAqB,EAAE,CAAC;IACxB,WAAW,EAAE,EAAE;IACf,qBAAqB,EAAE,EAAE;IACzB,WAAW,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,2BAA2B,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,CAAC;IAC/H,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,IAAI;IAChB,eAAe,EAAE,KAAK;CACvB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook — Fire-and-forget HTTP POST of usage events to an external URL.
|
|
3
|
+
*
|
|
4
|
+
* Events are batched (max 10, flush every 5s) to reduce overhead.
|
|
5
|
+
* Failed deliveries are retried once, then dropped (no queue bloat).
|
|
6
|
+
*/
|
|
7
|
+
import { UsageEvent } from './types';
|
|
8
|
+
export declare class WebhookEmitter {
|
|
9
|
+
private readonly url;
|
|
10
|
+
private readonly isHttps;
|
|
11
|
+
private buffer;
|
|
12
|
+
private timer;
|
|
13
|
+
private readonly batchSize;
|
|
14
|
+
private readonly flushIntervalMs;
|
|
15
|
+
constructor(url: string, batchSize?: number, flushIntervalMs?: number);
|
|
16
|
+
emit(event: UsageEvent): void;
|
|
17
|
+
flush(): void;
|
|
18
|
+
private send;
|
|
19
|
+
destroy(): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,GAAG,EAAE,MAAM,EAAE,SAAS,SAAK,EAAE,eAAe,SAAO;IAU/D,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAO7B,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,IAAI;IA4CZ,OAAO,IAAI,IAAI;CAOhB"}
|
package/dist/webhook.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Webhook — Fire-and-forget HTTP POST of usage events to an external URL.
|
|
4
|
+
*
|
|
5
|
+
* Events are batched (max 10, flush every 5s) to reduce overhead.
|
|
6
|
+
* Failed deliveries are retried once, then dropped (no queue bloat).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.WebhookEmitter = void 0;
|
|
10
|
+
const http_1 = require("http");
|
|
11
|
+
const https_1 = require("https");
|
|
12
|
+
class WebhookEmitter {
|
|
13
|
+
url;
|
|
14
|
+
isHttps;
|
|
15
|
+
buffer = [];
|
|
16
|
+
timer = null;
|
|
17
|
+
batchSize;
|
|
18
|
+
flushIntervalMs;
|
|
19
|
+
constructor(url, batchSize = 10, flushIntervalMs = 5000) {
|
|
20
|
+
this.url = url;
|
|
21
|
+
this.isHttps = url.startsWith('https://');
|
|
22
|
+
this.batchSize = batchSize;
|
|
23
|
+
this.flushIntervalMs = flushIntervalMs;
|
|
24
|
+
this.timer = setInterval(() => this.flush(), this.flushIntervalMs);
|
|
25
|
+
if (this.timer.unref)
|
|
26
|
+
this.timer.unref(); // Don't block process exit
|
|
27
|
+
}
|
|
28
|
+
emit(event) {
|
|
29
|
+
this.buffer.push(event);
|
|
30
|
+
if (this.buffer.length >= this.batchSize) {
|
|
31
|
+
this.flush();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
flush() {
|
|
35
|
+
if (this.buffer.length === 0)
|
|
36
|
+
return;
|
|
37
|
+
const batch = this.buffer.splice(0, this.batchSize);
|
|
38
|
+
this.send(batch, 1);
|
|
39
|
+
}
|
|
40
|
+
send(events, retriesLeft) {
|
|
41
|
+
const body = JSON.stringify({ events, sentAt: new Date().toISOString() });
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = new URL(this.url);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Invalid URL — drop silently (don't crash the server)
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const reqFn = this.isHttps ? https_1.request : http_1.request;
|
|
51
|
+
const req = reqFn({
|
|
52
|
+
hostname: parsed.hostname,
|
|
53
|
+
port: parsed.port || (this.isHttps ? 443 : 80),
|
|
54
|
+
path: parsed.pathname + parsed.search,
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: {
|
|
57
|
+
'Content-Type': 'application/json',
|
|
58
|
+
'Content-Length': Buffer.byteLength(body),
|
|
59
|
+
'User-Agent': 'paygate-mcp-webhook/1.0',
|
|
60
|
+
},
|
|
61
|
+
timeout: 10_000,
|
|
62
|
+
}, (res) => {
|
|
63
|
+
// Drain response to free socket
|
|
64
|
+
res.resume();
|
|
65
|
+
if (res.statusCode && res.statusCode >= 400 && retriesLeft > 0) {
|
|
66
|
+
setTimeout(() => this.send(events, retriesLeft - 1), 2000);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
req.on('error', () => {
|
|
70
|
+
if (retriesLeft > 0) {
|
|
71
|
+
setTimeout(() => this.send(events, retriesLeft - 1), 2000);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
req.on('timeout', () => {
|
|
75
|
+
req.destroy();
|
|
76
|
+
});
|
|
77
|
+
req.write(body);
|
|
78
|
+
req.end();
|
|
79
|
+
}
|
|
80
|
+
destroy() {
|
|
81
|
+
if (this.timer) {
|
|
82
|
+
clearInterval(this.timer);
|
|
83
|
+
this.timer = null;
|
|
84
|
+
}
|
|
85
|
+
this.flush(); // Send remaining events
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.WebhookEmitter = WebhookEmitter;
|
|
89
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paygate-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Pay-per-tool-call gating proxy for MCP servers. Wrap any MCP server with API key auth, per-tool pricing, rate limiting, and usage metering.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|