paygate-mcp 8.11.0 → 8.13.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 +50 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +176 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -118,6 +118,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
118
118
|
- **Security Audit** — `GET /admin/security` security posture analysis identifying keys without IP allowlists, quotas, ACL restrictions, spending limits, or expiry dates, flagging high-credit keys, and computing a composite security score
|
|
119
119
|
- **Revenue Analysis** — `GET /admin/revenue` revenue metrics with per-tool revenue breakdown, per-key spending, hourly revenue trends, credit flow summary (allocated/spent/remaining), and average revenue per call
|
|
120
120
|
- **Key Portfolio Health** — `GET /admin/key-portfolio` portfolio-wide key health with active/inactive/suspended counts, stale keys, expiring-soon keys, age distribution, credit utilization, and namespace breakdown
|
|
121
|
+
- **Anomaly Detection** — `GET /admin/anomalies` identifies unusual patterns: keys with high denial rates, rapid credit depletion, low remaining credits, with severity ratings and detailed descriptions
|
|
122
|
+
- **Usage Forecasting** — `GET /admin/forecast` predicts future credit consumption with per-key depletion estimates, calls remaining, at-risk key identification, system-wide consumption aggregates, and per-tool cost breakdown
|
|
121
123
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
122
124
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
123
125
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -2714,6 +2716,54 @@ curl http://localhost:3000/admin/key-portfolio -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
|
2714
2716
|
|
|
2715
2717
|
Returns portfolio-wide key health: active/inactive/suspended counts, average credit utilization, stale keys (created but never used), keys expiring within 7 days sorted by urgency, age distribution statistics, and namespace breakdown. Read-only.
|
|
2716
2718
|
|
|
2719
|
+
### Anomaly Detection
|
|
2720
|
+
|
|
2721
|
+
```bash
|
|
2722
|
+
curl http://localhost:3000/admin/anomalies -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2723
|
+
```
|
|
2724
|
+
|
|
2725
|
+
```json
|
|
2726
|
+
{
|
|
2727
|
+
"summary": { "totalAnomalies": 3, "byType": { "high_denial_rate": 1, "rapid_credit_depletion": 1, "low_credits": 1 } },
|
|
2728
|
+
"anomalies": [
|
|
2729
|
+
{ "type": "high_denial_rate", "severity": "warning", "keyName": "test-key", "description": "Key \"test-key\" has 80% denial rate (8/10 calls denied)" },
|
|
2730
|
+
{ "type": "rapid_credit_depletion", "severity": "warning", "keyName": "fast-spender", "description": "Key \"fast-spender\" has used 95% of allocated credits (950/1000)" },
|
|
2731
|
+
{ "type": "low_credits", "severity": "info", "keyName": "nearly-empty", "description": "Key \"nearly-empty\" has only 5 credits remaining (5% of allocated)" }
|
|
2732
|
+
],
|
|
2733
|
+
"analyzedAt": "2025-01-15T14:30:00Z"
|
|
2734
|
+
}
|
|
2735
|
+
```
|
|
2736
|
+
|
|
2737
|
+
Scans all active keys for anomalous patterns: keys with >50% denial rates (3+ calls minimum), rapid credit depletion (>=75% spent), and low remaining credits (<=10 credits or <=10% remaining). Each anomaly includes type, severity, affected key name, and human-readable description. Read-only.
|
|
2738
|
+
|
|
2739
|
+
### Usage Forecasting
|
|
2740
|
+
|
|
2741
|
+
```bash
|
|
2742
|
+
curl http://localhost:3000/admin/forecast -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2743
|
+
```
|
|
2744
|
+
|
|
2745
|
+
```json
|
|
2746
|
+
{
|
|
2747
|
+
"summary": { "totalActiveKeys": 3, "keysAtRisk": 1 },
|
|
2748
|
+
"keyForecasts": [
|
|
2749
|
+
{ "keyName": "heavy-user", "creditsRemaining": 50, "totalSpent": 950, "callCount": 95, "avgCreditsPerCall": 10, "estimatedCallsRemaining": 5, "atRisk": true },
|
|
2750
|
+
{ "keyName": "light-user", "creditsRemaining": 900, "totalSpent": 100, "callCount": 20, "avgCreditsPerCall": 5, "estimatedCallsRemaining": 180, "atRisk": false }
|
|
2751
|
+
],
|
|
2752
|
+
"systemForecast": {
|
|
2753
|
+
"totalCreditsRemaining": 950,
|
|
2754
|
+
"totalCreditsSpent": 1050,
|
|
2755
|
+
"totalCalls": 115,
|
|
2756
|
+
"byTool": [
|
|
2757
|
+
{ "tool": "expensive_tool", "calls": 50, "totalCredits": 500, "avgCreditsPerCall": 10 },
|
|
2758
|
+
{ "tool": "cheap_tool", "calls": 65, "totalCredits": 325, "avgCreditsPerCall": 5 }
|
|
2759
|
+
]
|
|
2760
|
+
},
|
|
2761
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
2762
|
+
}
|
|
2763
|
+
```
|
|
2764
|
+
|
|
2765
|
+
Forecasts credit consumption for all active keys: per-key depletion estimates with calls remaining, at-risk identification (<=5 estimated calls), system-wide credit aggregates, and per-tool cost breakdown sorted by revenue. Keys with no usage history show `estimatedCallsRemaining: null`. Read-only.
|
|
2766
|
+
|
|
2717
2767
|
### IP Allowlisting
|
|
2718
2768
|
|
|
2719
2769
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -253,6 +253,8 @@ export declare class PayGateServer {
|
|
|
253
253
|
private handleSecurityAudit;
|
|
254
254
|
private handleRevenueAnalysis;
|
|
255
255
|
private handleLifecycleAnalysis;
|
|
256
|
+
private handleAnomalyDetection;
|
|
257
|
+
private handleUsageForecasting;
|
|
256
258
|
private handleGetNotes;
|
|
257
259
|
private handleAddNote;
|
|
258
260
|
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
|
@@ -864,6 +864,18 @@ class PayGateServer {
|
|
|
864
864
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
865
865
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
866
866
|
return;
|
|
867
|
+
case '/admin/anomalies':
|
|
868
|
+
if (req.method === 'GET')
|
|
869
|
+
return this.handleAnomalyDetection(req, res);
|
|
870
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
871
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
872
|
+
return;
|
|
873
|
+
case '/admin/forecast':
|
|
874
|
+
if (req.method === 'GET')
|
|
875
|
+
return this.handleUsageForecasting(req, res);
|
|
876
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
877
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
878
|
+
return;
|
|
867
879
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
868
880
|
case '/plugins':
|
|
869
881
|
return this.handleListPlugins(req, res);
|
|
@@ -1415,6 +1427,8 @@ class PayGateServer {
|
|
|
1415
1427
|
securityAudit: 'GET /admin/security — Security posture analysis with findings for missing IP allowlists, quotas, ACLs, spending limits, expiry, high-credit keys, and composite score (requires X-Admin-Key)',
|
|
1416
1428
|
revenueAnalysis: 'GET /admin/revenue — Revenue metrics with per-tool revenue, per-key spending, hourly revenue trends, credit flow summary, and average revenue per call (requires X-Admin-Key)',
|
|
1417
1429
|
keyPortfolio: 'GET /admin/key-portfolio — Key portfolio health with active/inactive/suspended counts, stale keys, expiring-soon keys, age distribution, credit utilization, and namespace breakdown (requires X-Admin-Key)',
|
|
1430
|
+
anomalyDetection: 'GET /admin/anomalies — Anomaly detection identifying high denial rates, rapid credit depletion, low credit balances, and other unusual patterns (requires X-Admin-Key)',
|
|
1431
|
+
usageForecasting: 'GET /admin/forecast — Usage forecasting with per-key depletion estimates, system-wide consumption trends, per-tool breakdown, and at-risk key identification (requires X-Admin-Key)',
|
|
1418
1432
|
...(this.oauth ? {
|
|
1419
1433
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1420
1434
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -5571,6 +5585,168 @@ class PayGateServer {
|
|
|
5571
5585
|
byNamespace,
|
|
5572
5586
|
}));
|
|
5573
5587
|
}
|
|
5588
|
+
// ─── /admin/anomalies — Anomaly detection ──────────────────────────────
|
|
5589
|
+
handleAnomalyDetection(req, res) {
|
|
5590
|
+
if (!this.checkAdmin(req, res))
|
|
5591
|
+
return;
|
|
5592
|
+
const events = this.gate.meter.getEvents();
|
|
5593
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
5594
|
+
const anomalies = [];
|
|
5595
|
+
// ── High denial rate per key (>50% denied with at least 3 calls) ──
|
|
5596
|
+
const keyEvents = new Map();
|
|
5597
|
+
for (const e of events) {
|
|
5598
|
+
const name = e.keyName || e.apiKey;
|
|
5599
|
+
if (!keyEvents.has(name))
|
|
5600
|
+
keyEvents.set(name, { allowed: 0, denied: 0, name });
|
|
5601
|
+
const k = keyEvents.get(name);
|
|
5602
|
+
if (e.allowed)
|
|
5603
|
+
k.allowed++;
|
|
5604
|
+
else
|
|
5605
|
+
k.denied++;
|
|
5606
|
+
}
|
|
5607
|
+
for (const [, stats] of keyEvents) {
|
|
5608
|
+
const total = stats.allowed + stats.denied;
|
|
5609
|
+
if (total >= 3 && stats.denied / total > 0.5) {
|
|
5610
|
+
anomalies.push({
|
|
5611
|
+
type: 'high_denial_rate',
|
|
5612
|
+
severity: 'warning',
|
|
5613
|
+
keyName: stats.name,
|
|
5614
|
+
description: `Key "${stats.name}" has ${Math.round(stats.denied / total * 100)}% denial rate (${stats.denied}/${total} calls denied)`,
|
|
5615
|
+
details: { allowed: stats.allowed, denied: stats.denied, total, denialRate: Math.round(stats.denied / total * 10000) / 10000 },
|
|
5616
|
+
});
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5619
|
+
// ── Rapid credit depletion (>75% credits spent with at least 1 call) ──
|
|
5620
|
+
for (const record of allRecords) {
|
|
5621
|
+
if (!record.active)
|
|
5622
|
+
continue;
|
|
5623
|
+
const totalAllocated = record.credits + (record.totalSpent || 0);
|
|
5624
|
+
if (totalAllocated > 0 && record.totalSpent > 0) {
|
|
5625
|
+
const utilization = record.totalSpent / totalAllocated;
|
|
5626
|
+
if (utilization >= 0.75) {
|
|
5627
|
+
anomalies.push({
|
|
5628
|
+
type: 'rapid_credit_depletion',
|
|
5629
|
+
severity: 'warning',
|
|
5630
|
+
keyName: record.name,
|
|
5631
|
+
description: `Key "${record.name}" has used ${Math.round(utilization * 100)}% of allocated credits (${record.totalSpent}/${totalAllocated})`,
|
|
5632
|
+
details: { totalAllocated, totalSpent: record.totalSpent, remaining: record.credits, utilization: Math.round(utilization * 10000) / 10000 },
|
|
5633
|
+
});
|
|
5634
|
+
}
|
|
5635
|
+
}
|
|
5636
|
+
}
|
|
5637
|
+
// ── Low remaining credits (active key with <10% remaining or <10 credits) ──
|
|
5638
|
+
for (const record of allRecords) {
|
|
5639
|
+
if (!record.active)
|
|
5640
|
+
continue;
|
|
5641
|
+
const totalAllocated = record.credits + (record.totalSpent || 0);
|
|
5642
|
+
if (totalAllocated > 0 && record.totalSpent > 0) {
|
|
5643
|
+
const remaining = record.credits;
|
|
5644
|
+
const remainingPct = remaining / totalAllocated;
|
|
5645
|
+
if (remaining <= 10 || remainingPct <= 0.1) {
|
|
5646
|
+
// Don't duplicate if already flagged as rapid depletion
|
|
5647
|
+
const alreadyFlagged = anomalies.some(a => a.type === 'rapid_credit_depletion' && a.keyName === record.name);
|
|
5648
|
+
if (!alreadyFlagged) {
|
|
5649
|
+
anomalies.push({
|
|
5650
|
+
type: 'low_credits',
|
|
5651
|
+
severity: 'info',
|
|
5652
|
+
keyName: record.name,
|
|
5653
|
+
description: `Key "${record.name}" has only ${remaining} credits remaining (${Math.round(remainingPct * 100)}% of allocated)`,
|
|
5654
|
+
details: { remaining, totalAllocated, remainingPct: Math.round(remainingPct * 10000) / 10000 },
|
|
5655
|
+
});
|
|
5656
|
+
}
|
|
5657
|
+
else {
|
|
5658
|
+
// Still add as separate anomaly type for detection
|
|
5659
|
+
anomalies.push({
|
|
5660
|
+
type: 'low_credits',
|
|
5661
|
+
severity: 'info',
|
|
5662
|
+
keyName: record.name,
|
|
5663
|
+
description: `Key "${record.name}" has only ${remaining} credits remaining (${Math.round(remainingPct * 100)}% of allocated)`,
|
|
5664
|
+
details: { remaining, totalAllocated, remainingPct: Math.round(remainingPct * 10000) / 10000 },
|
|
5665
|
+
});
|
|
5666
|
+
}
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
5670
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
5671
|
+
res.end(JSON.stringify({
|
|
5672
|
+
summary: {
|
|
5673
|
+
totalAnomalies: anomalies.length,
|
|
5674
|
+
byType: anomalies.reduce((acc, a) => { acc[a.type] = (acc[a.type] || 0) + 1; return acc; }, {}),
|
|
5675
|
+
},
|
|
5676
|
+
anomalies,
|
|
5677
|
+
analyzedAt: new Date().toISOString(),
|
|
5678
|
+
}));
|
|
5679
|
+
}
|
|
5680
|
+
// ─── /admin/forecast — Usage Forecasting ─────────────────────────────────
|
|
5681
|
+
handleUsageForecasting(req, res) {
|
|
5682
|
+
if (!this.checkAdmin(req, res))
|
|
5683
|
+
return;
|
|
5684
|
+
const events = this.gate.meter.getEvents();
|
|
5685
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
5686
|
+
const activeRecords = allRecords.filter(r => r.active);
|
|
5687
|
+
// ── Per-key forecasts ──
|
|
5688
|
+
const keyForecasts = [];
|
|
5689
|
+
for (const record of activeRecords) {
|
|
5690
|
+
const keyName = record.name;
|
|
5691
|
+
const creditsRemaining = record.credits;
|
|
5692
|
+
const totalSpent = record.totalSpent || 0;
|
|
5693
|
+
const callCount = record.totalCalls || 0;
|
|
5694
|
+
const avgCreditsPerCall = callCount > 0 ? totalSpent / callCount : 0;
|
|
5695
|
+
const estimatedCallsRemaining = callCount > 0 && avgCreditsPerCall > 0
|
|
5696
|
+
? Math.floor(creditsRemaining / avgCreditsPerCall)
|
|
5697
|
+
: null;
|
|
5698
|
+
// At risk: has usage history and <= 5 estimated calls remaining
|
|
5699
|
+
const atRisk = estimatedCallsRemaining !== null && estimatedCallsRemaining <= 5;
|
|
5700
|
+
keyForecasts.push({
|
|
5701
|
+
keyName,
|
|
5702
|
+
creditsRemaining,
|
|
5703
|
+
totalSpent,
|
|
5704
|
+
callCount,
|
|
5705
|
+
avgCreditsPerCall: Math.round(avgCreditsPerCall * 100) / 100,
|
|
5706
|
+
estimatedCallsRemaining,
|
|
5707
|
+
atRisk,
|
|
5708
|
+
});
|
|
5709
|
+
}
|
|
5710
|
+
// ── System-wide forecast ──
|
|
5711
|
+
const totalCreditsRemaining = activeRecords.reduce((sum, r) => sum + r.credits, 0);
|
|
5712
|
+
const totalCreditsSpent = activeRecords.reduce((sum, r) => sum + (r.totalSpent || 0), 0);
|
|
5713
|
+
const totalCalls = activeRecords.reduce((sum, r) => sum + (r.totalCalls || 0), 0);
|
|
5714
|
+
// Per-tool breakdown from events
|
|
5715
|
+
const toolMap = new Map();
|
|
5716
|
+
const allowedEvents = events.filter(e => e.allowed);
|
|
5717
|
+
for (const e of allowedEvents) {
|
|
5718
|
+
const tool = e.tool || 'unknown';
|
|
5719
|
+
if (!toolMap.has(tool))
|
|
5720
|
+
toolMap.set(tool, { calls: 0, totalCredits: 0 });
|
|
5721
|
+
const t = toolMap.get(tool);
|
|
5722
|
+
t.calls++;
|
|
5723
|
+
t.totalCredits += e.creditsCharged || 0;
|
|
5724
|
+
}
|
|
5725
|
+
const byTool = Array.from(toolMap.entries())
|
|
5726
|
+
.map(([tool, stats]) => ({
|
|
5727
|
+
tool,
|
|
5728
|
+
calls: stats.calls,
|
|
5729
|
+
totalCredits: stats.totalCredits,
|
|
5730
|
+
avgCreditsPerCall: stats.calls > 0 ? Math.round(stats.totalCredits / stats.calls * 100) / 100 : 0,
|
|
5731
|
+
}))
|
|
5732
|
+
.sort((a, b) => b.totalCredits - a.totalCredits);
|
|
5733
|
+
const keysAtRisk = keyForecasts.filter(f => f.atRisk).length;
|
|
5734
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
5735
|
+
res.end(JSON.stringify({
|
|
5736
|
+
summary: {
|
|
5737
|
+
totalActiveKeys: activeRecords.length,
|
|
5738
|
+
keysAtRisk,
|
|
5739
|
+
},
|
|
5740
|
+
keyForecasts,
|
|
5741
|
+
systemForecast: {
|
|
5742
|
+
totalCreditsRemaining,
|
|
5743
|
+
totalCreditsSpent,
|
|
5744
|
+
totalCalls,
|
|
5745
|
+
byTool,
|
|
5746
|
+
},
|
|
5747
|
+
generatedAt: new Date().toISOString(),
|
|
5748
|
+
}));
|
|
5749
|
+
}
|
|
5574
5750
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
5575
5751
|
handleGetNotes(req, res) {
|
|
5576
5752
|
if (!this.checkAdmin(req, res))
|