web3-tools-mcp 3.0.0 → 3.2.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 (113) hide show
  1. package/CHANGELOG.md +115 -2
  2. package/README.md +96 -60
  3. package/dist/chain-meta.d.ts.map +1 -1
  4. package/dist/chain-meta.js +19 -8
  5. package/dist/chain-meta.js.map +1 -1
  6. package/dist/chains.d.ts +609 -65
  7. package/dist/chains.d.ts.map +1 -1
  8. package/dist/chains.js +89 -28
  9. package/dist/chains.js.map +1 -1
  10. package/dist/clear-signing.d.ts.map +1 -1
  11. package/dist/clear-signing.js +17 -6
  12. package/dist/clear-signing.js.map +1 -1
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.js +2 -4
  15. package/dist/client.js.map +1 -1
  16. package/dist/http-server.d.ts +1 -1
  17. package/dist/http-server.d.ts.map +1 -1
  18. package/dist/http-server.js +12 -5
  19. package/dist/http-server.js.map +1 -1
  20. package/dist/index.js +5 -6
  21. package/dist/index.js.map +1 -1
  22. package/dist/kv-storage.d.ts +2 -1
  23. package/dist/kv-storage.d.ts.map +1 -1
  24. package/dist/kv-storage.js +5 -2
  25. package/dist/kv-storage.js.map +1 -1
  26. package/dist/oauth.d.ts +18 -4
  27. package/dist/oauth.d.ts.map +1 -1
  28. package/dist/oauth.js +62 -26
  29. package/dist/oauth.js.map +1 -1
  30. package/dist/preview.d.ts.map +1 -1
  31. package/dist/preview.js +7 -5
  32. package/dist/preview.js.map +1 -1
  33. package/dist/tools/index.d.ts.map +1 -1
  34. package/dist/tools/index.js +16 -1
  35. package/dist/tools/index.js.map +1 -1
  36. package/dist/tools/read/advanced.d.ts +25 -20
  37. package/dist/tools/read/advanced.d.ts.map +1 -1
  38. package/dist/tools/read/advanced.js +45 -33
  39. package/dist/tools/read/advanced.js.map +1 -1
  40. package/dist/tools/read/balance.d.ts +6 -6
  41. package/dist/tools/read/balance.d.ts.map +1 -1
  42. package/dist/tools/read/balance.js +17 -32
  43. package/dist/tools/read/balance.js.map +1 -1
  44. package/dist/tools/read/contract-info.d.ts +14 -12
  45. package/dist/tools/read/contract-info.d.ts.map +1 -1
  46. package/dist/tools/read/contract-info.js +53 -122
  47. package/dist/tools/read/contract-info.js.map +1 -1
  48. package/dist/tools/read/contract.d.ts +10 -10
  49. package/dist/tools/read/contract.d.ts.map +1 -1
  50. package/dist/tools/read/contract.js +2 -1
  51. package/dist/tools/read/contract.js.map +1 -1
  52. package/dist/tools/read/defi.d.ts +86 -0
  53. package/dist/tools/read/defi.d.ts.map +1 -0
  54. package/dist/tools/read/defi.js +210 -0
  55. package/dist/tools/read/defi.js.map +1 -0
  56. package/dist/tools/read/ens.d.ts +20 -40
  57. package/dist/tools/read/ens.d.ts.map +1 -1
  58. package/dist/tools/read/ens.js +25 -33
  59. package/dist/tools/read/ens.js.map +1 -1
  60. package/dist/tools/read/gas.d.ts +16 -16
  61. package/dist/tools/read/gas.d.ts.map +1 -1
  62. package/dist/tools/read/gas.js +13 -48
  63. package/dist/tools/read/gas.js.map +1 -1
  64. package/dist/tools/read/logs.d.ts +65 -4
  65. package/dist/tools/read/logs.d.ts.map +1 -1
  66. package/dist/tools/read/logs.js +96 -115
  67. package/dist/tools/read/logs.js.map +1 -1
  68. package/dist/tools/read/signatures.d.ts.map +1 -1
  69. package/dist/tools/read/signatures.js +4 -3
  70. package/dist/tools/read/signatures.js.map +1 -1
  71. package/dist/tools/read/signing.d.ts.map +1 -1
  72. package/dist/tools/read/signing.js +8 -2
  73. package/dist/tools/read/signing.js.map +1 -1
  74. package/dist/tools/sign/transactions.d.ts +16 -16
  75. package/dist/tools/sign/transactions.d.ts.map +1 -1
  76. package/dist/tools/sign/transactions.js +54 -9
  77. package/dist/tools/sign/transactions.js.map +1 -1
  78. package/dist/tools/sign/wallet.d.ts +4 -4
  79. package/dist/types.d.ts +0 -1
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/utils.d.ts +18 -0
  82. package/dist/utils.d.ts.map +1 -1
  83. package/dist/utils.js +43 -2
  84. package/dist/utils.js.map +1 -1
  85. package/dist/wallet-client.d.ts +1 -0
  86. package/dist/wallet-client.d.ts.map +1 -1
  87. package/dist/wallet-client.js +18 -5
  88. package/dist/wallet-client.js.map +1 -1
  89. package/package.json +4 -7
  90. package/src/chain-meta.ts +16 -7
  91. package/src/chains.ts +101 -31
  92. package/src/clear-signing.ts +15 -9
  93. package/src/client.ts +2 -3
  94. package/src/http-server.ts +11 -6
  95. package/src/index.ts +5 -6
  96. package/src/kv-storage.ts +6 -3
  97. package/src/oauth.ts +93 -34
  98. package/src/preview.ts +7 -5
  99. package/src/tools/index.ts +14 -1
  100. package/src/tools/read/advanced.ts +63 -34
  101. package/src/tools/read/balance.ts +18 -33
  102. package/src/tools/read/contract-info.ts +64 -144
  103. package/src/tools/read/contract.ts +2 -1
  104. package/src/tools/read/defi.ts +287 -0
  105. package/src/tools/read/ens.ts +26 -33
  106. package/src/tools/read/gas.ts +13 -50
  107. package/src/tools/read/logs.ts +131 -143
  108. package/src/tools/read/signatures.ts +4 -4
  109. package/src/tools/read/signing.ts +8 -2
  110. package/src/tools/sign/transactions.ts +60 -9
  111. package/src/types.ts +0 -1
  112. package/src/utils.ts +47 -2
  113. package/src/wallet-client.ts +26 -5
