paygate-mcp 8.14.0 → 8.16.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 +52 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +182 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,6 +121,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
121
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
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
|
|
123
123
|
- **Compliance Report** — `GET /admin/compliance` generates compliance-ready report with key governance (expiry coverage), access control (ACL/IP/spending limit coverage), audit trail completeness, weighted overall score, and actionable recommendations
|
|
124
|
+
- **SLA Monitoring** — `GET /admin/sla` tracks service level metrics: success rates, denial breakdowns by reason, per-tool availability and error rates, uptime tracking, sorted by call volume
|
|
125
|
+
- **Capacity Planning** — `GET /admin/capacity` system capacity analysis with credit burn rates, utilization percentages, top consumers, per-namespace breakdown, and scaling recommendations
|
|
124
126
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
125
127
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
126
128
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -2791,6 +2793,56 @@ curl http://localhost:3000/admin/compliance -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
|
2791
2793
|
|
|
2792
2794
|
Compliance-ready report scoring key governance (expiry 25%), access control (ACL 25%, IP 20%, spending limits 15%), and audit trail (15%). Actionable recommendations for each gap. Read-only.
|
|
2793
2795
|
|
|
2796
|
+
### SLA Monitoring
|
|
2797
|
+
|
|
2798
|
+
```bash
|
|
2799
|
+
curl http://localhost:3000/admin/sla -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2800
|
+
```
|
|
2801
|
+
|
|
2802
|
+
```json
|
|
2803
|
+
{
|
|
2804
|
+
"summary": {
|
|
2805
|
+
"totalCalls": 150, "allowedCalls": 140, "deniedCalls": 10,
|
|
2806
|
+
"successRate": 93.33,
|
|
2807
|
+
"denialReasons": { "insufficient_credits": 6, "rate_limited": 3, "acl_denied": 1 }
|
|
2808
|
+
},
|
|
2809
|
+
"byTool": [
|
|
2810
|
+
{ "tool": "tool_a", "totalCalls": 100, "allowedCalls": 95, "deniedCalls": 5, "successRate": 95 },
|
|
2811
|
+
{ "tool": "tool_b", "totalCalls": 50, "allowedCalls": 45, "deniedCalls": 5, "successRate": 90 }
|
|
2812
|
+
],
|
|
2813
|
+
"uptime": { "startedAt": "2025-01-15T10:00:00Z", "uptimeSeconds": 16200 },
|
|
2814
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
2815
|
+
}
|
|
2816
|
+
```
|
|
2817
|
+
|
|
2818
|
+
Service level metrics: overall success rate, denial breakdown by canonical reason (insufficient_credits, rate_limited, quota_exceeded, acl_denied, spending_limit, key_suspended, key_expired), per-tool availability sorted by call volume, and server uptime tracking. Read-only.
|
|
2819
|
+
|
|
2820
|
+
### Capacity Planning
|
|
2821
|
+
|
|
2822
|
+
```bash
|
|
2823
|
+
curl http://localhost:3000/admin/capacity -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2824
|
+
```
|
|
2825
|
+
|
|
2826
|
+
```json
|
|
2827
|
+
{
|
|
2828
|
+
"summary": {
|
|
2829
|
+
"totalCreditsAllocated": 10000, "totalCreditsSpent": 3500, "totalCreditsRemaining": 6500,
|
|
2830
|
+
"utilizationPct": 35,
|
|
2831
|
+
"burnRate": { "creditsPerCall": 10, "totalCalls": 350 }
|
|
2832
|
+
},
|
|
2833
|
+
"topConsumers": [
|
|
2834
|
+
{ "keyName": "heavy-user", "creditsSpent": 2000, "creditsRemaining": 500, "callCount": 200 }
|
|
2835
|
+
],
|
|
2836
|
+
"byNamespace": {
|
|
2837
|
+
"prod": { "allocated": 8000, "spent": 3000, "remaining": 5000, "keys": 3, "utilizationPct": 37 }
|
|
2838
|
+
},
|
|
2839
|
+
"recommendations": ["1 key(s) have less than 10% credits remaining"],
|
|
2840
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
2841
|
+
}
|
|
2842
|
+
```
|
|
2843
|
+
|
|
2844
|
+
System capacity analysis: overall credit utilization, burn rate (credits/call), top 10 consumers ranked by spend, per-namespace breakdown, and scaling recommendations for high utilization (>=75%) or depleted keys. Read-only.
|
|
2845
|
+
|
|
2794
2846
|
### IP Allowlisting
|
|
2795
2847
|
|
|
2796
2848
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -256,6 +256,8 @@ export declare class PayGateServer {
|
|
|
256
256
|
private handleAnomalyDetection;
|
|
257
257
|
private handleUsageForecasting;
|
|
258
258
|
private handleComplianceReport;
|
|
259
|
+
private handleSlaMonitoring;
|
|
260
|
+
private handleCapacityPlanning;
|
|
259
261
|
private handleGetNotes;
|
|
260
262
|
private handleAddNote;
|
|
261
263
|
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
|
@@ -882,6 +882,18 @@ class PayGateServer {
|
|
|
882
882
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
883
883
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
884
884
|
return;
|
|
885
|
+
case '/admin/sla':
|
|
886
|
+
if (req.method === 'GET')
|
|
887
|
+
return this.handleSlaMonitoring(req, res);
|
|
888
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
889
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
890
|
+
return;
|
|
891
|
+
case '/admin/capacity':
|
|
892
|
+
if (req.method === 'GET')
|
|
893
|
+
return this.handleCapacityPlanning(req, res);
|
|
894
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
895
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
896
|
+
return;
|
|
885
897
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
886
898
|
case '/plugins':
|
|
887
899
|
return this.handleListPlugins(req, res);
|
|
@@ -1436,6 +1448,8 @@ class PayGateServer {
|
|
|
1436
1448
|
anomalyDetection: 'GET /admin/anomalies — Anomaly detection identifying high denial rates, rapid credit depletion, low credit balances, and other unusual patterns (requires X-Admin-Key)',
|
|
1437
1449
|
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)',
|
|
1438
1450
|
complianceReport: 'GET /admin/compliance — Compliance report with key governance, access control coverage, audit trail completeness, recommendations, and overall compliance score (requires X-Admin-Key)',
|
|
1451
|
+
slaMonitoring: 'GET /admin/sla — SLA monitoring with success rates, denial breakdowns, per-tool availability, uptime tracking, and denial reason aggregation (requires X-Admin-Key)',
|
|
1452
|
+
capacityPlanning: 'GET /admin/capacity — Capacity planning with credit burn rates, utilization percentages, top consumers, per-namespace breakdown, and scaling recommendations (requires X-Admin-Key)',
|
|
1439
1453
|
...(this.oauth ? {
|
|
1440
1454
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1441
1455
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -5858,6 +5872,174 @@ class PayGateServer {
|
|
|
5858
5872
|
generatedAt: new Date().toISOString(),
|
|
5859
5873
|
}));
|
|
5860
5874
|
}
|
|
5875
|
+
// ─── /admin/sla — SLA Monitoring ─────────────────────────────────────────
|
|
5876
|
+
handleSlaMonitoring(req, res) {
|
|
5877
|
+
if (!this.checkAdmin(req, res))
|
|
5878
|
+
return;
|
|
5879
|
+
const events = this.gate.meter.getEvents();
|
|
5880
|
+
// ── Summary metrics ──
|
|
5881
|
+
let allowedCalls = 0;
|
|
5882
|
+
let deniedCalls = 0;
|
|
5883
|
+
const denialReasons = {};
|
|
5884
|
+
for (const e of events) {
|
|
5885
|
+
if (e.allowed) {
|
|
5886
|
+
allowedCalls++;
|
|
5887
|
+
}
|
|
5888
|
+
else {
|
|
5889
|
+
deniedCalls++;
|
|
5890
|
+
// Normalize deny reason to canonical type
|
|
5891
|
+
const reason = e.denyReason || 'unknown';
|
|
5892
|
+
let canonical = 'unknown';
|
|
5893
|
+
if (reason.includes('insufficient_credits'))
|
|
5894
|
+
canonical = 'insufficient_credits';
|
|
5895
|
+
else if (reason.includes('rate_limited'))
|
|
5896
|
+
canonical = 'rate_limited';
|
|
5897
|
+
else if (reason.includes('quota'))
|
|
5898
|
+
canonical = 'quota_exceeded';
|
|
5899
|
+
else if (reason.includes('acl') || reason.includes('not allowed'))
|
|
5900
|
+
canonical = 'acl_denied';
|
|
5901
|
+
else if (reason.includes('spending_limit'))
|
|
5902
|
+
canonical = 'spending_limit';
|
|
5903
|
+
else if (reason.includes('suspended'))
|
|
5904
|
+
canonical = 'key_suspended';
|
|
5905
|
+
else if (reason.includes('expired'))
|
|
5906
|
+
canonical = 'key_expired';
|
|
5907
|
+
else
|
|
5908
|
+
canonical = reason.split(':')[0] || 'unknown';
|
|
5909
|
+
denialReasons[canonical] = (denialReasons[canonical] || 0) + 1;
|
|
5910
|
+
}
|
|
5911
|
+
}
|
|
5912
|
+
const totalCalls = allowedCalls + deniedCalls;
|
|
5913
|
+
const successRate = totalCalls > 0 ? Math.round(allowedCalls / totalCalls * 10000) / 100 : 100;
|
|
5914
|
+
// ── Per-tool breakdown ──
|
|
5915
|
+
const toolMap = new Map();
|
|
5916
|
+
for (const e of events) {
|
|
5917
|
+
const tool = e.tool || 'unknown';
|
|
5918
|
+
if (!toolMap.has(tool))
|
|
5919
|
+
toolMap.set(tool, { allowed: 0, denied: 0 });
|
|
5920
|
+
const t = toolMap.get(tool);
|
|
5921
|
+
if (e.allowed)
|
|
5922
|
+
t.allowed++;
|
|
5923
|
+
else
|
|
5924
|
+
t.denied++;
|
|
5925
|
+
}
|
|
5926
|
+
const byTool = Array.from(toolMap.entries())
|
|
5927
|
+
.map(([tool, stats]) => {
|
|
5928
|
+
const total = stats.allowed + stats.denied;
|
|
5929
|
+
return {
|
|
5930
|
+
tool,
|
|
5931
|
+
totalCalls: total,
|
|
5932
|
+
allowedCalls: stats.allowed,
|
|
5933
|
+
deniedCalls: stats.denied,
|
|
5934
|
+
successRate: total > 0 ? Math.round(stats.allowed / total * 10000) / 100 : 100,
|
|
5935
|
+
};
|
|
5936
|
+
})
|
|
5937
|
+
.sort((a, b) => b.totalCalls - a.totalCalls);
|
|
5938
|
+
// ── Uptime ──
|
|
5939
|
+
const uptimeMs = Date.now() - this.startedAt;
|
|
5940
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
5941
|
+
res.end(JSON.stringify({
|
|
5942
|
+
summary: {
|
|
5943
|
+
totalCalls,
|
|
5944
|
+
allowedCalls,
|
|
5945
|
+
deniedCalls,
|
|
5946
|
+
successRate,
|
|
5947
|
+
denialReasons,
|
|
5948
|
+
},
|
|
5949
|
+
byTool,
|
|
5950
|
+
uptime: {
|
|
5951
|
+
startedAt: new Date(this.startedAt).toISOString(),
|
|
5952
|
+
uptimeSeconds: Math.floor(uptimeMs / 1000),
|
|
5953
|
+
},
|
|
5954
|
+
generatedAt: new Date().toISOString(),
|
|
5955
|
+
}));
|
|
5956
|
+
}
|
|
5957
|
+
// ─── /admin/capacity — Capacity Planning ─────────────────────────────────
|
|
5958
|
+
handleCapacityPlanning(req, res) {
|
|
5959
|
+
if (!this.checkAdmin(req, res))
|
|
5960
|
+
return;
|
|
5961
|
+
const events = this.gate.meter.getEvents();
|
|
5962
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
5963
|
+
const activeRecords = allRecords.filter(r => r.active);
|
|
5964
|
+
// ── Summary ──
|
|
5965
|
+
const totalCreditsAllocated = activeRecords.reduce((sum, r) => sum + r.credits + (r.totalSpent || 0), 0);
|
|
5966
|
+
const totalCreditsSpent = activeRecords.reduce((sum, r) => sum + (r.totalSpent || 0), 0);
|
|
5967
|
+
const totalCreditsRemaining = activeRecords.reduce((sum, r) => sum + r.credits, 0);
|
|
5968
|
+
const utilizationPct = totalCreditsAllocated > 0
|
|
5969
|
+
? Math.round(totalCreditsSpent / totalCreditsAllocated * 100)
|
|
5970
|
+
: 0;
|
|
5971
|
+
// ── Burn rate ──
|
|
5972
|
+
const allowedEvents = events.filter(e => e.allowed);
|
|
5973
|
+
const totalCalls = allowedEvents.length;
|
|
5974
|
+
const totalCreditsFromEvents = allowedEvents.reduce((sum, e) => sum + (e.creditsCharged || 0), 0);
|
|
5975
|
+
const creditsPerCall = totalCalls > 0 ? Math.round(totalCreditsFromEvents / totalCalls * 100) / 100 : 0;
|
|
5976
|
+
// ── Top consumers (by credits spent) ──
|
|
5977
|
+
const topConsumers = activeRecords
|
|
5978
|
+
.filter(r => (r.totalSpent || 0) > 0)
|
|
5979
|
+
.map(r => ({
|
|
5980
|
+
keyName: r.name,
|
|
5981
|
+
creditsSpent: r.totalSpent || 0,
|
|
5982
|
+
creditsRemaining: r.credits,
|
|
5983
|
+
callCount: r.totalCalls || 0,
|
|
5984
|
+
}))
|
|
5985
|
+
.sort((a, b) => b.creditsSpent - a.creditsSpent)
|
|
5986
|
+
.slice(0, 10);
|
|
5987
|
+
// ── Per-namespace breakdown ──
|
|
5988
|
+
const nsMap = new Map();
|
|
5989
|
+
for (const r of activeRecords) {
|
|
5990
|
+
const ns = r.namespace || 'default';
|
|
5991
|
+
if (!nsMap.has(ns))
|
|
5992
|
+
nsMap.set(ns, { allocated: 0, spent: 0, remaining: 0, keys: 0 });
|
|
5993
|
+
const n = nsMap.get(ns);
|
|
5994
|
+
n.allocated += r.credits + (r.totalSpent || 0);
|
|
5995
|
+
n.spent += r.totalSpent || 0;
|
|
5996
|
+
n.remaining += r.credits;
|
|
5997
|
+
n.keys++;
|
|
5998
|
+
}
|
|
5999
|
+
const byNamespace = {};
|
|
6000
|
+
for (const [ns, stats] of nsMap) {
|
|
6001
|
+
byNamespace[ns] = {
|
|
6002
|
+
...stats,
|
|
6003
|
+
utilizationPct: stats.allocated > 0 ? Math.round(stats.spent / stats.allocated * 100) : 0,
|
|
6004
|
+
};
|
|
6005
|
+
}
|
|
6006
|
+
// ── Recommendations ──
|
|
6007
|
+
const recommendations = [];
|
|
6008
|
+
if (utilizationPct >= 90) {
|
|
6009
|
+
recommendations.push(`System utilization is at ${utilizationPct}% — top up credits immediately to avoid service disruption`);
|
|
6010
|
+
}
|
|
6011
|
+
else if (utilizationPct >= 75) {
|
|
6012
|
+
recommendations.push(`System utilization is at ${utilizationPct}% — consider adding more credits soon`);
|
|
6013
|
+
}
|
|
6014
|
+
const depleted = activeRecords.filter(r => r.credits <= 0 && (r.totalSpent || 0) > 0);
|
|
6015
|
+
if (depleted.length > 0) {
|
|
6016
|
+
recommendations.push(`${depleted.length} key(s) have zero remaining credits and need top-up`);
|
|
6017
|
+
}
|
|
6018
|
+
const lowCredit = activeRecords.filter(r => {
|
|
6019
|
+
const alloc = r.credits + (r.totalSpent || 0);
|
|
6020
|
+
return alloc > 0 && r.credits > 0 && r.credits / alloc <= 0.1;
|
|
6021
|
+
});
|
|
6022
|
+
if (lowCredit.length > 0) {
|
|
6023
|
+
recommendations.push(`${lowCredit.length} key(s) have less than 10% credits remaining`);
|
|
6024
|
+
}
|
|
6025
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6026
|
+
res.end(JSON.stringify({
|
|
6027
|
+
summary: {
|
|
6028
|
+
totalCreditsAllocated,
|
|
6029
|
+
totalCreditsSpent,
|
|
6030
|
+
totalCreditsRemaining,
|
|
6031
|
+
utilizationPct,
|
|
6032
|
+
burnRate: {
|
|
6033
|
+
creditsPerCall,
|
|
6034
|
+
totalCalls,
|
|
6035
|
+
},
|
|
6036
|
+
},
|
|
6037
|
+
topConsumers,
|
|
6038
|
+
byNamespace,
|
|
6039
|
+
recommendations,
|
|
6040
|
+
generatedAt: new Date().toISOString(),
|
|
6041
|
+
}));
|
|
6042
|
+
}
|
|
5861
6043
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
5862
6044
|
handleGetNotes(req, res) {
|
|
5863
6045
|
if (!this.checkAdmin(req, res))
|