agentwallet-mcp 1.3.0 → 1.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.
Files changed (3) hide show
  1. package/README.md +37 -3
  2. package/build/index.js +109 -1
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -4,11 +4,15 @@ Permissionless EVM wallet infrastructure for AI agents. Create wallets, sign tra
4
4
 
5
5
  **No KYC. No KYT. No transaction monitoring. No one can block your wallet.**
6
6
 
7
+ <p align="center">
8
+ <img src="assets/demo.svg" alt="AgentWallet demo — AI agent pays x402 invoice automatically" width="800">
9
+ </p>
10
+
7
11
  ## Features
8
12
 
9
- - **21 MCP tools** — create wallets, send transactions, approve tokens, wrap ETH, pay x402 invoices, and more
13
+ - **28 MCP tools** — create wallets, send transactions, approve tokens, wrap ETH, pay and accept x402 payments, and more
10
14
  - **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
15
+ - **x402 payments** — pay for x402-enabled APIs automatically, or accept x402 payments on your own endpoints
12
16
  - **Secure** — Private keys encrypted at rest, decrypted only during signing, zeroed from memory immediately after
13
17
  - **Permissionless** — No identity verification, no compliance gatekeeping. Create a wallet and transact immediately.
14
18
 
@@ -91,6 +95,13 @@ Add to your settings:
91
95
  | `wrap_eth` | Wrap native tokens to WETH/WAVAX/etc. |
92
96
  | `unwrap_eth` | Unwrap WETH back to native tokens |
93
97
  | `pay_x402` | Pay x402 invoices automatically (fetch, pay, retry) |
98
+ | `create_paywall` | Create an x402 paywall to charge for a resource |
99
+ | `list_paywalls` | List all your x402 paywalls |
100
+ | `get_paywall` | Get paywall details by ID |
101
+ | `update_paywall` | Update paywall pricing, resource, or status |
102
+ | `delete_paywall` | Delete a paywall |
103
+ | `get_paywall_payments` | View payment history for a paywall |
104
+ | `get_x402_revenue` | Aggregate revenue stats across all paywalls |
94
105
  | `get_usage` | Check your monthly usage and billing |
95
106
  | `get_chains` | List all supported chains |
96
107
  | `pause_wallet` | Emergency pause a wallet |
