web3-tools-mcp 2.0.2 → 3.0.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/CHANGELOG.md +97 -0
- package/README.md +5 -0
- package/dist/anvil.d.ts +17 -19
- package/dist/anvil.d.ts.map +1 -1
- package/dist/anvil.js +124 -228
- package/dist/anvil.js.map +1 -1
- package/dist/chains.d.ts +9 -1
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +11 -2
- package/dist/chains.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/context.d.ts +22 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +24 -0
- package/dist/context.js.map +1 -0
- package/dist/hosted.d.ts +12 -0
- package/dist/hosted.d.ts.map +1 -0
- package/dist/hosted.js +12 -0
- package/dist/hosted.js.map +1 -0
- package/dist/http-server.d.ts +13 -0
- package/dist/http-server.d.ts.map +1 -1
- package/dist/http-server.js +13 -4
- package/dist/http-server.js.map +1 -1
- package/dist/index.js +15 -11
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +24 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +23 -0
- package/dist/lib.js.map +1 -0
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +43 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/oauth.d.ts +41 -6
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +75 -41
- package/dist/oauth.js.map +1 -1
- package/dist/preview.d.ts +7 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +14 -2
- package/dist/preview.js.map +1 -1
- package/dist/signing-requests.d.ts +81 -0
- package/dist/signing-requests.d.ts.map +1 -0
- package/dist/signing-requests.js +138 -0
- package/dist/signing-requests.js.map +1 -0
- package/dist/tools/index.d.ts +27 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +37 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/{advanced.d.ts → read/advanced.d.ts} +30 -26
- package/dist/tools/read/advanced.d.ts.map +1 -0
- package/dist/tools/{advanced.js → read/advanced.js} +10 -10
- package/dist/tools/read/advanced.js.map +1 -0
- package/dist/tools/{balance.d.ts → read/balance.d.ts} +8 -7
- package/dist/tools/read/balance.d.ts.map +1 -0
- package/dist/tools/{balance.js → read/balance.js} +2 -2
- package/dist/tools/read/balance.js.map +1 -0
- package/dist/tools/{contract-info.d.ts → read/contract-info.d.ts} +18 -15
- package/dist/tools/read/contract-info.d.ts.map +1 -0
- package/dist/tools/{contract-info.js → read/contract-info.js} +2 -2
- package/dist/tools/read/contract-info.js.map +1 -0
- package/dist/tools/{contract.d.ts → read/contract.d.ts} +14 -12
- package/dist/tools/read/contract.d.ts.map +1 -0
- package/dist/tools/{contract.js → read/contract.js} +2 -2
- package/dist/tools/read/contract.js.map +1 -0
- package/dist/tools/{ens.d.ts → read/ens.d.ts} +30 -25
- package/dist/tools/read/ens.d.ts.map +1 -0
- package/dist/tools/{ens.js → read/ens.js} +2 -2
- package/dist/tools/read/ens.js.map +1 -0
- package/dist/tools/read/gas.d.ts +171 -0
- package/dist/tools/read/gas.d.ts.map +1 -0
- package/dist/tools/read/gas.js +368 -0
- package/dist/tools/read/gas.js.map +1 -0
- package/dist/tools/{logs.d.ts → read/logs.d.ts} +6 -5
- package/dist/tools/read/logs.d.ts.map +1 -0
- package/dist/tools/{logs.js → read/logs.js} +2 -2
- package/dist/tools/read/logs.js.map +1 -0
- package/dist/tools/{signatures.d.ts → read/signatures.d.ts} +8 -4
- package/dist/tools/read/signatures.d.ts.map +1 -0
- package/dist/tools/{signatures.js → read/signatures.js} +1 -1
- package/dist/tools/read/signatures.js.map +1 -0
- package/dist/tools/read/signing.d.ts +27 -0
- package/dist/tools/read/signing.d.ts.map +1 -0
- package/dist/tools/read/signing.js +75 -0
- package/dist/tools/read/signing.js.map +1 -0
- package/dist/tools/sign/errors.d.ts +9 -0
- package/dist/tools/sign/errors.d.ts.map +1 -0
- package/dist/tools/sign/errors.js +29 -0
- package/dist/tools/sign/errors.js.map +1 -0
- package/dist/tools/{transactions.d.ts → sign/transactions.d.ts} +48 -62
- package/dist/tools/sign/transactions.d.ts.map +1 -0
- package/dist/tools/sign/transactions.js +316 -0
- package/dist/tools/sign/transactions.js.map +1 -0
- package/dist/tools/sign/wallet.d.ts +50 -0
- package/dist/tools/sign/wallet.d.ts.map +1 -0
- package/dist/tools/sign/wallet.js +180 -0
- package/dist/tools/sign/wallet.js.map +1 -0
- package/dist/utils.d.ts +5 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +5 -2
- package/dist/utils.js.map +1 -1
- package/dist/wallet-client.d.ts +33 -4
- package/dist/wallet-client.d.ts.map +1 -1
- package/dist/wallet-client.js +90 -24
- package/dist/wallet-client.js.map +1 -1
- package/dist/walletconnect.d.ts +100 -13
- package/dist/walletconnect.d.ts.map +1 -1
- package/dist/walletconnect.js +215 -50
- package/dist/walletconnect.js.map +1 -1
- package/package.json +10 -4
- package/src/anvil.ts +150 -271
- package/src/chains.ts +14 -2
- package/src/client.ts +0 -1
- package/src/context.ts +27 -0
- package/src/hosted.ts +11 -0
- package/src/http-server.ts +30 -5
- package/src/index.ts +15 -12
- package/src/lib.ts +24 -0
- package/src/mcp-server.ts +47 -0
- package/src/oauth.ts +98 -45
- package/src/preview.ts +21 -2
- package/src/signing-requests.ts +198 -0
- package/src/tools/index.ts +67 -16
- package/src/tools/{advanced.ts → read/advanced.ts} +13 -11
- package/src/tools/{balance.ts → read/balance.ts} +3 -3
- package/src/tools/{contract-info.ts → read/contract-info.ts} +3 -3
- package/src/tools/{contract.ts → read/contract.ts} +3 -3
- package/src/tools/{ens.ts → read/ens.ts} +3 -3
- package/src/tools/read/gas.ts +480 -0
- package/src/tools/{logs.ts → read/logs.ts} +3 -3
- package/src/tools/{signatures.ts → read/signatures.ts} +2 -2
- package/src/tools/read/signing.ts +86 -0
- package/src/tools/sign/errors.ts +28 -0
- package/src/tools/sign/transactions.ts +428 -0
- package/src/tools/sign/wallet.ts +216 -0
- package/src/utils.ts +5 -2
- package/src/wallet-client.ts +91 -22
- package/src/walletconnect.ts +250 -48
- package/dist/tools/advanced.d.ts.map +0 -1
- package/dist/tools/advanced.js.map +0 -1
- package/dist/tools/balance.d.ts.map +0 -1
- package/dist/tools/balance.js.map +0 -1
- package/dist/tools/contract-info.d.ts.map +0 -1
- package/dist/tools/contract-info.js.map +0 -1
- package/dist/tools/contract.d.ts.map +0 -1
- package/dist/tools/contract.js.map +0 -1
- package/dist/tools/ens.d.ts.map +0 -1
- package/dist/tools/ens.js.map +0 -1
- package/dist/tools/gas.d.ts +0 -99
- package/dist/tools/gas.d.ts.map +0 -1
- package/dist/tools/gas.js +0 -181
- package/dist/tools/gas.js.map +0 -1
- package/dist/tools/logs.d.ts.map +0 -1
- package/dist/tools/logs.js.map +0 -1
- package/dist/tools/signatures.d.ts.map +0 -1
- package/dist/tools/signatures.js.map +0 -1
- package/dist/tools/transactions.d.ts.map +0 -1
- package/dist/tools/transactions.js +0 -365
- package/dist/tools/transactions.js.map +0 -1
- package/src/tools/gas.ts +0 -219
- package/src/tools/transactions.ts +0 -456
package/src/tools/index.ts
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
2
2
|
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js'
|
|
3
3
|
import type { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types.js'
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
import { identityFrom } from '../context.js'
|
|
5
|
+
import type { ToolResult } from '../types.js'
|
|
6
|
+
import advancedTools from './read/advanced.js'
|
|
7
|
+
import balanceTools from './read/balance.js'
|
|
8
|
+
import contractTools from './read/contract.js'
|
|
9
|
+
import contractInfoTools from './read/contract-info.js'
|
|
10
|
+
import ensTools from './read/ens.js'
|
|
11
|
+
import gasTools from './read/gas.js'
|
|
12
|
+
import logTools from './read/logs.js'
|
|
13
|
+
import signatureTools from './read/signatures.js'
|
|
14
|
+
import signingRequestTools from './read/signing.js'
|
|
15
|
+
import transactionTools from './sign/transactions.js'
|
|
16
|
+
import walletTools from './sign/wallet.js'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* What a tool does with a wallet, which is the line everything else divides along.
|
|
20
|
+
*
|
|
21
|
+
* `read` answers questions about a chain and costs an RPC call. `sign` puts a transaction
|
|
22
|
+
* in front of somebody's wallet, and is the reason identity and rooms exist. A host pricing
|
|
23
|
+
* or rate-limiting tool calls almost always wants this distinction, and taking it from the
|
|
24
|
+
* folder a tool lives in means it cannot drift from a hand-kept list.
|
|
25
|
+
*/
|
|
26
|
+
export type ToolGroup = 'read' | 'sign'
|
|
27
|
+
|
|
28
|
+
const readTools = {
|
|
15
29
|
...signatureTools,
|
|
16
30
|
...contractTools,
|
|
17
31
|
...contractInfoTools,
|
|
@@ -20,12 +34,45 @@ const allToolDefinitions = {
|
|
|
20
34
|
...advancedTools,
|
|
21
35
|
...ensTools,
|
|
22
36
|
...gasTools,
|
|
23
|
-
|
|
37
|
+
// A signature already asked for and paid for; collecting it is not a second request.
|
|
38
|
+
...signingRequestTools
|
|
24
39
|
} as const
|
|
25
40
|
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
const signTools = {
|
|
42
|
+
...transactionTools,
|
|
43
|
+
...walletTools
|
|
44
|
+
} as const
|
|
45
|
+
|
|
46
|
+
const allToolDefinitions = { ...readTools, ...signTools } as const
|
|
47
|
+
|
|
48
|
+
const groups = new Map<string, ToolGroup>([
|
|
49
|
+
...Object.keys(readTools).map((name) => [name, 'read'] as const),
|
|
50
|
+
...Object.keys(signTools).map((name) => [name, 'sign'] as const)
|
|
51
|
+
])
|
|
52
|
+
|
|
53
|
+
/** The group a tool belongs to, for a host deciding what it costs or who may call it. */
|
|
54
|
+
export function toolGroup(name: string): ToolGroup | undefined {
|
|
55
|
+
return groups.get(name)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Wraps every tool call, for a host that needs to say who may run what.
|
|
60
|
+
*
|
|
61
|
+
* Deliberately only the tool's name, its group and who is calling: enough to count calls,
|
|
62
|
+
* refuse them past a limit and record what was used, without this package taking a view on
|
|
63
|
+
* any of it. Throwing refuses the call, and the message reaches the agent — so it should
|
|
64
|
+
* say what to do about it. Whatever the returned promise settles as is what the caller
|
|
65
|
+
* sees, so a host can also time a call or meter it once it has succeeded.
|
|
66
|
+
*/
|
|
67
|
+
export type ToolMiddleware = (
|
|
68
|
+
call: { tool: string; group: ToolGroup; identity: string },
|
|
69
|
+
run: () => Promise<ToolResult>
|
|
70
|
+
) => Promise<ToolResult>
|
|
71
|
+
|
|
72
|
+
export function registerAllTools(server: McpServer, middleware?: ToolMiddleware) {
|
|
28
73
|
Object.entries(allToolDefinitions).forEach(([name, tool]) => {
|
|
74
|
+
if (tool.available && !tool.available()) return
|
|
75
|
+
|
|
29
76
|
server.registerTool(
|
|
30
77
|
name,
|
|
31
78
|
{
|
|
@@ -33,8 +80,12 @@ export function registerAllTools(server: McpServer) {
|
|
|
33
80
|
description: tool.description,
|
|
34
81
|
inputSchema: tool.schema.shape
|
|
35
82
|
},
|
|
36
|
-
async (args: any,
|
|
37
|
-
|
|
83
|
+
async (args: any, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => {
|
|
84
|
+
// Passed to every handler; the ones that reach a signer must say whose it is.
|
|
85
|
+
const identity = identityFrom(extra.authInfo)
|
|
86
|
+
const run = () => tool.handler(args, identity)
|
|
87
|
+
const group = toolGroup(name) as ToolGroup
|
|
88
|
+
return await (middleware ? middleware({ tool: name, group, identity }, run) : run())
|
|
38
89
|
}
|
|
39
90
|
)
|
|
40
91
|
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type Address, decodeAbiParameters, isAddress, parseAbiParameters } from 'viem'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
-
import {
|
|
4
|
-
import { getClientManager, SUPPORTED_CHAINS } from '
|
|
5
|
-
import type { ChainName } from '
|
|
6
|
-
import { createTool, formatResponse, summarizeTrace } from '
|
|
3
|
+
import { isDebugNodeAvailable, simulateCallWithTrace, traceTransactionWithAnvil } from '../../anvil.js'
|
|
4
|
+
import { getClientManager, SUPPORTED_CHAINS } from '../../client.js'
|
|
5
|
+
import type { ChainName } from '../../types.js'
|
|
6
|
+
import { createTool, formatResponse, summarizeTrace } from '../../utils.js'
|
|
7
7
|
|
|
8
8
|
export default {
|
|
9
9
|
get_storage_at: createTool(
|
|
@@ -155,7 +155,9 @@ export default {
|
|
|
155
155
|
useAnvil: z
|
|
156
156
|
.boolean()
|
|
157
157
|
.optional()
|
|
158
|
-
.describe(
|
|
158
|
+
.describe(
|
|
159
|
+
'Force tracing through the debug node (ANVIL_RPC_URL). Used automatically as a fallback when the RPC cannot trace.'
|
|
160
|
+
)
|
|
159
161
|
.default(false),
|
|
160
162
|
summarize: z
|
|
161
163
|
.boolean()
|
|
@@ -213,14 +215,14 @@ export default {
|
|
|
213
215
|
(traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult) ||
|
|
214
216
|
args.useAnvil
|
|
215
217
|
) {
|
|
216
|
-
const anvilAvailable = await
|
|
218
|
+
const anvilAvailable = await isDebugNodeAvailable()
|
|
217
219
|
if (anvilAvailable) {
|
|
218
220
|
usedAnvil = true // Mark as used before attempting (even if it fails)
|
|
219
221
|
try {
|
|
220
222
|
const forkUrl = clientManager.getRpcUrl(args.chain as ChainName)
|
|
221
223
|
const blockNumber = transaction.blockNumber ?? 0n
|
|
222
224
|
|
|
223
|
-
traceResult = await traceTransactionWithAnvil(forkUrl, args.transactionHash, blockNumber, tracer
|
|
225
|
+
traceResult = await traceTransactionWithAnvil(forkUrl, args.transactionHash, blockNumber, tracer)
|
|
224
226
|
} catch (anvilError) {
|
|
225
227
|
// Anvil tracing also failed
|
|
226
228
|
traceResult = {
|
|
@@ -235,7 +237,7 @@ export default {
|
|
|
235
237
|
// Anvil not available and RPC failed
|
|
236
238
|
traceResult = {
|
|
237
239
|
error:
|
|
238
|
-
'Tracing not available.
|
|
240
|
+
'Tracing not available. Point ANVIL_RPC_URL at a node exposing debug_traceCall — a local Anvil on 127.0.0.1:8545 is picked up automatically.',
|
|
239
241
|
rpcError:
|
|
240
242
|
traceResult && typeof traceResult === 'object' && 'rpcError' in traceResult
|
|
241
243
|
? (traceResult as { rpcError: string }).rpcError
|
|
@@ -299,7 +301,7 @@ export default {
|
|
|
299
301
|
|
|
300
302
|
debug_call: createTool(
|
|
301
303
|
'Debug Contract Call',
|
|
302
|
-
'Simulate a contract call with full trace output.
|
|
304
|
+
'Simulate a contract call with full trace output. Needs a node exposing debug_traceCall (a local Anvil, or ANVIL_RPC_URL). Useful for debugging reverts and understanding call execution.',
|
|
303
305
|
z.object({
|
|
304
306
|
chain: z.enum(SUPPORTED_CHAINS).describe('The blockchain network to fork'),
|
|
305
307
|
to: z.string().describe('Contract address to call'),
|
|
@@ -328,9 +330,9 @@ export default {
|
|
|
328
330
|
}),
|
|
329
331
|
async (args) => {
|
|
330
332
|
// Check if Anvil is installed
|
|
331
|
-
const anvilAvailable = await
|
|
333
|
+
const anvilAvailable = await isDebugNodeAvailable()
|
|
332
334
|
if (!anvilAvailable) {
|
|
333
|
-
throw new Error('
|
|
335
|
+
throw new Error('No tracing node reachable. Run a local Anvil, or set ANVIL_RPC_URL to a node exposing debug_traceCall.')
|
|
334
336
|
}
|
|
335
337
|
|
|
336
338
|
const clientManager = getClientManager()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Address, formatEther, formatUnits, isAddress } from 'viem'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
-
import { getClientManager, SUPPORTED_CHAINS } from '
|
|
4
|
-
import type { ChainName } from '
|
|
5
|
-
import { createTool, formatResponse } from '
|
|
3
|
+
import { getClientManager, SUPPORTED_CHAINS } from '../../client.js'
|
|
4
|
+
import type { ChainName } from '../../types.js'
|
|
5
|
+
import { createTool, formatResponse } from '../../utils.js'
|
|
6
6
|
|
|
7
7
|
const BalanceQuerySchema = z.object({
|
|
8
8
|
chain: z.enum(SUPPORTED_CHAINS).describe('The blockchain network to use'),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isAddress } from 'viem'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
-
import { getClientManager, SUPPORTED_CHAINS } from '
|
|
4
|
-
import type { ChainName } from '
|
|
5
|
-
import { createTool, formatResponse } from '
|
|
3
|
+
import { getClientManager, SUPPORTED_CHAINS } from '../../client.js'
|
|
4
|
+
import type { ChainName } from '../../types.js'
|
|
5
|
+
import { createTool, formatResponse } from '../../utils.js'
|
|
6
6
|
|
|
7
7
|
// Type for raw Etherscan contract info
|
|
8
8
|
interface EtherscanContractInfo {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type AbiFunction, type Address, isAddress, parseAbiItem } from 'viem'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
-
import { getClientManager, SUPPORTED_CHAINS } from '
|
|
4
|
-
import type { ChainName } from '
|
|
5
|
-
import { convertArgumentsToTypes, createTool, formatResponse } from '
|
|
3
|
+
import { getClientManager, SUPPORTED_CHAINS } from '../../client.js'
|
|
4
|
+
import type { ChainName } from '../../types.js'
|
|
5
|
+
import { convertArgumentsToTypes, createTool, formatResponse } from '../../utils.js'
|
|
6
6
|
|
|
7
7
|
const ContractCallSchema = z.object({
|
|
8
8
|
chain: z.enum(SUPPORTED_CHAINS).describe('Blockchain network (mainnet, base, arbitrum, polygon, optimism, celo, localhost)'),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type Address, isAddress, namehash } from 'viem'
|
|
2
2
|
import { normalize } from 'viem/ens'
|
|
3
3
|
import { z } from 'zod'
|
|
4
|
-
import { getClientManager, SUPPORTED_CHAINS } from '
|
|
5
|
-
import type { ChainName } from '
|
|
6
|
-
import { createTool, formatResponse } from '
|
|
4
|
+
import { getClientManager, SUPPORTED_CHAINS } from '../../client.js'
|
|
5
|
+
import type { ChainName } from '../../types.js'
|
|
6
|
+
import { createTool, formatResponse } from '../../utils.js'
|
|
7
7
|
|
|
8
8
|
// Base ENS Contract Addresses
|
|
9
9
|
const BASE_ENS_CONTRACTS = {
|