paygate-mcp 8.20.0 → 8.22.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 +44 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +123 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -127,6 +127,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
127
127
|
- **Tool Latency Analysis** — `GET /admin/latency` per-tool response time metrics with avg/p95/min/max durations, slowest tools ranking, and per-key latency breakdown
|
|
128
128
|
- **Error Rate Trends** — `GET /admin/error-trends` denial rate trends with per-tool error rates, denial reason breakdown, worst-performing tools, and trend direction
|
|
129
129
|
- **Credit Flow Analysis** — `GET /admin/credit-flow` credit inflow/outflow analysis with utilization percentage, top spenders, and per-tool spend breakdown
|
|
130
|
+
- **Key Age Analysis** — `GET /admin/key-age` key age distribution with oldest/newest keys, age buckets (24h/7d/30d/older), and recently created list
|
|
131
|
+
- **Namespace Usage Summary** — `GET /admin/namespace-usage` per-namespace usage metrics with credit allocation, spending, call counts, and cross-namespace comparison
|
|
130
132
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
131
133
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
132
134
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -2940,6 +2942,48 @@ curl http://localhost:3000/admin/credit-flow -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
|
2940
2942
|
|
|
2941
2943
|
Credit inflow/outflow analysis: total credits allocated (initial + spent) vs spent vs remaining, utilization percentage, top 10 spenders ranked by credits consumed, and per-tool spend breakdown sorted by revenue. Read-only.
|
|
2942
2944
|
|
|
2945
|
+
### Key Age Analysis
|
|
2946
|
+
|
|
2947
|
+
```bash
|
|
2948
|
+
curl http://localhost:3000/admin/key-age -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2949
|
+
```
|
|
2950
|
+
|
|
2951
|
+
```json
|
|
2952
|
+
{
|
|
2953
|
+
"summary": {
|
|
2954
|
+
"totalKeys": 15, "avgAgeHours": 168.5,
|
|
2955
|
+
"oldestKey": { "keyName": "legacy", "ageHours": 720, "createdAt": "2025-01-01T00:00:00Z" },
|
|
2956
|
+
"newestKey": { "keyName": "fresh", "ageHours": 0.5, "createdAt": "2025-01-31T12:00:00Z" }
|
|
2957
|
+
},
|
|
2958
|
+
"distribution": { "last24h": 3, "last7d": 5, "last30d": 4, "older": 3 },
|
|
2959
|
+
"recentlyCreated": [
|
|
2960
|
+
{ "keyName": "fresh", "ageHours": 0.5, "createdAt": "2025-01-31T12:00:00Z" }
|
|
2961
|
+
],
|
|
2962
|
+
"generatedAt": "2025-01-31T12:30:00Z"
|
|
2963
|
+
}
|
|
2964
|
+
```
|
|
2965
|
+
|
|
2966
|
+
Key age distribution: average age across all active keys, oldest/newest key identification, age buckets (last 24h / 7d / 30d / older), and recently created list (newest first, top 10). Read-only.
|
|
2967
|
+
|
|
2968
|
+
### Namespace Usage Summary
|
|
2969
|
+
|
|
2970
|
+
```bash
|
|
2971
|
+
curl http://localhost:3000/admin/namespace-usage -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2972
|
+
```
|
|
2973
|
+
|
|
2974
|
+
```json
|
|
2975
|
+
{
|
|
2976
|
+
"summary": { "totalNamespaces": 3 },
|
|
2977
|
+
"namespaces": [
|
|
2978
|
+
{ "namespace": "prod", "keyCount": 5, "totalAllocated": 5000, "totalSpent": 2000, "totalRemaining": 3000, "totalCalls": 400, "utilizationPct": 40 },
|
|
2979
|
+
{ "namespace": "staging", "keyCount": 2, "totalAllocated": 1000, "totalSpent": 200, "totalRemaining": 800, "totalCalls": 40, "utilizationPct": 20 }
|
|
2980
|
+
],
|
|
2981
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
2982
|
+
}
|
|
2983
|
+
```
|
|
2984
|
+
|
|
2985
|
+
Per-namespace usage metrics: key counts, credit allocation/spending/remaining, call counts, and utilization percentages. Sorted by spending (highest first). Keys without a namespace appear under "default". Read-only.
|
|
2986
|
+
|
|
2943
2987
|
### IP Allowlisting
|
|
2944
2988
|
|
|
2945
2989
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -262,6 +262,8 @@ export declare class PayGateServer {
|
|
|
262
262
|
private handleLatencyAnalysis;
|
|
263
263
|
private handleErrorTrends;
|
|
264
264
|
private handleCreditFlow;
|
|
265
|
+
private handleKeyAge;
|
|
266
|
+
private handleNamespaceUsage;
|
|
265
267
|
private handleGetNotes;
|
|
266
268
|
private handleAddNote;
|
|
267
269
|
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
|
@@ -918,6 +918,18 @@ class PayGateServer {
|
|
|
918
918
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
919
919
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
920
920
|
return;
|
|
921
|
+
case '/admin/key-age':
|
|
922
|
+
if (req.method === 'GET')
|
|
923
|
+
return this.handleKeyAge(req, res);
|
|
924
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
925
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
926
|
+
return;
|
|
927
|
+
case '/admin/namespace-usage':
|
|
928
|
+
if (req.method === 'GET')
|
|
929
|
+
return this.handleNamespaceUsage(req, res);
|
|
930
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
931
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
932
|
+
return;
|
|
921
933
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
922
934
|
case '/plugins':
|
|
923
935
|
return this.handleListPlugins(req, res);
|
|
@@ -1478,6 +1490,8 @@ class PayGateServer {
|
|
|
1478
1490
|
latencyAnalysis: 'GET /admin/latency — Per-tool response time metrics with avg/p95/min/max, slowest tools ranking, and per-key latency breakdown (requires X-Admin-Key)',
|
|
1479
1491
|
errorTrends: 'GET /admin/error-trends — Denial rate trends with per-tool error rates, denial reason breakdown, and trend direction (requires X-Admin-Key)',
|
|
1480
1492
|
creditFlow: 'GET /admin/credit-flow — Credit inflow/outflow analysis with utilization, top spenders, and per-tool spend breakdown (requires X-Admin-Key)',
|
|
1493
|
+
keyAge: 'GET /admin/key-age — Key age distribution with oldest/newest keys, age buckets, and recently created list (requires X-Admin-Key)',
|
|
1494
|
+
namespaceUsage: 'GET /admin/namespace-usage — Per-namespace usage metrics with credit allocation, spending, call counts, and cross-namespace comparison (requires X-Admin-Key)',
|
|
1481
1495
|
...(this.oauth ? {
|
|
1482
1496
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1483
1497
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -6341,6 +6355,115 @@ class PayGateServer {
|
|
|
6341
6355
|
generatedAt: new Date().toISOString(),
|
|
6342
6356
|
}));
|
|
6343
6357
|
}
|
|
6358
|
+
// ─── /admin/key-age — Key Age Analysis ──────────────────────────────────
|
|
6359
|
+
handleKeyAge(req, res) {
|
|
6360
|
+
if (!this.checkAdmin(req, res))
|
|
6361
|
+
return;
|
|
6362
|
+
const records = this.gate.store.getAllRecords().filter(r => r.active);
|
|
6363
|
+
const now = Date.now();
|
|
6364
|
+
if (records.length === 0) {
|
|
6365
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6366
|
+
res.end(JSON.stringify({
|
|
6367
|
+
summary: { totalKeys: 0, avgAgeHours: 0 },
|
|
6368
|
+
distribution: { last24h: 0, last7d: 0, last30d: 0, older: 0 },
|
|
6369
|
+
recentlyCreated: [],
|
|
6370
|
+
generatedAt: new Date().toISOString(),
|
|
6371
|
+
}));
|
|
6372
|
+
return;
|
|
6373
|
+
}
|
|
6374
|
+
// ── Age calculations ──
|
|
6375
|
+
const keysWithAge = records.map(r => {
|
|
6376
|
+
const createdMs = r.createdAt ? new Date(r.createdAt).getTime() : now;
|
|
6377
|
+
const ageMs = now - createdMs;
|
|
6378
|
+
const ageHours = Math.round((ageMs / (1000 * 60 * 60)) * 100) / 100;
|
|
6379
|
+
return { keyName: r.name, createdAt: r.createdAt, ageHours };
|
|
6380
|
+
});
|
|
6381
|
+
const totalKeys = keysWithAge.length;
|
|
6382
|
+
const avgAgeHours = Math.round((keysWithAge.reduce((sum, k) => sum + k.ageHours, 0) / totalKeys) * 100) / 100;
|
|
6383
|
+
// ── Distribution buckets ──
|
|
6384
|
+
const h24 = 24;
|
|
6385
|
+
const d7 = 7 * 24;
|
|
6386
|
+
const d30 = 30 * 24;
|
|
6387
|
+
let last24h = 0, last7d = 0, last30d = 0, older = 0;
|
|
6388
|
+
for (const k of keysWithAge) {
|
|
6389
|
+
if (k.ageHours < h24)
|
|
6390
|
+
last24h++;
|
|
6391
|
+
else if (k.ageHours < d7)
|
|
6392
|
+
last7d++;
|
|
6393
|
+
else if (k.ageHours < d30)
|
|
6394
|
+
last30d++;
|
|
6395
|
+
else
|
|
6396
|
+
older++;
|
|
6397
|
+
}
|
|
6398
|
+
// ── Oldest and newest ──
|
|
6399
|
+
const sorted = [...keysWithAge].sort((a, b) => b.ageHours - a.ageHours);
|
|
6400
|
+
const oldestKey = { keyName: sorted[0].keyName, ageHours: sorted[0].ageHours, createdAt: sorted[0].createdAt };
|
|
6401
|
+
const newestKey = { keyName: sorted[sorted.length - 1].keyName, ageHours: sorted[sorted.length - 1].ageHours, createdAt: sorted[sorted.length - 1].createdAt };
|
|
6402
|
+
// ── Recently created (newest first, top 10) ──
|
|
6403
|
+
const recentlyCreated = [...keysWithAge]
|
|
6404
|
+
.sort((a, b) => {
|
|
6405
|
+
const diff = a.ageHours - b.ageHours;
|
|
6406
|
+
if (diff !== 0)
|
|
6407
|
+
return diff;
|
|
6408
|
+
// Tie-break: compare createdAt descending (newest first)
|
|
6409
|
+
return (b.createdAt || '').localeCompare(a.createdAt || '');
|
|
6410
|
+
})
|
|
6411
|
+
.slice(0, 10)
|
|
6412
|
+
.map(k => ({ keyName: k.keyName, ageHours: k.ageHours, createdAt: k.createdAt }));
|
|
6413
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6414
|
+
res.end(JSON.stringify({
|
|
6415
|
+
summary: { totalKeys, avgAgeHours, oldestKey, newestKey },
|
|
6416
|
+
distribution: { last24h, last7d, last30d, older },
|
|
6417
|
+
recentlyCreated,
|
|
6418
|
+
generatedAt: new Date().toISOString(),
|
|
6419
|
+
}));
|
|
6420
|
+
}
|
|
6421
|
+
// ─── /admin/namespace-usage — Namespace Usage Summary ────────────────────
|
|
6422
|
+
handleNamespaceUsage(req, res) {
|
|
6423
|
+
if (!this.checkAdmin(req, res))
|
|
6424
|
+
return;
|
|
6425
|
+
const records = this.gate.store.getAllRecords().filter(r => r.active);
|
|
6426
|
+
if (records.length === 0) {
|
|
6427
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6428
|
+
res.end(JSON.stringify({
|
|
6429
|
+
summary: { totalNamespaces: 0 },
|
|
6430
|
+
namespaces: [],
|
|
6431
|
+
generatedAt: new Date().toISOString(),
|
|
6432
|
+
}));
|
|
6433
|
+
return;
|
|
6434
|
+
}
|
|
6435
|
+
// ── Group records by namespace ──
|
|
6436
|
+
const nsMap = new Map();
|
|
6437
|
+
for (const r of records) {
|
|
6438
|
+
const ns = r.namespace || 'default';
|
|
6439
|
+
if (!nsMap.has(ns))
|
|
6440
|
+
nsMap.set(ns, { keys: [], totalAllocated: 0, totalSpent: 0, totalCalls: 0 });
|
|
6441
|
+
const entry = nsMap.get(ns);
|
|
6442
|
+
entry.keys.push(r);
|
|
6443
|
+
entry.totalAllocated += r.credits + r.totalSpent;
|
|
6444
|
+
entry.totalSpent += r.totalSpent;
|
|
6445
|
+
entry.totalCalls += r.totalCalls;
|
|
6446
|
+
}
|
|
6447
|
+
const namespaces = Array.from(nsMap.entries())
|
|
6448
|
+
.map(([ns, data]) => ({
|
|
6449
|
+
namespace: ns,
|
|
6450
|
+
keyCount: data.keys.length,
|
|
6451
|
+
totalAllocated: data.totalAllocated,
|
|
6452
|
+
totalSpent: data.totalSpent,
|
|
6453
|
+
totalRemaining: data.totalAllocated - data.totalSpent,
|
|
6454
|
+
totalCalls: data.totalCalls,
|
|
6455
|
+
utilizationPct: data.totalAllocated > 0
|
|
6456
|
+
? Math.round((data.totalSpent / data.totalAllocated) * 100)
|
|
6457
|
+
: 0,
|
|
6458
|
+
}))
|
|
6459
|
+
.sort((a, b) => b.totalSpent - a.totalSpent);
|
|
6460
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6461
|
+
res.end(JSON.stringify({
|
|
6462
|
+
summary: { totalNamespaces: nsMap.size },
|
|
6463
|
+
namespaces,
|
|
6464
|
+
generatedAt: new Date().toISOString(),
|
|
6465
|
+
}));
|
|
6466
|
+
}
|
|
6344
6467
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
6345
6468
|
handleGetNotes(req, res) {
|
|
6346
6469
|
if (!this.checkAdmin(req, res))
|