mcp-server-agentpay 1.0.5 → 1.1.1
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/LICENSE +21 -0
- package/README.md +37 -22
- package/index.js +211 -25
- package/package.json +7 -7
- package/server.json +12 -5
- package/SKILL.md +0 -112
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MetalTorque
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# mcp-server-agentpay
|
|
2
2
|
|
|
3
|
+
<a href="https://glama.ai/mcp/servers/@joepangallo/mcp-server-agentpay"><img width="380" height="200" src="https://glama.ai/mcp/servers/@joepangallo/mcp-server-agentpay/badge" alt="AgentPay MCP server" /></a>
|
|
4
|
+
|
|
3
5
|
MCP server for **AgentPay** — the payment gateway for autonomous AI agents.
|
|
4
6
|
|
|
5
|
-
Fund a wallet once, give your agent the key, and it discovers, provisions, and pays for tool APIs on its own.
|
|
7
|
+
Fund a wallet once, give your agent the key, and it discovers, provisions, and pays for tool APIs on its own. One key, every tool.
|
|
6
8
|
|
|
7
9
|
## Quick Setup
|
|
8
10
|
|
|
@@ -23,8 +25,7 @@ Or add to `~/.claude/settings.json`:
|
|
|
23
25
|
"command": "npx",
|
|
24
26
|
"args": ["-y", "mcp-server-agentpay"],
|
|
25
27
|
"env": {
|
|
26
|
-
"AGENTPAY_GATEWAY_KEY": "apg_your_key_here"
|
|
27
|
-
"AGENTPAY_URL": "https://agentpay.metaltorque.dev"
|
|
28
|
+
"AGENTPAY_GATEWAY_KEY": "apg_your_key_here"
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
}
|
|
@@ -34,36 +35,54 @@ Or add to `~/.claude/settings.json`:
|
|
|
34
35
|
## Get a Gateway Key
|
|
35
36
|
|
|
36
37
|
```bash
|
|
37
|
-
curl -X POST https://
|
|
38
|
+
curl -X POST https://pay.leddconsulting.com/gateway/register \
|
|
38
39
|
-H "Content-Type: application/json" \
|
|
39
40
|
-d '{"email": "you@example.com"}'
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
You get $1 in free credits to start.
|
|
43
44
|
|
|
44
|
-
## Tools
|
|
45
|
+
## Tools
|
|
45
46
|
|
|
46
47
|
| Tool | Description |
|
|
47
48
|
|------|-------------|
|
|
48
|
-
| `discover_tools` | Search tools by keyword |
|
|
49
|
+
| `discover_tools` | Search tools by keyword (e.g. 'security', 'seo') |
|
|
49
50
|
| `list_tools` | List all available tools with pricing |
|
|
50
51
|
| `check_balance` | Check wallet balance and provisioned tools |
|
|
51
52
|
| `call_tool` | Call any tool method (metered, auto-provisions) |
|
|
52
53
|
| `provision_tool` | Pre-provision access to a tool |
|
|
53
54
|
| `get_usage` | View recent call history and costs |
|
|
54
55
|
| `fund_wallet_stripe` | Get Stripe checkout URL for credits |
|
|
55
|
-
| `fund_wallet_x402` | Get x402 crypto funding info |
|
|
56
|
+
| `fund_wallet_x402` | Get x402 crypto funding info (autonomous USDC) |
|
|
56
57
|
| `x402_info` | View x402 payment options and setup |
|
|
57
58
|
|
|
59
|
+
### Admin Tools (optional, requires `AGENTPAY_ADMIN_KEY`)
|
|
60
|
+
|
|
61
|
+
| Tool | Description |
|
|
62
|
+
|------|-------------|
|
|
63
|
+
| `reliability_dashboard` | Circuit breaker states, health metrics, recent events |
|
|
64
|
+
| `reliability_tool_detail` | Detailed reliability info for a specific tool |
|
|
65
|
+
| `reliability_reset` | Force-close a tripped circuit breaker |
|
|
66
|
+
| `reliability_config` | Update circuit breaker settings |
|
|
67
|
+
|
|
68
|
+
## How It Works
|
|
69
|
+
|
|
70
|
+
1. **Register** — create a wallet, get a gateway key
|
|
71
|
+
2. **Fund** — add credits via Stripe or x402 USDC
|
|
72
|
+
3. **Discover** — agent searches for tools by capability
|
|
73
|
+
4. **Call** — agent calls any tool, gateway handles auth + billing
|
|
74
|
+
|
|
75
|
+
The agent never needs to know about individual tool APIs, accounts, or payment. One key, every tool.
|
|
76
|
+
|
|
58
77
|
## Funding Methods
|
|
59
78
|
|
|
60
79
|
### Stripe (human-in-the-loop)
|
|
61
80
|
Use `fund_wallet_stripe` — returns a checkout URL for a human to complete.
|
|
62
81
|
|
|
63
82
|
### x402 USDC (fully autonomous)
|
|
64
|
-
Use `fund_wallet_x402` — returns endpoint, network, and instructions for autonomous USDC payments via the x402 protocol
|
|
83
|
+
Use `fund_wallet_x402` — returns endpoint, network, and instructions for autonomous USDC payments via the [x402 protocol](https://www.x402.org/). No human needed.
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
### Credit Packages
|
|
67
86
|
|
|
68
87
|
| Package | Price | Credits |
|
|
69
88
|
|---------|-------|---------|
|
|
@@ -73,31 +92,27 @@ Use `fund_wallet_x402` — returns endpoint, network, and instructions for auton
|
|
|
73
92
|
| large | $350 | 500 |
|
|
74
93
|
| whale | $600 | 1,000 |
|
|
75
94
|
|
|
76
|
-
## How It Works
|
|
77
|
-
|
|
78
|
-
1. **Register** — create a wallet, get a gateway key
|
|
79
|
-
2. **Fund** — add credits via Stripe or x402 USDC
|
|
80
|
-
3. **Discover** — agent searches for tools by capability
|
|
81
|
-
4. **Call** — agent calls any tool, gateway handles auth + billing
|
|
82
|
-
|
|
83
|
-
The agent never needs to know about individual tool APIs, accounts, or payment. One key, every tool.
|
|
84
|
-
|
|
85
95
|
## Environment Variables
|
|
86
96
|
|
|
87
97
|
| Variable | Required | Description |
|
|
88
98
|
|----------|----------|-------------|
|
|
89
99
|
| `AGENTPAY_GATEWAY_KEY` | Yes | Your gateway API key (starts with `apg_`) |
|
|
90
|
-
| `
|
|
100
|
+
| `AGENTPAY_ADMIN_KEY` | No | Admin key for reliability endpoints |
|
|
101
|
+
| `AGENTPAY_URL` | No | Custom gateway URL (default: `https://pay.leddconsulting.com`) |
|
|
91
102
|
|
|
92
103
|
## Available Tools (via gateway)
|
|
93
104
|
|
|
94
105
|
- **Security Audit** — scan websites for vulnerabilities, SSL issues, OWASP risks
|
|
95
106
|
- **IndexForge SEO** — submit URLs to Google/Bing, scan sitemaps, check index status
|
|
96
107
|
|
|
97
|
-
More tools added regularly.
|
|
108
|
+
More tools added regularly. Developers can register tools at the [marketplace](https://pay.leddconsulting.com/docs).
|
|
98
109
|
|
|
99
110
|
## Links
|
|
100
111
|
|
|
101
|
-
- [
|
|
102
|
-
- [
|
|
112
|
+
- [API Docs](https://pay.leddconsulting.com/docs)
|
|
113
|
+
- [Status Page](https://pay.leddconsulting.com/status)
|
|
103
114
|
- [MCP Registry](https://registry.modelcontextprotocol.io) — `io.github.joepangallo/agent-pay`
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT
|
package/index.js
CHANGED
|
@@ -10,20 +10,8 @@ const { version } = require("./package.json");
|
|
|
10
10
|
// ── Config ──────────────────────────────────────────────────────────
|
|
11
11
|
|
|
12
12
|
const GATEWAY_KEY = process.env.AGENTPAY_GATEWAY_KEY || "";
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const parsedHost = new URL(rawUrl).hostname;
|
|
16
|
-
if (!ALLOWED_HOSTS.includes(parsedHost)) {
|
|
17
|
-
console.error(`[agentpay] SECURITY: AGENTPAY_URL host "${parsedHost}" not in allowlist. Refusing to start.`);
|
|
18
|
-
console.error(`[agentpay] Allowed: ${ALLOWED_HOSTS.join(", ")}. Override with caution.`);
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
const BASE_URL = rawUrl;
|
|
22
|
-
|
|
23
|
-
// ── Session spending cap ────────────────────────────────────────────
|
|
24
|
-
|
|
25
|
-
const SESSION_BUDGET = Number(process.env.AGENTPAY_SESSION_BUDGET) || 25; // $25 default
|
|
26
|
-
let sessionSpent = 0;
|
|
13
|
+
const ADMIN_KEY = process.env.AGENTPAY_ADMIN_KEY || "";
|
|
14
|
+
const BASE_URL = (process.env.AGENTPAY_URL || "https://pay.leddconsulting.com").replace(/\/$/, "");
|
|
27
15
|
|
|
28
16
|
// ── HTTP helper ─────────────────────────────────────────────────────
|
|
29
17
|
|
|
@@ -85,10 +73,70 @@ function request(method, urlPath, body, timeout = 120_000) {
|
|
|
85
73
|
|
|
86
74
|
function noKeyError() {
|
|
87
75
|
return {
|
|
88
|
-
content: [{ type: "text", text: "Error: AGENTPAY_GATEWAY_KEY environment variable is required.\n\nRegister at https://
|
|
76
|
+
content: [{ type: "text", text: "Error: AGENTPAY_GATEWAY_KEY environment variable is required.\n\nRegister at https://pay.leddconsulting.com to get a gateway key.\nYou get $1 in free credits to start." }],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function noAdminKeyError() {
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: "text", text: "Error: AGENTPAY_ADMIN_KEY environment variable is required for reliability endpoints.\n\nThis is the admin key configured on the AgentPay server." }],
|
|
89
83
|
};
|
|
90
84
|
}
|
|
91
85
|
|
|
86
|
+
function adminRequest(method, urlPath, body, timeout = 30_000) {
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
const fullUrl = `${BASE_URL}${urlPath}`;
|
|
89
|
+
const parsed = new URL(fullUrl);
|
|
90
|
+
const isHttps = parsed.protocol === "https:";
|
|
91
|
+
|
|
92
|
+
if (!isHttps && ADMIN_KEY) {
|
|
93
|
+
return reject(new Error("Refusing to send admin key over insecure HTTP. Use HTTPS."));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const mod = isHttps ? https : http;
|
|
97
|
+
|
|
98
|
+
const headers = {
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
"User-Agent": `mcp-server-agentpay/${version}`,
|
|
101
|
+
"Authorization": `Bearer ${ADMIN_KEY}`,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const opts = {
|
|
105
|
+
hostname: parsed.hostname,
|
|
106
|
+
port: parsed.port || (isHttps ? 443 : 80),
|
|
107
|
+
path: parsed.pathname + parsed.search,
|
|
108
|
+
method,
|
|
109
|
+
headers,
|
|
110
|
+
timeout,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const req = mod.request(opts, (res) => {
|
|
114
|
+
let data = "";
|
|
115
|
+
let size = 0;
|
|
116
|
+
res.on("data", (c) => {
|
|
117
|
+
size += c.length;
|
|
118
|
+
if (size > MAX_RESPONSE_SIZE) { req.destroy(); return reject(new Error("Response too large")); }
|
|
119
|
+
data += c;
|
|
120
|
+
});
|
|
121
|
+
res.on("end", () => {
|
|
122
|
+
try {
|
|
123
|
+
const json = JSON.parse(data);
|
|
124
|
+
if (res.statusCode >= 400) return reject(new Error(json.error || `HTTP ${res.statusCode}`));
|
|
125
|
+
resolve(json);
|
|
126
|
+
} catch {
|
|
127
|
+
if (res.statusCode >= 400) return reject(new Error(`HTTP ${res.statusCode}: ${data.slice(0, 300)}`));
|
|
128
|
+
resolve(data);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
req.on("error", reject);
|
|
134
|
+
req.on("timeout", () => { req.destroy(); reject(new Error("Request timed out")); });
|
|
135
|
+
if (body) req.write(JSON.stringify(body));
|
|
136
|
+
req.end();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
92
140
|
// ── MCP Server ──────────────────────────────────────────────────────
|
|
93
141
|
|
|
94
142
|
const server = new McpServer({
|
|
@@ -154,7 +202,7 @@ server.tool(
|
|
|
154
202
|
|
|
155
203
|
server.tool(
|
|
156
204
|
"call_tool",
|
|
157
|
-
"Call any tool method through the AgentPay gateway. Automatically provisions access on first use. Credits are deducted per call
|
|
205
|
+
"Call any tool method through the AgentPay gateway. Automatically provisions access on first use. Credits are deducted per call. Use discover_tools or list_tools first to see available tools and methods.",
|
|
158
206
|
{
|
|
159
207
|
tool: z.string().describe("Tool ID (e.g. 'agent-audit', 'indexforge')"),
|
|
160
208
|
method: z.string().describe("Method name (e.g. 'security_scan', 'scan_sitemap')"),
|
|
@@ -162,12 +210,6 @@ server.tool(
|
|
|
162
210
|
},
|
|
163
211
|
async ({ tool, method, params_json }) => {
|
|
164
212
|
if (!GATEWAY_KEY) return noKeyError();
|
|
165
|
-
|
|
166
|
-
// Session spending cap
|
|
167
|
-
if (sessionSpent >= SESSION_BUDGET) {
|
|
168
|
-
return { content: [{ type: "text", text: `Session budget exhausted ($${sessionSpent.toFixed(2)}/$${SESSION_BUDGET}). Restart the MCP server or increase AGENTPAY_SESSION_BUDGET to continue.` }] };
|
|
169
|
-
}
|
|
170
|
-
|
|
171
213
|
try {
|
|
172
214
|
let params = {};
|
|
173
215
|
if (params_json) {
|
|
@@ -175,9 +217,8 @@ server.tool(
|
|
|
175
217
|
}
|
|
176
218
|
const result = await request("POST", "/gateway/call", { tool, method, params }, 600_000);
|
|
177
219
|
const cost = Number(result.cost) || 0;
|
|
178
|
-
sessionSpent += cost;
|
|
179
220
|
const balance = Number(result.balance) || 0;
|
|
180
|
-
const meta = `[Cost: $${cost.toFixed(2)} | Balance: $${balance.toFixed(2)} |
|
|
221
|
+
const meta = `[Cost: $${cost.toFixed(2)} | Balance: $${balance.toFixed(2)} | Time: ${result.elapsed || 0}ms]`;
|
|
181
222
|
return {
|
|
182
223
|
content: [{ type: "text", text: `${meta}\n\n${JSON.stringify(result.result, null, 2)}` }],
|
|
183
224
|
};
|
|
@@ -248,7 +289,7 @@ server.tool(
|
|
|
248
289
|
|
|
249
290
|
server.tool(
|
|
250
291
|
"fund_wallet_x402",
|
|
251
|
-
"Get x402 crypto funding info for your wallet. Returns the endpoint URL, network, and setup instructions.
|
|
292
|
+
"Get x402 crypto funding info for your wallet. Returns the endpoint URL, network, and setup instructions. To actually pay, your HTTP client needs @x402/fetch which automatically handles the 402 payment flow with USDC. This is the fully autonomous funding method — no human needed.",
|
|
252
293
|
{
|
|
253
294
|
package: z.enum(["micro", "small", "medium", "large", "whale"]).describe("Credit package: micro ($10/10cr), small ($45/50cr), medium ($80/100cr), large ($350/500cr), whale ($600/1000cr)"),
|
|
254
295
|
},
|
|
@@ -301,6 +342,151 @@ server.tool(
|
|
|
301
342
|
}
|
|
302
343
|
);
|
|
303
344
|
|
|
345
|
+
// ── Tool: reliability_dashboard ────────────────────────────────────
|
|
346
|
+
|
|
347
|
+
server.tool(
|
|
348
|
+
"reliability_dashboard",
|
|
349
|
+
"View the full reliability dashboard — circuit breaker states, health metrics (latency p50/p95/p99, success rates), and recent events for all tool backends. Requires admin key.",
|
|
350
|
+
{},
|
|
351
|
+
async () => {
|
|
352
|
+
if (!ADMIN_KEY) return noAdminKeyError();
|
|
353
|
+
try {
|
|
354
|
+
const result = await adminRequest("GET", "/admin/reliability");
|
|
355
|
+
const circuits = result.circuits || {};
|
|
356
|
+
const health = result.health || {};
|
|
357
|
+
const events = result.events || [];
|
|
358
|
+
|
|
359
|
+
let text = "=== Reliability Dashboard ===\n\n";
|
|
360
|
+
|
|
361
|
+
// Circuit states
|
|
362
|
+
text += "CIRCUITS:\n";
|
|
363
|
+
const toolIds = Object.keys(circuits);
|
|
364
|
+
if (toolIds.length === 0) {
|
|
365
|
+
text += " No circuit data yet (no tool calls made since restart)\n";
|
|
366
|
+
} else {
|
|
367
|
+
for (const id of toolIds) {
|
|
368
|
+
const c = circuits[id];
|
|
369
|
+
text += ` ${id}: ${c.state} (failures: ${c.failureCount}, successes: ${c.successCount})\n`;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Health metrics
|
|
374
|
+
text += "\nHEALTH:\n";
|
|
375
|
+
const healthIds = Object.keys(health);
|
|
376
|
+
if (healthIds.length === 0) {
|
|
377
|
+
text += " No health data yet\n";
|
|
378
|
+
} else {
|
|
379
|
+
for (const id of healthIds) {
|
|
380
|
+
const h = health[id];
|
|
381
|
+
text += ` ${id}: ${h.successRate}% success (${h.requests.total} calls) — latency avg ${h.latency.avg}ms, p95 ${h.latency.p95}ms\n`;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Recent events
|
|
386
|
+
if (events.length > 0) {
|
|
387
|
+
text += `\nRECENT EVENTS (last ${events.length}):\n`;
|
|
388
|
+
for (const e of events.slice(-10)) {
|
|
389
|
+
const status = e.success ? "OK" : "FAIL";
|
|
390
|
+
text += ` [${e.timestamp}] ${e.toolId}.${e.method} ${status} ${e.latencyMs}ms${e.error ? " — " + e.error : ""}\n`;
|
|
391
|
+
}
|
|
392
|
+
if (events.length > 10) text += ` ... and ${events.length - 10} more\n`;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return { content: [{ type: "text", text }] };
|
|
396
|
+
} catch (e) {
|
|
397
|
+
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
// ── Tool: reliability_tool_detail ─────────────────────────────────
|
|
403
|
+
|
|
404
|
+
server.tool(
|
|
405
|
+
"reliability_tool_detail",
|
|
406
|
+
"Get detailed reliability info for a specific tool — circuit breaker state, config (thresholds, timeouts), health metrics, and recent events.",
|
|
407
|
+
{
|
|
408
|
+
tool_id: z.string().describe("Tool ID (e.g. 'agent-audit', 'indexforge')"),
|
|
409
|
+
},
|
|
410
|
+
async ({ tool_id }) => {
|
|
411
|
+
if (!ADMIN_KEY) return noAdminKeyError();
|
|
412
|
+
try {
|
|
413
|
+
const result = await adminRequest("GET", `/admin/reliability/${encodeURIComponent(tool_id)}`);
|
|
414
|
+
const c = result.circuit || {};
|
|
415
|
+
const cfg = result.config || {};
|
|
416
|
+
const h = result.health || {};
|
|
417
|
+
const events = result.events || [];
|
|
418
|
+
|
|
419
|
+
let text = `=== ${tool_id} Reliability ===\n\n`;
|
|
420
|
+
text += `CIRCUIT: ${c.state} (failures: ${c.failureCount}, successes: ${c.successCount})\n`;
|
|
421
|
+
text += `CONFIG: threshold=${cfg.failureThreshold} failures, recovery=${cfg.recoveryTimeoutMs}ms, timeout=${cfg.requestTimeoutMs}ms\n`;
|
|
422
|
+
text += `HEALTH: ${h.successRate}% success (${h.requests?.total || 0} calls)\n`;
|
|
423
|
+
text += `LATENCY: avg=${h.latency?.avg || 0}ms, p50=${h.latency?.p50 || 0}ms, p95=${h.latency?.p95 || 0}ms, p99=${h.latency?.p99 || 0}ms (${h.latency?.samples || 0} samples)\n`;
|
|
424
|
+
if (h.lastCall) text += `LAST CALL: ${h.lastCall}\n`;
|
|
425
|
+
|
|
426
|
+
if (events.length > 0) {
|
|
427
|
+
text += `\nEVENTS (${events.length}):\n`;
|
|
428
|
+
for (const e of events.slice(-20)) {
|
|
429
|
+
const status = e.success ? "OK" : "FAIL";
|
|
430
|
+
text += ` [${e.timestamp}] ${e.method} ${status} ${e.latencyMs}ms${e.error ? " — " + e.error : ""}\n`;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return { content: [{ type: "text", text }] };
|
|
435
|
+
} catch (e) {
|
|
436
|
+
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
// ── Tool: reliability_reset ───────────────────────────────────────
|
|
442
|
+
|
|
443
|
+
server.tool(
|
|
444
|
+
"reliability_reset",
|
|
445
|
+
"Force-close a tripped circuit breaker for a tool, allowing calls to resume immediately. Use when a backend has recovered but the circuit hasn't automatically reset yet.",
|
|
446
|
+
{
|
|
447
|
+
tool_id: z.string().describe("Tool ID to reset (e.g. 'agent-audit', 'indexforge')"),
|
|
448
|
+
},
|
|
449
|
+
async ({ tool_id }) => {
|
|
450
|
+
if (!ADMIN_KEY) return noAdminKeyError();
|
|
451
|
+
try {
|
|
452
|
+
const result = await adminRequest("POST", `/admin/reliability/${encodeURIComponent(tool_id)}/reset`);
|
|
453
|
+
return { content: [{ type: "text", text: `Circuit reset for ${tool_id}: ${result.previousState} → ${result.currentState}` }] };
|
|
454
|
+
} catch (e) {
|
|
455
|
+
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
// ── Tool: reliability_config ──────────────────────────────────────
|
|
461
|
+
|
|
462
|
+
server.tool(
|
|
463
|
+
"reliability_config",
|
|
464
|
+
"Update reliability settings for a specific tool — failure threshold, recovery timeout, and request timeout. Changes take effect immediately.",
|
|
465
|
+
{
|
|
466
|
+
tool_id: z.string().describe("Tool ID to configure (e.g. 'agent-audit', 'indexforge')"),
|
|
467
|
+
failure_threshold: z.number().int().min(1).max(100).optional().describe("Number of consecutive failures before circuit opens (1-100)"),
|
|
468
|
+
recovery_timeout_ms: z.number().int().min(5000).max(600000).optional().describe("Milliseconds before OPEN circuit tries recovery (5000-600000)"),
|
|
469
|
+
request_timeout_ms: z.number().int().min(1000).max(600000).optional().describe("Per-request timeout in milliseconds (1000-600000)"),
|
|
470
|
+
},
|
|
471
|
+
async ({ tool_id, failure_threshold, recovery_timeout_ms, request_timeout_ms }) => {
|
|
472
|
+
if (!ADMIN_KEY) return noAdminKeyError();
|
|
473
|
+
const body = {};
|
|
474
|
+
if (failure_threshold !== undefined) body.failureThreshold = failure_threshold;
|
|
475
|
+
if (recovery_timeout_ms !== undefined) body.recoveryTimeoutMs = recovery_timeout_ms;
|
|
476
|
+
if (request_timeout_ms !== undefined) body.requestTimeoutMs = request_timeout_ms;
|
|
477
|
+
if (Object.keys(body).length === 0) {
|
|
478
|
+
return { content: [{ type: "text", text: "Error: Provide at least one setting to update (failure_threshold, recovery_timeout_ms, request_timeout_ms)" }] };
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
const result = await adminRequest("POST", `/admin/reliability/${encodeURIComponent(tool_id)}/config`, body);
|
|
482
|
+
const cfg = result.config || {};
|
|
483
|
+
return { content: [{ type: "text", text: `Config updated for ${tool_id}:\n failureThreshold: ${cfg.failureThreshold}\n recoveryTimeoutMs: ${cfg.recoveryTimeoutMs}\n requestTimeoutMs: ${cfg.requestTimeoutMs}` }] };
|
|
484
|
+
} catch (e) {
|
|
485
|
+
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
|
|
304
490
|
// ── Start ───────────────────────────────────────────────────────────
|
|
305
491
|
|
|
306
492
|
async function main() {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-server-agentpay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"mcpName": "io.github.joepangallo/agent-pay",
|
|
5
|
-
"description": "MCP server for AgentPay — the payment gateway for autonomous AI agents.
|
|
5
|
+
"description": "MCP server for AgentPay — the payment gateway for autonomous AI agents. Discover, provision, and pay for MCP tool APIs. Includes reliability monitoring with circuit breakers and health metrics.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mcp-server-agentpay": "index.js"
|
|
8
8
|
},
|
|
@@ -41,11 +41,12 @@
|
|
|
41
41
|
"author": "MetalTorque",
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
44
|
-
"url": "https://github.com/joepangallo/
|
|
44
|
+
"url": "https://github.com/joepangallo/mcp-server-agentpay"
|
|
45
45
|
},
|
|
46
|
+
"homepage": "https://pay.leddconsulting.com",
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"@modelcontextprotocol/sdk": "1.27.0",
|
|
48
|
-
"zod": "3.
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
49
|
+
"zod": "^3.23.0"
|
|
49
50
|
},
|
|
50
51
|
"engines": {
|
|
51
52
|
"node": ">=18"
|
|
@@ -53,8 +54,7 @@
|
|
|
53
54
|
"files": [
|
|
54
55
|
"index.js",
|
|
55
56
|
"README.md",
|
|
56
|
-
"SKILL.md",
|
|
57
57
|
"server.json",
|
|
58
58
|
"package.json"
|
|
59
59
|
]
|
|
60
|
-
}
|
|
60
|
+
}
|
package/server.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.joepangallo/agent-pay",
|
|
4
|
-
"description": "Payment gateway for AI agents.
|
|
4
|
+
"description": "Payment gateway for AI agents. Discover, provision, and pay for tool APIs.",
|
|
5
5
|
"repository": {
|
|
6
|
-
"url": "https://github.com/joepangallo/
|
|
6
|
+
"url": "https://github.com/joepangallo/mcp-server-agentpay",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.1.1",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "mcp-server-agentpay",
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.1.1",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -24,7 +24,14 @@
|
|
|
24
24
|
"name": "AGENTPAY_GATEWAY_KEY"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
"description": "
|
|
27
|
+
"description": "Admin key for reliability endpoints (circuit breakers, health metrics, config)",
|
|
28
|
+
"isRequired": false,
|
|
29
|
+
"format": "string",
|
|
30
|
+
"isSecret": true,
|
|
31
|
+
"name": "AGENTPAY_ADMIN_KEY"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"description": "AgentPay API URL. Defaults to https://pay.leddconsulting.com",
|
|
28
35
|
"isRequired": false,
|
|
29
36
|
"format": "string",
|
|
30
37
|
"isSecret": false,
|
package/SKILL.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: agentpay
|
|
3
|
-
description: "Payment gateway for autonomous AI agents — discover, provision, and pay for MCP tool APIs with a single gateway key. Use when building agents that need to pay for API calls, integrating metered billing into MCP workflows, setting up agent wallets, or working with the AgentPay gateway (Stripe + x402 USDC funding). Triggers on: agent payments, tool marketplace, metered billing, agent wallet, gateway key, AgentPay, pay-per-call, autonomous funding, x402, agent economy."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# AgentPay — Payment Gateway for AI Agents
|
|
7
|
-
|
|
8
|
-
One key, every tool. Agents discover, provision, and pay for tool APIs through a single gateway — no per-service accounts or auth.
|
|
9
|
-
|
|
10
|
-
## Quick Setup
|
|
11
|
-
|
|
12
|
-
### Add MCP Server
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
claude mcp add agentpay -- npx -y mcp-server-agentpay
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Or in `~/.claude/settings.json`:
|
|
19
|
-
|
|
20
|
-
```json
|
|
21
|
-
{
|
|
22
|
-
"mcpServers": {
|
|
23
|
-
"agentpay": {
|
|
24
|
-
"command": "npx",
|
|
25
|
-
"args": ["-y", "mcp-server-agentpay"],
|
|
26
|
-
"env": {
|
|
27
|
-
"AGENTPAY_GATEWAY_KEY": "apg_your_key_here"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Register
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
curl -X POST https://agentpay.metaltorque.dev/gateway/register \
|
|
38
|
-
-H "Content-Type: application/json" \
|
|
39
|
-
-d '{"email": "you@example.com"}'
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Returns `apg_` key + $1 free credits.
|
|
43
|
-
|
|
44
|
-
## MCP Tools
|
|
45
|
-
|
|
46
|
-
| Tool | Purpose |
|
|
47
|
-
|------|---------|
|
|
48
|
-
| `discover_tools` | Search tools by keyword |
|
|
49
|
-
| `list_tools` | List all tools with pricing |
|
|
50
|
-
| `check_balance` | Wallet balance and provisioned tools |
|
|
51
|
-
| `call_tool` | Call any tool method (auto-provisions, metered) |
|
|
52
|
-
| `provision_tool` | Pre-provision access (optional) |
|
|
53
|
-
| `get_usage` | Call history with costs |
|
|
54
|
-
| `fund_wallet_stripe` | Stripe checkout URL (human pays) |
|
|
55
|
-
| `fund_wallet_x402` | x402 USDC funding (fully autonomous) |
|
|
56
|
-
| `x402_info` | x402 payment details |
|
|
57
|
-
|
|
58
|
-
## Workflow
|
|
59
|
-
|
|
60
|
-
1. **Register** → get `apg_` key + $1 free
|
|
61
|
-
2. **Fund** → Stripe (human) or x402 USDC (autonomous)
|
|
62
|
-
3. **Discover** → search tools by capability
|
|
63
|
-
4. **Call** → gateway handles auth + billing
|
|
64
|
-
|
|
65
|
-
## Calling Tools
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
call_tool(tool: "agent-audit", method: "security_scan", params_json: '{"url": "example.com"}')
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Response: `[Cost: $0.50 | Balance: $9.50 | Time: 1200ms]` + tool result.
|
|
72
|
-
|
|
73
|
-
## Credit Packages
|
|
74
|
-
|
|
75
|
-
| Package | Price | Credits |
|
|
76
|
-
|---------|-------|---------|
|
|
77
|
-
| micro | $10 | 10 |
|
|
78
|
-
| small | $45 | 50 |
|
|
79
|
-
| medium | $80 | 100 |
|
|
80
|
-
| large | $350 | 500 |
|
|
81
|
-
| whale | $600 | 1,000 |
|
|
82
|
-
|
|
83
|
-
## Autonomous Funding (x402 USDC)
|
|
84
|
-
|
|
85
|
-
For fully autonomous operation without human intervention:
|
|
86
|
-
|
|
87
|
-
```javascript
|
|
88
|
-
import { wrapFetchWithPayment } from "@x402/fetch";
|
|
89
|
-
const res = await fetchWithPayment(endpoint, {
|
|
90
|
-
method: "POST",
|
|
91
|
-
headers: { "X-Gateway-Key": key }
|
|
92
|
-
});
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Requires: `npm install @x402/fetch @x402/evm` + `EVM_PRIVATE_KEY` env var.
|
|
96
|
-
|
|
97
|
-
## Environment Variables
|
|
98
|
-
|
|
99
|
-
| Variable | Required | Default |
|
|
100
|
-
|----------|----------|---------|
|
|
101
|
-
| `AGENTPAY_GATEWAY_KEY` | Yes | — |
|
|
102
|
-
| `AGENTPAY_URL` | No | `https://agentpay.metaltorque.dev` |
|
|
103
|
-
|
|
104
|
-
## For Tool Providers
|
|
105
|
-
|
|
106
|
-
Register tools on the marketplace — see `references/api_reference.md` for developer endpoints, SDK usage, and enterprise features.
|
|
107
|
-
|
|
108
|
-
## Links
|
|
109
|
-
|
|
110
|
-
- npm: `mcp-server-agentpay`
|
|
111
|
-
- GitHub: `github.com/joepangallo/agent-pay`
|
|
112
|
-
- MCP Registry: `io.github.joepangallo/agent-pay`
|