agentwallet-mcp 1.2.0 → 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HiFriendbot
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 ADDED
@@ -0,0 +1,164 @@
1
+ # AgentWallet MCP Server
2
+
3
+ Permissionless EVM wallet infrastructure for AI agents. Create wallets, sign transactions, and broadcast on-chain — on any EVM chain.
4
+
5
+ **No KYC. No KYT. No transaction monitoring. No one can block your wallet.**
6
+
7
+ ## Features
8
+
9
+ - **21 MCP tools** — create wallets, send transactions, approve tokens, wrap ETH, pay x402 invoices, and more
10
+ - **Any EVM chain** — Ethereum, Base, Polygon, BSC, Arbitrum, Optimism, Avalanche, Zora, PulseChain, and any other EVM-compatible chain
11
+ - **x402 payments** — automatically pay for x402-enabled APIs and resources on any supported chain
12
+ - **Secure** — Private keys encrypted at rest, decrypted only during signing, zeroed from memory immediately after
13
+ - **Permissionless** — No identity verification, no compliance gatekeeping. Create a wallet and transact immediately.
14
+
15
+ ## Pricing
16
+
17
+ - **$0.0069 per transaction** (31% less expensive than Coinbase CDP)
18
+ - **6,000 free transactions/month**
19
+ - No monthly fee, no tiers — just pay as you go
20
+
21
+ ## Quick Start
22
+
23
+ Get your free API key at [hifriendbot.com/wallet](https://hifriendbot.com/wallet) (no credit card required).
24
+
25
+ ### Claude Desktop / OpenClaw
26
+
27
+ Add to your config:
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "agentwallet": {
33
+ "command": "npx",
34
+ "args": ["-y", "agentwallet-mcp"],
35
+ "env": {
36
+ "AGENTWALLET_USER": "your_username",
37
+ "AGENTWALLET_PASS": "your_api_key"
38
+ }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ ### Claude Code
45
+
46
+ ```bash
47
+ claude mcp add agentwallet \
48
+ -e AGENTWALLET_USER=your_username \
49
+ -e AGENTWALLET_PASS=your_api_key \
50
+ -- npx -y agentwallet-mcp
51
+ ```
52
+
53
+ ### VS Code
54
+
55
+ Add to your settings:
56
+
57
+ ```json
58
+ {
59
+ "mcp": {
60
+ "servers": {
61
+ "agentwallet": {
62
+ "command": "npx",
63
+ "args": ["-y", "agentwallet-mcp"],
64
+ "env": {
65
+ "AGENTWALLET_USER": "your_username",
66
+ "AGENTWALLET_PASS": "your_api_key"
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ## Tools
75
+
76
+ | Tool | Description |
77
+ |------|-------------|
78
+ | `create_wallet` | Create a new wallet on any EVM chain |
79
+ | `list_wallets` | List all your wallets |
80
+ | `get_wallet` | Get wallet details by ID |
81
+ | `get_balance` | Check native token balance on any chain |
82
+ | `get_token_balance` | Check ERC-20 token balance |
83
+ | `get_token_info` | Get ERC-20 token name, symbol, and decimals |
84
+ | `transfer` | Send native tokens (ETH, POL, BNB, etc.) |
85
+ | `transfer_token` | Send ERC-20 tokens (USDC, USDT, etc.) |
86
+ | `send_transaction` | Sign and broadcast a raw transaction |
87
+ | `sign_transaction` | Sign a transaction without broadcasting |
88
+ | `call_contract` | Read-only contract call (eth_call) |
89
+ | `approve_token` | Approve ERC-20 token spending for DeFi |
90
+ | `get_allowance` | Check ERC-20 token allowance |
91
+ | `wrap_eth` | Wrap native tokens to WETH/WAVAX/etc. |
92
+ | `unwrap_eth` | Unwrap WETH back to native tokens |
93
+ | `pay_x402` | Pay x402 invoices automatically (fetch, pay, retry) |
94
+ | `get_usage` | Check your monthly usage and billing |
95
+ | `get_chains` | List all supported chains |
96
+ | `pause_wallet` | Emergency pause a wallet |
97
+ | `unpause_wallet` | Resume a paused wallet |
98
+ | `delete_wallet` | Delete a wallet |
99
+
100
+ ## Supported Chains
101
+
102
+ | Chain | ID | Native Token | Stablecoin |
103
+ |-------|-----|-------------|------------|
104
+ | Ethereum | 1 | ETH | USDC |
105
+ | Base | 8453 | ETH | USDC |
106
+ | Polygon | 137 | POL | USDC |
107
+ | BSC | 56 | BNB | USDT |
108
+ | Arbitrum | 42161 | ETH | USDC |
109
+ | Optimism | 10 | ETH | USDC |
110
+ | Avalanche | 43114 | AVAX | USDC |
111
+ | Zora | 7777777 | ETH | USDC |
112
+ | PulseChain | 369 | PLS | USDC |
113
+
114
+ ## Use Case: GuessMarket
115
+
116
+ Pair with [guessmarket-mcp](https://www.npmjs.com/package/guessmarket-mcp) to let your AI agent trade prediction markets:
117
+
118
+ 1. Create a wallet on Base
119
+ 2. Approve USDC spending
120
+ 3. Buy YES/NO shares on prediction markets
121
+ 4. Provide liquidity and earn trading fees
122
+ 5. Claim winnings
123
+
124
+ All on-chain. All through MCP. No frontend needed.
125
+
126
+ ## x402 Payments
127
+
128
+ AgentWallet natively supports the [x402 open payment standard](https://x402.org). When your Ai agent encounters an API that returns HTTP 402 Payment Required, the `pay_x402` tool handles the entire flow automatically:
129
+
130
+ 1. Fetches the URL and detects the 402 response
131
+ 2. Parses the payment requirements (amount, token, chain)
132
+ 3. Executes the on-chain payment from your wallet
133
+ 4. Retries the request with proof of payment
134
+ 5. Returns the final response
135
+
136
+ **Always set `max_payment` to control spending:**
137
+
138
+ ```
139
+ pay_x402(
140
+ url="https://api.example.com/premium-data",
141
+ wallet_id=1,
142
+ max_payment="1.00"
143
+ )
144
+ ```
145
+
146
+ Supports ERC-20 tokens (USDC, USDT) and native tokens on any chain. Compatible with x402 V1 and V2 (CAIP-2 chain identifiers).
147
+
148
+ ## Security
149
+
150
+ - Private keys are generated server-side and encrypted at rest
151
+ - Keys are decrypted only during transaction signing and zeroed from memory immediately after
152
+ - EIP-1559 transactions only with gas safety caps
153
+ - Emergency pause: freeze any wallet or all wallets instantly
154
+ - Bug bounty program: $50–$500 for responsible disclosure ([details](https://hifriendbot.com/wallet))
155
+
156
+ ## Links
157
+
158
+ - **Website:** [hifriendbot.com/wallet](https://hifriendbot.com/wallet)
159
+ - **npm:** [agentwallet-mcp](https://www.npmjs.com/package/agentwallet-mcp)
160
+ - **Security:** [security@hifriendbot.com](mailto:security@hifriendbot.com)
161
+
162
+ ## License
163
+
164
+ MIT
package/build/index.js CHANGED
@@ -80,9 +80,38 @@ function encodeUint256(value) {
80
80
  return hex.padStart(64, '0');
81
81
  }
82
82
  // ─── Server ──────────────────────────────────────────────────────
83
+ // ─── x402 Network Mapping ──────────────────────────────────────
84
+ const X402_NETWORKS = {
85
+ 'ethereum': 1,
86
+ 'base': 8453,
87
+ 'base-sepolia': 84532,
88
+ 'polygon': 137,
89
+ 'arbitrum': 42161,
90
+ 'optimism': 10,
91
+ 'bsc': 56,
92
+ 'avalanche': 43114,
93
+ 'zora': 7777777,
94
+ 'pulsechain': 369,
95
+ };
96
+ /**
97
+ * Resolve an x402 network identifier to a chain ID.
98
+ * Supports plain names ("base"), CAIP-2 format ("eip155:8453"), and raw chain IDs ("8453").
99
+ */
100
+ function resolveChainId(network) {
101
+ if (X402_NETWORKS[network])
102
+ return X402_NETWORKS[network];
103
+ const caipMatch = network.match(/^eip155:(\d+)$/);
104
+ if (caipMatch)
105
+ return parseInt(caipMatch[1], 10);
106
+ const num = parseInt(network, 10);
107
+ if (!isNaN(num) && num > 0)
108
+ return num;
109
+ return null;
110
+ }
111
+ // ─── Server ──────────────────────────────────────────────────────
83
112
  const server = new McpServer({
84
113
  name: 'agentwallet',
85
- version: '1.2.0',
114
+ version: '1.3.0',
86
115
  });
87
116
  // ─── Tool: create_wallet ─────────────────────────────────────────
88
117
  server.tool('create_wallet', 'Create a new EVM wallet. Returns the wallet ID and address. ' +
@@ -425,6 +454,181 @@ server.tool('get_token_info', 'Get the name, symbol, and decimals of any ERC-20
425
454
  decimals,
426
455
  });
427
456
  });
457
+ // ─── Tool: pay_x402 ─────────────────────────────────────────────
458
+ server.tool('pay_x402', 'Handle an x402 payment flow. Fetches a URL, and if the server returns HTTP 402 Payment Required, ' +
459
+ 'parses the payment requirements, executes the on-chain payment, and retries the request with ' +
460
+ 'proof of payment. Returns the final response. Supports the x402 open payment standard ' +
461
+ '(https://x402.org). Set max_payment to prevent overspending.', {
462
+ url: z.string().url().describe('The URL to access (will handle 402 payment if required)'),
463
+ wallet_id: z.number().int().describe('Wallet ID to pay from'),
464
+ method: z.string().default('GET').describe('HTTP method (GET, POST, PUT, DELETE)'),
465
+ headers: z.string().optional().describe('Optional JSON string of additional request headers'),
466
+ body: z.string().optional().describe('Optional request body for POST/PUT requests'),
467
+ max_payment: z.string().optional().describe('Maximum payment in human-readable format (e.g. "1.00" for 1 USDC). ' +
468
+ 'Rejects payments above this amount. Strongly recommended to prevent overspending.'),
469
+ prefer_chain: z.number().int().optional().describe('Preferred chain ID if the server accepts payment on multiple chains ' +
470
+ '(e.g. 8453 for Base, 1 for Ethereum)'),
471
+ }, async ({ url, wallet_id, method, headers: headersJson, body: reqBody, max_payment, prefer_chain }) => {
472
+ // Build request headers
473
+ const reqHeaders = { Accept: 'application/json' };
474
+ if (headersJson) {
475
+ try {
476
+ Object.assign(reqHeaders, JSON.parse(headersJson));
477
+ }
478
+ catch {
479
+ throw new Error('Invalid headers JSON. Must be a JSON object (e.g. {"Authorization": "Bearer ..."}).');
480
+ }
481
+ }
482
+ // Validate URL — block private IPs and cloud metadata endpoints
483
+ const urlObj = new URL(url);
484
+ const hostname = urlObj.hostname.toLowerCase();
485
+ const blockedHosts = ['localhost', '127.0.0.1', '0.0.0.0', '[::1]', '169.254.169.254', 'metadata.google.internal'];
486
+ const blockedPrefixes = ['10.', '172.16.', '172.17.', '172.18.', '172.19.', '172.20.', '172.21.',
487
+ '172.22.', '172.23.', '172.24.', '172.25.', '172.26.', '172.27.', '172.28.', '172.29.',
488
+ '172.30.', '172.31.', '192.168.'];
489
+ if (blockedHosts.includes(hostname) || blockedPrefixes.some(p => hostname.startsWith(p))) {
490
+ throw new Error('URL points to a private/internal address. Only public URLs are allowed.');
491
+ }
492
+ if (!['http:', 'https:'].includes(urlObj.protocol)) {
493
+ throw new Error('Only http: and https: URLs are supported.');
494
+ }
495
+ // Step 1: Make initial request
496
+ const reqOptions = {
497
+ method,
498
+ headers: reqHeaders,
499
+ signal: AbortSignal.timeout(30_000), // 30s timeout
500
+ };
501
+ if (reqBody && method !== 'GET') {
502
+ reqOptions.body = reqBody;
503
+ if (!reqHeaders['Content-Type'])
504
+ reqHeaders['Content-Type'] = 'application/json';
505
+ }
506
+ const initialRes = await fetch(url, reqOptions);
507
+ // If not 402, return the response as-is (no payment needed)
508
+ if (initialRes.status !== 402) {
509
+ const text = await initialRes.text();
510
+ let parsed;
511
+ try {
512
+ parsed = JSON.parse(text);
513
+ }
514
+ catch {
515
+ parsed = text;
516
+ }
517
+ return jsonResponse({
518
+ status: initialRes.status,
519
+ payment_required: false,
520
+ response: parsed,
521
+ });
522
+ }
523
+ // Step 2: Parse x402 payment requirements from 402 response
524
+ let paymentInfo;
525
+ try {
526
+ paymentInfo = await initialRes.json();
527
+ }
528
+ catch {
529
+ throw new Error('402 response body is not valid JSON. This server may not support x402.');
530
+ }
531
+ if (!paymentInfo.accepts || paymentInfo.accepts.length === 0) {
532
+ throw new Error('402 response has no payment options in "accepts" array.');
533
+ }
534
+ const options = paymentInfo.accepts;
535
+ let option;
536
+ if (prefer_chain) {
537
+ option = options.find(a => resolveChainId(a.network) === prefer_chain) || options[0];
538
+ }
539
+ else {
540
+ option = options[0];
541
+ }
542
+ // Resolve the chain
543
+ const chainId = resolveChainId(option.network);
544
+ if (!chainId) {
545
+ throw new Error(`Unsupported x402 network: "${option.network}". ` +
546
+ `Supported: ${Object.keys(X402_NETWORKS).join(', ')}, or any CAIP-2 / numeric chain ID.`);
547
+ }
548
+ // Calculate human-readable amount
549
+ const amount = formatUnits(option.maxAmountRequired, option.requiredDecimals);
550
+ // Step 4: Check spending limit
551
+ if (max_payment) {
552
+ const maxRaw = parseUnits(max_payment, option.requiredDecimals);
553
+ if (BigInt(option.maxAmountRequired) > BigInt(maxRaw)) {
554
+ return jsonResponse({
555
+ status: 402,
556
+ payment_required: true,
557
+ payment_made: false,
558
+ error: `Payment of ${amount} ${option.extra?.name || 'tokens'} exceeds your max_payment limit of ${max_payment}`,
559
+ required_amount: amount,
560
+ max_allowed: max_payment,
561
+ token: option.extra?.name || 'native',
562
+ network: option.network,
563
+ chain_id: chainId,
564
+ pay_to: option.payTo,
565
+ description: option.description,
566
+ });
567
+ }
568
+ }
569
+ // Step 5: Execute payment
570
+ let txResult;
571
+ if (option.extra?.token) {
572
+ // ERC-20 token payment (e.g. USDC)
573
+ const calldata = '0xa9059cbb' + padAddress(option.payTo) + encodeUint256(option.maxAmountRequired);
574
+ txResult = (await api(`/wallets/${wallet_id}/send`, 'POST', {
575
+ to: option.extra.token,
576
+ value: '0',
577
+ data: calldata,
578
+ chain_id: chainId,
579
+ }));
580
+ }
581
+ else {
582
+ // Native token payment (ETH, etc.)
583
+ txResult = (await api(`/wallets/${wallet_id}/send`, 'POST', {
584
+ to: option.payTo,
585
+ value: option.maxAmountRequired,
586
+ data: '',
587
+ chain_id: chainId,
588
+ }));
589
+ }
590
+ const txHash = txResult.tx_hash;
591
+ // Step 6: Build x402 payment proof and retry
592
+ const paymentProof = {
593
+ x402Version: paymentInfo.x402Version || 1,
594
+ scheme: option.scheme,
595
+ network: option.network,
596
+ payload: { txHash },
597
+ };
598
+ const paymentHeader = Buffer.from(JSON.stringify(paymentProof)).toString('base64');
599
+ const retryHeaders = { ...reqHeaders, 'X-PAYMENT': paymentHeader };
600
+ const retryOptions = {
601
+ method,
602
+ headers: retryHeaders,
603
+ signal: AbortSignal.timeout(30_000),
604
+ };
605
+ if (reqBody && method !== 'GET') {
606
+ retryOptions.body = reqBody;
607
+ }
608
+ const retryRes = await fetch(url, retryOptions);
609
+ const retryText = await retryRes.text();
610
+ let retryParsed;
611
+ try {
612
+ retryParsed = JSON.parse(retryText);
613
+ }
614
+ catch {
615
+ retryParsed = retryText;
616
+ }
617
+ return jsonResponse({
618
+ status: retryRes.status,
619
+ payment_required: true,
620
+ payment_made: true,
621
+ amount,
622
+ token: option.extra?.name || 'native',
623
+ token_address: option.extra?.token || null,
624
+ network: option.network,
625
+ chain_id: chainId,
626
+ pay_to: option.payTo,
627
+ tx_hash: txHash,
628
+ description: option.description,
629
+ response: retryParsed,
630
+ });
631
+ });
428
632
  // ─── Tool: get_usage ─────────────────────────────────────────────
429
633
  server.tool('get_usage', 'Get the current month\'s usage statistics. ' +
430
634
  'Returns operations count, tier info, remaining quota, and fees.', {}, async () => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentwallet-mcp",
3
- "version": "1.2.0",
4
- "description": "MCP server for AgentWallet — lets AI agents create wallets, sign transactions, and broadcast on any EVM chain",
3
+ "version": "1.3.0",
4
+ "description": "MCP server for AgentWallet — lets AI agents create wallets, sign transactions, broadcast on any EVM chain, and pay x402 invoices",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
7
7
  "bin": {
@@ -36,6 +36,9 @@
36
36
  "erc20",
37
37
  "token-transfer",
38
38
  "transaction-signing",
39
+ "x402",
40
+ "http-402",
41
+ "agent-payments",
39
42
  "agentwallet"
40
43
  ],
41
44
  "author": "HiFriendbot (https://hifriendbot.com)",