agentwallet-mcp 1.7.3 → 1.7.5

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
@@ -52,7 +52,9 @@ Add to your config:
52
52
  }
53
53
  ```
54
54
 
55
- > `AGENTWALLET_WALLET_ID` is optional. Set it to enable x402 auto-pay — when you exceed the free tier without a credit card, the MCP server will automatically pay for operations with USDC from this wallet.
55
+ > `AGENTWALLET_WALLET_ID` is optional. Set it to enable x402 auto-pay: when you exceed the free tier without a credit card, the MCP server automatically pays for operations with USDC from this wallet.
56
+ >
57
+ > **Auto-pay safety cap.** `AGENTWALLET_MAX_AUTOPAY` (optional, default `1`) is the maximum amount, in human-readable units of the asset, that x402 auto-pay will authorize for a single payment. Any 402 requirement above this cap is rejected instead of paid, so a malformed or tampered payment requirement cannot drain the wallet. Raise it only if you genuinely need larger automatic payments (for example `"5"` to allow up to 5 USDC per call).
56
58
 
57
59
  ### Claude Code
58
60
 
package/build/index.js CHANGED
@@ -12,6 +12,7 @@
12
12
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
13
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
14
  import { z } from 'zod';
15
+ import { deriveX402Payment } from './x402-payment.js';
15
16
  // ─── Configuration ──────────────────────────────────────────────
16
17
  const API_BASE = process.env.AGENTWALLET_API_URL || 'https://hifriendbot.com/wp-json/agentwallet/v1';
17
18
  const API_USER = process.env.AGENTWALLET_USER || '';
@@ -55,15 +56,19 @@ async function handleX402Payment(x402Data, originalPath, originalMethod, origina
55
56
  throw new Error('402 Payment Required but no payment options available.');
56
57
  }
57
58
  const accept = accepts[0]; // Use first option
58
- const tokenAddress = accept.extra?.token || '';
59
- const amount = accept.maxAmountRequired;
60
59
  const payTo = accept.payTo;
61
- const decimals = accept.requiredDecimals || 6;
62
60
  // Determine chain_id from network string (CAIP-2, plain name, or raw ID)
63
61
  const network = accept.network || '';
64
62
  const chainId = resolveChainId(network) ?? 8453;
65
- // Convert human-readable amount to raw (e.g. "0.01" with 6 decimals = "10000")
66
- const rawAmount = parseUnits(amount, decimals);
63
+ // x402 maxAmountRequired is ALREADY in base/atomic units (e.g. "10000" =
64
+ // 0.01 USDC at 6 decimals) and must be used directly. The previous code ran
65
+ // it through parseUnits(), which re-scaled it by 10**decimals and overpaid by
66
+ // that factor (1,000,000x for USDC). deriveX402Payment uses it directly (like
67
+ // the pay_x402 tool) and enforces a hard ceiling so a malformed or malicious
68
+ // 402 response cannot drain the wallet. AGENTWALLET_MAX_AUTOPAY is in
69
+ // human-readable units of the asset; default 1.
70
+ const maxAutopay = process.env.AGENTWALLET_MAX_AUTOPAY || '1';
71
+ const { tokenAddress, rawAmount, decimals } = deriveX402Payment(accept, maxAutopay);
67
72
  // Send payment using our wallet (with X-AGW-SKIP-X402 to prevent recursion)
68
73
  let txHash;
69
74
  try {
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Pure helpers for x402 auto-pay amount/token derivation.
3
+ *
4
+ * Isolated from the server bootstrap in index.ts so the funds-sensitive amount
5
+ * math can be unit-tested without starting the MCP server.
6
+ */
7
+ export interface X402AcceptLike {
8
+ maxAmountRequired: string;
9
+ requiredDecimals?: number;
10
+ asset?: string;
11
+ extra?: {
12
+ token?: string;
13
+ };
14
+ }
15
+ /**
16
+ * Derive the on-chain transfer parameters from an x402 payment requirement.
17
+ *
18
+ * CRITICAL: x402 `maxAmountRequired` is ALREADY denominated in base/atomic
19
+ * units (e.g. "10000" = 0.01 USDC at 6 decimals). It MUST be used directly.
20
+ * Running it through parseUnits() re-scales it by 10**decimals and overpays by
21
+ * that factor (1,000,000x for USDC). This mirrors the pay_x402 tool, which has
22
+ * always used maxAmountRequired directly.
23
+ *
24
+ * Also enforces a hard ceiling so a malformed or malicious 402 response can
25
+ * never authorize a transfer larger than `maxAutopayHuman` units of the asset.
26
+ *
27
+ * @param accept the chosen x402 accept option
28
+ * @param maxAutopayHuman max auto-pay, in human-readable units of the asset
29
+ */
30
+ export declare function deriveX402Payment(accept: X402AcceptLike, maxAutopayHuman: string): {
31
+ tokenAddress: string;
32
+ rawAmount: string;
33
+ decimals: number;
34
+ };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Pure helpers for x402 auto-pay amount/token derivation.
3
+ *
4
+ * Isolated from the server bootstrap in index.ts so the funds-sensitive amount
5
+ * math can be unit-tested without starting the MCP server.
6
+ */
7
+ /** Convert a human-readable decimal amount (e.g. "0.01") to base/atomic units. */
8
+ function toBaseUnits(amount, decimals) {
9
+ if (!/^\d+(\.\d+)?$/.test(amount)) {
10
+ throw new Error(`Invalid amount "${amount}".`);
11
+ }
12
+ const [whole, frac = ''] = amount.split('.');
13
+ const fracPadded = frac.slice(0, decimals).padEnd(decimals, '0');
14
+ return BigInt(whole + fracPadded).toString();
15
+ }
16
+ /**
17
+ * Derive the on-chain transfer parameters from an x402 payment requirement.
18
+ *
19
+ * CRITICAL: x402 `maxAmountRequired` is ALREADY denominated in base/atomic
20
+ * units (e.g. "10000" = 0.01 USDC at 6 decimals). It MUST be used directly.
21
+ * Running it through parseUnits() re-scales it by 10**decimals and overpays by
22
+ * that factor (1,000,000x for USDC). This mirrors the pay_x402 tool, which has
23
+ * always used maxAmountRequired directly.
24
+ *
25
+ * Also enforces a hard ceiling so a malformed or malicious 402 response can
26
+ * never authorize a transfer larger than `maxAutopayHuman` units of the asset.
27
+ *
28
+ * @param accept the chosen x402 accept option
29
+ * @param maxAutopayHuman max auto-pay, in human-readable units of the asset
30
+ */
31
+ export function deriveX402Payment(accept, maxAutopayHuman) {
32
+ const decimals = accept.requiredDecimals || 6;
33
+ // Standard x402 uses `asset` for the token address; AgentWallet's own server
34
+ // currently emits it under extra.token. Prefer the standard field, fall back.
35
+ const tokenAddress = accept.asset || accept.extra?.token || '';
36
+ const rawAmount = accept.maxAmountRequired;
37
+ if (!/^\d+$/.test(rawAmount)) {
38
+ throw new Error(`x402 auto-pay: invalid maxAmountRequired "${rawAmount}" (expected an integer base-unit amount).`);
39
+ }
40
+ const capRaw = toBaseUnits(maxAutopayHuman, decimals);
41
+ if (BigInt(rawAmount) > BigInt(capRaw)) {
42
+ throw new Error(`x402 auto-pay blocked: required amount (${rawAmount} base units) exceeds the ` +
43
+ `AGENTWALLET_MAX_AUTOPAY cap of ${maxAutopayHuman}. Raise AGENTWALLET_MAX_AUTOPAY to allow it.`);
44
+ }
45
+ return { tokenAddress, rawAmount, decimals };
46
+ }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "agentwallet-mcp",
3
- "version": "1.7.3",
4
- "description": "MCP server for AgentWallet — lets AI agents create wallets, sign transactions, broadcast on EVM + Solana, pay x402 invoices, and accept x402 payments",
3
+ "mcpName": "io.github.hifriendbot/agentwallet",
4
+ "version": "1.7.5",
5
+ "description": "MCP server for AgentWallet: lets AI agents create wallets, sign transactions, broadcast on EVM + Solana, pay x402 invoices, and accept x402 payments",
5
6
  "type": "module",
6
7
  "main": "build/index.js",
7
8
  "bin": {
@@ -15,6 +16,7 @@
15
16
  "scripts": {
16
17
  "build": "tsc",
17
18
  "start": "node build/index.js",
19
+ "test": "node test/x402-payment.test.mjs",
18
20
  "prepublishOnly": "npm run build"
19
21
  },
20
22
  "keywords": [
@@ -45,7 +47,7 @@
45
47
  ],
46
48
  "author": "HiFriendbot (https://hifriendbot.com)",
47
49
  "license": "MIT",
48
- "homepage": "https://hifriendbot.com/agentwallet",
50
+ "homepage": "https://hifriendbot.com/wallet/",
49
51
  "engines": {
50
52
  "node": ">=18.0.0"
51
53
  },