paygate-mcp 8.34.0 → 8.36.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 +45 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +139 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -141,6 +141,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
141
141
|
- **Access Heatmap** — `GET /admin/access-heatmap` hourly access patterns with tool breakdown, unique consumers, and peak hour identification
|
|
142
142
|
- **Key Churn Analysis** — `GET /admin/key-churn` key churn metrics with creation/revocation rates, churn and retention percentages, and never-used key detection
|
|
143
143
|
- **Tool Correlation** — `GET /admin/tool-correlation` tool co-occurrence analysis showing which tools are commonly used together by the same consumers
|
|
144
|
+
- **Consumer Segmentation** — `GET /admin/consumer-segmentation` classifies API key consumers into power/regular/casual/dormant segments with per-segment metrics
|
|
145
|
+
- **Credit Distribution** — `GET /admin/credit-distribution` histogram of credit balances across active keys with bucket ranges and median calculation
|
|
144
146
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
145
147
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
146
148
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -3297,6 +3299,49 @@ curl http://localhost:3000/admin/tool-correlation -H "X-Admin-Key: YOUR_ADMIN_KE
|
|
|
3297
3299
|
|
|
3298
3300
|
Tool co-occurrence analysis showing which tools are commonly used together. `sharedConsumers` counts API keys that used both tools. `strength` is the percentage of all consumers who use the pair. Sorted by shared consumers descending. Helps identify tool bundles and usage patterns. Read-only.
|
|
3299
3301
|
|
|
3302
|
+
### Consumer Segmentation
|
|
3303
|
+
|
|
3304
|
+
```bash
|
|
3305
|
+
curl http://localhost:3000/admin/consumer-segmentation -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
3306
|
+
```
|
|
3307
|
+
|
|
3308
|
+
```json
|
|
3309
|
+
{
|
|
3310
|
+
"segments": [
|
|
3311
|
+
{ "segment": "power", "count": 3, "totalCredits": 500, "totalSpent": 2400, "avgCallsPerKey": 35 },
|
|
3312
|
+
{ "segment": "regular", "count": 8, "totalCredits": 1200, "totalSpent": 800, "avgCallsPerKey": 12 },
|
|
3313
|
+
{ "segment": "casual", "count": 15, "totalCredits": 3000, "totalSpent": 150, "avgCallsPerKey": 2 },
|
|
3314
|
+
{ "segment": "dormant", "count": 5, "totalCredits": 1000, "totalSpent": 0, "avgCallsPerKey": 0 }
|
|
3315
|
+
],
|
|
3316
|
+
"summary": { "totalConsumers": 31 },
|
|
3317
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
3318
|
+
}
|
|
3319
|
+
```
|
|
3320
|
+
|
|
3321
|
+
Classifies active API key consumers into segments based on usage: **power** (20+ calls), **regular** (5–19 calls), **casual** (1–4 calls), **dormant** (0 calls). Each segment includes aggregate metrics: count, total credits remaining, total spent, and average calls per key. Excludes revoked and suspended keys. Read-only.
|
|
3322
|
+
|
|
3323
|
+
### Credit Distribution
|
|
3324
|
+
|
|
3325
|
+
```bash
|
|
3326
|
+
curl http://localhost:3000/admin/credit-distribution -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
3327
|
+
```
|
|
3328
|
+
|
|
3329
|
+
```json
|
|
3330
|
+
{
|
|
3331
|
+
"buckets": [
|
|
3332
|
+
{ "range": "0-10", "count": 5, "totalCredits": 30 },
|
|
3333
|
+
{ "range": "11-50", "count": 12, "totalCredits": 420 },
|
|
3334
|
+
{ "range": "51-100", "count": 8, "totalCredits": 640 },
|
|
3335
|
+
{ "range": "101-500", "count": 4, "totalCredits": 1200 },
|
|
3336
|
+
{ "range": "1001+", "count": 2, "totalCredits": 5000 }
|
|
3337
|
+
],
|
|
3338
|
+
"summary": { "totalKeys": 31, "medianCredits": 50 },
|
|
3339
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
3340
|
+
}
|
|
3341
|
+
```
|
|
3342
|
+
|
|
3343
|
+
Histogram of credit balances across active, non-suspended keys. Buckets: 0–10, 11–50, 51–100, 101–500, 501–1000, 1001+. Only non-empty buckets are returned. `medianCredits` is the median remaining balance. Useful for pricing analysis and capacity planning. Read-only.
|
|
3344
|
+
|
|
3300
3345
|
### IP Allowlisting
|
|
3301
3346
|
|
|
3302
3347
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -276,6 +276,8 @@ export declare class PayGateServer {
|
|
|
276
276
|
private handleAccessHeatmap;
|
|
277
277
|
private handleKeyChurn;
|
|
278
278
|
private handleToolCorrelation;
|
|
279
|
+
private handleConsumerSegmentation;
|
|
280
|
+
private handleCreditDistribution;
|
|
279
281
|
private handleGetNotes;
|
|
280
282
|
private handleAddNote;
|
|
281
283
|
private handleDeleteNote;
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -1002,6 +1002,18 @@ class PayGateServer {
|
|
|
1002
1002
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
1003
1003
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
1004
1004
|
return;
|
|
1005
|
+
case '/admin/consumer-segmentation':
|
|
1006
|
+
if (req.method === 'GET')
|
|
1007
|
+
return this.handleConsumerSegmentation(req, res);
|
|
1008
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
1009
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
1010
|
+
return;
|
|
1011
|
+
case '/admin/credit-distribution':
|
|
1012
|
+
if (req.method === 'GET')
|
|
1013
|
+
return this.handleCreditDistribution(req, res);
|
|
1014
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
1015
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
1016
|
+
return;
|
|
1005
1017
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
1006
1018
|
case '/plugins':
|
|
1007
1019
|
return this.handleListPlugins(req, res);
|
|
@@ -1576,6 +1588,8 @@ class PayGateServer {
|
|
|
1576
1588
|
accessHeatmap: 'GET /admin/access-heatmap — Hourly access patterns with tool breakdown, unique consumers, and peak hour identification for capacity planning (requires X-Admin-Key)',
|
|
1577
1589
|
keyChurn: 'GET /admin/key-churn — Key churn analysis with creation/revocation rates, churn and retention percentages, and never-used key detection (requires X-Admin-Key)',
|
|
1578
1590
|
toolCorrelation: 'GET /admin/tool-correlation — Tool co-occurrence analysis showing which tools are commonly used together by the same consumers (requires X-Admin-Key)',
|
|
1591
|
+
consumerSegmentation: 'GET /admin/consumer-segmentation — Consumer classification into power/regular/casual/dormant segments with per-segment metrics (requires X-Admin-Key)',
|
|
1592
|
+
creditDistribution: 'GET /admin/credit-distribution — Histogram of credit balances across active keys with configurable buckets and median calculation (requires X-Admin-Key)',
|
|
1579
1593
|
...(this.oauth ? {
|
|
1580
1594
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1581
1595
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -7253,6 +7267,131 @@ class PayGateServer {
|
|
|
7253
7267
|
generatedAt: new Date().toISOString(),
|
|
7254
7268
|
}));
|
|
7255
7269
|
}
|
|
7270
|
+
// ─── /admin/consumer-segmentation — Consumer classification ──────────────
|
|
7271
|
+
handleConsumerSegmentation(req, res) {
|
|
7272
|
+
if (!this.checkAdmin(req, res))
|
|
7273
|
+
return;
|
|
7274
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
7275
|
+
const activeRecords = allRecords.filter(r => r.active && !r.suspended);
|
|
7276
|
+
if (activeRecords.length === 0) {
|
|
7277
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
7278
|
+
res.end(JSON.stringify({
|
|
7279
|
+
segments: [],
|
|
7280
|
+
summary: { totalConsumers: 0 },
|
|
7281
|
+
generatedAt: new Date().toISOString(),
|
|
7282
|
+
}));
|
|
7283
|
+
return;
|
|
7284
|
+
}
|
|
7285
|
+
// Classify each active key into a segment based on totalCalls
|
|
7286
|
+
const segmentMap = new Map();
|
|
7287
|
+
for (const rec of activeRecords) {
|
|
7288
|
+
const calls = rec.totalCalls || 0;
|
|
7289
|
+
let segment;
|
|
7290
|
+
if (calls >= 20)
|
|
7291
|
+
segment = 'power';
|
|
7292
|
+
else if (calls >= 5)
|
|
7293
|
+
segment = 'regular';
|
|
7294
|
+
else if (calls >= 1)
|
|
7295
|
+
segment = 'casual';
|
|
7296
|
+
else
|
|
7297
|
+
segment = 'dormant';
|
|
7298
|
+
let data = segmentMap.get(segment);
|
|
7299
|
+
if (!data) {
|
|
7300
|
+
data = { count: 0, totalCredits: 0, totalSpent: 0, totalCalls: 0 };
|
|
7301
|
+
segmentMap.set(segment, data);
|
|
7302
|
+
}
|
|
7303
|
+
data.count++;
|
|
7304
|
+
data.totalCredits += rec.credits || 0;
|
|
7305
|
+
data.totalSpent += rec.totalSpent || 0;
|
|
7306
|
+
data.totalCalls += calls;
|
|
7307
|
+
}
|
|
7308
|
+
// Build segments array sorted by segment order: power, regular, casual, dormant
|
|
7309
|
+
const order = ['power', 'regular', 'casual', 'dormant'];
|
|
7310
|
+
const segments = order
|
|
7311
|
+
.filter(s => segmentMap.has(s))
|
|
7312
|
+
.map(s => {
|
|
7313
|
+
const data = segmentMap.get(s);
|
|
7314
|
+
return {
|
|
7315
|
+
segment: s,
|
|
7316
|
+
count: data.count,
|
|
7317
|
+
totalCredits: data.totalCredits,
|
|
7318
|
+
totalSpent: data.totalSpent,
|
|
7319
|
+
avgCallsPerKey: data.count > 0 ? Math.round(data.totalCalls / data.count) : 0,
|
|
7320
|
+
};
|
|
7321
|
+
});
|
|
7322
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
7323
|
+
res.end(JSON.stringify({
|
|
7324
|
+
segments,
|
|
7325
|
+
summary: {
|
|
7326
|
+
totalConsumers: activeRecords.length,
|
|
7327
|
+
},
|
|
7328
|
+
generatedAt: new Date().toISOString(),
|
|
7329
|
+
}));
|
|
7330
|
+
}
|
|
7331
|
+
// ─── /admin/credit-distribution — Credit balance histogram ───────────────
|
|
7332
|
+
handleCreditDistribution(req, res) {
|
|
7333
|
+
if (!this.checkAdmin(req, res))
|
|
7334
|
+
return;
|
|
7335
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
7336
|
+
const activeRecords = allRecords.filter(r => r.active && !r.suspended);
|
|
7337
|
+
if (activeRecords.length === 0) {
|
|
7338
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
7339
|
+
res.end(JSON.stringify({
|
|
7340
|
+
buckets: [],
|
|
7341
|
+
summary: { totalKeys: 0, medianCredits: 0 },
|
|
7342
|
+
generatedAt: new Date().toISOString(),
|
|
7343
|
+
}));
|
|
7344
|
+
return;
|
|
7345
|
+
}
|
|
7346
|
+
// Define bucket ranges
|
|
7347
|
+
const bucketDefs = [
|
|
7348
|
+
{ range: '0-10', min: 0, max: 10 },
|
|
7349
|
+
{ range: '11-50', min: 11, max: 50 },
|
|
7350
|
+
{ range: '51-100', min: 51, max: 100 },
|
|
7351
|
+
{ range: '101-500', min: 101, max: 500 },
|
|
7352
|
+
{ range: '501-1000', min: 501, max: 1000 },
|
|
7353
|
+
{ range: '1001+', min: 1001, max: Infinity },
|
|
7354
|
+
];
|
|
7355
|
+
// Count keys per bucket
|
|
7356
|
+
const bucketCounts = bucketDefs.map(def => ({
|
|
7357
|
+
range: def.range,
|
|
7358
|
+
min: def.min,
|
|
7359
|
+
max: def.max,
|
|
7360
|
+
count: 0,
|
|
7361
|
+
totalCredits: 0,
|
|
7362
|
+
}));
|
|
7363
|
+
const creditValues = [];
|
|
7364
|
+
for (const rec of activeRecords) {
|
|
7365
|
+
const credits = rec.credits || 0;
|
|
7366
|
+
creditValues.push(credits);
|
|
7367
|
+
for (const bucket of bucketCounts) {
|
|
7368
|
+
if (credits >= bucket.min && credits <= bucket.max) {
|
|
7369
|
+
bucket.count++;
|
|
7370
|
+
bucket.totalCredits += credits;
|
|
7371
|
+
break;
|
|
7372
|
+
}
|
|
7373
|
+
}
|
|
7374
|
+
}
|
|
7375
|
+
// Calculate median
|
|
7376
|
+
creditValues.sort((a, b) => a - b);
|
|
7377
|
+
const mid = Math.floor(creditValues.length / 2);
|
|
7378
|
+
const medianCredits = creditValues.length % 2 === 0
|
|
7379
|
+
? Math.round((creditValues[mid - 1] + creditValues[mid]) / 2)
|
|
7380
|
+
: creditValues[mid];
|
|
7381
|
+
// Only include non-empty buckets, in order
|
|
7382
|
+
const buckets = bucketCounts
|
|
7383
|
+
.filter(b => b.count > 0)
|
|
7384
|
+
.map(({ range, count, totalCredits }) => ({ range, count, totalCredits }));
|
|
7385
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
7386
|
+
res.end(JSON.stringify({
|
|
7387
|
+
buckets,
|
|
7388
|
+
summary: {
|
|
7389
|
+
totalKeys: activeRecords.length,
|
|
7390
|
+
medianCredits,
|
|
7391
|
+
},
|
|
7392
|
+
generatedAt: new Date().toISOString(),
|
|
7393
|
+
}));
|
|
7394
|
+
}
|
|
7256
7395
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
7257
7396
|
handleGetNotes(req, res) {
|
|
7258
7397
|
if (!this.checkAdmin(req, res))
|