web3-tools-mcp 1.6.0 → 2.0.1
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/CHANGELOG.md +109 -0
- package/README.md +328 -234
- package/dist/anvil.d.ts +1 -1
- package/dist/anvil.d.ts.map +1 -1
- package/dist/anvil.js +11 -9
- package/dist/anvil.js.map +1 -1
- package/dist/chain-meta.d.ts.map +1 -1
- package/dist/chain-meta.js +7 -3
- package/dist/chain-meta.js.map +1 -1
- package/dist/chains.d.ts +960 -0
- package/dist/chains.d.ts.map +1 -0
- package/dist/chains.js +108 -0
- package/dist/chains.js.map +1 -0
- package/dist/client.d.ts +10 -1717
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +33 -218
- package/dist/client.js.map +1 -1
- package/dist/http-server.d.ts +6 -0
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +55 -40
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +50 -29
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +31 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +227 -0
- package/dist/oauth.js.map +1 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +2 -2
- package/dist/preview.js.map +1 -1
- package/dist/tools/advanced.d.ts +4 -4
- package/dist/tools/advanced.d.ts.map +1 -1
- package/dist/tools/advanced.js +228 -247
- package/dist/tools/advanced.js.map +1 -1
- package/dist/tools/balance.d.ts +1 -1
- package/dist/tools/balance.d.ts.map +1 -1
- package/dist/tools/balance.js +97 -103
- package/dist/tools/balance.js.map +1 -1
- package/dist/tools/contract-info.d.ts +3 -3
- package/dist/tools/contract-info.d.ts.map +1 -1
- package/dist/tools/contract-info.js +150 -161
- package/dist/tools/contract-info.js.map +1 -1
- package/dist/tools/contract.d.ts +4 -4
- package/dist/tools/contract.d.ts.map +1 -1
- package/dist/tools/contract.js +91 -110
- package/dist/tools/contract.js.map +1 -1
- package/dist/tools/ens.d.ts +6 -6
- package/dist/tools/ens.d.ts.map +1 -1
- package/dist/tools/ens.js +239 -297
- package/dist/tools/ens.js.map +1 -1
- package/dist/tools/gas.d.ts +4 -4
- package/dist/tools/gas.d.ts.map +1 -1
- package/dist/tools/gas.js +90 -138
- package/dist/tools/gas.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/logs.d.ts +1 -1
- package/dist/tools/logs.d.ts.map +1 -1
- package/dist/tools/logs.js +36 -37
- package/dist/tools/logs.js.map +1 -1
- package/dist/tools/signatures.d.ts.map +1 -1
- package/dist/tools/signatures.js +67 -89
- package/dist/tools/signatures.js.map +1 -1
- package/dist/tools/transactions.d.ts +35 -5
- package/dist/tools/transactions.d.ts.map +1 -1
- package/dist/tools/transactions.js +148 -74
- package/dist/tools/transactions.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +35 -98
- package/dist/utils.js.map +1 -1
- package/dist/wallet-client.d.ts +11 -1
- package/dist/wallet-client.d.ts.map +1 -1
- package/dist/wallet-client.js +27 -9
- package/dist/wallet-client.js.map +1 -1
- package/dist/walletconnect.d.ts +22 -1
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js +106 -8
- package/dist/walletconnect.js.map +1 -1
- package/package.json +17 -9
- package/src/anvil.ts +15 -18
- package/src/chain-meta.ts +8 -4
- package/src/chains.ts +145 -0
- package/src/client.ts +39 -254
- package/src/http-server.ts +67 -44
- package/src/index.ts +77 -53
- package/src/oauth.ts +270 -0
- package/src/preview.ts +3 -12
- package/src/tools/advanced.ts +195 -213
- package/src/tools/balance.ts +103 -108
- package/src/tools/contract-info.ts +163 -184
- package/src/tools/contract.ts +123 -144
- package/src/tools/ens.ts +290 -345
- package/src/tools/gas.ts +122 -170
- package/src/tools/index.ts +2 -2
- package/src/tools/logs.ts +45 -43
- package/src/tools/signatures.ts +68 -86
- package/src/tools/transactions.ts +194 -87
- package/src/types.ts +1 -15
- package/src/utils.ts +52 -110
- package/src/wallet-client.ts +31 -9
- package/src/walletconnect.ts +124 -7
package/README.md
CHANGED
|
@@ -1,79 +1,188 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# web3-tools-mcp
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Your agent proposes the transaction. You approve it — in your own wallet, on your phone.** 📱
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- Clear signing: transactions are decoded, named and simulated before you approve them
|
|
10
|
-
- Smart contract interactions (read & write functions, ABI retrieval, source code)
|
|
11
|
-
- Contract simulation & gas estimation (simulate transactions, estimate costs)
|
|
12
|
-
- Real-time gas price tracking (legacy & EIP-1559)
|
|
13
|
-
- ENS resolution (names ↔ addresses, text records, avatars)
|
|
14
|
-
- Token balances & transfers (native & ERC20, batch queries)
|
|
15
|
-
- Event log queries with Hypersync acceleration
|
|
16
|
-
- Transaction tracing and analysis
|
|
17
|
-
- Storage slot reading with type decoding
|
|
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.
|
|
18
9
|
|
|
19
|
-
|
|
10
|
+
[](https://www.npmjs.com/package/web3-tools-mcp)
|
|
11
|
+
[](https://www.npmjs.com/package/web3-tools-mcp)
|
|
12
|
+
[](https://nodejs.org)
|
|
13
|
+
[](LICENSE)
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
**Claude Desktop, Cursor, VS Code, Windsurf** and **Claude Code** launch it on your machine.
|
|
18
|
+
One entry in that client's MCP config:
|
|
25
19
|
|
|
26
|
-
### Claude Desktop
|
|
27
|
-
Add to `config.json`:
|
|
28
20
|
```json
|
|
29
|
-
{
|
|
30
|
-
"mcpServers": {
|
|
31
|
-
"web3-tools": {
|
|
32
|
-
"command": "npx",
|
|
33
|
-
"args": ["-y", "web3-tools-mcp"]
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
21
|
+
{ "mcpServers": { "web3-tools": { "command": "npx", "args": ["-y", "web3-tools-mcp"] } } }
|
|
37
22
|
```
|
|
38
23
|
|
|
39
|
-
|
|
24
|
+
Each app keeps that config somewhere different —
|
|
25
|
+
[the file paths are below ↓](#-setup). You need Node.js ≥ 20; `npx` fetches the rest.
|
|
40
26
|
|
|
41
|
-
|
|
27
|
+
**ChatGPT, Grok** and **claude.ai** cannot launch anything locally — they only reach a URL.
|
|
28
|
+
[Host it once ↓](#-hosting) and add it as a connector, and there is nothing running on your
|
|
29
|
+
laptop at all.
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- `--hypersync-api-key` or `HYPERSYNC_API_KEY` - Fast event queries (10-100x faster)
|
|
46
|
-
- `--alchemy-api-key` or `ALCHEMY_API_KEY` - Enhanced RPC reliability
|
|
47
|
-
- `--infura-api-key` or `INFURA_API_KEY` - Additional RPC provider
|
|
48
|
-
- `--custom-rpc` - Custom RPC URLs as JSON
|
|
49
|
-
- `--walletconnect-project-id` or `WALLETCONNECT_PROJECT_ID` - Sign from a phone
|
|
31
|
+
It runs with no API keys at all — reads on recent state work on public RPCs, and signing
|
|
32
|
+
previews still decode. Keys widen what it can reach; [see what each unlocks ↓](#-setup).
|
|
50
33
|
|
|
51
|
-
|
|
52
|
-
- `WALLET_SERVER_URL` + `WALLET_TOKEN` - Use a hosted relay instead of a local one
|
|
53
|
-
- `PORT`, `HOST`, `WALLET_PUBLIC_URL` - Read by the relay itself when you host it
|
|
34
|
+
## 🔍 No blind signing
|
|
54
35
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- Hypersync: [hypersync.xyz](https://hypersync.xyz)
|
|
58
|
-
- Alchemy: [alchemy.com](https://alchemy.com)
|
|
59
|
-
- Infura: [infura.io](https://infura.io)
|
|
36
|
+
Your agent proposes. You see what it actually does, then approve it in your own wallet.
|
|
37
|
+
The server never holds a private key.
|
|
60
38
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
39
|
+
<table>
|
|
40
|
+
<tr><th>What a wallet usually shows</th><th>What you get here</th></tr>
|
|
41
|
+
<tr><td>
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
To 0x87870Bca…B4fA4E2
|
|
45
|
+
Data 0x617ba037000000000…
|
|
46
|
+
Value 0
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
*Unknown contract, unknown call.*
|
|
50
|
+
|
|
51
|
+
</td><td>
|
|
65
52
|
|
|
66
|
-
# Environment variables
|
|
67
|
-
export ETHERSCAN_API_KEY=your_key
|
|
68
|
-
export HYPERSYNC_API_KEY=your_key
|
|
69
|
-
npx web3-tools-mcp
|
|
70
53
|
```
|
|
54
|
+
Supply · Aave V3
|
|
55
|
+
Amount to supply 250 USDC
|
|
56
|
+
On behalf of you
|
|
57
|
+
|
|
58
|
+
−250 USDC → +250 aUSDC
|
|
59
|
+
184,207 gas · will succeed
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
</td></tr>
|
|
63
|
+
</table>
|
|
64
|
+
|
|
65
|
+
Four things go into that panel:
|
|
66
|
+
|
|
67
|
+
| | | |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| 🏷️ | **Intent** | Field labels straight from the protocol, via the [ERC-7730 registry](https://github.com/LedgerHQ/clear-signing-erc7730-registry) — 600+ contracts, 3,000+ selectors, bundled offline and refreshed weekly by a PR |
|
|
70
|
+
| 🔎 | **Decoded call** | Otherwise the function and named arguments, from the verified ABI (Sourcify / Etherscan) — or recovered straight from bytecode with [WhatsABI](https://github.com/shazow/whatsabi) when a contract is unverified. Proxies resolve to their implementation |
|
|
71
|
+
| 💰 | **Real amounts** | Formatted with on-chain decimals and symbol. Unlimited approvals are called out |
|
|
72
|
+
| 🧪 | **Simulation** | `eth_simulateV1` reports the gas and every ERC-20 movement the transaction would cause, marked in or out. A transaction that would revert says so before you can sign it |
|
|
71
73
|
|
|
72
|
-
##
|
|
74
|
+
## 📱 Sign on your phone
|
|
75
|
+
|
|
76
|
+
**Your agent runs wherever it likes. Your keys stay in your pocket.**
|
|
77
|
+
|
|
78
|
+
A phone can't host a local signing page — so it doesn't have to. Point the server at a
|
|
79
|
+
[WalletConnect](https://dashboard.walletconnect.com) project id and it talks to your wallet
|
|
80
|
+
app directly, over WalletConnect's own end-to-end encrypted relay. Nothing to load, nothing
|
|
81
|
+
to host, no browser anywhere in the path.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx web3-tools-mcp --walletconnect-project-id YOUR_PROJECT_ID
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
| | |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| 🌍 | **Works hosted.** A deployed server can sign on your phone with nothing running beside you — and now in your browser too, from the page it serves itself |
|
|
90
|
+
| 📷 | **Pair once.** Ask the agent to run `pair_phone_wallet`. You get a QR to scan — or, when the agent is already on your phone, a tap-through link straight into your wallet app |
|
|
91
|
+
| 💾 | **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
|
+
| ✍️ | **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
|
+
| 🧾 | **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 |
|
|
95
|
+
|
|
96
|
+
Works with **MetaMask · Rabby · Trust · Coinbase Wallet** — anything speaking WalletConnect v2.
|
|
97
|
+
|
|
98
|
+
> ### ☁️ + 📱 The combination that unlocks everything
|
|
99
|
+
>
|
|
100
|
+
> Because signing no longer needs anything next to you, the server can live in the cloud and
|
|
101
|
+
> **still** have your phone sign. Host it once and every client you own — laptop, browser,
|
|
102
|
+
> the Claude phone app — drives the same instance, with approvals landing on your phone
|
|
103
|
+
> wherever you are. [Hosting takes about a minute ↓](#-hosting)
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary>💻 <b>On a laptop?</b> Sign in the wallet extension you already run — zero configuration</summary>
|
|
107
|
+
|
|
108
|
+
Nothing to install and nothing to set up: the server serves a local page, and that page talks
|
|
109
|
+
to whatever wallet extension your browser already has. The first transaction opens it, you
|
|
110
|
+
connect MetaMask, Rabby or Coinbase once, and every later request lands in that same tab.
|
|
111
|
+
|
|
112
|
+
**One relay per machine** — all your editor sessions share the page, so you connect once and
|
|
113
|
+
a transaction from any session shows up there. The page and the server are both clients of a
|
|
114
|
+
local relay on `127.0.0.1:3456` (next free port up to 3460), authenticated with a pairing
|
|
115
|
+
token carried in the URL fragment (`#t=…`) of the link the server prints. The token lives in
|
|
116
|
+
`~/.config/web3-tools-mcp/relay-token` (mode 0600) — delete it to rotate.
|
|
117
|
+
|
|
118
|
+
Works with MetaMask, Rabby, Coinbase Wallet, and any EIP-1193 browser wallet. `wallet_status`
|
|
119
|
+
returns the page URL any time you want to open it yourself.
|
|
120
|
+
|
|
121
|
+
</details>
|
|
122
|
+
|
|
123
|
+
## 🧰 Tools
|
|
124
|
+
|
|
125
|
+
<details>
|
|
126
|
+
<summary><b>30 tools</b> — reads, writes, ENS, logs, tracing</summary>
|
|
127
|
+
|
|
128
|
+
### ✍️ Transactions & signing
|
|
129
|
+
| Tool | |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `write_contract` | Send a transaction calling a state-changing function, via your wallet |
|
|
132
|
+
| `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 |
|
|
136
|
+
| `pair_phone_wallet` | Pair a phone over WalletConnect, returns a QR |
|
|
137
|
+
| `disconnect_phone_wallet` | Drop every WalletConnect session and pairing |
|
|
138
|
+
|
|
139
|
+
The four signing tools take a required `signWith` of `phone` or `browser`. There is no
|
|
140
|
+
default on purpose — the agent has to ask you, so a request never lands on a device you are
|
|
141
|
+
not holding.
|
|
142
|
+
|
|
143
|
+
### 📜 Contracts
|
|
144
|
+
| Tool | |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `read_contract` | Read state via view/pure functions — batched, no wallet, no gas |
|
|
147
|
+
| `simulate_contract` | Simulate without broadcasting, with gas |
|
|
148
|
+
| `get_contract_abi` | ABI, with proxy detection and verification status |
|
|
149
|
+
| `get_contract_source_code` | Verified source, proxies included |
|
|
150
|
+
| `get_contract_source_file` | One file out of the cached source |
|
|
151
|
+
| `is_contract` | Contract or EOA |
|
|
152
|
+
| `encode_function_data` | Calldata from an ABI and arguments |
|
|
153
|
+
| `get_function_signature` | 4-byte selector |
|
|
154
|
+
| `get_event_signature` | 32-byte topic0 |
|
|
155
|
+
| `get_error_signature` | 4-byte error selector |
|
|
156
|
+
|
|
157
|
+
### ⛓️ Chain data
|
|
158
|
+
| Tool | |
|
|
159
|
+
| --- | --- |
|
|
160
|
+
| `get_balance` | Native or ERC-20 balances — batched |
|
|
161
|
+
| `get_logs` | Query and decode events, with Hypersync fallback |
|
|
162
|
+
| `get_block_info` | Block data |
|
|
163
|
+
| `get_storage_at` | Storage slots, with type decoding |
|
|
164
|
+
| `get_gas_price` | Current gas — legacy and EIP-1559 |
|
|
165
|
+
| `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 |
|
|
168
|
+
|
|
169
|
+
### 🏷️ ENS
|
|
170
|
+
| Tool | |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| `resolve_ens_name` | Name → address |
|
|
173
|
+
| `reverse_resolve_ens` | Address → name |
|
|
174
|
+
| `get_ens_text_record` | Text records |
|
|
175
|
+
| `get_ens_avatar` | Avatar URI |
|
|
176
|
+
| `batch_resolve_ens_names` | Many names at once |
|
|
177
|
+
|
|
178
|
+
</details>
|
|
179
|
+
|
|
180
|
+
<details>
|
|
181
|
+
<summary>🌐 <b>13 networks</b></summary>
|
|
73
182
|
|
|
74
183
|
| Network | Chain ID | Hypersync |
|
|
75
|
-
|
|
76
|
-
| Ethereum
|
|
184
|
+
| --- | --- | --- |
|
|
185
|
+
| Ethereum | 1 | ✅ |
|
|
77
186
|
| Arbitrum | 42161 | ✅ |
|
|
78
187
|
| Avalanche | 43114 | ✅ |
|
|
79
188
|
| Base | 8453 | ✅ |
|
|
@@ -87,247 +196,232 @@ npx web3-tools-mcp
|
|
|
87
196
|
| Unichain | 130 | ✅ |
|
|
88
197
|
| Localhost | 1337 | ❌ |
|
|
89
198
|
|
|
90
|
-
|
|
199
|
+
Adding one is a single entry in [`mcp/src/chains.ts`](mcp/src/chains.ts).
|
|
91
200
|
|
|
92
|
-
|
|
201
|
+
</details>
|
|
93
202
|
|
|
94
|
-
|
|
203
|
+
## 🔧 Setup
|
|
95
204
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Opens your browser to connect your wallet (MetaMask, Rabby, Coinbase Wallet, etc.)
|
|
99
|
-
2. You connect your wallet once in the browser
|
|
100
|
-
3. The transaction is decoded and simulated, then the request appears in the browser for approval
|
|
101
|
-
4. Sign or reject transactions directly in your wallet
|
|
205
|
+
<details open>
|
|
206
|
+
<summary>🖥️ <b>Local clients</b> — where the config file lives</summary>
|
|
102
207
|
|
|
103
|
-
|
|
104
|
-
|
|
208
|
+
Add the entry below to your client's MCP config, then restart the app. Every one of these
|
|
209
|
+
also has a UI route that creates the file for you, which is usually quicker than finding it:
|
|
105
210
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
211
|
+
| Client | Config file | Or via the UI |
|
|
212
|
+
| --- | --- | --- |
|
|
213
|
+
| **Claude Desktop** | macOS `~/Library/Application Support/Claude/claude_desktop_config.json`<br>Windows `%APPDATA%\Claude\claude_desktop_config.json`<br>Linux `~/.config/Claude/claude_desktop_config.json` | Settings → Developer → **Edit Config** |
|
|
214
|
+
| **Cursor** | `~/.cursor/mcp.json` (all projects)<br>`.cursor/mcp.json` (this project) | Settings → Tools & MCP → **Add new MCP server** |
|
|
215
|
+
| **VS Code** | `.vscode/mcp.json` (workspace)<br>or your user profile | Command Palette → **MCP: Add Server** |
|
|
216
|
+
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json`<br>global only, no per-project | Cascade panel → **MCP** icon |
|
|
110
217
|
|
|
111
|
-
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"mcpServers": {
|
|
221
|
+
"web3-tools": {
|
|
222
|
+
"command": "npx",
|
|
223
|
+
"args": ["-y", "web3-tools-mcp"],
|
|
224
|
+
"env": {
|
|
225
|
+
"WALLETCONNECT_PROJECT_ID": "<your project id>",
|
|
226
|
+
"ETHERSCAN_API_KEY": "<your key>"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
112
232
|
|
|
113
|
-
|
|
233
|
+
Drop the whole `env` block if you have no keys yet: the server runs without them, with less
|
|
234
|
+
reach. **🔑 API keys** below says exactly what each one turns on.
|
|
114
235
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
via [WhatsABI](https://github.com/shazow/whatsabi). Proxies resolve to their implementation.
|
|
122
|
-
- **Token amounts** — formatted with on-chain decimals and symbol; unlimited approvals are
|
|
123
|
-
flagged explicitly.
|
|
124
|
-
- **Simulation** — `eth_simulateV1` (falling back to `eth_call` + `estimateGas`) reports the
|
|
125
|
-
gas estimate and every ERC20 transfer the transaction would cause, marked in/out for your
|
|
126
|
-
account. A reverting transaction is shown as such before you can approve it.
|
|
236
|
+
> ⚠️ **VS Code is the exception.** Its `mcp.json` nests servers under `"servers"`, not
|
|
237
|
+
> `"mcpServers"` — paste the block above unchanged and it is silently ignored:
|
|
238
|
+
>
|
|
239
|
+
> ```json
|
|
240
|
+
> { "servers": { "web3-tools": { "command": "npx", "args": ["-y", "web3-tools-mcp"] } } }
|
|
241
|
+
> ```
|
|
127
242
|
|
|
128
|
-
|
|
243
|
+
</details>
|
|
129
244
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
wallet directly, over WalletConnect's own (end-to-end encrypted) relay. No page to load,
|
|
133
|
-
nothing to host.
|
|
245
|
+
<details>
|
|
246
|
+
<summary>⌨️ <b>Claude Code</b></summary>
|
|
134
247
|
|
|
135
248
|
```bash
|
|
136
|
-
|
|
249
|
+
claude mcp add --scope user --transport stdio web3-tools -- npx -y web3-tools-mcp
|
|
137
250
|
```
|
|
138
251
|
|
|
139
|
-
|
|
140
|
-
Rabby, Trust or any WalletConnect wallet. The session is stored in
|
|
141
|
-
`~/.config/web3-tools-mcp/walletconnect.db`, so you pair once and it survives restarts.
|
|
252
|
+
Or, against a hosted instance:
|
|
142
253
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
254
|
+
```bash
|
|
255
|
+
claude mcp add --transport http web3-tools https://your-host/mcp \
|
|
256
|
+
--header "Authorization: Bearer <MCP_TOKEN>"
|
|
257
|
+
```
|
|
147
258
|
|
|
148
|
-
|
|
259
|
+
</details>
|
|
149
260
|
|
|
150
|
-
|
|
151
|
-
|
|
261
|
+
<details>
|
|
262
|
+
<summary>🤖 <b>ChatGPT</b>, 🦾 <b>Grok</b> and 🌐 <b>claude.ai</b> — remote only</summary>
|
|
152
263
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
could send someone else's transaction to your phone.
|
|
264
|
+
None of these can launch a local process, so they need a hosted instance:
|
|
265
|
+
[deploy one ↓](#-hosting), then point the client at `https://your-host/mcp`.
|
|
156
266
|
|
|
157
|
-
|
|
267
|
+
**ChatGPT** — Settings → Apps & Connectors → Advanced → enable Developer mode, then
|
|
268
|
+
**Create**. Give it a name and the server URL. The URL has to include the `/mcp` path; that
|
|
269
|
+
is the usual mistake. Pick OAuth and it walks you through the login page the server serves,
|
|
270
|
+
or pick token and paste `MCP_TOKEN`. Needs a paid plan.
|
|
158
271
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Or on [Fly](https://fly.io), where volumes come with any plan, so the pairing survives
|
|
162
|
-
redeploys without paying for a disk:
|
|
272
|
+
**Grok** — [grok.com/connectors](https://grok.com/connectors) → **New Connector** →
|
|
273
|
+
**Custom**, then the same URL and authentication. Needs a paid plan.
|
|
163
274
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
fly secrets set MCP_TOKEN=$(openssl rand -hex 24) WALLETCONNECT_PROJECT_ID=<id>
|
|
168
|
-
fly deploy
|
|
169
|
-
```
|
|
275
|
+
**claude.ai** — Settings → Connectors → **Add custom connector**, then the URL. It uses
|
|
276
|
+
OAuth, which the server implements against `MCP_TOKEN`: it shows a page asking for the
|
|
277
|
+
token and issues one once you paste it.
|
|
170
278
|
|
|
171
|
-
|
|
279
|
+
Once connected, pair your phone and approvals arrive there — no laptop in the loop at all.
|
|
172
280
|
|
|
173
|
-
|
|
174
|
-
docker build -t web3-tools-mcp .
|
|
175
|
-
docker run -p 8080:8080 \
|
|
176
|
-
-e MCP_TOKEN=<long random string> \
|
|
177
|
-
-e WALLETCONNECT_PROJECT_ID=<id> \
|
|
178
|
-
web3-tools-mcp
|
|
179
|
-
```
|
|
281
|
+
</details>
|
|
180
282
|
|
|
181
|
-
|
|
283
|
+
<details>
|
|
284
|
+
<summary>🔑 <b>API keys</b> — none required, but they decide how much works</summary>
|
|
182
285
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
286
|
+
Nothing here is required to start, and the server will not refuse to run without any of it.
|
|
287
|
+
What you lose is reach, not stability — so here is the honest version:
|
|
288
|
+
|
|
289
|
+
| Key | Free from | Without it |
|
|
290
|
+
| --- | --- | --- |
|
|
291
|
+
| `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` |
|
|
293
|
+
| `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 |
|
|
295
|
+
|
|
296
|
+
So with nothing configured you get current balances, contract reads, gas, ENS, simulation
|
|
297
|
+
and browser signing. Add `WALLETCONNECT_PROJECT_ID` for your phone and one provider key for
|
|
298
|
+
history, and everything above lights up.
|
|
299
|
+
|
|
300
|
+
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.
|
|
187
303
|
|
|
188
304
|
```bash
|
|
189
|
-
|
|
190
|
-
--header "Authorization: Bearer <MCP_TOKEN>"
|
|
305
|
+
npx web3-tools-mcp --etherscan-api-key KEY --walletconnect-project-id ID
|
|
191
306
|
```
|
|
192
307
|
|
|
193
|
-
|
|
194
|
-
`/mcp` while your phone is paired can push signing prompts at it. You would still approve
|
|
195
|
-
each one, but that is a phishing surface, not a feature.
|
|
196
|
-
|
|
197
|
-
Two things decide whether the pairing survives:
|
|
308
|
+
</details>
|
|
198
309
|
|
|
199
|
-
|
|
200
|
-
depends on, so the first transaction after an idle period waits for the host to wake
|
|
201
|
-
(about a minute on a free tier) before it reaches your phone.
|
|
202
|
-
- **Give the session somewhere durable to live.** Most hosts have an ephemeral filesystem,
|
|
203
|
-
so a plain file is lost on every redeploy and you rescan the QR. Either attach a volume
|
|
204
|
-
and point `XDG_CONFIG_HOME` at it (what `render.yaml` does), or set
|
|
205
|
-
`UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN`
|
|
206
|
-
([Upstash](https://upstash.com) has a free plan) and the session moves to Redis.
|
|
310
|
+
## 🚀 Hosting
|
|
207
311
|
|
|
208
|
-
|
|
209
|
-
|
|
312
|
+
With WalletConnect nothing has to run next to you, so the server can live in the cloud and
|
|
313
|
+
still have your phone sign. Run your own rather than sharing one: your wallet, your keys,
|
|
314
|
+
your quota, and no multi-tenant server in the middle that could push someone else's
|
|
315
|
+
transaction at your phone.
|
|
210
316
|
|
|
211
|
-
|
|
212
|
-
|
|
317
|
+
<a href="https://render.com/deploy?repo=https://github.com/hajnalben/web3-tools-mcp"><img src="https://render.com/images/deploy-to-render-button.svg" alt="Deploy to Render" height="32"></a>
|
|
318
|
+
|
|
319
|
+
<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>
|
|
213
320
|
|
|
214
|
-
|
|
321
|
+
**Render** reads `render.yaml`, generates `MCP_TOKEN` and asks for `WALLETCONNECT_PROJECT_ID`
|
|
322
|
+
— genuinely one click.
|
|
215
323
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
that keeps a Node process alive and supports WebSockets — Render, Railway, Fly:
|
|
324
|
+
**Fly** ships no deploy button, so it is four commands. Worth it for a personal instance:
|
|
325
|
+
volumes come with any plan, so the pairing survives redeploys without paying for a disk.
|
|
219
326
|
|
|
220
327
|
```bash
|
|
221
|
-
|
|
222
|
-
|
|
328
|
+
fly launch --no-deploy --copy-config
|
|
329
|
+
fly volumes create data --size 1
|
|
330
|
+
fly secrets set MCP_TOKEN=$(openssl rand -hex 24) WALLETCONNECT_PROJECT_ID=<id>
|
|
331
|
+
fly deploy
|
|
223
332
|
```
|
|
224
333
|
|
|
225
|
-
|
|
334
|
+
<details>
|
|
335
|
+
<summary>🐳 <b>Docker, and connecting a client</b></summary>
|
|
336
|
+
|
|
337
|
+
There is a plain `Dockerfile` too, so Railway, Cloud Run or your own box work the same way:
|
|
226
338
|
|
|
227
339
|
```bash
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
340
|
+
docker run -p 8080:8080 \
|
|
341
|
+
-e MCP_TOKEN=<long random string> \
|
|
342
|
+
-e WALLETCONNECT_PROJECT_ID=<id> \
|
|
343
|
+
web3-tools-mcp
|
|
231
344
|
```
|
|
232
345
|
|
|
233
|
-
|
|
234
|
-
installed). Anyone holding `WALLET_TOKEN` can send your browser transactions to sign, so
|
|
235
|
-
treat it like a password and always serve the page over HTTPS.
|
|
346
|
+
Then point a client at it:
|
|
236
347
|
|
|
237
|
-
|
|
238
|
-
|
|
348
|
+
```bash
|
|
349
|
+
claude mcp add --transport http web3-tools https://your-host/mcp \
|
|
350
|
+
--header "Authorization: Bearer <MCP_TOKEN>"
|
|
351
|
+
```
|
|
239
352
|
|
|
240
|
-
|
|
353
|
+
Clients that cannot send a header — claude.ai connectors, and the browser and phone apps —
|
|
354
|
+
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.
|
|
241
357
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
- Any browser wallet supporting EIP-1193
|
|
358
|
+
> 🔐 **`MCP_TOKEN` is mandatory** and the server refuses to start without it. Anyone who
|
|
359
|
+
> reaches `/mcp` while your phone is paired can push signing prompts at it. You would still
|
|
360
|
+
> approve each one, but that is a phishing surface, not a feature.
|
|
246
361
|
|
|
247
|
-
|
|
362
|
+
Two things decide whether the pairing survives:
|
|
248
363
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
-
|
|
252
|
-
|
|
364
|
+
- ⏰ **Keep the instance awake.** Sleeping drops the WalletConnect socket, so the first
|
|
365
|
+
transaction after an idle period waits for the host to wake — about a minute on a free tier.
|
|
366
|
+
- 💾 **Give the session somewhere durable.** Most hosts have an ephemeral filesystem, so a
|
|
367
|
+
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).
|
|
253
370
|
|
|
254
|
-
|
|
371
|
+
Render's free Key Value instance is not an option here — no persistence, so the pairing
|
|
372
|
+
disappears at its next maintenance.
|
|
255
373
|
|
|
256
|
-
|
|
374
|
+
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.
|
|
257
379
|
|
|
258
|
-
|
|
259
|
-
- `get_function_signature` - Generate 4-byte function selectors
|
|
260
|
-
- `get_event_signature` - Generate 32-byte event topic0 hashes
|
|
261
|
-
- `get_error_signature` - Generate 4-byte error selectors
|
|
262
|
-
- `encode_function_data` - Encode a call's calldata from its ABI and arguments
|
|
380
|
+
</details>
|
|
263
381
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
- `get_contract_source_code` - Get verified source code with proxy support
|
|
267
|
-
- `get_contract_source_file` - Retrieve specific source file from cache
|
|
268
|
-
- `is_contract` - Check if address is contract or EOA
|
|
382
|
+
<details>
|
|
383
|
+
<summary>🖇️ <b>Host the signing page</b> separately</summary>
|
|
269
384
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
- `simulate_contract` - Simulate contract calls without broadcasting (includes gas estimate)
|
|
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.
|
|
274
388
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
- `pair_phone_wallet` - Pair a phone wallet over WalletConnect, returning a QR to scan
|
|
389
|
+
```bash
|
|
390
|
+
WALLET_TOKEN=<long random string> \
|
|
391
|
+
WALLET_PUBLIC_URL=https://wallet.example.com \
|
|
392
|
+
npx web3-wallet-relay
|
|
393
|
+
```
|
|
281
394
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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.
|
|
285
398
|
|
|
286
|
-
|
|
287
|
-
- `resolve_ens_name` - ENS name → address
|
|
288
|
-
- `reverse_resolve_ens` - Address → ENS name
|
|
289
|
-
- `get_ens_text_record` - Get text records (avatar, email, twitter, etc.)
|
|
290
|
-
- `get_ens_avatar` - Get avatar URI
|
|
291
|
-
- `batch_resolve_ens_names` - Batch resolve multiple names
|
|
399
|
+
Locally nothing changes: the server embeds the same relay.
|
|
292
400
|
|
|
293
|
-
|
|
294
|
-
- `get_balance` - Get native or ERC20 balances (supports batch)
|
|
401
|
+
</details>
|
|
295
402
|
|
|
296
|
-
|
|
297
|
-
- `get_logs` - Query and decode events with Hypersync fallback
|
|
403
|
+
## 🔄 How signing works
|
|
298
404
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
- `debug_call` - Trace a call without broadcasting it, falling back to a local anvil fork
|
|
405
|
+
1. 🤖 A transaction tool runs. The server decodes and simulates the transaction first.
|
|
406
|
+
2. 📨 It goes to the signer you picked — your phone, or the browser page.
|
|
407
|
+
3. 👀 You read the summary and approve or reject in your wallet.
|
|
408
|
+
4. 🔗 The result, with an explorer link, comes back to the agent.
|
|
304
409
|
|
|
305
|
-
##
|
|
410
|
+
## 🛠️ Development
|
|
306
411
|
|
|
307
|
-
### Custom RPC
|
|
308
412
|
```bash
|
|
309
|
-
|
|
413
|
+
npm install
|
|
414
|
+
npm run lint # Biome; npm run format fixes what it can
|
|
415
|
+
npm run typecheck
|
|
416
|
+
npm test
|
|
310
417
|
```
|
|
311
418
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
### Batch Operations
|
|
316
|
-
Many tools support batching for improved efficiency (contract calls, balances, ENS resolution).
|
|
419
|
+
Two workspaces: [`mcp/`](mcp) is this server, [`wallet-relay/`](wallet-relay) is the signing
|
|
420
|
+
page. [CONTRIBUTING.md](CONTRIBUTING.md) covers running a checkout against a client, the
|
|
421
|
+
layout, and how to add a chain or a tool. Releases: [CHANGELOG.md](CHANGELOG.md).
|
|
317
422
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
- Node.js ≥ 20.0.0
|
|
321
|
-
- Internet connection for RPC calls
|
|
322
|
-
|
|
323
|
-
## Testing
|
|
324
|
-
|
|
325
|
-
```bash
|
|
326
|
-
npm test # Run all tests
|
|
327
|
-
npm run test:watch # Watch mode
|
|
328
|
-
npm run test:ui # UI mode
|
|
329
|
-
```
|
|
423
|
+
Requires Node.js ≥ 20.
|
|
330
424
|
|
|
331
|
-
## License
|
|
425
|
+
## 📄 License
|
|
332
426
|
|
|
333
427
|
MIT
|