paygate-mcp 8.17.0 → 8.19.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 +160 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,6 +124,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
124
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
125
|
- **Capacity Planning** — `GET /admin/capacity` system capacity analysis with credit burn rates, utilization percentages, top consumers, per-namespace breakdown, and scaling recommendations
|
|
126
126
|
- **Key Dependency Map** — `GET /admin/dependencies` tool-to-key relationship map with tool usage popularity, unique key counts per tool, per-key tool lists, and used/unused tool identification
|
|
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
|
+
- **Error Rate Trends** — `GET /admin/error-trends` denial rate trends with per-tool error rates, denial reason breakdown, worst-performing tools, and trend direction
|
|
127
129
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
128
130
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
129
131
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -2867,6 +2869,54 @@ curl http://localhost:3000/admin/dependencies -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
|
2867
2869
|
|
|
2868
2870
|
Tool-to-key relationship map: shows which tools each key uses, tool popularity ranked by total calls, unique key counts per tool, and identifies orphaned tools (available but unused). Useful for understanding tool adoption and pruning unused capabilities. Read-only.
|
|
2869
2871
|
|
|
2872
|
+
### Tool Latency Analysis
|
|
2873
|
+
|
|
2874
|
+
```bash
|
|
2875
|
+
curl http://localhost:3000/admin/latency -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2876
|
+
```
|
|
2877
|
+
|
|
2878
|
+
```json
|
|
2879
|
+
{
|
|
2880
|
+
"summary": { "totalCalls": 200, "avgDurationMs": 45, "minDurationMs": 8, "maxDurationMs": 312, "p95DurationMs": 120 },
|
|
2881
|
+
"byTool": [
|
|
2882
|
+
{ "tool": "translate", "totalCalls": 80, "avgDurationMs": 65, "minDurationMs": 20, "maxDurationMs": 312, "p95DurationMs": 150 },
|
|
2883
|
+
{ "tool": "search", "totalCalls": 120, "avgDurationMs": 32, "minDurationMs": 8, "maxDurationMs": 95, "p95DurationMs": 78 }
|
|
2884
|
+
],
|
|
2885
|
+
"slowestTools": [
|
|
2886
|
+
{ "tool": "translate", "avgDurationMs": 65, "totalCalls": 80 }
|
|
2887
|
+
],
|
|
2888
|
+
"byKey": [
|
|
2889
|
+
{ "keyName": "heavy-user", "totalCalls": 150, "avgDurationMs": 48, "minDurationMs": 8, "maxDurationMs": 312 }
|
|
2890
|
+
],
|
|
2891
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
2892
|
+
}
|
|
2893
|
+
```
|
|
2894
|
+
|
|
2895
|
+
Per-tool response time metrics: average, p95, min, and max durations for each tool sorted by slowest average first, top 10 slowest tools ranking, per-key latency breakdown, and global summary. Only counts successful (allowed) calls. Read-only.
|
|
2896
|
+
|
|
2897
|
+
### Error Rate Trends
|
|
2898
|
+
|
|
2899
|
+
```bash
|
|
2900
|
+
curl http://localhost:3000/admin/error-trends -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2901
|
+
```
|
|
2902
|
+
|
|
2903
|
+
```json
|
|
2904
|
+
{
|
|
2905
|
+
"summary": { "totalCalls": 500, "totalDenials": 45, "overallErrorRate": 9, "trend": "improving" },
|
|
2906
|
+
"byTool": [
|
|
2907
|
+
{ "tool": "translate", "totalCalls": 200, "denials": 30, "errorRate": 15 },
|
|
2908
|
+
{ "tool": "search", "totalCalls": 300, "denials": 15, "errorRate": 5 }
|
|
2909
|
+
],
|
|
2910
|
+
"denialReasons": [
|
|
2911
|
+
{ "reason": "insufficient_credits", "count": 30 },
|
|
2912
|
+
{ "reason": "rate_limited", "count": 15 }
|
|
2913
|
+
],
|
|
2914
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
2915
|
+
}
|
|
2916
|
+
```
|
|
2917
|
+
|
|
2918
|
+
Denial rate trends: overall error rate, per-tool error rates sorted by worst-performing, denial reason breakdown, and trend direction (improving/degrading/stable based on first-half vs second-half comparison). Read-only.
|
|
2919
|
+
|
|
2870
2920
|
### IP Allowlisting
|
|
2871
2921
|
|
|
2872
2922
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -259,6 +259,8 @@ export declare class PayGateServer {
|
|
|
259
259
|
private handleSlaMonitoring;
|
|
260
260
|
private handleCapacityPlanning;
|
|
261
261
|
private handleDependencyMap;
|
|
262
|
+
private handleLatencyAnalysis;
|
|
263
|
+
private handleErrorTrends;
|
|
262
264
|
private handleGetNotes;
|
|
263
265
|
private handleAddNote;
|
|
264
266
|
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
|
@@ -900,6 +900,18 @@ class PayGateServer {
|
|
|
900
900
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
901
901
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
902
902
|
return;
|
|
903
|
+
case '/admin/latency':
|
|
904
|
+
if (req.method === 'GET')
|
|
905
|
+
return this.handleLatencyAnalysis(req, res);
|
|
906
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
907
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
908
|
+
return;
|
|
909
|
+
case '/admin/error-trends':
|
|
910
|
+
if (req.method === 'GET')
|
|
911
|
+
return this.handleErrorTrends(req, res);
|
|
912
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
913
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
914
|
+
return;
|
|
903
915
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
904
916
|
case '/plugins':
|
|
905
917
|
return this.handleListPlugins(req, res);
|
|
@@ -1457,6 +1469,8 @@ class PayGateServer {
|
|
|
1457
1469
|
slaMonitoring: 'GET /admin/sla — SLA monitoring with success rates, denial breakdowns, per-tool availability, uptime tracking, and denial reason aggregation (requires X-Admin-Key)',
|
|
1458
1470
|
capacityPlanning: 'GET /admin/capacity — Capacity planning with credit burn rates, utilization percentages, top consumers, per-namespace breakdown, and scaling recommendations (requires X-Admin-Key)',
|
|
1459
1471
|
dependencyMap: 'GET /admin/dependencies — Tool-to-key dependency map with tool usage popularity, unique key counts, per-key tool lists, and used/unused tool identification (requires X-Admin-Key)',
|
|
1472
|
+
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)',
|
|
1473
|
+
errorTrends: 'GET /admin/error-trends — Denial rate trends with per-tool error rates, denial reason breakdown, and trend direction (requires X-Admin-Key)',
|
|
1460
1474
|
...(this.oauth ? {
|
|
1461
1475
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1462
1476
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -6109,6 +6123,152 @@ class PayGateServer {
|
|
|
6109
6123
|
generatedAt: new Date().toISOString(),
|
|
6110
6124
|
}));
|
|
6111
6125
|
}
|
|
6126
|
+
// ─── /admin/latency — Tool Latency Analysis ─────────────────────────────
|
|
6127
|
+
handleLatencyAnalysis(req, res) {
|
|
6128
|
+
if (!this.checkAdmin(req, res))
|
|
6129
|
+
return;
|
|
6130
|
+
// Only count allowed calls from request log
|
|
6131
|
+
const allowed = this.requestLog.filter(e => e.status === 'allowed');
|
|
6132
|
+
if (allowed.length === 0) {
|
|
6133
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6134
|
+
res.end(JSON.stringify({
|
|
6135
|
+
summary: { totalCalls: 0, avgDurationMs: 0, minDurationMs: 0, maxDurationMs: 0, p95DurationMs: 0 },
|
|
6136
|
+
byTool: [],
|
|
6137
|
+
slowestTools: [],
|
|
6138
|
+
byKey: [],
|
|
6139
|
+
generatedAt: new Date().toISOString(),
|
|
6140
|
+
}));
|
|
6141
|
+
return;
|
|
6142
|
+
}
|
|
6143
|
+
// ── Summary across all tools ──
|
|
6144
|
+
const allDurations = allowed.map(e => e.durationMs);
|
|
6145
|
+
const totalCalls = allowed.length;
|
|
6146
|
+
const avgDurationMs = Math.round(allDurations.reduce((a, b) => a + b, 0) / totalCalls);
|
|
6147
|
+
const minDurationMs = Math.min(...allDurations);
|
|
6148
|
+
const maxDurationMs = Math.max(...allDurations);
|
|
6149
|
+
const p95DurationMs = this.percentile(allDurations, 95);
|
|
6150
|
+
// ── Per-tool breakdown ──
|
|
6151
|
+
const toolMap = new Map();
|
|
6152
|
+
for (const e of allowed) {
|
|
6153
|
+
if (!toolMap.has(e.tool))
|
|
6154
|
+
toolMap.set(e.tool, []);
|
|
6155
|
+
toolMap.get(e.tool).push(e.durationMs);
|
|
6156
|
+
}
|
|
6157
|
+
const byTool = Array.from(toolMap.entries())
|
|
6158
|
+
.map(([tool, durations]) => ({
|
|
6159
|
+
tool,
|
|
6160
|
+
totalCalls: durations.length,
|
|
6161
|
+
avgDurationMs: Math.round(durations.reduce((a, b) => a + b, 0) / durations.length),
|
|
6162
|
+
minDurationMs: Math.min(...durations),
|
|
6163
|
+
maxDurationMs: Math.max(...durations),
|
|
6164
|
+
p95DurationMs: this.percentile(durations, 95),
|
|
6165
|
+
}))
|
|
6166
|
+
.sort((a, b) => b.avgDurationMs - a.avgDurationMs);
|
|
6167
|
+
// ── Slowest tools (top 10) ──
|
|
6168
|
+
const slowestTools = byTool.slice(0, 10).map(t => ({
|
|
6169
|
+
tool: t.tool,
|
|
6170
|
+
avgDurationMs: t.avgDurationMs,
|
|
6171
|
+
totalCalls: t.totalCalls,
|
|
6172
|
+
}));
|
|
6173
|
+
// ── Per-key breakdown ──
|
|
6174
|
+
// Build masked-key → name lookup from store
|
|
6175
|
+
const maskedToName = new Map();
|
|
6176
|
+
for (const rec of this.gate.store.getAllRecords()) {
|
|
6177
|
+
maskedToName.set((0, audit_1.maskKeyForAudit)(rec.key), rec.name);
|
|
6178
|
+
}
|
|
6179
|
+
const keyMap = new Map();
|
|
6180
|
+
for (const e of allowed) {
|
|
6181
|
+
const keyName = maskedToName.get(e.key) || e.key;
|
|
6182
|
+
if (!keyMap.has(keyName))
|
|
6183
|
+
keyMap.set(keyName, { keyName, durations: [] });
|
|
6184
|
+
keyMap.get(keyName).durations.push(e.durationMs);
|
|
6185
|
+
}
|
|
6186
|
+
const byKey = Array.from(keyMap.values())
|
|
6187
|
+
.map(k => ({
|
|
6188
|
+
keyName: k.keyName,
|
|
6189
|
+
totalCalls: k.durations.length,
|
|
6190
|
+
avgDurationMs: Math.round(k.durations.reduce((a, b) => a + b, 0) / k.durations.length),
|
|
6191
|
+
minDurationMs: Math.min(...k.durations),
|
|
6192
|
+
maxDurationMs: Math.max(...k.durations),
|
|
6193
|
+
}))
|
|
6194
|
+
.sort((a, b) => b.avgDurationMs - a.avgDurationMs);
|
|
6195
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6196
|
+
res.end(JSON.stringify({
|
|
6197
|
+
summary: { totalCalls, avgDurationMs, minDurationMs, maxDurationMs, p95DurationMs },
|
|
6198
|
+
byTool,
|
|
6199
|
+
slowestTools,
|
|
6200
|
+
byKey,
|
|
6201
|
+
generatedAt: new Date().toISOString(),
|
|
6202
|
+
}));
|
|
6203
|
+
}
|
|
6204
|
+
// ─── /admin/error-trends — Error Rate Trends ─────────────────────────────
|
|
6205
|
+
handleErrorTrends(req, res) {
|
|
6206
|
+
if (!this.checkAdmin(req, res))
|
|
6207
|
+
return;
|
|
6208
|
+
const entries = this.requestLog;
|
|
6209
|
+
if (entries.length === 0) {
|
|
6210
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6211
|
+
res.end(JSON.stringify({
|
|
6212
|
+
summary: { totalCalls: 0, totalDenials: 0, overallErrorRate: 0, trend: 'stable' },
|
|
6213
|
+
byTool: [],
|
|
6214
|
+
denialReasons: [],
|
|
6215
|
+
generatedAt: new Date().toISOString(),
|
|
6216
|
+
}));
|
|
6217
|
+
return;
|
|
6218
|
+
}
|
|
6219
|
+
const totalCalls = entries.length;
|
|
6220
|
+
const denied = entries.filter(e => e.status === 'denied');
|
|
6221
|
+
const totalDenials = denied.length;
|
|
6222
|
+
const overallErrorRate = Math.round((totalDenials / totalCalls) * 10000) / 100; // 2 decimal places
|
|
6223
|
+
// ── Trend direction: compare first half vs second half error rates ──
|
|
6224
|
+
let trend = 'stable';
|
|
6225
|
+
if (entries.length >= 4) {
|
|
6226
|
+
const mid = Math.floor(entries.length / 2);
|
|
6227
|
+
const firstHalf = entries.slice(0, mid);
|
|
6228
|
+
const secondHalf = entries.slice(mid);
|
|
6229
|
+
const firstRate = firstHalf.filter(e => e.status === 'denied').length / firstHalf.length;
|
|
6230
|
+
const secondRate = secondHalf.filter(e => e.status === 'denied').length / secondHalf.length;
|
|
6231
|
+
const diff = secondRate - firstRate;
|
|
6232
|
+
if (diff > 0.05)
|
|
6233
|
+
trend = 'degrading';
|
|
6234
|
+
else if (diff < -0.05)
|
|
6235
|
+
trend = 'improving';
|
|
6236
|
+
}
|
|
6237
|
+
// ── Per-tool breakdown ──
|
|
6238
|
+
const toolMap = new Map();
|
|
6239
|
+
for (const e of entries) {
|
|
6240
|
+
if (!toolMap.has(e.tool))
|
|
6241
|
+
toolMap.set(e.tool, { total: 0, denied: 0 });
|
|
6242
|
+
const t = toolMap.get(e.tool);
|
|
6243
|
+
t.total++;
|
|
6244
|
+
if (e.status === 'denied')
|
|
6245
|
+
t.denied++;
|
|
6246
|
+
}
|
|
6247
|
+
const byTool = Array.from(toolMap.entries())
|
|
6248
|
+
.map(([tool, stats]) => ({
|
|
6249
|
+
tool,
|
|
6250
|
+
totalCalls: stats.total,
|
|
6251
|
+
denials: stats.denied,
|
|
6252
|
+
errorRate: Math.round((stats.denied / stats.total) * 10000) / 100,
|
|
6253
|
+
}))
|
|
6254
|
+
.sort((a, b) => b.errorRate - a.errorRate);
|
|
6255
|
+
// ── Denial reasons breakdown ──
|
|
6256
|
+
const reasonMap = new Map();
|
|
6257
|
+
for (const e of denied) {
|
|
6258
|
+
const reason = e.denyReason || 'unknown';
|
|
6259
|
+
reasonMap.set(reason, (reasonMap.get(reason) || 0) + 1);
|
|
6260
|
+
}
|
|
6261
|
+
const denialReasons = Array.from(reasonMap.entries())
|
|
6262
|
+
.map(([reason, count]) => ({ reason, count }))
|
|
6263
|
+
.sort((a, b) => b.count - a.count);
|
|
6264
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6265
|
+
res.end(JSON.stringify({
|
|
6266
|
+
summary: { totalCalls, totalDenials, overallErrorRate, trend },
|
|
6267
|
+
byTool,
|
|
6268
|
+
denialReasons,
|
|
6269
|
+
generatedAt: new Date().toISOString(),
|
|
6270
|
+
}));
|
|
6271
|
+
}
|
|
6112
6272
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
6113
6273
|
handleGetNotes(req, res) {
|
|
6114
6274
|
if (!this.checkAdmin(req, res))
|