package/CHANGELOG.md CHANGED
@@ -2,7 +2,104 @@
2
2
 
3
3
  Notable changes per release. Dates are release dates; unreleased work sits at the top.
4
4
 
5
- ## [3.0.0] — 2026-09-23
5
+ ## [3.2.0] — 2026-10-02
6
+
7
+ ### Added
8
+
9
+ - Monad, Robinhood Chain, Arc, Plasma, Ink, Mantle, Celo and HyperEVM (`hyperevm`).
10
+ `get_portfolio` skips Plasma and Mantle, where Alchemy has no token API, and
11
+ `get_contract_abi` cannot reach Ink, which Etherscan does not index.
12
+ - **`get_portfolio`** values a wallet across chains in one call: Alchemy finds the native and
13
+ ERC20 balances, DefiLlama prices them, largest first. Tokens DefiLlama cannot price are
14
+ left out and counted, which drops the spam airdrops that otherwise bury a wallet's real
15
+ holdings. Offered when `ALCHEMY_API_KEY` is set.
16
+ - **`get_token_prices`** prices up to 25 tokens on a chain in USD, now or at a past
17
+ timestamp, from DefiLlama's free API — the zero address for the native token. Tokens it
18
+ cannot price come back as unpriced.
19
+ - **`get_yield_pools`** lists DefiLlama's lending, staking and liquidity pools on the
20
+ supported chains, filtered by token, protocol, stablecoins and TVL, highest APY first.
21
+
22
+ ### Changed
23
+
24
+ - The signing page moved from `/` to `/sign/`, leaving the root free for a host's own page.
25
+ Signing links in the old `/#t=…` form no longer open it. `SIGN_PATH` is exported for hosts
26
+ building links.
27
+
28
+ ### Removed
29
+
30
+ - Infura: `INFURA_API_KEY` and `--infura-api-key`. Any other provider still works through
31
+ `CUSTOM_RPC`, chain by chain.
32
+ - Sonic. Alchemy serves no token API there, and its DeFi activity has largely moved on.
33
+
34
+ ## [3.1.0] — 2026-10-01
35
+
36
+ Mostly fixes, several of them for security — worth taking on any hosted server.
37
+
38
+ From this release `web3-wallet-relay` shares the server's version number, jumping from 2.0.0
39
+ to 3.1.0. The two speak one protocol that carries no version of its own, so the package
40
+ version is what matches them: a relay hosted on its own runs at the version of the server
41
+ pointing at it. `web3-tools-mcp` still pins it exactly.
42
+
43
+ ### Added
44
+
45
+ - A host's `Login` can name the `credential` it checks, binding every code and token issued
46
+ under it so that rotating the secret revokes them, and its `page()` is told which client
47
+ is asking and where the code will go.
48
+
49
+ ### Changed
50
+
51
+ - `trace_transaction`'s `traceType` is `trace`, `prestate` or `stateDiff`. `vmTrace` is gone:
52
+ it ran the prestate tracer under another name, and `stateDiff` asked for a tracer no node
53
+ has. Traces too large for an agent's context are cut short and say so.
54
+ - `get_logs` returns at most 1,000 logs, with `truncated` and the `nextBlock` to continue
55
+ from. `toBlock` is inclusive on both paths, a list in `eventArgs` is an OR filter, and an
56
+ invalid `address` is an error rather than a filter silently dropped.
57
+ - `get_balance`, `read_contract` and `batch_resolve_ens_names` take at most 25 items.
58
+ - ENS tools take `mainnet`, `linea` or `base` — the chains that have a resolver — and the
59
+ no-op `universalResolver` parameter is gone.
60
+ - `render.yaml` is a single service: the relay runs inside the MCP server, as on Fly.
61
+ - Keeping OAuth state in Upstash needs per-field hash expiry (`HEXPIRE`, Redis ≥ 7.4), so
62
+ expired tokens no longer pile up. The file store prunes them on write.
63
+
64
+ ### Fixed
65
+
66
+ - `send_erc20_token` no longer assumes 18 decimals. It reads them on-chain and refuses a
67
+ `decimals` that disagrees; a token whose decimals cannot be read needs them passed.
68
+ - `write_contract` takes numeric arguments only as safe integers — pass a large uint or int
69
+ as a string — and coerces string arguments to their ABI types, as `read_contract` does.
70
+ - `sign_message` sends the browser the message hex-encoded, as the phone gets it, so both
71
+ sign the same bytes. The phone signs on a chain its session approved, not mainnet.
72
+ - Phone signing on `localhost` is refused up front: the phone has no route to that node. Use
73
+ the browser.
74
+ - The signing preview names each labelled address as `Name (0x…)`, shows token amounts with
75
+ the token's address, and gives an amount whose decimals are unknown as the raw integer,
76
+ marked so, rather than assuming 18. Its summary includes `to`.
77
+ - `get_logs` over Hypersync no longer drops the last block, reports a response cut short
78
+ by the server, or scans from genesis when `fromBlock` is omitted.
79
+ - `get_error_signature` hashes tuple parameters correctly.
80
+ - `get_gas_price` shows sub-gwei L2 prices instead of "0.00", and costs in the chain's own
81
+ native token.
82
+ - An invalid, expired or replayed OAuth code or refresh token answers `invalid_grant`, not a
83
+ 500, so connectors re-authorise instead of retrying.
84
+ - Etherscan errors say why ("Invalid API Key", rate limit) rather than "NOTOK".
85
+ - `npx web3-wallet-relay` starts the relay.
86
+
87
+ ### Security
88
+
89
+ - The provider API key no longer appears in tool output.
90
+ - `get_ens_avatar` returns the raw avatar record rather than fetching it server-side.
91
+ - Requests carry `expiresAt`, and the signing page cancels an approval that arrives after
92
+ the request timed out or was disconnected. A request that failed any way but an explicit
93
+ rejection now reports `outcome_unknown` — it may still have been broadcast — instead of
94
+ `rejected_or_failed`, so an agent checks before retrying rather than paying twice.
95
+ - The signing page is hardened against script injection and framing, with a strict CSP.
96
+ - OAuth refresh tokens expire, and rotating `MCP_TOKEN` revokes every token issued under
97
+ it — existing tokens predate the binding, so single-token deployments re-authorise once.
98
+ The login page names the client and where it redirects, and cannot be framed.
99
+ `MCP_TRUST_PROXY` lets rate limiting see client addresses behind a proxy.
100
+ - The hosted signer link is no longer written to the logs.
101
+
102
+ ## [3.0.0] — 2026-09-26
6
103
 
