web3-tools-mcp 1.3.3 → 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.
- package/README.md +51 -4
- package/dist/anvil.d.ts +34 -0
- package/dist/anvil.d.ts.map +1 -0
- package/dist/anvil.js +254 -0
- package/dist/anvil.js.map +1 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +13 -2
- package/dist/client.js.map +1 -1
- package/dist/index.js +25 -5
- package/dist/index.js.map +1 -1
- package/dist/preview.d.ts +55 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +233 -0
- package/dist/preview.js.map +1 -0
- package/dist/tools/advanced.d.ts +67 -9
- package/dist/tools/advanced.d.ts.map +1 -1
- package/dist/tools/advanced.js +206 -67
- package/dist/tools/advanced.js.map +1 -1
- package/dist/tools/balance.d.ts +5 -5
- package/dist/tools/contract-info.d.ts +9 -9
- package/dist/tools/contract.d.ts +8 -8
- package/dist/tools/contract.d.ts.map +1 -1
- package/dist/tools/contract.js +3 -0
- package/dist/tools/contract.js.map +1 -1
- package/dist/tools/ens.d.ts +15 -15
- package/dist/tools/gas.d.ts +18 -18
- package/dist/tools/logs.d.ts +3 -3
- package/dist/tools/transactions.d.ts +9 -9
- package/dist/tools/transactions.d.ts.map +1 -1
- package/dist/tools/transactions.js +92 -113
- package/dist/tools/transactions.js.map +1 -1
- package/dist/utils.d.ts +13 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +76 -0
- package/dist/utils.js.map +1 -1
- package/dist/wallet-client.d.ts +83 -0
- package/dist/wallet-client.d.ts.map +1 -0
- package/dist/wallet-client.js +357 -0
- package/dist/wallet-client.js.map +1 -0
- package/package.json +9 -8
- package/src/anvil.ts +323 -0
- package/src/client.ts +16 -2
- package/src/index.ts +26 -5
- package/src/preview.ts +320 -0
- package/src/tools/advanced.ts +239 -70
- package/src/tools/contract.ts +3 -0
- package/src/tools/transactions.ts +98 -125
- package/src/utils.ts +95 -0
- package/src/wallet-client.ts +380 -0
- package/dist/wallet-server.d.ts +0 -35
- package/dist/wallet-server.d.ts.map +0 -1
- package/dist/wallet-server.js +0 -232
- package/dist/wallet-server.js.map +0 -1
- package/public/wallet-app.js +0 -677
- package/public/wallet.html +0 -723
- package/src/wallet-server.ts +0 -283
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-client.js","sourceRoot":"","sources":["../src/wallet-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "web3-tools-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Model Context Protocol server for blockchain interactions using viem, Etherscan, and Hypersync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
-
"public",
|
|
14
13
|
"README.md",
|
|
15
14
|
"LICENSE",
|
|
16
15
|
"src"
|
|
@@ -20,8 +19,9 @@
|
|
|
20
19
|
},
|
|
21
20
|
"scripts": {
|
|
22
21
|
"clean": "rm -rf dist",
|
|
23
|
-
"build": "npm run clean && tsc",
|
|
22
|
+
"build": "npm run clean && npm run build -w web3-wallet-relay && tsc",
|
|
24
23
|
"watch": "tsc --watch",
|
|
24
|
+
"start:wallet": "npm start -w web3-wallet-relay",
|
|
25
25
|
"prepare": "npm run build",
|
|
26
26
|
"test": "vitest run",
|
|
27
27
|
"test:watch": "vitest",
|
|
@@ -51,20 +51,21 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@envio-dev/hypersync-client": "^0.6.5",
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
54
|
-
"
|
|
55
|
-
"express": "^4.21.2",
|
|
54
|
+
"@shazow/whatsabi": "^0.29.0",
|
|
56
55
|
"viem": "^2.31.4",
|
|
56
|
+
"web3-wallet-relay": "^1.0.0",
|
|
57
57
|
"ws": "^8.18.0",
|
|
58
58
|
"zod": "^3.25.76"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@types/cors": "^2.8.17",
|
|
62
|
-
"@types/express": "^5.0.0",
|
|
63
61
|
"@types/node": "^20.19.23",
|
|
64
62
|
"@types/ws": "^8.5.13",
|
|
65
63
|
"@vitest/ui": "^3.2.4",
|
|
66
64
|
"dotenv": "^17.2.3",
|
|
67
65
|
"typescript": "^5.0.0",
|
|
68
66
|
"vitest": "^3.2.4"
|
|
69
|
-
}
|
|
67
|
+
},
|
|
68
|
+
"workspaces": [
|
|
69
|
+
"wallet"
|
|
70
|
+
]
|
|
70
71
|
}
|
package/src/anvil.ts
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { spawn, ChildProcess } from 'child_process'
|
|
2
|
+
import { createPublicClient, http } from 'viem'
|
|
3
|
+
import { mainnet } from 'viem/chains'
|
|
4
|
+
|
|
5
|
+
export interface AnvilInstance {
|
|
6
|
+
process: ChildProcess
|
|
7
|
+
port: number
|
|
8
|
+
rpcUrl: string
|
|
9
|
+
client: ReturnType<typeof createPublicClient>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface AnvilConfig {
|
|
13
|
+
forkUrl: string
|
|
14
|
+
forkBlockNumber?: bigint
|
|
15
|
+
port?: number
|
|
16
|
+
chainId?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Check if anvil is installed
|
|
20
|
+
export async function isAnvilInstalled(): Promise<boolean> {
|
|
21
|
+
return new Promise(resolve => {
|
|
22
|
+
const proc = spawn('anvil', ['--version'], { shell: true })
|
|
23
|
+
proc.on('close', code => resolve(code === 0))
|
|
24
|
+
proc.on('error', () => resolve(false))
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Find an available port
|
|
29
|
+
async function findAvailablePort(startPort: number = 8545): Promise<number> {
|
|
30
|
+
const net = await import('net')
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const server = net.createServer()
|
|
33
|
+
server.listen(startPort, () => {
|
|
34
|
+
const address = server.address()
|
|
35
|
+
if (address && typeof address === 'object') {
|
|
36
|
+
server.close(() => resolve(address.port))
|
|
37
|
+
} else {
|
|
38
|
+
server.close(() => reject(new Error('Could not get port')))
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
server.on('error', () => {
|
|
42
|
+
// Port in use, try next one
|
|
43
|
+
findAvailablePort(startPort + 1).then(resolve).catch(reject)
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Start an Anvil instance
|
|
49
|
+
export async function startAnvil(config: AnvilConfig): Promise<AnvilInstance> {
|
|
50
|
+
const installed = await isAnvilInstalled()
|
|
51
|
+
if (!installed) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
'Anvil is not installed. Please install Foundry: https://book.getfoundry.sh/getting-started/installation'
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const port = config.port ?? (await findAvailablePort())
|
|
58
|
+
const rpcUrl = `http://127.0.0.1:${port}`
|
|
59
|
+
|
|
60
|
+
const args = ['--fork-url', config.forkUrl, '--port', port.toString(), '--silent']
|
|
61
|
+
|
|
62
|
+
if (config.forkBlockNumber !== undefined) {
|
|
63
|
+
args.push('--fork-block-number', config.forkBlockNumber.toString())
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (config.chainId !== undefined) {
|
|
67
|
+
args.push('--chain-id', config.chainId.toString())
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
const proc = spawn('anvil', args, {
|
|
72
|
+
shell: true,
|
|
73
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
let stderr = ''
|
|
77
|
+
proc.stderr?.on('data', data => {
|
|
78
|
+
stderr += data.toString()
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
proc.on('error', err => {
|
|
82
|
+
reject(new Error(`Failed to start Anvil: ${err.message}`))
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
proc.on('close', code => {
|
|
86
|
+
if (code !== 0 && code !== null) {
|
|
87
|
+
reject(new Error(`Anvil exited with code ${code}: ${stderr}`))
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Wait for Anvil to be ready by polling the RPC
|
|
92
|
+
const maxAttempts = 50 // 5 seconds
|
|
93
|
+
let attempts = 0
|
|
94
|
+
|
|
95
|
+
const checkReady = async () => {
|
|
96
|
+
attempts++
|
|
97
|
+
try {
|
|
98
|
+
const response = await fetch(rpcUrl, {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: { 'Content-Type': 'application/json' },
|
|
101
|
+
body: JSON.stringify({
|
|
102
|
+
jsonrpc: '2.0',
|
|
103
|
+
method: 'eth_blockNumber',
|
|
104
|
+
params: [],
|
|
105
|
+
id: 1
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
if (response.ok) {
|
|
109
|
+
// Add small delay to ensure all RPC methods are ready (including debug_*)
|
|
110
|
+
await new Promise(r => setTimeout(r, 100))
|
|
111
|
+
const client = createPublicClient({
|
|
112
|
+
chain: mainnet, // Chain is overridden by fork anyway
|
|
113
|
+
transport: http(rpcUrl)
|
|
114
|
+
})
|
|
115
|
+
resolve({ process: proc, port, rpcUrl, client })
|
|
116
|
+
} else if (attempts < maxAttempts) {
|
|
117
|
+
setTimeout(checkReady, 100)
|
|
118
|
+
} else {
|
|
119
|
+
proc.kill()
|
|
120
|
+
reject(new Error('Anvil failed to start within timeout'))
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
if (attempts < maxAttempts) {
|
|
124
|
+
setTimeout(checkReady, 100)
|
|
125
|
+
} else {
|
|
126
|
+
proc.kill()
|
|
127
|
+
reject(new Error('Anvil failed to start within timeout'))
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Start checking after a small delay
|
|
133
|
+
setTimeout(checkReady, 200)
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Stop an Anvil instance
|
|
138
|
+
export function stopAnvil(instance: AnvilInstance): void {
|
|
139
|
+
if (instance.process && !instance.process.killed) {
|
|
140
|
+
instance.process.kill('SIGTERM')
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Helper to run a function with a temporary Anvil instance
|
|
145
|
+
export async function withAnvil<T>(
|
|
146
|
+
config: AnvilConfig,
|
|
147
|
+
fn: (instance: AnvilInstance) => Promise<T>
|
|
148
|
+
): Promise<T> {
|
|
149
|
+
const instance = await startAnvil(config)
|
|
150
|
+
try {
|
|
151
|
+
return await fn(instance)
|
|
152
|
+
} finally {
|
|
153
|
+
stopAnvil(instance)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Archive RPC URLs for chains that need historical state access
|
|
158
|
+
const ARCHIVE_RPCS: Record<string, string> = {
|
|
159
|
+
arbitrum: 'https://arbitrum-one.arpc.x.superfluid.dev'
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Trace a transaction using Anvil fork
|
|
163
|
+
export async function traceTransactionWithAnvil(
|
|
164
|
+
forkUrl: string,
|
|
165
|
+
transactionHash: string,
|
|
166
|
+
blockNumber: bigint,
|
|
167
|
+
tracer: 'callTracer' | 'prestateTracer' | 'stateDiffTracer' = 'callTracer',
|
|
168
|
+
chainName?: string
|
|
169
|
+
): Promise<unknown> {
|
|
170
|
+
// Use archive RPC if available for better historical state access
|
|
171
|
+
const archiveUrl = chainName && ARCHIVE_RPCS[chainName] ? ARCHIVE_RPCS[chainName] : forkUrl
|
|
172
|
+
|
|
173
|
+
// First, fetch the original transaction from the RPC
|
|
174
|
+
const fetchClient = createPublicClient({
|
|
175
|
+
chain: mainnet,
|
|
176
|
+
transport: http(forkUrl)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const tx = await fetchClient.getTransaction({
|
|
180
|
+
hash: transactionHash as `0x${string}`
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
if (!tx) {
|
|
184
|
+
throw new Error(`Transaction ${transactionHash} not found`)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Fork at the block BEFORE the transaction to replay it accurately
|
|
188
|
+
// Note: This requires an archival RPC that has historical state
|
|
189
|
+
const forkBlock = blockNumber > 0n ? blockNumber - 1n : 0n
|
|
190
|
+
|
|
191
|
+
return withAnvil(
|
|
192
|
+
{
|
|
193
|
+
forkUrl: archiveUrl,
|
|
194
|
+
forkBlockNumber: forkBlock
|
|
195
|
+
},
|
|
196
|
+
async instance => {
|
|
197
|
+
// Use debug_traceCall to simulate and trace the transaction
|
|
198
|
+
// Note: This replays the tx against the post-block state, which may differ slightly
|
|
199
|
+
// from the original execution if state changed within the block
|
|
200
|
+
const trace = await instance.client.request({
|
|
201
|
+
method: 'debug_traceCall' as never,
|
|
202
|
+
params: [
|
|
203
|
+
{
|
|
204
|
+
from: tx.from,
|
|
205
|
+
to: tx.to,
|
|
206
|
+
data: tx.input,
|
|
207
|
+
value: tx.value ? `0x${tx.value.toString(16)}` : '0x0',
|
|
208
|
+
gas: tx.gas ? `0x${tx.gas.toString(16)}` : undefined
|
|
209
|
+
},
|
|
210
|
+
'latest',
|
|
211
|
+
{ tracer }
|
|
212
|
+
] as never
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
return trace
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Simulate a call with tracing
|
|
221
|
+
export interface SimulateCallParams {
|
|
222
|
+
to: string
|
|
223
|
+
data?: string
|
|
224
|
+
from?: string
|
|
225
|
+
value?: bigint
|
|
226
|
+
gas?: bigint
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export async function simulateCallWithTrace(
|
|
230
|
+
forkUrl: string,
|
|
231
|
+
params: SimulateCallParams,
|
|
232
|
+
blockNumber?: bigint,
|
|
233
|
+
tracer: 'callTracer' | 'prestateTracer' = 'callTracer'
|
|
234
|
+
): Promise<{
|
|
235
|
+
result: string
|
|
236
|
+
trace: unknown
|
|
237
|
+
gasUsed: bigint
|
|
238
|
+
success: boolean
|
|
239
|
+
revertReason?: string
|
|
240
|
+
}> {
|
|
241
|
+
return withAnvil(
|
|
242
|
+
{
|
|
243
|
+
forkUrl,
|
|
244
|
+
forkBlockNumber: blockNumber
|
|
245
|
+
},
|
|
246
|
+
async instance => {
|
|
247
|
+
// First, try a regular call to get the result
|
|
248
|
+
let result = '0x'
|
|
249
|
+
let success = true
|
|
250
|
+
let revertReason: string | undefined
|
|
251
|
+
let gasUsed = 0n
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
// Use eth_call to get the result
|
|
255
|
+
result = (await instance.client.request({
|
|
256
|
+
method: 'eth_call' as never,
|
|
257
|
+
params: [
|
|
258
|
+
{
|
|
259
|
+
to: params.to,
|
|
260
|
+
data: params.data,
|
|
261
|
+
from: params.from ?? '0x0000000000000000000000000000000000000000',
|
|
262
|
+
value: params.value ? `0x${params.value.toString(16)}` : undefined,
|
|
263
|
+
gas: params.gas ? `0x${params.gas.toString(16)}` : undefined
|
|
264
|
+
},
|
|
265
|
+
'latest'
|
|
266
|
+
] as never
|
|
267
|
+
})) as string
|
|
268
|
+
|
|
269
|
+
// Estimate gas
|
|
270
|
+
try {
|
|
271
|
+
gasUsed = await instance.client.estimateGas({
|
|
272
|
+
to: params.to as `0x${string}`,
|
|
273
|
+
data: params.data as `0x${string}` | undefined,
|
|
274
|
+
account: params.from as `0x${string}` | undefined,
|
|
275
|
+
value: params.value
|
|
276
|
+
})
|
|
277
|
+
} catch {
|
|
278
|
+
// Ignore gas estimation errors
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
success = false
|
|
282
|
+
const errorMessage = (error as Error).message
|
|
283
|
+
// Try to extract revert reason
|
|
284
|
+
const revertMatch = errorMessage.match(/revert(?:ed)?[:\s]*(.+?)(?:\n|$)/i)
|
|
285
|
+
if (revertMatch) {
|
|
286
|
+
revertReason = revertMatch[1].trim()
|
|
287
|
+
} else {
|
|
288
|
+
revertReason = errorMessage
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Get the trace using debug_traceCall
|
|
293
|
+
let trace: unknown = null
|
|
294
|
+
try {
|
|
295
|
+
trace = await instance.client.request({
|
|
296
|
+
method: 'debug_traceCall' as never,
|
|
297
|
+
params: [
|
|
298
|
+
{
|
|
299
|
+
to: params.to,
|
|
300
|
+
data: params.data,
|
|
301
|
+
from: params.from ?? '0x0000000000000000000000000000000000000000',
|
|
302
|
+
value: params.value ? `0x${params.value.toString(16)}` : undefined,
|
|
303
|
+
gas: params.gas ? `0x${params.gas.toString(16)}` : undefined
|
|
304
|
+
},
|
|
305
|
+
'latest',
|
|
306
|
+
{ tracer }
|
|
307
|
+
] as never
|
|
308
|
+
})
|
|
309
|
+
} catch (traceError) {
|
|
310
|
+
// If tracing fails, include the error
|
|
311
|
+
trace = { error: (traceError as Error).message }
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
result,
|
|
316
|
+
trace,
|
|
317
|
+
gasUsed,
|
|
318
|
+
success,
|
|
319
|
+
revertReason
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -29,11 +29,11 @@ function getRpcUrl(chainName: string, config: Config): string {
|
|
|
29
29
|
? `https://eth-mainnet.g.alchemy.com/v2/${config.alchemyApiKey}`
|
|
30
30
|
: config.infuraApiKey
|
|
31
31
|
? `https://mainnet.infura.io/v3/${config.infuraApiKey}`
|
|
32
|
-
: 'https://
|
|
32
|
+
: 'https://ethereum-rpc.publicnode.com',
|
|
33
33
|
|
|
34
34
|
base: config.alchemyApiKey
|
|
35
35
|
? `https://base-mainnet.g.alchemy.com/v2/${config.alchemyApiKey}`
|
|
36
|
-
: 'https://base.
|
|
36
|
+
: 'https://base-rpc.publicnode.com',
|
|
37
37
|
|
|
38
38
|
arbitrum: config.alchemyApiKey
|
|
39
39
|
? `https://arb-mainnet.g.alchemy.com/v2/${config.alchemyApiKey}`
|
|
@@ -238,6 +238,10 @@ export class ClientManager {
|
|
|
238
238
|
return client as ReturnType<typeof createPublicClient>
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
getConfig(): Config {
|
|
242
|
+
return this.config
|
|
243
|
+
}
|
|
244
|
+
|
|
241
245
|
getEtherscanDomain(chainName: ChainName): string {
|
|
242
246
|
const domains: Record<ChainName, string> = {
|
|
243
247
|
mainnet: 'etherscan.io',
|
|
@@ -256,6 +260,16 @@ export class ClientManager {
|
|
|
256
260
|
}
|
|
257
261
|
return domains[chainName] || 'etherscan.io'
|
|
258
262
|
}
|
|
263
|
+
|
|
264
|
+
getRpcUrl(chainName: ChainName): string {
|
|
265
|
+
const chains = CHAINS(this.config)
|
|
266
|
+
return chains[chainName].rpc
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
getChainId(chainName: ChainName): number {
|
|
270
|
+
const chains = CHAINS(this.config)
|
|
271
|
+
return chains[chainName].chain.id
|
|
272
|
+
}
|
|
259
273
|
}
|
|
260
274
|
|
|
261
275
|
// Export a global client manager instance
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
6
6
|
import { initializeClientManager } from "./client.js";
|
|
7
7
|
import { registerAllTools } from "./tools/index.js";
|
|
8
8
|
import { parseCommandLineArgs } from "./utils.js";
|
|
9
|
-
import {
|
|
9
|
+
import { getWalletClient } from "./wallet-client.js";
|
|
10
10
|
|
|
11
11
|
// Parse configuration
|
|
12
12
|
const config = parseCommandLineArgs();
|
|
@@ -34,6 +34,8 @@ ENVIRONMENT VARIABLES:
|
|
|
34
34
|
ALCHEMY_API_KEY Alternative to --alchemy-api-key
|
|
35
35
|
INFURA_API_KEY Alternative to --infura-api-key
|
|
36
36
|
HYPERSYNC_API_KEY Alternative to --hypersync-api-key
|
|
37
|
+
WALLET_SERVER_URL URL of a hosted wallet relay (omit to run one locally)
|
|
38
|
+
WALLET_TOKEN Shared pairing token for the wallet relay
|
|
37
39
|
|
|
38
40
|
SUPPORTED CHAINS:
|
|
39
41
|
mainnet, arbitrum, avalanche, base, bnb, gnosis, sonic, optimism, polygon, zksync, linea, unichain, localhost
|
|
@@ -84,18 +86,37 @@ const server = new McpServer({
|
|
|
84
86
|
// Register all tools
|
|
85
87
|
registerAllTools(server);
|
|
86
88
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
// Connect to the wallet relay (hosted when WALLET_SERVER_URL is set, embedded otherwise)
|
|
90
|
+
const wallet = getWalletClient();
|
|
91
|
+
const walletReady = wallet.connect().catch((error) => {
|
|
92
|
+
console.error("[MCP] Wallet relay unavailable:", error.message);
|
|
90
93
|
console.error("[MCP] Transaction signing features will not be available");
|
|
91
94
|
});
|
|
92
95
|
|
|
96
|
+
// The wallet relay's listening socket keeps the event loop alive, so this process would
|
|
97
|
+
// outlive the client that spawned it and go on holding its port. Leave when the client does.
|
|
98
|
+
let shuttingDown = false;
|
|
99
|
+
async function shutdown(reason: string) {
|
|
100
|
+
if (shuttingDown) return;
|
|
101
|
+
shuttingDown = true;
|
|
102
|
+
console.error(`[MCP] Shutting down (${reason})`);
|
|
103
|
+
await wallet.stop().catch(() => {});
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
process.stdin.on("end", () => shutdown("client disconnected"));
|
|
108
|
+
process.stdin.on("close", () => shutdown("client disconnected"));
|
|
109
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
110
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
111
|
+
|
|
93
112
|
// Start server
|
|
94
113
|
async function main() {
|
|
95
114
|
const transport = new StdioServerTransport();
|
|
96
115
|
await server.connect(transport);
|
|
97
116
|
console.error("Web3 Tools MCP Server running on stdio");
|
|
98
|
-
|
|
117
|
+
// The relay may still be picking a free port, and its URL carries the pairing token.
|
|
118
|
+
await walletReady;
|
|
119
|
+
console.error(`Wallet interface available at ${wallet.getUrl()}`);
|
|
99
120
|
}
|
|
100
121
|
|
|
101
122
|
main().catch((error) => {
|