toll402-mcp 0.2.1 → 0.3.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 +8 -3
- package/dist/mcp.js +76 -0
- package/package.json +15 -7
- package/bin.js +0 -3
package/README.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# toll402-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP (stdio) server that exposes every tool at https://toll402.dev — web reading, PDF, email/fx, provenance (human vs synthetic), trusted lookup with citations, a verified business directory, community-forged tools and proxied x402 services — and **pays per call in USDC via x402**. No accounts, no API keys.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```bash
|
|
6
|
+
npx -y toll402-mcp
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Env: `TOLL402_URL` (default https://toll402.dev) · `TOLL402_WALLET_KEY` (0x private key holding a little USDC on Base; omit to use the free trial: 25 calls/day on cheap tools) · `TOLL402_MAX_USD` (cap per call, default 0.25).
|
|
6
10
|
|
|
7
|
-
Claude Code / Cursor / Claude Desktop
|
|
11
|
+
Claude Code / Cursor / Claude Desktop / OpenClaw:
|
|
8
12
|
```json
|
|
9
13
|
{ "mcpServers": { "toll402": { "command": "npx", "args": ["-y", "toll402-mcp"], "env": { "TOLL402_WALLET_KEY": "0x..." } } } }
|
|
10
14
|
```
|
|
15
|
+
You are charged only when a call succeeds (2xx). Catalog and prices: https://toll402.dev/v1/catalog · Docs for agents: https://toll402.dev/llms.txt
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* toll402-mcp — MCP (stdio) server that exposes every Toll402 tool to an agent and
|
|
4
|
+
* pays for calls automatically with x402 from a wallet you control.
|
|
5
|
+
*
|
|
6
|
+
* Env:
|
|
7
|
+
* TOLL402_URL base URL of the Toll402 server (default https://toll402.dev)
|
|
8
|
+
* TOLL402_WALLET_KEY 0x-prefixed EVM private key holding USDC on Base (omit for free instances)
|
|
9
|
+
* TOLL402_MAX_USD max USD per single payment (default 0.25)
|
|
10
|
+
*/
|
|
11
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
12
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
14
|
+
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
|
|
15
|
+
import { ExactEvmScheme } from "@x402/evm/exact/client";
|
|
16
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
17
|
+
const BASE = (process.env.TOLL402_URL ?? "https://toll402.dev").replace(/\/$/, "");
|
|
18
|
+
const KEY = process.env.TOLL402_WALLET_KEY;
|
|
19
|
+
const MAX_USD = process.env.TOLL402_MAX_USD ?? "0.25";
|
|
20
|
+
async function main() {
|
|
21
|
+
const res = await fetch(`${BASE}/v1/catalog`);
|
|
22
|
+
if (!res.ok)
|
|
23
|
+
throw new Error(`Could not load catalog from ${BASE}: HTTP ${res.status}`);
|
|
24
|
+
const catalog = (await res.json());
|
|
25
|
+
catalog.tools = catalog.tools.filter((t) => t.available !== false);
|
|
26
|
+
const byName = new Map(catalog.tools.map((t) => [t.name, t]));
|
|
27
|
+
let paidFetch = fetch;
|
|
28
|
+
if (KEY) {
|
|
29
|
+
const account = privateKeyToAccount(KEY);
|
|
30
|
+
paidFetch = wrapFetchWithPaymentFromConfig(fetch, {
|
|
31
|
+
schemes: [{ network: "eip155:*", client: new ExactEvmScheme(account) }],
|
|
32
|
+
spendControls: { maxAmountPerPayment: `$${MAX_USD}` },
|
|
33
|
+
});
|
|
34
|
+
console.error(`toll402-mcp: paying from ${account.address} on ${catalog.payment.networkName ?? "?"} (max $${MAX_USD}/call)`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.error("toll402-mcp: TOLL402_WALLET_KEY not set — calls will fail with 402 unless the server is free");
|
|
38
|
+
}
|
|
39
|
+
const server = new Server({ name: "toll402", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
40
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
41
|
+
tools: catalog.tools.map((t) => ({
|
|
42
|
+
name: t.name,
|
|
43
|
+
description: `[${t.kind ?? "tool"}] ${t.description} (costs ${t.price} per call, paid automatically in USDC via x402)`,
|
|
44
|
+
inputSchema: t.inputSchema,
|
|
45
|
+
})),
|
|
46
|
+
}));
|
|
47
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
48
|
+
const t = byName.get(req.params.name);
|
|
49
|
+
if (!t)
|
|
50
|
+
return { isError: true, content: [{ type: "text", text: `Unknown tool ${req.params.name}` }] };
|
|
51
|
+
const r = await paidFetch(`${BASE}${t.path}`, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: { "content-type": "application/json" },
|
|
54
|
+
body: JSON.stringify(req.params.arguments ?? {}),
|
|
55
|
+
});
|
|
56
|
+
const text = await r.text();
|
|
57
|
+
if (!r.ok)
|
|
58
|
+
return { isError: true, content: [{ type: "text", text: `HTTP ${r.status}: ${text.slice(0, 2000)}` }] };
|
|
59
|
+
let out = text;
|
|
60
|
+
try {
|
|
61
|
+
const j = JSON.parse(text);
|
|
62
|
+
out = JSON.stringify(j.result ?? j, null, 2);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
/* leave as-is */
|
|
66
|
+
}
|
|
67
|
+
const paid = r.headers.get("payment-response") ? `\n\n[paid ${t.price} via x402]` : "";
|
|
68
|
+
return { content: [{ type: "text", text: out + paid }] };
|
|
69
|
+
});
|
|
70
|
+
await server.connect(new StdioServerTransport());
|
|
71
|
+
console.error(`toll402-mcp: ${catalog.tools.length} tools from ${BASE} ready`);
|
|
72
|
+
}
|
|
73
|
+
main().catch((e) => {
|
|
74
|
+
console.error("toll402-mcp fatal:", e);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
});
|
package/package.json
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toll402-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for Toll402 (https://toll402.dev): every Toll402 tool as MCP tools, paid per call in USDC via x402.
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "MCP server for Toll402 (https://toll402.dev): every Toll402 tool as MCP tools, paid per call in USDC via x402. No accounts, no API keys.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": { "toll402-mcp": "./
|
|
7
|
-
"files": ["
|
|
8
|
-
"
|
|
6
|
+
"bin": { "toll402-mcp": "./dist/mcp.js" },
|
|
7
|
+
"files": ["dist", "README.md"],
|
|
8
|
+
"scripts": { "build": "tsc -p tsconfig.json", "prepublishOnly": "npm run build" },
|
|
9
|
+
"engines": { "node": ">=20" },
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
12
|
+
"@x402/evm": "~2.25.0",
|
|
13
|
+
"@x402/fetch": "~2.25.0",
|
|
14
|
+
"viem": "^2.56.3"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": { "@types/node": "^22", "typescript": "^5.7.0" },
|
|
9
17
|
"license": "MIT",
|
|
10
18
|
"homepage": "https://toll402.dev",
|
|
11
|
-
"repository": { "type": "git", "url": "https://gitlab.com/toll402/toll402" },
|
|
12
|
-
"keywords": ["mcp", "x402", "ai-agents", "usdc", "tools"]
|
|
19
|
+
"repository": { "type": "git", "url": "https://gitlab.com/toll402/toll402-sdk" },
|
|
20
|
+
"keywords": ["mcp", "x402", "ai-agents", "usdc", "base", "tools", "toll402"]
|
|
13
21
|
}
|
package/bin.js
DELETED