paygate-mcp 8.27.0 → 8.29.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 +49 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +165 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,6 +134,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
134
134
|
- **Request Volume Trends** — `GET /admin/request-trends` hourly time-series of request volume, success/failure counts, credit spend, avg duration, and peak hour identification
|
|
135
135
|
- **Key Status Overview** — `GET /admin/key-status` key status dashboard with active/suspended/revoked/expired counts and keys needing attention (low credits, near expiry)
|
|
136
136
|
- **Webhook Health** — `GET /admin/webhook-health` webhook delivery health overview with success rate, pending retries, dead letter count, pause status, and buffered events
|
|
137
|
+
- **Consumer Insights** — `GET /admin/consumer-insights` per-key behavioral analytics with top spenders, most active callers, tool diversity, and spending patterns
|
|
138
|
+
- **System Health Score** — `GET /admin/system-health` composite 0-100 health score with weighted component breakdowns for key health, error rates, and credit utilization
|
|
137
139
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
138
140
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
139
141
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -3108,6 +3110,53 @@ curl http://localhost:3000/admin/webhook-health -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
|
3108
3110
|
|
|
3109
3111
|
Webhook delivery health overview. Status is `healthy`, `retrying`, `degraded` (dead letters exist), `paused`, or `not_configured`. Includes success rate, pending retries, dead letter count, and buffered events. Read-only.
|
|
3110
3112
|
|
|
3113
|
+
### Consumer Insights
|
|
3114
|
+
|
|
3115
|
+
```bash
|
|
3116
|
+
curl http://localhost:3000/admin/consumer-insights -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
3117
|
+
```
|
|
3118
|
+
|
|
3119
|
+
```json
|
|
3120
|
+
{
|
|
3121
|
+
"summary": {
|
|
3122
|
+
"totalConsumers": 15,
|
|
3123
|
+
"activeConsumers": 12,
|
|
3124
|
+
"totalCreditsSpent": 4850,
|
|
3125
|
+
"totalCalls": 970
|
|
3126
|
+
},
|
|
3127
|
+
"topSpenders": [
|
|
3128
|
+
{ "name": "heavy-user", "totalSpent": 1200, "totalCalls": 240, "uniqueTools": 5 }
|
|
3129
|
+
],
|
|
3130
|
+
"mostActive": [
|
|
3131
|
+
{ "name": "heavy-user", "totalCalls": 240, "totalSpent": 1200, "uniqueTools": 5 }
|
|
3132
|
+
],
|
|
3133
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
3134
|
+
}
|
|
3135
|
+
```
|
|
3136
|
+
|
|
3137
|
+
Per-key behavioral analytics. Top 10 spenders ranked by credits consumed, top 10 most active by call count. Each entry includes tool diversity (unique tools used). Summary shows total/active consumers and aggregate spend. Read-only.
|
|
3138
|
+
|
|
3139
|
+
### System Health Score
|
|
3140
|
+
|
|
3141
|
+
```bash
|
|
3142
|
+
curl http://localhost:3000/admin/system-health -H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
3143
|
+
```
|
|
3144
|
+
|
|
3145
|
+
```json
|
|
3146
|
+
{
|
|
3147
|
+
"score": 85,
|
|
3148
|
+
"level": "healthy",
|
|
3149
|
+
"components": {
|
|
3150
|
+
"keyHealth": { "score": 90, "weight": 0.4, "detail": "2 suspended" },
|
|
3151
|
+
"errorRate": { "score": 80, "weight": 0.35, "detail": "10% denial rate (5/50)" },
|
|
3152
|
+
"creditUtilization": { "score": 85, "weight": 0.25, "detail": "45% utilized (4500/10000 credits)" }
|
|
3153
|
+
},
|
|
3154
|
+
"generatedAt": "2025-01-15T14:30:00Z"
|
|
3155
|
+
}
|
|
3156
|
+
```
|
|
3157
|
+
|
|
3158
|
+
Composite system health score 0-100 with weighted component breakdowns. Key health (40%): penalizes suspended/revoked/expired/low-credit keys. Error rate (35%): penalizes high denial rates. Credit utilization (25%): healthy at 10-80%, degrades at >80%. Levels: healthy (>=80), good (>=60), warning (>=40), critical (<40). Read-only.
|
|
3159
|
+
|
|
3111
3160
|
### IP Allowlisting
|
|
3112
3161
|
|
|
3113
3162
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -269,6 +269,8 @@ export declare class PayGateServer {
|
|
|
269
269
|
private handleRequestTrends;
|
|
270
270
|
private handleKeyStatus;
|
|
271
271
|
private handleWebhookHealth;
|
|
272
|
+
private handleConsumerInsights;
|
|
273
|
+
private handleSystemHealth;
|
|
272
274
|
private handleGetNotes;
|
|
273
275
|
private handleAddNote;
|
|
274
276
|
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
|
@@ -960,6 +960,18 @@ class PayGateServer {
|
|
|
960
960
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
961
961
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
962
962
|
return;
|
|
963
|
+
case '/admin/consumer-insights':
|
|
964
|
+
if (req.method === 'GET')
|
|
965
|
+
return this.handleConsumerInsights(req, res);
|
|
966
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
967
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
968
|
+
return;
|
|
969
|
+
case '/admin/system-health':
|
|
970
|
+
if (req.method === 'GET')
|
|
971
|
+
return this.handleSystemHealth(req, res);
|
|
972
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
973
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
974
|
+
return;
|
|
963
975
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
964
976
|
case '/plugins':
|
|
965
977
|
return this.handleListPlugins(req, res);
|
|
@@ -1527,6 +1539,8 @@ class PayGateServer {
|
|
|
1527
1539
|
requestTrends: 'GET /admin/request-trends — Hourly request volume time-series with success/failure counts, credit spend, and avg duration (requires X-Admin-Key)',
|
|
1528
1540
|
keyStatus: 'GET /admin/key-status — Key status dashboard with active/suspended/revoked/expired counts and keys needing attention (requires X-Admin-Key)',
|
|
1529
1541
|
webhookHealth: 'GET /admin/webhook-health — Webhook delivery health overview with success rate, retries, dead letters, and pause status (requires X-Admin-Key)',
|
|
1542
|
+
consumerInsights: 'GET /admin/consumer-insights — Per-key behavioral analytics with top spenders, most active callers, tool diversity, and spending patterns (requires X-Admin-Key)',
|
|
1543
|
+
systemHealth: 'GET /admin/system-health — Composite system health score 0-100 with component breakdowns for key health, error rates, and credit utilization (requires X-Admin-Key)',
|
|
1530
1544
|
...(this.oauth ? {
|
|
1531
1545
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1532
1546
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -6788,6 +6802,157 @@ class PayGateServer {
|
|
|
6788
6802
|
generatedAt: new Date().toISOString(),
|
|
6789
6803
|
}));
|
|
6790
6804
|
}
|
|
6805
|
+
// ─── /admin/consumer-insights — Per-key behavioral analytics ──────────────
|
|
6806
|
+
handleConsumerInsights(req, res) {
|
|
6807
|
+
if (!this.checkAdmin(req, res))
|
|
6808
|
+
return;
|
|
6809
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
6810
|
+
const activeRecords = allRecords.filter(r => r.active && !r.suspended);
|
|
6811
|
+
// Build per-key data from records
|
|
6812
|
+
const keyMap = new Map();
|
|
6813
|
+
for (const r of allRecords) {
|
|
6814
|
+
keyMap.set(r.key, {
|
|
6815
|
+
name: r.name,
|
|
6816
|
+
totalSpent: r.totalSpent || 0,
|
|
6817
|
+
totalCalls: r.totalCalls || 0,
|
|
6818
|
+
uniqueTools: new Set(),
|
|
6819
|
+
});
|
|
6820
|
+
}
|
|
6821
|
+
// Enrich with tool diversity from request log
|
|
6822
|
+
for (const entry of this.requestLog) {
|
|
6823
|
+
if (entry.status === 'allowed' && entry.tool) {
|
|
6824
|
+
// Match key by masked prefix — request log stores masked keys
|
|
6825
|
+
for (const [fullKey, data] of keyMap) {
|
|
6826
|
+
const masked = fullKey.slice(0, 7) + '...' + fullKey.slice(-4);
|
|
6827
|
+
if (masked === entry.key) {
|
|
6828
|
+
data.uniqueTools.add(entry.tool);
|
|
6829
|
+
break;
|
|
6830
|
+
}
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6833
|
+
}
|
|
6834
|
+
// Top spenders (sorted by totalSpent descending, top 10)
|
|
6835
|
+
const topSpenders = Array.from(keyMap.values())
|
|
6836
|
+
.filter(d => d.totalSpent > 0)
|
|
6837
|
+
.sort((a, b) => b.totalSpent - a.totalSpent)
|
|
6838
|
+
.slice(0, 10)
|
|
6839
|
+
.map(d => ({
|
|
6840
|
+
name: d.name,
|
|
6841
|
+
totalSpent: d.totalSpent,
|
|
6842
|
+
totalCalls: d.totalCalls,
|
|
6843
|
+
uniqueTools: d.uniqueTools.size,
|
|
6844
|
+
}));
|
|
6845
|
+
// Most active (sorted by totalCalls descending, top 10)
|
|
6846
|
+
const mostActive = Array.from(keyMap.values())
|
|
6847
|
+
.filter(d => d.totalCalls > 0)
|
|
6848
|
+
.sort((a, b) => b.totalCalls - a.totalCalls)
|
|
6849
|
+
.slice(0, 10)
|
|
6850
|
+
.map(d => ({
|
|
6851
|
+
name: d.name,
|
|
6852
|
+
totalCalls: d.totalCalls,
|
|
6853
|
+
totalSpent: d.totalSpent,
|
|
6854
|
+
uniqueTools: d.uniqueTools.size,
|
|
6855
|
+
}));
|
|
6856
|
+
// Summary
|
|
6857
|
+
const totalSpent = allRecords.reduce((sum, r) => sum + (r.totalSpent || 0), 0);
|
|
6858
|
+
const totalCalls = allRecords.reduce((sum, r) => sum + (r.totalCalls || 0), 0);
|
|
6859
|
+
const activeConsumers = allRecords.filter(r => (r.totalCalls || 0) > 0).length;
|
|
6860
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6861
|
+
res.end(JSON.stringify({
|
|
6862
|
+
summary: {
|
|
6863
|
+
totalConsumers: allRecords.length,
|
|
6864
|
+
activeConsumers,
|
|
6865
|
+
totalCreditsSpent: totalSpent,
|
|
6866
|
+
totalCalls,
|
|
6867
|
+
},
|
|
6868
|
+
topSpenders,
|
|
6869
|
+
mostActive,
|
|
6870
|
+
generatedAt: new Date().toISOString(),
|
|
6871
|
+
}));
|
|
6872
|
+
}
|
|
6873
|
+
// ─── /admin/system-health — Composite system health score ─────────────────
|
|
6874
|
+
handleSystemHealth(req, res) {
|
|
6875
|
+
if (!this.checkAdmin(req, res))
|
|
6876
|
+
return;
|
|
6877
|
+
const allRecords = this.gate.store.getAllRecords();
|
|
6878
|
+
const now = Date.now();
|
|
6879
|
+
// ── Component 1: Key Health (weight: 40%) ──
|
|
6880
|
+
let keyHealthScore = 100;
|
|
6881
|
+
let keyHealthDetail = 'All keys healthy';
|
|
6882
|
+
if (allRecords.length > 0) {
|
|
6883
|
+
const active = allRecords.filter(r => r.active && !r.suspended).length;
|
|
6884
|
+
const suspended = allRecords.filter(r => r.suspended).length;
|
|
6885
|
+
const revoked = allRecords.filter(r => !r.active && !r.suspended).length;
|
|
6886
|
+
const expired = allRecords.filter(r => r.active && !r.suspended && r.expiresAt && new Date(r.expiresAt).getTime() <= now).length;
|
|
6887
|
+
const lowCredits = allRecords.filter(r => r.active && !r.suspended && r.credits <= 10).length;
|
|
6888
|
+
const problemRatio = (suspended + revoked + expired + lowCredits) / allRecords.length;
|
|
6889
|
+
keyHealthScore = Math.max(0, Math.round(100 - problemRatio * 100));
|
|
6890
|
+
const issues = [];
|
|
6891
|
+
if (suspended > 0)
|
|
6892
|
+
issues.push(`${suspended} suspended`);
|
|
6893
|
+
if (revoked > 0)
|
|
6894
|
+
issues.push(`${revoked} revoked`);
|
|
6895
|
+
if (expired > 0)
|
|
6896
|
+
issues.push(`${expired} expired`);
|
|
6897
|
+
if (lowCredits > 0)
|
|
6898
|
+
issues.push(`${lowCredits} low credits`);
|
|
6899
|
+
keyHealthDetail = issues.length > 0 ? issues.join(', ') : `${active} active keys`;
|
|
6900
|
+
}
|
|
6901
|
+
// ── Component 2: Error Rate (weight: 35%) ──
|
|
6902
|
+
let errorRateScore = 100;
|
|
6903
|
+
let errorRateDetail = 'No errors';
|
|
6904
|
+
const totalRequests = this.requestLog.length;
|
|
6905
|
+
if (totalRequests > 0) {
|
|
6906
|
+
const denied = this.requestLog.filter(e => e.status === 'denied').length;
|
|
6907
|
+
const errorRate = denied / totalRequests;
|
|
6908
|
+
errorRateScore = Math.max(0, Math.round(100 - errorRate * 200)); // 50% error rate = 0 score
|
|
6909
|
+
errorRateDetail = `${Math.round(errorRate * 100)}% denial rate (${denied}/${totalRequests})`;
|
|
6910
|
+
}
|
|
6911
|
+
// ── Component 3: Credit Utilization (weight: 25%) ──
|
|
6912
|
+
let creditScore = 100;
|
|
6913
|
+
let creditDetail = 'No credits tracked';
|
|
6914
|
+
const totalAllocated = allRecords.reduce((s, r) => s + (r.credits || 0) + (r.totalSpent || 0), 0);
|
|
6915
|
+
const totalRemaining = allRecords.reduce((s, r) => s + (r.credits || 0), 0);
|
|
6916
|
+
if (totalAllocated > 0) {
|
|
6917
|
+
const utilization = (totalAllocated - totalRemaining) / totalAllocated;
|
|
6918
|
+
// Healthy: 10-80% utilization; too low or too high degrade score
|
|
6919
|
+
if (utilization > 0.9) {
|
|
6920
|
+
creditScore = Math.round(50 - (utilization - 0.9) * 500);
|
|
6921
|
+
}
|
|
6922
|
+
else if (utilization > 0.8) {
|
|
6923
|
+
creditScore = Math.round(80 - (utilization - 0.8) * 300);
|
|
6924
|
+
}
|
|
6925
|
+
else {
|
|
6926
|
+
creditScore = 100;
|
|
6927
|
+
}
|
|
6928
|
+
creditScore = Math.max(0, Math.min(100, creditScore));
|
|
6929
|
+
creditDetail = `${Math.round(utilization * 100)}% utilized (${totalAllocated - totalRemaining}/${totalAllocated} credits)`;
|
|
6930
|
+
}
|
|
6931
|
+
// ── Composite Score ──
|
|
6932
|
+
const compositeScore = Math.round(keyHealthScore * 0.4 +
|
|
6933
|
+
errorRateScore * 0.35 +
|
|
6934
|
+
creditScore * 0.25);
|
|
6935
|
+
let level;
|
|
6936
|
+
if (compositeScore >= 80)
|
|
6937
|
+
level = 'healthy';
|
|
6938
|
+
else if (compositeScore >= 60)
|
|
6939
|
+
level = 'good';
|
|
6940
|
+
else if (compositeScore >= 40)
|
|
6941
|
+
level = 'warning';
|
|
6942
|
+
else
|
|
6943
|
+
level = 'critical';
|
|
6944
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
6945
|
+
res.end(JSON.stringify({
|
|
6946
|
+
score: compositeScore,
|
|
6947
|
+
level,
|
|
6948
|
+
components: {
|
|
6949
|
+
keyHealth: { score: keyHealthScore, weight: 0.4, detail: keyHealthDetail },
|
|
6950
|
+
errorRate: { score: errorRateScore, weight: 0.35, detail: errorRateDetail },
|
|
6951
|
+
creditUtilization: { score: creditScore, weight: 0.25, detail: creditDetail },
|
|
6952
|
+
},
|
|
6953
|
+
generatedAt: new Date().toISOString(),
|
|
6954
|
+
}));
|
|
6955
|
+
}
|
|
6791
6956
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
6792
6957
|
handleGetNotes(req, res) {
|
|
6793
6958
|
if (!this.checkAdmin(req, res))
|