paygate-mcp 8.3.0 → 8.4.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 +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +125 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,6 +110,7 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
|
|
|
110
110
|
- **Admin Notifications** — `GET /admin/notifications` scans all keys for actionable issues: expired/expiring keys, zero credits, credit depletion velocity, suspended keys, high error rates, and rate limit pressure — with severity filtering and priority sorting
|
|
111
111
|
- **System Dashboard** — `GET /admin/dashboard` system-wide overview with key counts (active/suspended/revoked/expired), credit summary (allocated/spent/remaining), usage breakdown with deny reasons, top consumers, top tools, notification counts, and uptime
|
|
112
112
|
- **Key Lifecycle Report** — `GET /admin/lifecycle` aggregated lifecycle trends with daily creation/revocation/suspension buckets, average key lifetime, and at-risk keys (expiring, expired, zero credits)
|
|
113
|
+
- **Cost Analysis** — `GET /admin/costs` cost-centric view with per-tool and per-namespace cost breakdowns, hourly spending trends, top spenders, average cost per call, and namespace filtering
|
|
113
114
|
- **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
|
|
114
115
|
- **Webhook Events** — POST batched usage events to any URL for external billing/alerting
|
|
115
116
|
- **Config File Mode** — Load all settings from a JSON file (`--config`)
|
|
@@ -2502,6 +2503,54 @@ curl "http://localhost:3402/admin/lifecycle?since=2026-02-01&until=2026-02-28" \
|
|
|
2502
2503
|
|
|
2503
2504
|
Shows aggregated lifecycle event counts, daily trend buckets (sorted chronologically), average key lifetime in hours (for revoked keys), and at-risk keys with their risk category (`expired`, `expiring_soon`, `zero_credits`). Supports `?since=` and `?until=` date filters. Excludes suspended and revoked keys from at-risk list. Read-only.
|
|
2504
2505
|
|
|
2506
|
+
### Cost Analysis
|
|
2507
|
+
|
|
2508
|
+
Get a cost-centric breakdown of credit usage across tools, namespaces, and time:
|
|
2509
|
+
|
|
2510
|
+
```bash
|
|
2511
|
+
# Full cost analysis
|
|
2512
|
+
curl http://localhost:3402/admin/costs \
|
|
2513
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2514
|
+
|
|
2515
|
+
# Filter by namespace
|
|
2516
|
+
curl "http://localhost:3402/admin/costs?namespace=prod" \
|
|
2517
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2518
|
+
|
|
2519
|
+
# Filter by time range
|
|
2520
|
+
curl "http://localhost:3402/admin/costs?since=2026-02-01" \
|
|
2521
|
+
-H "X-Admin-Key: YOUR_ADMIN_KEY"
|
|
2522
|
+
```
|
|
2523
|
+
|
|
2524
|
+
```json
|
|
2525
|
+
{
|
|
2526
|
+
"summary": {
|
|
2527
|
+
"totalCredits": 4250,
|
|
2528
|
+
"totalCalls": 312,
|
|
2529
|
+
"totalAllowed": 298,
|
|
2530
|
+
"totalDenied": 14,
|
|
2531
|
+
"avgCostPerCall": 13.62
|
|
2532
|
+
},
|
|
2533
|
+
"perTool": [
|
|
2534
|
+
{ "tool": "generate_report", "calls": 85, "credits": 1700, "avgCost": 20 },
|
|
2535
|
+
{ "tool": "query_data", "calls": 142, "credits": 1420, "avgCost": 10 }
|
|
2536
|
+
],
|
|
2537
|
+
"perNamespace": [
|
|
2538
|
+
{ "namespace": "prod", "calls": 210, "credits": 3150 },
|
|
2539
|
+
{ "namespace": "staging", "calls": 102, "credits": 1100 }
|
|
2540
|
+
],
|
|
2541
|
+
"hourlyTrends": [
|
|
2542
|
+
{ "hour": "2026-02-26T14:00:00.000Z", "calls": 23, "credits": 345, "denied": 1 },
|
|
2543
|
+
{ "hour": "2026-02-26T15:00:00.000Z", "calls": 31, "credits": 465, "denied": 0 }
|
|
2544
|
+
],
|
|
2545
|
+
"topSpenders": [
|
|
2546
|
+
{ "key": "pg_a1b2...c3d4", "name": "ml-pipeline", "credits": 1800, "calls": 90 },
|
|
2547
|
+
{ "key": "pg_e5f6...g7h8", "name": "batch-worker", "credits": 1200, "calls": 120 }
|
|
2548
|
+
]
|
|
2549
|
+
}
|
|
2550
|
+
```
|
|
2551
|
+
|
|
2552
|
+
Returns per-tool cost breakdown (with average cost per call), per-namespace spending, hourly trend buckets (last 24 hours), and top 10 spenders ranked by credits consumed. Supports `?since=` and `?namespace=` query filters. Keys without an explicit namespace appear under `default`. Read-only.
|
|
2553
|
+
|
|
2505
2554
|
### IP Allowlisting
|
|
2506
2555
|
|
|
2507
2556
|
Restrict API keys to specific IP addresses or CIDR ranges:
|
package/dist/server.d.ts
CHANGED
|
@@ -245,6 +245,7 @@ export declare class PayGateServer {
|
|
|
245
245
|
private handleAdminNotifications;
|
|
246
246
|
private handleSystemDashboard;
|
|
247
247
|
private handleKeyLifecycleReport;
|
|
248
|
+
private handleCostAnalysis;
|
|
248
249
|
private handleGetNotes;
|
|
249
250
|
private handleAddNote;
|
|
250
251
|
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
|
@@ -816,6 +816,12 @@ class PayGateServer {
|
|
|
816
816
|
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
817
817
|
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
818
818
|
return;
|
|
819
|
+
case '/admin/costs':
|
|
820
|
+
if (req.method === 'GET')
|
|
821
|
+
return this.handleCostAnalysis(req, res);
|
|
822
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
823
|
+
res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
|
|
824
|
+
return;
|
|
819
825
|
// ─── Plugin endpoints ──────────────────────────────────────────────
|
|
820
826
|
case '/plugins':
|
|
821
827
|
return this.handleListPlugins(req, res);
|
|
@@ -1359,6 +1365,7 @@ class PayGateServer {
|
|
|
1359
1365
|
adminNotifications: 'GET /admin/notifications — Actionable notifications for expiring keys, low credits, high error rates, and rate limit pressure (requires X-Admin-Key)',
|
|
1360
1366
|
systemDashboard: 'GET /admin/dashboard — System-wide overview with key stats, credit summary, usage breakdown, top consumers, and uptime (requires X-Admin-Key)',
|
|
1361
1367
|
keyLifecycle: 'GET /admin/lifecycle — Key lifecycle report with creation/revocation/expiry trends, average lifetime, and at-risk keys (requires X-Admin-Key)',
|
|
1368
|
+
costAnalysis: 'GET /admin/costs — Cost analysis with per-tool, per-namespace breakdown, hourly trends, and top spenders (requires X-Admin-Key)',
|
|
1362
1369
|
...(this.oauth ? {
|
|
1363
1370
|
oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
|
|
1364
1371
|
oauthRegister: 'POST /oauth/register — Register OAuth client',
|
|
@@ -4658,6 +4665,124 @@ class PayGateServer {
|
|
|
4658
4665
|
atRisk: atRiskKeys,
|
|
4659
4666
|
}));
|
|
4660
4667
|
}
|
|
4668
|
+
// ─── /admin/costs — Cost analysis ─────────────────────────────────────────
|
|
4669
|
+
handleCostAnalysis(req, res) {
|
|
4670
|
+
if (!this.checkAdmin(req, res))
|
|
4671
|
+
return;
|
|
4672
|
+
const urlParts = req.url?.split('?') || [];
|
|
4673
|
+
const params = new URLSearchParams(urlParts[1] || '');
|
|
4674
|
+
const since = params.get('since') || undefined;
|
|
4675
|
+
const namespace = params.get('namespace') || undefined;
|
|
4676
|
+
// Get all usage events
|
|
4677
|
+
const events = this.gate.meter.getEvents(since, namespace);
|
|
4678
|
+
// ── Per-tool cost breakdown ──
|
|
4679
|
+
const toolCosts = new Map();
|
|
4680
|
+
for (const e of events) {
|
|
4681
|
+
if (!toolCosts.has(e.tool))
|
|
4682
|
+
toolCosts.set(e.tool, { calls: 0, credits: 0, denied: 0, avgCost: 0 });
|
|
4683
|
+
const t = toolCosts.get(e.tool);
|
|
4684
|
+
t.calls++;
|
|
4685
|
+
if (e.allowed) {
|
|
4686
|
+
t.credits += e.creditsCharged;
|
|
4687
|
+
}
|
|
4688
|
+
else {
|
|
4689
|
+
t.denied++;
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
for (const [, t] of toolCosts) {
|
|
4693
|
+
const allowed = t.calls - t.denied;
|
|
4694
|
+
t.avgCost = allowed > 0 ? Math.round(t.credits / allowed * 100) / 100 : 0;
|
|
4695
|
+
}
|
|
4696
|
+
const perTool = Array.from(toolCosts.entries())
|
|
4697
|
+
.map(([tool, stats]) => ({ tool, ...stats }))
|
|
4698
|
+
.sort((a, b) => b.credits - a.credits);
|
|
4699
|
+
// ── Per-namespace cost breakdown ──
|
|
4700
|
+
const nsCosts = new Map();
|
|
4701
|
+
for (const e of events) {
|
|
4702
|
+
const ns = e.namespace || 'default';
|
|
4703
|
+
if (!nsCosts.has(ns))
|
|
4704
|
+
nsCosts.set(ns, { calls: 0, credits: 0, denied: 0 });
|
|
4705
|
+
const n = nsCosts.get(ns);
|
|
4706
|
+
n.calls++;
|
|
4707
|
+
if (e.allowed) {
|
|
4708
|
+
n.credits += e.creditsCharged;
|
|
4709
|
+
}
|
|
4710
|
+
else {
|
|
4711
|
+
n.denied++;
|
|
4712
|
+
}
|
|
4713
|
+
}
|
|
4714
|
+
const perNamespace = Array.from(nsCosts.entries())
|
|
4715
|
+
.map(([ns, stats]) => ({ namespace: ns, ...stats }))
|
|
4716
|
+
.sort((a, b) => b.credits - a.credits);
|
|
4717
|
+
// ── Hourly trends (last 24 buckets) ──
|
|
4718
|
+
const hourBuckets = new Map();
|
|
4719
|
+
for (const e of events) {
|
|
4720
|
+
const hour = e.timestamp.slice(0, 13); // YYYY-MM-DDTHH
|
|
4721
|
+
if (!hourBuckets.has(hour))
|
|
4722
|
+
hourBuckets.set(hour, { calls: 0, credits: 0, denied: 0 });
|
|
4723
|
+
const h = hourBuckets.get(hour);
|
|
4724
|
+
h.calls++;
|
|
4725
|
+
if (e.allowed) {
|
|
4726
|
+
h.credits += e.creditsCharged;
|
|
4727
|
+
}
|
|
4728
|
+
else {
|
|
4729
|
+
h.denied++;
|
|
4730
|
+
}
|
|
4731
|
+
}
|
|
4732
|
+
const hourlyTrends = Array.from(hourBuckets.entries())
|
|
4733
|
+
.map(([hour, stats]) => ({ hour, ...stats }))
|
|
4734
|
+
.sort((a, b) => a.hour.localeCompare(b.hour))
|
|
4735
|
+
.slice(-24);
|
|
4736
|
+
// ── Top spenders (by credits) ──
|
|
4737
|
+
const keyCosts = new Map();
|
|
4738
|
+
for (const e of events) {
|
|
4739
|
+
const name = e.keyName || e.apiKey.slice(0, 10);
|
|
4740
|
+
if (!keyCosts.has(name))
|
|
4741
|
+
keyCosts.set(name, { calls: 0, credits: 0, denied: 0 });
|
|
4742
|
+
const k = keyCosts.get(name);
|
|
4743
|
+
k.calls++;
|
|
4744
|
+
if (e.allowed) {
|
|
4745
|
+
k.credits += e.creditsCharged;
|
|
4746
|
+
}
|
|
4747
|
+
else {
|
|
4748
|
+
k.denied++;
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
const topSpenders = Array.from(keyCosts.entries())
|
|
4752
|
+
.map(([name, stats]) => ({ name, ...stats }))
|
|
4753
|
+
.sort((a, b) => b.credits - a.credits)
|
|
4754
|
+
.slice(0, 10);
|
|
4755
|
+
// ── Totals ──
|
|
4756
|
+
let totalCredits = 0;
|
|
4757
|
+
let totalCalls = 0;
|
|
4758
|
+
let totalDenied = 0;
|
|
4759
|
+
for (const e of events) {
|
|
4760
|
+
totalCalls++;
|
|
4761
|
+
if (e.allowed) {
|
|
4762
|
+
totalCredits += e.creditsCharged;
|
|
4763
|
+
}
|
|
4764
|
+
else {
|
|
4765
|
+
totalDenied++;
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
const avgCostPerCall = totalCalls - totalDenied > 0
|
|
4769
|
+
? Math.round(totalCredits / (totalCalls - totalDenied) * 100) / 100
|
|
4770
|
+
: 0;
|
|
4771
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
4772
|
+
res.end(JSON.stringify({
|
|
4773
|
+
summary: {
|
|
4774
|
+
totalCredits,
|
|
4775
|
+
totalCalls,
|
|
4776
|
+
totalAllowed: totalCalls - totalDenied,
|
|
4777
|
+
totalDenied,
|
|
4778
|
+
avgCostPerCall,
|
|
4779
|
+
},
|
|
4780
|
+
perTool,
|
|
4781
|
+
perNamespace,
|
|
4782
|
+
hourlyTrends,
|
|
4783
|
+
topSpenders,
|
|
4784
|
+
}));
|
|
4785
|
+
}
|
|
4661
4786
|
// ─── /keys/notes — Timestamped notes on API keys ─────────────────────────
|
|
4662
4787
|
handleGetNotes(req, res) {
|
|
4663
4788
|
if (!this.checkAdmin(req, res))
|