paygate-mcp 7.4.0 → 7.6.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 CHANGED
@@ -101,6 +101,8 @@ Agent → PayGate (auth + billing) → Your MCP Server (stdio or HTTP)
101
101
  - **Key Activity Timeline** — `GET /keys/activity?key=...` returns a unified chronological feed of audit events and usage events for a specific key — newest first, optional `?since=` and `?limit=` filters, alias support
102
102
  - **Credit Reservations** — `POST /keys/reserve` holds credits, `POST /keys/reserve/commit` deducts held credits, `POST /keys/reserve/release` frees the hold, `GET /keys/reserve` lists active reservations — prevents overcommit, configurable TTL (10s–1h), max 50 per key, auto-expiry, audit trail
103
103
  - **Request Log** — `GET /requests` queryable log of every tool call with timing, credits charged, status (allowed/denied), deny reason, key, and request ID — filter by key/tool/status/since, pagination, summary statistics (totals + avg duration), 5000-entry ring buffer
104
+ - **Tool Stats** — `GET /tools/stats` per-tool analytics: call counts, success rate, avg/p95 latency, credits consumed, deny reason breakdown, top 10 consumers — optional `?tool=` for detailed single-tool view, `?since=` filter
105
+ - **Request Log Export** — `GET /requests/export` exports the full request log as JSON or CSV with Content-Disposition headers — filter by key/tool/status/since/until, combined time-window queries, no pagination limit
104
106
  - **Config Hot Reload** — `POST /config/reload` reloads pricing, rate limits, webhooks, quotas, and behavior flags from config file without server restart
105
107
  - **Webhook Events** — POST batched usage events to any URL for external billing/alerting
106
108
  - **Config File Mode** — Load all settings from a JSON file (`--config`)
@@ -2143,6 +2145,96 @@ curl "http://localhost:3402/requests?tool=my_tool&status=allowed&limit=10" \
2143
2145
 
2144
2146
  5000-entry ring buffer. Summary statistics are computed on filtered results. Deny reasons: `insufficient_credits`, `rate_limited`, `invalid_api_key`, `key_suspended`, `api_key_expired`, `tool_not_allowed`, `quota_exceeded`.
2145
2147
 
2148
+ ### Tool Stats
2149
+
2150
+ Per-tool analytics derived from the request log:
2151
+
2152
+ ```bash
2153
+ # Overview of all tools
2154
+ curl "http://localhost:3402/tools/stats" -H "X-Admin-Key: YOUR_ADMIN_KEY"
2155
+
2156
+ # Detailed stats for a specific tool
2157
+ curl "http://localhost:3402/tools/stats?tool=my_tool" -H "X-Admin-Key: YOUR_ADMIN_KEY"
2158
+
2159
+ # Filter by time range
2160
+ curl "http://localhost:3402/tools/stats?since=2025-03-01T00:00:00Z" \
2161
+ -H "X-Admin-Key: YOUR_ADMIN_KEY"
2162
+ ```
2163
+
2164
+ **Response (overview):**
2165
+
2166
+ ```json
2167
+ {
2168
+ "totalTools": 3,
2169
+ "totalCalls": 150,
2170
+ "tools": [
2171
+ {
2172
+ "tool": "my_tool",
2173
+ "totalCalls": 100,
2174
+ "allowed": 95,
2175
+ "denied": 5,
2176
+ "successRate": 95,
2177
+ "totalCredits": 475,
2178
+ "avgDurationMs": 42
2179
+ }
2180
+ ]
2181
+ }
2182
+ ```
2183
+
2184
+ **Response (detailed `?tool=my_tool`):**
2185
+
2186
+ ```json
2187
+ {
2188
+ "tool": "my_tool",
2189
+ "totalCalls": 100,
2190
+ "allowed": 95,
2191
+ "denied": 5,
2192
+ "successRate": 95,
2193
+ "totalCredits": 475,
2194
+ "avgDurationMs": 42,
2195
+ "p95DurationMs": 120,
2196
+ "denyReasons": {
2197
+ "insufficient_credits": 3,
2198
+ "rate_limited": 2
2199
+ },
2200
+ "topConsumers": [
2201
+ { "key": "pg_abc1...2345", "calls": 50, "credits": 250 },
2202
+ { "key": "pg_xyz9...8765", "calls": 30, "credits": 150 }
2203
+ ]
2204
+ }
2205
+ ```
2206
+
2207
+ Top consumers limited to 10. Tools sorted by call count in overview. Data sourced from request log (5000-entry ring buffer).
2208
+
2209
+ ### Request Log Export
2210
+
2211
+ Export the request log as JSON or CSV for offline analysis:
2212
+
2213
+ ```bash
2214
+ # Export as JSON (default)
2215
+ curl "http://localhost:3402/requests/export" \
2216
+ -H "X-Admin-Key: YOUR_ADMIN_KEY" -o paygate-requests.json
2217
+
2218
+ # Export as CSV
2219
+ curl "http://localhost:3402/requests/export?format=csv" \
2220
+ -H "X-Admin-Key: YOUR_ADMIN_KEY" -o paygate-requests.csv
2221
+
2222
+ # Export with filters
2223
+ curl "http://localhost:3402/requests/export?tool=my_tool&status=denied&since=2025-03-01T00:00:00Z&until=2025-03-31T23:59:59Z" \
2224
+ -H "X-Admin-Key: YOUR_ADMIN_KEY"
2225
+ ```
2226
+
2227
+ | Parameter | Description |
2228
+ |-----------|-------------|
2229
+ | `format` | `json` (default) or `csv` |
2230
+ | `key` | Filter by API key (partial match) |
2231
+ | `tool` | Filter by tool name (exact match) |
2232
+ | `status` | `allowed` or `denied` |
2233
+ | `since` | ISO 8601 start timestamp |
2234
+ | `until` | ISO 8601 end timestamp |
2235
+
2236
+ Both formats include Content-Disposition headers for automatic file download. Unlike `/requests`, the export endpoint returns **all** matching entries (no pagination limit). CSV includes proper quoting for values with commas.
2237
+
2146
2238
  ### IP Allowlisting