7
104
  The theme is multi-tenancy: one server can now carry several people without their wallets
8
105
  meeting. Nothing turns that on by itself — a server still authenticates its deployment
@@ -36,6 +133,22 @@ handshake changed, so a mismatched pair cannot pair at all.
36
133
  tools take `account` to choose between them, as does `disconnect_phone_wallet` — which
37
134
  still clears everything when no account is named. With one wallet paired nothing changes,
38
135
  and omitting `account` uses the most recently paired.
136
+ - **`simulate_bundle`** runs several transactions in order in one block, each on the state
137
+ the last left — approve then swap, deposit then borrow. Offered with an Alchemy key.
138
+ - **Signing requests outlive their call.** One not approved in time comes back with a
139
+ `requestId`, and `check_signing_request` collects it instead of a second prompt landing in
140
+ the wallet. A phone request returns as soon as the wallet has it, and both signers wait
141
+ for the receipt, reporting mined, reverted or still pending. The signing page shows every
142
+ request waiting, approvable in any order.
143
+ - A host assembling its own server can mount routes, hand a pairing made under a
144
+ placeholder to the address it proved, and draw the pairing QR as SVG (`qrSvg`).
145
+ - The server declares an icon, so a connector list shows more than a letter.
146
+ - `pair_phone_wallet` warns when the same wallet app is already paired, and reports a
147
+ pairing the wallet ended itself.
148
+
149
+ ### Fixed
150
+
151
+ - An ERC-721 `Transfer` reads as a token id, not as an ERC-20 transfer of nothing.
39
152
 
40
153
  ### Security
41
154
 
@@ -177,7 +290,7 @@ sign it.
177
290
  `call_contract_write` is now `write_contract` — the old pair gave no hint which one
178
291
  spent gas. The names now match viem's, and a saved prompt naming the old ones will need
179
292
  updating.