@@ -145,12 +156,35 @@ pay_x402(
145
156
 
146
157
  Supports ERC-20 tokens (USDC, USDT) and native tokens on any chain. Compatible with x402 V1 and V2 (CAIP-2 chain identifiers).
147
158
 
159
+ ## x402 Acceptance
160
+
161
+ AgentWallet also lets you **accept** x402 payments. Create a paywall, point it at any resource, and get a public URL that charges agents automatically:
162
+
163
+ ```
164
+ create_paywall(
165
+ wallet_id=1,
166
+ name="Premium API",
167
+ amount="0.01",
168
+ token_name="USDC",
169
+ token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
170
+ chain_id=8453,
171
+ resource_url="https://your-api.com/data"
172
+ )
173
+ ```
174
+
175
+ When an agent hits the paywall URL:
176
+ 1. Gets back HTTP 402 with payment requirements
177
+ 2. Pays on-chain using `pay_x402` (or any x402-compatible client)
178
+ 3. Retries with proof of payment
179
+ 4. Receives the protected content
180
+
181
+ On-chain verification ensures every payment is real. Replay protection prevents double-spending. Revenue tracking shows you who paid, how much, and when.
182
+
148
183
  ## Security
149
184
 
150
185
  - Private keys are generated server-side and encrypted at rest
151
186
  - Keys are decrypted only during transaction signing and zeroed from memory immediately after
152
187
  - EIP-1559 transactions only with gas safety caps
153
- - Emergency pause: freeze any wallet or all wallets instantly
154
188
  - Bug bounty program: $50–$500 for responsible disclosure ([details](https://hifriendbot.com/wallet))
155
189
 
156
190
  ## Links
package/build/index.js CHANGED
@@ -111,7 +111,7 @@ function resolveChainId(network) {
111
111
  // ─── Server ──────────────────────────────────────────────────────
112
112
  const server = new McpServer({
113
113
  name: 'agentwallet',
114
- version: '1.3.0',
114
+ version: '1.4.0',
115
115
  });
116
116
  // ─── Tool: create_wallet ─────────────────────────────────────────
117
117
  server.tool('create_wallet', 'Create a new EVM wallet. Returns the wallet ID and address. ' +
@@ -663,6 +663,114 @@ server.tool('delete_wallet', 'Delete (soft-delete) a wallet. The wallet will no
663
663
  const data = await api(`/wallets/${wallet_id}`, 'DELETE');
664
664
  return jsonResponse(data);
665
665
  });
666
+ // ─── Tool: create_paywall ────────────────────────────────────────
667
+ server.tool('create_paywall', 'Create an x402 paywall that charges agents/clients for accessing a resource. ' +
668
+ 'Returns a public access URL that returns HTTP 402 until paid. ' +
669
+ 'Agents pay on-chain, then retry with proof to get the content.', {
670
+ wallet_id: z.number().int().describe('Wallet ID to receive payments'),
671
+ name: z.string().describe('Human-readable paywall name (e.g. "Premium API Access")'),
672
+ description: z.string().default('').describe('Description shown in the 402 response'),
673
+ amount: z.string().describe('Price in human-readable format (e.g. "0.01" for 0.01 USDC)'),
674
+ token_type: z.enum(['erc20', 'native']).default('erc20').describe('"erc20" for stablecoin payments, "native" for ETH/POL/etc.'),
675
+ token_address: z.string().default('').describe('ERC-20 token contract address (required if token_type is "erc20"). Use get_chains to find stablecoin addresses.'),
676
+ token_decimals: z.number().int().default(6).describe('Token decimals (6 for USDC, 18 for ETH/most tokens)'),
677
+ token_name: z.string().default('USDC').describe('Token display name (e.g. "USDC", "ETH")'),
678
+ chain_id: z.number().int().default(8453).describe('Chain ID for payments (8453=Base, 1=Ethereum, etc.)'),
679
+ resource_url: z.string().url().describe('URL of the protected resource to serve after payment verification'),
680
+ resource_mime: z.string().default('application/json').describe('MIME type of the resource (e.g. "application/json", "text/plain")'),
681
+ }, async ({ wallet_id, name, description, amount, token_type, token_address, token_decimals, token_name, chain_id, resource_url, resource_mime }) => {
682
+ // Convert human-readable amount to raw token units
683
+ const rawAmount = parseUnits(amount, token_decimals);
684
+ const data = await api('/x402/paywalls', 'POST', {
685
+ wallet_id,
686
+ name,
687
+ description,
688
+ amount: rawAmount,
689
+ token_type,
690
+ token_address,
691
+ token_decimals,
692
+ token_name,
693
+ chain_id,
694
+ resource_url,
695
+ resource_mime,
696
+ });
697
+ return jsonResponse({
698
+ ...data,
699
+ price: `${amount} ${token_name}`,
700
+ chain_id,
701
+ });
702
+ });
703
+ // ─── Tool: list_paywalls ────────────────────────────────────────
704
+ server.tool('list_paywalls', 'List all your x402 paywalls. Returns paywall IDs, names, pricing, ' +
705
+ 'access URLs, payment counts, and revenue totals.', {
706
+ page: z.number().int().default(1).describe('Page number'),
707
+ per_page: z.number().int().default(50).describe('Results per page (max 100)'),
708
+ }, async ({ page, per_page }) => {
709
+ const data = await api(`/x402/paywalls?page=${page}&per_page=${per_page}`);
710
+ return jsonResponse(data);
711
+ });
712
+ // ─── Tool: get_paywall ──────────────────────────────────────────
713
+ server.tool('get_paywall', 'Get details for a specific x402 paywall by ID. ' +
714
+ 'Returns pricing, access URL, payment stats, and configuration.', {
715
+ paywall_id: z.number().int().describe('Paywall ID'),
716
+ }, async ({ paywall_id }) => {
717
+ const data = await api(`/x402/paywalls/${paywall_id}`);
718
+ return jsonResponse(data);
719
+ });
720
+ // ─── Tool: update_paywall ───────────────────────────────────────
721
+ server.tool('update_paywall', 'Update an x402 paywall configuration. ' +
722
+ 'Can change price, resource URL, active status, or any other field.', {
723
+ paywall_id: z.number().int().describe('Paywall ID to update'),
724
+ name: z.string().optional().describe('New paywall name'),
725
+ description: z.string().optional().describe('New description'),
726
+ amount: z.string().optional().describe('New price in human-readable format (e.g. "0.05")'),
727
+ token_decimals: z.number().int().optional().describe('Token decimals (needed if changing amount)'),
728
+ resource_url: z.string().url().optional().describe('New resource URL'),
729
+ resource_mime: z.string().optional().describe('New MIME type'),
730
+ is_active: z.boolean().optional().describe('Enable (true) or disable (false) the paywall'),
731
+ }, async ({ paywall_id, name, description, amount, token_decimals, resource_url, resource_mime, is_active }) => {
732
+ const body = {};
733
+ if (name !== undefined)
734
+ body.name = name;
735
+ if (description !== undefined)
736
+ body.description = description;
737
+ if (resource_url !== undefined)
738
+ body.resource_url = resource_url;
739
+ if (resource_mime !== undefined)
740
+ body.resource_mime = resource_mime;
741
+ if (is_active !== undefined)
742
+ body.is_active = is_active;
743
+ // Convert human-readable amount to raw if provided
744
+ if (amount !== undefined) {
745
+ const decimals = token_decimals ?? 6; // Default to USDC decimals
746
+ body.amount = parseUnits(amount, decimals);
747
+ }
748
+ const data = await api(`/x402/paywalls/${paywall_id}`, 'PUT', body);
749
+ return jsonResponse(data);
750
+ });
751
+ // ─── Tool: delete_paywall ───────────────────────────────────────
752
+ server.tool('delete_paywall', 'Delete an x402 paywall. The access URL will return 404 after deletion.', {
753
+ paywall_id: z.number().int().describe('Paywall ID to delete'),
754
+ }, async ({ paywall_id }) => {
755
+ const data = await api(`/x402/paywalls/${paywall_id}`, 'DELETE');
756
+ return jsonResponse(data);
757
+ });
758
+ // ─── Tool: get_paywall_payments ─────────────────────────────────
759
+ server.tool('get_paywall_payments', 'Get payment history for a specific x402 paywall. ' +
760
+ 'Returns verified payments with TX hashes, payer addresses, amounts, and timestamps.', {
761
+ paywall_id: z.number().int().describe('Paywall ID'),
762
+ page: z.number().int().default(1).describe('Page number'),
763
+ per_page: z.number().int().default(20).describe('Results per page (max 100)'),
764
+ }, async ({ paywall_id, page, per_page }) => {
765
+ const data = await api(`/x402/paywalls/${paywall_id}/payments?page=${page}&per_page=${per_page}`);
766
+ return jsonResponse(data);
767
+ });
768
+ // ─── Tool: get_x402_revenue ─────────────────────────────────────
769
+ server.tool('get_x402_revenue', 'Get aggregate x402 revenue statistics across all your paywalls. ' +
770
+ 'Returns total payments and revenue broken down by chain and token.', {}, async () => {
771
+ const data = await api('/x402/revenue');
772
+ return jsonResponse(data);
773
+ });
666
774
  // ─── Start ──────────────────────────────────────────────────────
667
775
  async function main() {
668
776
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentwallet-mcp",
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",
3
+ "version": "1.4.0",
4
+ "description": "MCP server for AgentWallet — lets AI agents create wallets, sign transactions, broadcast on any EVM chain, pay x402 invoices, and accept x402 payments",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
7
7
  "bin": {