2147
2239
 
2148
2240
  Restrict API keys to specific IP addresses or CIDR ranges:
package/dist/server.d.ts CHANGED
@@ -315,6 +315,10 @@ export declare class PayGateServer {
315
315
  */
316
316
  gracefulStop(timeoutMs?: number): Promise<void>;
317
317
  private handleRequestLog;
318
+ private handleToolStats;
319
+ private handleRequestLogExport;
320
+ /** Calculate percentile from an array of numbers. */
321
+ private percentile;
318
322
  }
319
323
  export {};
320
324
  //# sourceMappingURL=server.d.ts.map
@@ -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
@@ -678,6 +678,12 @@ class PayGateServer {
678
678
  res.writeHead(405, { 'Content-Type': 'application/json' });
679
679
  res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
680
680
  return;
681
+ case '/requests/export':
682
+ if (req.method === 'GET')
683
+ return this.handleRequestLogExport(req, res);
684
+ res.writeHead(405, { 'Content-Type': 'application/json' });
685
+ res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
686
+ return;
681
687
  // ─── Registry / Discovery endpoints ──────────────────────────────
682
688
  case '/.well-known/mcp-payment':
683
689
  return this.handlePaymentMetadata(req, res);
@@ -687,6 +693,12 @@ class PayGateServer {
687
693
  return this.handleMetrics(req, res);
688
694
  case '/analytics':
689
695
  return this.handleAnalytics(req, res);
696
+ case '/tools/stats':
697
+ if (req.method === 'GET')
698
+ return this.handleToolStats(req, res);
699
+ res.writeHead(405, { 'Content-Type': 'application/json' });
700
+ res.end(JSON.stringify({ error: 'Method not allowed. Use GET.' }));
701
+ return;
690
702
  case '/alerts':
691
703
  if (req.method === 'GET')
692
704
  return this.handleGetAlerts(req, res);
@@ -1296,6 +1308,8 @@ class PayGateServer {
1296
1308
  keyActivity: 'GET /keys/activity?key=... — Unified activity timeline for a key (requires X-Admin-Key)',
1297
1309
  creditReservations: 'POST /keys/reserve to hold credits, POST /keys/reserve/commit to deduct, POST /keys/reserve/release to release, GET /keys/reserve to list (requires X-Admin-Key)',
1298
1310
  requestLog: 'GET /requests — Queryable log of tool call requests with timing, credits, status (requires X-Admin-Key)',
1311
+ requestLogExport: 'GET /requests/export — Export request log as JSON or CSV with filters (requires X-Admin-Key)',
1312
+ toolStats: 'GET /tools/stats — Per-tool call counts, success rates, latency, credits, and top consumers (requires X-Admin-Key)',
1299
1313
  ...(this.oauth ? {
1300
1314
  oauthMetadata: 'GET /.well-known/oauth-authorization-server — OAuth 2.1 server metadata',
1301
1315
  oauthRegister: 'POST /oauth/register — Register OAuth client',
@@ -6340,6 +6354,190 @@ class PayGateServer {
6340
6354
  requests: page,
6341
6355
  }));
6342
6356
  }
6357
+ // ─── /tools/stats — Per-tool analytics from request log ────────────────────
6358
+ handleToolStats(req, res) {
6359
+ if (!this.checkAdmin(req, res))
6360
+ return;
6361
+ const urlParts = req.url?.split('?') || [];
6362
+ const params = new URLSearchParams(urlParts[1] || '');
6363
+ const sinceFilter = params.get('since');
6364
+ const toolFilter = params.get('tool');
6365
+ let entries = this.requestLog;
6366
+ // Filter by since
6367
+ if (sinceFilter) {
6368
+ const sinceTime = new Date(sinceFilter).getTime();
6369
+ if (!isNaN(sinceTime)) {
6370
+ entries = entries.filter(e => new Date(e.timestamp).getTime() >= sinceTime);
6371
+ }
6372
+ }
6373
+ // If specific tool requested, return detailed stats for just that tool
6374
+ if (toolFilter) {
6375
+ const toolEntries = entries.filter(e => e.tool === toolFilter);
6376
+ const allowed = toolEntries.filter(e => e.status === 'allowed');
6377
+ const denied = toolEntries.filter(e => e.status === 'denied');
6378
+ const totalCredits = toolEntries.reduce((sum, e) => sum + e.credits, 0);
6379
+ const avgDurationMs = toolEntries.length > 0
6380
+ ? Math.round(toolEntries.reduce((sum, e) => sum + e.durationMs, 0) / toolEntries.length)
6381
+ : 0;
6382
+ const p95 = this.percentile(toolEntries.map(e => e.durationMs), 95);
6383
+ // Deny reason breakdown
6384
+ const denyReasons = {};
6385
+ for (const e of denied) {
6386
+ const reason = e.denyReason || 'unknown';
6387
+ denyReasons[reason] = (denyReasons[reason] || 0) + 1;
6388
+ }
6389
+ // Top consumers by call count
6390
+ const consumerCalls = {};
6391
+ const consumerCredits = {};
6392
+ for (const e of toolEntries) {
6393
+ consumerCalls[e.key] = (consumerCalls[e.key] || 0) + 1;
6394
+ consumerCredits[e.key] = (consumerCredits[e.key] || 0) + e.credits;
6395
+ }
6396
+ const topConsumers = Object.entries(consumerCalls)
6397
+ .sort((a, b) => b[1] - a[1])
6398
+ .slice(0, 10)
6399
+ .map(([key, calls]) => ({ key, calls, credits: consumerCredits[key] || 0 }));
6400
+ res.writeHead(200, { 'Content-Type': 'application/json' });
6401
+ res.end(JSON.stringify({
6402
+ tool: toolFilter,
6403
+ totalCalls: toolEntries.length,
6404
+ allowed: allowed.length,
6405
+ denied: denied.length,
6406
+ successRate: toolEntries.length > 0
6407
+ ? Math.round((allowed.length / toolEntries.length) * 10000) / 100
6408
+ : 0,
6409
+ totalCredits,
6410
+ avgDurationMs,
6411
+ p95DurationMs: p95,
6412
+ denyReasons,
6413
+ topConsumers,
6414
+ }));
6415
+ return;
6416
+ }
6417
+ // Aggregate stats per tool
6418
+ const toolMap = {};
6419
+ for (const e of entries) {
6420
+ if (!toolMap[e.tool]) {
6421
+ toolMap[e.tool] = { calls: 0, allowed: 0, denied: 0, credits: 0, totalDurationMs: 0 };
6422
+ }
6423
+ const t = toolMap[e.tool];
6424
+ t.calls++;
6425
+ if (e.status === 'allowed')
6426
+ t.allowed++;
6427
+ else
6428
+ t.denied++;
6429
+ t.credits += e.credits;
6430
+ t.totalDurationMs += e.durationMs;
6431
+ }
6432
+ const tools = Object.entries(toolMap)
6433
+ .map(([tool, stats]) => ({
6434
+ tool,
6435
+ totalCalls: stats.calls,
6436
+ allowed: stats.allowed,
6437
+ denied: stats.denied,
6438
+ successRate: stats.calls > 0
6439
+ ? Math.round((stats.allowed / stats.calls) * 10000) / 100
6440
+ : 0,
6441
+ totalCredits: stats.credits,
6442
+ avgDurationMs: stats.calls > 0 ? Math.round(stats.totalDurationMs / stats.calls) : 0,
6443
+ }))
6444
+ .sort((a, b) => b.totalCalls - a.totalCalls);
6445
+ res.writeHead(200, { 'Content-Type': 'application/json' });
6446
+ res.end(JSON.stringify({
6447
+ totalTools: tools.length,
6448
+ totalCalls: entries.length,
6449
+ tools,
6450
+ }));
6451
+ }
6452
+ // ─── /requests/export — Export request log as JSON or CSV ───────────────────
6453
+ handleRequestLogExport(req, res) {
6454
+ if (!this.checkAdmin(req, res))
6455
+ return;
6456
+ const urlParts = req.url?.split('?') || [];
6457
+ const params = new URLSearchParams(urlParts[1] || '');
6458
+ const format = params.get('format') || 'json';
6459
+ const keyFilter = params.get('key');
6460
+ const toolFilter = params.get('tool');
6461
+ const statusFilter = params.get('status');
6462
+ const sinceFilter = params.get('since');
6463
+ const untilFilter = params.get('until');
6464
+ let filtered = this.requestLog;
6465
+ // Filter by key (partial match on masked key)
6466
+ if (keyFilter) {
6467
+ const kf = keyFilter.toLowerCase();
6468
+ filtered = filtered.filter(e => e.key.toLowerCase().includes(kf));
6469
+ }
6470
+ // Filter by tool name (exact match)
6471
+ if (toolFilter) {
6472
+ filtered = filtered.filter(e => e.tool === toolFilter);
6473
+ }
6474
+ // Filter by status
6475
+ if (statusFilter === 'allowed' || statusFilter === 'denied') {
6476
+ filtered = filtered.filter(e => e.status === statusFilter);
6477
+ }
6478
+ // Filter by since timestamp
6479
+ if (sinceFilter) {
6480
+ const sinceTime = new Date(sinceFilter).getTime();
6481
+ if (!isNaN(sinceTime)) {
6482
+ filtered = filtered.filter(e => new Date(e.timestamp).getTime() >= sinceTime);
6483
+ }
6484
+ }
6485
+ // Filter by until timestamp
6486
+ if (untilFilter) {
6487
+ const untilTime = new Date(untilFilter).getTime();
6488
+ if (!isNaN(untilTime)) {
6489
+ filtered = filtered.filter(e => new Date(e.timestamp).getTime() <= untilTime);
6490
+ }
6491
+ }
6492
+ // Return newest first
6493
+ const sorted = [...filtered].reverse();
6494
+ if (format === 'csv') {
6495
+ const header = 'id,timestamp,tool,key,status,credits,durationMs,denyReason,requestId';
6496
+ const rows = sorted.map(e => {
6497
+ const escapeCsv = (v) => {
6498
+ if (v === undefined || v === null)
6499
+ return '';
6500
+ const s = String(v);
6501
+ if (s.includes(',') || s.includes('"') || s.includes('\n')) {
6502
+ return '"' + s.replace(/"/g, '""') + '"';
6503
+ }
6504
+ return s;
6505
+ };
6506
+ return [
6507
+ e.id,
6508
+ e.timestamp,
6509
+ escapeCsv(e.tool),
6510
+ escapeCsv(e.key),
6511
+ e.status,
6512
+ e.credits,
6513
+ e.durationMs,
6514
+ escapeCsv(e.denyReason),
6515
+ escapeCsv(e.requestId),
6516
+ ].join(',');
6517
+ });
6518
+ const csv = [header, ...rows].join('\n');
6519
+ res.writeHead(200, {
6520
+ 'Content-Type': 'text/csv',
6521
+ 'Content-Disposition': 'attachment; filename="paygate-requests.csv"',
6522
+ });
6523
+ res.end(csv);
6524
+ }
6525
+ else {
6526
+ res.writeHead(200, {
6527
+ 'Content-Type': 'application/json',
6528
+ 'Content-Disposition': 'attachment; filename="paygate-requests.json"',
6529
+ });
6530
+ res.end(JSON.stringify({ count: sorted.length, requests: sorted }, null, 2));
6531
+ }
6532
+ }
6533
+ /** Calculate percentile from an array of numbers. */
6534
+ percentile(values, p) {
6535
+ if (values.length === 0)
6536
+ return 0;
6537
+ const sorted = [...values].sort((a, b) => a - b);
6538
+ const idx = Math.ceil((p / 100) * sorted.length) - 1;
6539
+ return sorted[Math.max(0, idx)];
6540
+ }
6343
6541
  }
6344
6542
  exports.PayGateServer = PayGateServer;
6345
6543
  //# sourceMappingURL=server.js.map