180
- - Every supported chain now lives in one table ([mcp/src/chains.ts](mcp/src/chains.ts)). Adding a
293
+ - Every supported chain now lives in one table ([mcp/src/chains.ts](https://github.com/hajnalben/web3-tools-mcp/blob/main/mcp/src/chains.ts)). Adding a
181
294
  chain is a single entry; the tool schemas, RPC selection, explorer links, Hypersync
182
295
  routing and `--help` all derive from it.
183
296
  - Tool errors surface the underlying failure rather than a re-wrapped message that hid it.
package/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  <div align="center">
2
2
 
3
- # web3-tools-mcp
3
+ <img src="https://raw.githubusercontent.com/hajnalben/web3-tools-mcp/main/wallet-relay/public/icon.png" alt="Web3 Tools logo" width="112" height="112">
4
4
 
5
- **Your agent proposes the transaction. You approve it — in your own wallet, on your phone.** 📱
5
+ # Web3 Tools MCP
6
6
 
7
- 30 MCP tools for reading any EVM network and signing transactions in *your own* wallet.
8
- Every transaction is decoded, named and simulated before you approve it.
7
+ **Everything onchain your agent needs — read, price, simulate, sign — with you holding the keys.** 🔐
8
+
9
+ 35 MCP tools across 19 EVM networks, signing in *your own* wallet on your phone or in the browser.
10
+ Every transaction is decoded, named and simulated before it reaches your wallet.
9
11
 
10
12
  [![npm](https://img.shields.io/npm/v/web3-tools-mcp?color=%233856d6&label=npm)](https://www.npmjs.com/package/web3-tools-mcp)
11
13
  [![downloads](https://img.shields.io/npm/dm/web3-tools-mcp?color=%233856d6)](https://www.npmjs.com/package/web3-tools-mcp)
12
14
  [![node](https://img.shields.io/node/v/web3-tools-mcp?color=%233856d6)](https://nodejs.org)
13
- [![license](https://img.shields.io/npm/l/web3-tools-mcp?color=%233856d6)](LICENSE)
15
+ [![license](https://img.shields.io/npm/l/web3-tools-mcp?color=%233856d6)](https://github.com/hajnalben/web3-tools-mcp/blob/main/LICENSE)
14
16
 
15
17
  </div>
16
18
 
@@ -22,7 +24,7 @@ One entry in that client's MCP config:
22
24
  ```
23
25
 
24
26
  Each app keeps that config somewhere different —
25
- [the file paths are below ↓](#-setup). You need Node.js ≥ 20; `npx` fetches the rest.
27
+ [the file paths are below ↓](#-setup). You need Node.js ≥ 20.19; `npx` fetches the rest.
26
28
 
27
29
  **ChatGPT, Grok** and **claude.ai** cannot launch anything locally — they only reach a URL.
28
30
  [Host it once ↓](#-hosting) and add it as a connector, and there is nothing running on your
@@ -91,7 +93,7 @@ npx web3-tools-mcp --walletconnect-project-id YOUR_PROJECT_ID
91
93
  | 💾 | **It sticks.** The session is stored on disk (or in Redis when hosted), so it survives restarts and redeploys. Pair once, not once a day |
92
94
  | ✍️ | **You choose each time.** Every signing tool takes a required `signWith`, so the agent asks whether this one goes to your phone or the browser. A paired phone never quietly claims a request |
93
95
  | 🧾 | **You still see the decode.** The full preview comes back in the tool response — your wallet shows its own summary, so read ours before you approve theirs |
94
- | 🔌 | **Drop it any time.** `disconnect_phone_wallet` clears every session and pairing |
96
+ | 🔌 | **Drop it any time.** `disconnect_phone_wallet` drops the wallet you name by `account`, or every session and pairing when you name none |
95
97
 
96
98
  Works with **MetaMask · Rabby · Trust · Coinbase Wallet** — anything speaking WalletConnect v2.
97
99
 
@@ -123,28 +125,36 @@ returns the page URL any time you want to open it yourself.
123
125
  ## 🧰 Tools
124
126
 
125
127
  <details>
126
- <summary><b>30 tools</b> — reads, writes, ENS, logs, tracing</summary>
128
+ <summary><b>35 tools</b> — reads, writes, ENS, logs, tracing</summary>
127
129
 
128
130
  ### ✍️ Transactions & signing
129
131
  | Tool | |
130
132
  | --- | --- |
131
- | `write_contract` | Send a transaction calling a state-changing function, via your wallet |
133
+ | `write_contract` | Send a transaction calling a state-changing function, via your wallet. Pass large integers as strings |
132
134
  | `send_native_token` | Send ETH or a native token |
133
- | `send_erc20_token` | Send an ERC-20 |
134
- | `sign_message` | Sign a message |
135
- | `wallet_status` | Which signer is connected — phone or browser |
135
+ | `send_erc20_token` | Send an ERC-20, with decimals read on-chain — a `decimals` you pass must agree |
136
+ | `sign_message` | Sign a message — the same bytes on either signer |
137
+ | `check_signing_request` | Collect a request still awaiting approval, by its `requestId` |
138
+ | `wallet_status` | Every signer and whether it is ready — phone wallets and the browser page |
136
139
  | `pair_phone_wallet` | Pair a phone over WalletConnect, returns a QR |
137
- | `disconnect_phone_wallet` | Drop every WalletConnect session and pairing |
140
+ | `disconnect_phone_wallet` | Drop one paired wallet by `account`, or every session and pairing |
138
141
 
139
142
  The four signing tools take a required `signWith` of `phone` or `browser`. There is no
140
143
  default on purpose — the agent has to ask you, so a request never lands on a device you are
141
- not holding.
144
+ not holding. On `localhost` only the browser can sign; a phone has no route to your node.
145
+ With several phones paired, the optional `account` picks one by address;
146
+ omitted, the most recently paired is used.
147
+
148
+ A request not approved within the call comes back with a `requestId` instead of hanging,
149
+ and `check_signing_request` collects it — asking again would put a second prompt in front
150
+ of your wallet.
142
151
 
143
152
  ### 📜 Contracts
144
153
  | Tool | |
145
154
  | --- | --- |
146
- | `read_contract` | Read state via view/pure functions — batched, no wallet, no gas |
155
+ | `read_contract` | Read state via view/pure functions — batched (up to 25 calls), no wallet, no gas |
147
156
  | `simulate_contract` | Simulate without broadcasting, with gas |
157
+ | `simulate_bundle` | Simulate several transactions in order, each on the state the last left — approve → swap. Needs `ALCHEMY_API_KEY` |
148
158
  | `get_contract_abi` | ABI, with proxy detection and verification status |
149
159
  | `get_contract_source_code` | Verified source, proxies included |
150
160
  | `get_contract_source_file` | One file out of the cached source |
@@ -157,14 +167,23 @@ not holding.
157
167
  ### ⛓️ Chain data
158
168
  | Tool | |
159
169
  | --- | --- |
160
- | `get_balance` | Native or ERC-20 balances — batched |
161
- | `get_logs` | Query and decode events, with Hypersync fallback |
170
+ | `get_balance` | Native or ERC-20 balances — batched, up to 25 queries |
171
+ | `get_logs` | Query and decode events; Hypersync when the RPC refuses the range. At most 1,000 logs — past that it returns `truncated` and the `nextBlock` to continue from. A list in `eventArgs` matches any of its values |
162
172
  | `get_block_info` | Block data |
163
173
  | `get_storage_at` | Storage slots, with type decoding |
164
174
  | `get_gas_price` | Current gas — legacy and EIP-1559 |
165
175
  | `estimate_gas` | Gas for any transaction |
166
- | `trace_transaction` | Call tree, VM trace, state diff |
167
- | `debug_call` | Trace a call without broadcasting, falling back to a local anvil fork |
176
+ | `trace_transaction` | Call tree, prestate or state diff |
177
+ | `debug_call` | Trace a call without broadcasting, through a node at `ANVIL_RPC_URL` |
178
+ | `get_portfolio` | A wallet's native and ERC-20 holdings across chains, valued in USD; tokens DefiLlama cannot price — spam, mostly — are left out. Needs `ALCHEMY_API_KEY` |
179
+ | `get_token_prices` | USD prices from DefiLlama, now or at a past timestamp, up to 25 tokens; the zero address prices the native token |
180
+ | `get_yield_pools` | DefiLlama yield pools by chain, token and protocol, highest APY first |
181
+
182
+ Tracing prefers an RPC that exposes `debug_*`, and otherwise uses a node you already run at
183
+ `ANVIL_RPC_URL` (default `127.0.0.1:8545`, e.g. `anvil --fork-url …`) — nothing is started
184
+ for you. Replaying a transaction older than the fork re-forks that node, clearing its state,
185
+ so it happens only with `ANVIL_ALLOW_RESET=1`. A hosted server has no default and traces only
186
+ through an explicit `ANVIL_RPC_URL`.
168
187
 
169
188
  ### 🏷️ ENS
170
189
  | Tool | |
@@ -172,13 +191,15 @@ not holding.
172
191
  | `resolve_ens_name` | Name → address |
173
192
  | `reverse_resolve_ens` | Address → name |
174
193
  | `get_ens_text_record` | Text records |
175
- | `get_ens_avatar` | Avatar URI |
176
- | `batch_resolve_ens_names` | Many names at once |
194
+ | `get_ens_avatar` | The raw avatar record — URL, data URI or NFT reference, not fetched |
195
+ | `batch_resolve_ens_names` | Up to 25 names at once |
196
+
197
+ ENS tools take `mainnet` (ENS), `linea` (Linea Names) or `base` (Basenames).
177
198
 
178
199
  </details>
179
200
 
180
201
  <details>
181
- <summary>🌐 <b>13 networks</b></summary>
202
+ <summary>🌐 <b>20 networks</b></summary>
182
203
 
183
204
  | Network | Chain ID | Hypersync |
184
205
  | --- | --- | --- |
@@ -188,15 +209,22 @@ not holding.
188
209
  | Base | 8453 | ✅ |
189
210
  | BNB Chain | 56 | ✅ |
190
211
  | Gnosis | 100 | ✅ |
191
- | Sonic | 146 | ✅ |
192
212
  | Optimism | 10 | ✅ |
193
213
  | Polygon | 137 | ✅ |
194
214
  | zkSync Era | 324 | ✅ |
195
215
  | Linea | 59144 | ✅ |
196
216
  | Unichain | 130 | ✅ |
217
+ | Monad | 143 | ✅ |
218
+ | Robinhood Chain | 4663 | ✅ |
219
+ | Arc | 5042 | ✅ |
220
+ | Plasma | 9745 | ✅ |
221
+ | Ink | 57073 | ✅ |
222
+ | Mantle | 5000 | ✅ |
223
+ | Celo | 42220 | ✅ |
224
+ | HyperEVM | 999 | ✅ |
197
225
  | Localhost | 1337 | ❌ |
198
226
 
199
- Adding one is a single entry in [`mcp/src/chains.ts`](mcp/src/chains.ts).
227
+ Adding one is a single entry in [`mcp/src/chains.ts`](https://github.com/hajnalben/web3-tools-mcp/blob/main/mcp/src/chains.ts).
200
228
 
201
229
  </details>
202
230
 
@@ -289,17 +317,17 @@ What you lose is reach, not stability — so here is the honest version:
289
317
  | Key | Free from | Without it |
290
318
  | --- | --- | --- |
291
319
  | `WALLETCONNECT_PROJECT_ID` | [walletconnect](https://dashboard.walletconnect.com) | 📱 **No phone signing at all.** Browser wallet only, so a hosted instance has no way to sign |
292
- | `ALCHEMY_API_KEY`<br>or `INFURA_API_KEY`<br>or `CUSTOM_RPC` | [alchemy](https://alchemy.com) · [infura](https://infura.io) | **No historical state.** Public endpoints answer `403 Archive requests require a personal token`, which takes out balances, storage and calls at a past block, event ranges, and `trace_transaction` |
320
+ | `ALCHEMY_API_KEY`<br>or `CUSTOM_RPC` | [alchemy](https://alchemy.com) | **No historical state.** Public endpoints answer `403 Archive requests require a personal token`, which takes out balances, storage and calls at a past block, event ranges, and `trace_transaction` |
293
321
  | `ETHERSCAN_API_KEY` | [etherscan](https://etherscan.io/apis) | `get_contract_abi`, `get_contract_source_code` and `get_contract_source_file` refuse. Signing previews still decode — they try Sourcify first, then recover the ABI from bytecode |
294
- | `HYPERSYNC_API_KEY` | [envio](https://envio.dev) | Event queries fall back to plain RPC — slower, and past ranges then need one of the provider keys above |
322
+ | `HYPERSYNC_API_KEY` | [envio](https://envio.dev) | `get_logs` asks the RPC first and falls back to Hypersync when the RPC refuses the range. Without a token that fallback is gone, so wide or past ranges depend on your provider's limits |
295
323
 
296
324
  So with nothing configured you get current balances, contract reads, gas, ENS, simulation
297
325
  and browser signing. Add `WALLETCONNECT_PROJECT_ID` for your phone and one provider key for
298
326
  history, and everything above lights up.
299
327
 
300
328
  Every key has a matching flag (`--etherscan-api-key`, …), RPC selection falls back
301
- Alchemy → Infura → public, and `CUSTOM_RPC` overrides all of it.
302
- `npx web3-tools-mcp --help` lists them; [.env.example](.env.example) documents each one.
329
+ Alchemy → public, and `CUSTOM_RPC` overrides both, chain by chain.
330
+ `npx web3-tools-mcp --help` lists them; [.env.example](https://github.com/hajnalben/web3-tools-mcp/blob/main/.env.example) documents each one.
303
331
 
304
332
  ```bash
305
333
  npx web3-tools-mcp --etherscan-api-key KEY --walletconnect-project-id ID
@@ -319,26 +347,34 @@ transaction at your phone.
319
347
  <a href="https://fly.io/docs/launch/"><img src="https://img.shields.io/badge/Deploy%20on-Fly.io-8b5cf6?style=for-the-badge&logo=flydotio&logoColor=white" alt="Deploy on Fly.io" height="32"></a>
320
348
 
321
349
  **Render** reads `render.yaml`, generates `MCP_TOKEN` and asks for `WALLETCONNECT_PROJECT_ID`
322
- — genuinely one click.
350
+ — one click, on a paid `starter` instance with a 1 GB disk so it stays awake and keeps the
351
+ pairing. `MCP_PUBLIC_URL` defaults to the service's `onrender.com` address; set it only for a
352
+ custom domain.
323
353
 
324
354
  **Fly** ships no deploy button, so it is four commands. Worth it for a personal instance:
325
355
  volumes come with any plan, so the pairing survives redeploys without paying for a disk.
326
356
 
327
357
  ```bash
328
- fly launch --no-deploy --copy-config
358
+ fly launch --no-deploy --copy-config # then set MCP_PUBLIC_URL in fly.toml to https://<app>.fly.dev
329
359
  fly volumes create data --size 1
330
360
  fly secrets set MCP_TOKEN=$(openssl rand -hex 24) WALLETCONNECT_PROJECT_ID=<id>
331
361
  fly deploy
332
362
  ```
333
363
 
364
+ Without the right `MCP_PUBLIC_URL` the OAuth metadata and the wallet links point somewhere
365
+ clients cannot reach. Both `fly.toml` and `render.yaml` set `MCP_TRUST_PROXY=1`, so rate
366
+ limiting sees client addresses rather than the platform's proxy.
367
+
334
368
  <details>
335
369
  <summary>🐳 <b>Docker, and connecting a client</b></summary>
336
370
 
337
371
  There is a plain `Dockerfile` too, so Railway, Cloud Run or your own box work the same way:
338
372
 
339
373
  ```bash
374
+ docker build -t web3-tools-mcp .
340
375
  docker run -p 8080:8080 \
341
376
  -e MCP_TOKEN=<long random string> \
377
+ -e MCP_PUBLIC_URL=https://your-host \
342
378
  -e WALLETCONNECT_PROJECT_ID=<id> \
343
379
  web3-tools-mcp
344
380
  ```
@@ -352,54 +388,54 @@ claude mcp add --transport http web3-tools https://your-host/mcp \
352
388
 
353
389
  Clients that cannot send a header — claude.ai connectors, and the browser and phone apps —
354
390
  use OAuth, which the server implements against the same credential: it shows a page asking
355
- for `MCP_TOKEN` and issues a token once you paste it. No identity provider, no accounts. Set
356
- `MCP_PUBLIC_URL` to the address clients reach you on, since OAuth metadata must advertise it.
391
+ for `MCP_TOKEN` and issues a token once you paste it. No identity provider, no accounts.
357
392
 
358
393
  > 🔐 **`MCP_TOKEN` is mandatory** and the server refuses to start without it. Anyone who
359
394
  > reaches `/mcp` while your phone is paired can push signing prompts at it. You would still
360
395
  > approve each one, but that is a phishing surface, not a feature.
361
396
 
397
+ | Variable | |
398
+ | --- | --- |
399
+ | `MCP_HTTP_PORT` | Serve over HTTP on this port instead of stdio. Also switches on the hosted guards: no `localhost` chain, no loopback tracing node |
400
+ | `MCP_HTTP_HOST` | Bind address, default `0.0.0.0` |
401
+ | `MCP_TOKEN` | The one credential, as a bearer header or through OAuth. Changing it revokes every OAuth token issued against the old one |
402
+ | `MCP_PUBLIC_URL` | The address clients reach you on — advertised in OAuth metadata and used for wallet links |
403
+ | `MCP_TRUST_PROXY` | Reverse-proxy hops to trust for client IPs in rate limiting. `1` behind Fly or Render; off by default |
404
+ | `MCP_HOSTED` | The hosted guards without `MCP_HTTP_PORT`, for a host assembling its own server from the library |
405
+ | `XDG_CONFIG_HOME` | Where pairings, OAuth tokens and the relay token are stored, under `web3-tools-mcp/` |
406
+ | `UPSTASH_REDIS_REST_URL`<br>`UPSTASH_REDIS_REST_TOKEN` | Keep sessions and tokens in Redis instead. Needs per-field hash expiry (`HEXPIRE`: Upstash, or Redis ≥ 7.4) |
407
+ | `WALLET_TOKEN` | Relay secret. Unset, a hosted server mints one per boot |
408
+ | `WALLET_SERVER_URL` | A separately hosted relay, below |
409
+ | `ANVIL_RPC_URL`<br>`ANVIL_ALLOW_RESET` | Tracing node, and whether it may be re-forked — see Tools |
410
+
362
411
  Two things decide whether the pairing survives:
363
412
 
364
413
  - ⏰ **Keep the instance awake.** Sleeping drops the WalletConnect socket, so the first
365
414
  transaction after an idle period waits for the host to wake — about a minute on a free tier.
366
415
  - 💾 **Give the session somewhere durable.** Most hosts have an ephemeral filesystem, so a
367
416
  plain file is lost on redeploy and you rescan the QR. Attach a volume and point
368
- `XDG_CONFIG_HOME` at it (what `render.yaml` does), or set `UPSTASH_REDIS_REST_URL` and
369
- `UPSTASH_REDIS_REST_TOKEN` ([Upstash](https://upstash.com) has a free plan).
417
+ `XDG_CONFIG_HOME` at it (what `render.yaml` and `fly.toml` do), or set
418
+ `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` ([Upstash](https://upstash.com)
419
+ has a free plan).
370
420
 
371
421
  Render's free Key Value instance is not an option here — no persistence, so the pairing
372
422
  disappears at its next maintenance.
373
423
 
374
424
  Both signers work on a hosted instance. The signing page is served from the same port as
375
- `/mcp`, so `https://your-host/#t=<relay token>` is your wallet page — no second service to
376
- deploy. Ask the agent for `wallet_status` to get the link; it is behind `MCP_TOKEN`, and the
377
- relay token is minted fresh each boot rather than stored, so the URL changes when you
378
- redeploy.
425
+ `/mcp`, so `https://your-host/sign/#t=<relay token>` is your wallet page — no second service to
426
+ deploy. The root is left free for a page of your own. Ask the agent for `wallet_status` to get the link; it is behind `MCP_TOKEN` and never written to the logs. Unless
427
+ you set `WALLET_TOKEN`, the relay secret is minted fresh each boot rather than stored, so the
428
+ URL changes when you redeploy.
379
429
 
380
430
  </details>
381
431
 
382
432
  <details>
383
433
  <summary>🖇️ <b>Host the signing page</b> separately</summary>
384
434
 
385
- The relay is its own package, [`wallet-relay/`](wallet-relay) — express, cors and ws, about
386
- 4 MB installed against ~180 MB for the server. It runs anywhere that keeps a Node process
387
- alive and supports WebSockets.
388
-
389
- ```bash
390
- WALLET_TOKEN=<long random string> \
391
- WALLET_PUBLIC_URL=https://wallet.example.com \
392
- npx web3-wallet-relay
393
- ```
394
-
395
- Then point the server at it with `WALLET_SERVER_URL` and the same `WALLET_TOKEN`.
396
- `render.yaml` deploys it as-is. Anyone holding `WALLET_TOKEN` can send your browser a
397
- transaction to sign — treat it like a password, and always serve over HTTPS.
398
-
399
- The pairing link the server prints carries a different token, derived from that one, which
400
- can only answer signing requests and not make them. Sharing a pairing link is therefore not
401
- the same as sharing `WALLET_TOKEN` — but it still lets whoever has it act as your wallet
402
- page, so a signing request can reach them instead of you.
435
+ The relay is its own package, [`web3-wallet-relay`](https://github.com/hajnalben/web3-tools-mcp/tree/main/wallet-relay),
436
+ and runs anywhere that keeps a Node process alive and supports WebSockets. Its README covers
437
+ hosting it; run it at this server's version, then point the server at it with
438
+ `WALLET_SERVER_URL` and the same `WALLET_TOKEN`.
403
439
 
404
440
  Locally nothing changes: the server embeds the same relay.
405
441
 
@@ -421,11 +457,11 @@ npm run typecheck
421
457
  npm test
422
458
  ```
423
459
 
424
- Two workspaces: [`mcp/`](mcp) is this server, [`wallet-relay/`](wallet-relay) is the signing
425
- page. [CONTRIBUTING.md](CONTRIBUTING.md) covers running a checkout against a client, the
426
- layout, and how to add a chain or a tool. Releases: [CHANGELOG.md](CHANGELOG.md).
460
+ Two workspaces: [`mcp/`](https://github.com/hajnalben/web3-tools-mcp/tree/main/mcp) is this server, [`wallet-relay/`](https://github.com/hajnalben/web3-tools-mcp/tree/main/wallet-relay) is the signing
461
+ page. [CONTRIBUTING.md](https://github.com/hajnalben/web3-tools-mcp/blob/main/CONTRIBUTING.md) covers running a checkout against a client, the
462
+ layout, and how to add a chain or a tool. Releases: [CHANGELOG.md](https://github.com/hajnalben/web3-tools-mcp/blob/main/CHANGELOG.md).
427
463
 
428
- Requires Node.js ≥ 20.
464
+ Requires Node.js ≥ 20.19.
429
465
 
430
466
  ## 📄 License
431
467
 
@@ -1 +1 @@
1
- {"version":3,"file":"chain-meta.d.ts","sourceRoot":"","sources":["../src/chain-meta.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,KAAK,GAAG,EAA8B,MAAM,MAAM,CAAA;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAW3C,wBAAsB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;SAJvB,GAAG;YAAU,UAAU,GAAG,SAAS;YAAU,MAAM;WAAS,MAAM;GAqCzG;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM;aArClB,MAAM;eAAa,MAAM;GAyDrE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmBjG;AAED,wEAAwE;AACxE,eAAO,MAAM,WAAW,QAAoB,CAAA;AAC5C,eAAO,MAAM,mBAAmB,QAAmB,CAAA"}
1
+ {"version":3,"file":"chain-meta.d.ts","sourceRoot":"","sources":["../src/chain-meta.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,KAAK,GAAG,EAA8B,MAAM,MAAM,CAAA;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAiB3C,wBAAsB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;SAP1B,GAAG;YAAU,UAAU,GAAG,SAAS;YAAU,MAAM;WAAS,MAAM;GAwCtG;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM;aAxCrB,MAAM;eAAa,MAAM;GA6DlE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAqBjG;AAED,wEAAwE;AACxE,eAAO,MAAM,WAAW,QAAoB,CAAA;AAC5C,eAAO,MAAM,mBAAmB,QAAmB,CAAA"}
@@ -6,13 +6,18 @@
6
6
  import { whatsabi } from '@shazow/whatsabi';
7
7
  import { parseAbiItem } from 'viem';
8
8
  import { getClientManager } from './client.js';
9
+ import { TtlCache } from './utils.js';
9
10
  const ERC20_META_ABI = [
10
11
  parseAbiItem('function decimals() view returns (uint8)'),
11
12
  parseAbiItem('function symbol() view returns (string)')
12
13
  ];
13
- const abiCache = new Map();
14
- const labelCache = new Map();
15
- const metaCache = new Map();
14
+ // An hour covers a session's repeats while still noticing an upgraded proxy.
15
+ const TTL_MS = 60 * 60 * 1000;
16
+ const abiCache = new TtlCache(200, TTL_MS);
17
+ const labelCache = new TtlCache(1000, TTL_MS);
18
+ const metaCache = new TtlCache(1000, TTL_MS);
19
+ /** A local node is reset and redeployed at will, so nothing learned from it stays true. */
20
+ const cacheable = (chain) => chain !== 'localhost';
16
21
  export async function loadAbi(chain, address) {
17
22
  const key = `${chain}:${address.toLowerCase()}`;
18
23
  const cached = abiCache.get(key);
@@ -41,7 +46,8 @@ export async function loadAbi(chain, address) {
41
46
  proxy: result.address !== address ? result.address : undefined,
42
47
  name: result.contractResult?.name ?? undefined
43
48
  };
44
- abiCache.set(key, loaded);
49
+ if (cacheable(chain))
50
+ abiCache.set(key, loaded);
45
51
  return loaded;
46
52
  }
47
53
  export async function tokenMeta(chain, token) {
@@ -61,7 +67,9 @@ export async function tokenMeta(chain, token) {
61
67
  decimals: decimals.status === 'success' ? Number(decimals.result) : undefined,
62
68
  symbol: symbol.status === 'success' ? symbol.result : undefined
63
69
  };
64
- metaCache.set(key, meta);
70
+ // A failed call may be a flaky RPC rather than a token without that method.
71
+ if (cacheable(chain) && decimals.status === 'success' && symbol.status === 'success')
72
+ metaCache.set(key, meta);
65
73
  return meta;
66
74
  }
67
75
  /**
@@ -71,8 +79,9 @@ export async function tokenMeta(chain, token) {
71
79
  */
72
80
  export async function addressLabel(chain, address) {
73
81
  const key = `${chain}:${address.toLowerCase()}`;
74
- if (labelCache.has(key))
75
- return labelCache.get(key);
82
+ const cached = labelCache.get(key);
83
+ if (cached)
84
+ return cached.label;
76
85
  let label;
77
86
  try {
78
87
  const code = await getClientManager()
@@ -86,8 +95,10 @@ export async function addressLabel(chain, address) {
86
95
  }
87
96
  catch {
88
97
  // Unknown address — show it bare rather than failing the preview.
98
+ return undefined;
89
99
  }
90
- labelCache.set(key, label);
100
+ if (cacheable(chain))
101
+ labelCache.set(key, { label });
91
102
  return label;
92
103
  }
93
104
  /** uint256 max and anything near it means "infinite" in an approval. */
@@ -1 +1 @@
1
- {"version":3,"file":"chain-meta.js","sourceRoot":"","sources":["../src/chain-meta.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chain-meta.js","sourceRoot":"","sources":["../src/chain-meta.ts"],"names":[],"mappings":"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"}