Skip to content

Commit 25ab4d9

Browse files
committed
feat: Update MCP SDK, configure server capabilities, and bump server version to 2.0.0.
1 parent b6d923b commit 25ab4d9

9 files changed

Lines changed: 1102 additions & 1437 deletions

File tree

bun.lock

Lines changed: 170 additions & 108 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"name": "@mcpdotdirect/evm-mcp-server",
33
"module": "src/index.ts",
44
"type": "module",
5-
"version": "1.2.0",
6-
"description": "Model Context Protocol (MCP) server for interacting with EVM-compatible networks",
5+
"version": "2.0.0",
6+
"description": "MCP server for interacting with EVM-compatible blockchains - supports 28 tools across 86+ networks",
77
"bin": {
88
"evm-mcp-server": "./bin/cli.js"
99
},
@@ -27,23 +27,21 @@
2727
"version:major": "npm version major",
2828
"release": "npm publish",
2929
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
30-
"changelog:latest": "conventional-changelog -p angular -r 1 > RELEASE_NOTES.md"
30+
"changelog:latest": "conventional-changelog -p angular -r 1 > RELEASE_NOTES.md",
31+
"inspect": "npx @modelcontextprotocol/inspector node build/index.js"
3132
},
3233
"devDependencies": {
3334
"@types/bun": "latest",
34-
"@types/cors": "^2.8.17",
35-
"@types/express": "^5.0.0",
35+
"@types/node": "^22.0.0",
3636
"conventional-changelog-cli": "^5.0.0"
3737
},
3838
"peerDependencies": {
3939
"typescript": "^5.8.2"
4040
},
4141
"dependencies": {
42-
"@modelcontextprotocol/sdk": "^1.7.0",
43-
"cors": "^2.8.5",
44-
"express": "^4.21.2",
45-
"viem": "^2.23.9",
46-
"zod": "^3.24.2"
42+
"@modelcontextprotocol/sdk": "^1.22.0",
43+
"viem": "^2.39.3",
44+
"zod": "^3.24.3"
4745
},
4846
"keywords": [
4947
"mcp",
@@ -59,7 +57,7 @@
5957
"author": "Etheral <etheral.eth.dev@gmail.com>",
6058
"license": "MIT",
6159
"engines": {
62-
"node": ">=18.0.0"
60+
"node": ">=20.0.0"
6361
},
6462
"repository": {
6563
"type": "git",

src/core/chains.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,9 @@ export function resolveChainId(chainIdentifier: number | string): number {
296296
const networkName = chainIdentifier.toLowerCase();
297297

298298
// Check if the network name is in our map
299-
if (networkName in networkNameMap) {
300-
return networkNameMap[networkName];
299+
const chainId = networkNameMap[networkName];
300+
if (chainId !== undefined) {
301+
return chainId;
301302
}
302303

303304
// Try parsing as a number

src/core/prompts.ts

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@ import { z } from "zod";
77
*/
88
export function registerEVMPrompts(server: McpServer) {
99
// Basic block explorer prompt
10-
server.prompt(
10+
server.registerPrompt(
1111
"explore_block",
12-
"Explore information about a specific block",
1312
{
14-
blockNumber: z.string().optional().describe("Block number to explore. If not provided, latest block will be used."),
15-
network: z.string().optional().describe("Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet.")
13+
description: "Explore information about a specific block",
14+
argsSchema: {
15+
blockNumber: z.string().optional().describe("Block number to explore. If not provided, latest block will be used."),
16+
network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.")
17+
}
1618
},
1719
({ blockNumber, network = "ethereum" }) => ({
1820
messages: [{
1921
role: "user",
2022
content: {
2123
type: "text",
22-
text: blockNumber
24+
text: blockNumber
2325
? `Please analyze block #${blockNumber} on the ${network} network and provide information about its key metrics, transactions, and significance.`
2426
: `Please analyze the latest block on the ${network} network and provide information about its key metrics, transactions, and significance.`
2527
}
@@ -28,12 +30,14 @@ export function registerEVMPrompts(server: McpServer) {
2830
);
2931

3032
// Transaction analysis prompt
31-
server.prompt(
33+
server.registerPrompt(
3234
"analyze_transaction",
33-
"Analyze a specific transaction",
3435
{
35-
txHash: z.string().describe("Transaction hash to analyze"),
36-
network: z.string().optional().describe("Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet.")
36+
description: "Analyze a specific transaction",
37+
argsSchema: {
38+
txHash: z.string().describe("Transaction hash to analyze"),
39+
network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.")
40+
}
3741
},
3842
({ txHash, network = "ethereum" }) => ({
3943
messages: [{
@@ -47,12 +51,14 @@ export function registerEVMPrompts(server: McpServer) {
4751
);
4852

4953
// Address analysis prompt
50-
server.prompt(
54+
server.registerPrompt(
5155
"analyze_address",
52-
"Analyze an EVM address",
5356
{
54-
address: z.string().describe("Ethereum address to analyze"),
55-
network: z.string().optional().describe("Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet.")
57+
description: "Analyze an EVM address",
58+
argsSchema: {
59+
address: z.string().describe("Ethereum address to analyze"),
60+
network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.")
61+
}
5662
},
5763
({ address, network = "ethereum" }) => ({
5864
messages: [{
@@ -66,33 +72,37 @@ export function registerEVMPrompts(server: McpServer) {
6672
);
6773

6874
// Smart contract interaction guidance
69-
server.prompt(
75+
server.registerPrompt(
7076
"interact_with_contract",
71-
"Get guidance on interacting with a smart contract",
7277
{
73-
contractAddress: z.string().describe("The contract address"),
74-
abiJson: z.string().optional().describe("The contract ABI as a JSON string"),
75-
network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.")
78+
description: "Get guidance on interacting with a smart contract",
79+
argsSchema: {
80+
contractAddress: z.string().describe("The contract address"),
81+
abiJson: z.string().optional().describe("The contract ABI as a JSON string"),
82+
network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.")
83+
}
7684
},
7785
({ contractAddress, abiJson, network = "ethereum" }) => ({
7886
messages: [{
7987
role: "user",
8088
content: {
8189
type: "text",
8290
text: abiJson
83-
? `I need to interact with the smart contract at address ${contractAddress} on the ${network} network. Here's the ABI:\n\n${abiJson}\n\nPlease analyze this contract's functions and provide guidance on how to interact with it safely. Explain what each function does and what parameters it requires.`
91+
? `I need to interact with the smart contract at address ${contractAddress} on the ${network} network. Here's the ABI:\n\n${abiJson}\n\nPlease analyze this contract's functions and provide guidance on how to interact with it safely.`
8492
: `I need to interact with the smart contract at address ${contractAddress} on the ${network} network. Please help me understand what this contract does and how I can interact with it safely.`
8593
}
8694
}]
8795
})
8896
);
8997

9098
// EVM concept explanation
91-
server.prompt(
99+
server.registerPrompt(
92100
"explain_evm_concept",
93-
"Get an explanation of an EVM concept",
94101
{
95-
concept: z.string().describe("The EVM concept to explain (e.g., gas, nonce, etc.)")
102+
description: "Get an explanation of an EVM concept",
103+
argsSchema: {
104+
concept: z.string().describe("The EVM concept to explain (e.g., gas, nonce, etc.)")
105+
}
96106
},
97107
({ concept }) => ({
98108
messages: [{
@@ -106,11 +116,13 @@ export function registerEVMPrompts(server: McpServer) {
106116
);
107117

108118
// Network comparison
109-
server.prompt(
119+
server.registerPrompt(
110120
"compare_networks",
111-
"Compare different EVM-compatible networks",
112121
{
113-
networkList: z.string().describe("Comma-separated list of networks to compare (e.g., 'ethereum,optimism,arbitrum')")
122+
description: "Compare different EVM-compatible networks",
123+
argsSchema: {
124+
networkList: z.string().describe("Comma-separated list of networks to compare")
125+
}
114126
},
115127
({ networkList }) => {
116128
const networks = networkList.split(',').map(n => n.trim());
@@ -127,24 +139,26 @@ export function registerEVMPrompts(server: McpServer) {
127139
);
128140

129141
// Token analysis prompt
130-
server.prompt(
142+
server.registerPrompt(
131143
"analyze_token",
132-
"Analyze an ERC20 or NFT token",
133144
{
134-
tokenAddress: z.string().describe("Token contract address to analyze"),
135-
tokenType: z.string().optional().describe("Type of token to analyze (erc20, erc721/nft, or auto-detect). Defaults to auto."),
136-
tokenId: z.string().optional().describe("Token ID (required for NFT analysis)"),
137-
network: z.string().optional().describe("Network name (e.g., 'ethereum', 'optimism', 'arbitrum', 'base', etc.) or chain ID. Supports all EVM-compatible networks. Defaults to Ethereum mainnet.")
145+
description: "Analyze an ERC20 or NFT token",
146+
argsSchema: {
147+
tokenAddress: z.string().describe("Token contract address to analyze"),
148+
tokenType: z.string().optional().describe("Type of token (erc20, erc721/nft, or auto-detect)"),
149+
tokenId: z.string().optional().describe("Token ID (required for NFT analysis)"),
150+
network: z.string().optional().describe("Network name or chain ID. Defaults to Ethereum mainnet.")
151+
}
138152
},
139153
({ tokenAddress, tokenType = "auto", tokenId, network = "ethereum" }) => {
140154
let promptText = "";
141-
155+
142156
if (tokenType === "erc20" || tokenType === "auto") {
143-
promptText = `Please analyze the ERC20 token at address ${tokenAddress} on the ${network} network. Provide information about its name, symbol, total supply, and any other relevant details. If possible, explain the token's purpose, utility, and market context.`;
157+
promptText = `Please analyze the ERC20 token at address ${tokenAddress} on the ${network} network. Provide information about its name, symbol, total supply, and any other relevant details.`;
144158
} else if ((tokenType === "erc721" || tokenType === "nft") && tokenId) {
145-
promptText = `Please analyze the NFT with token ID ${tokenId} from the collection at address ${tokenAddress} on the ${network} network. Provide information about the collection name, token details, ownership history if available, and any other relevant information about this specific NFT.`;
159+
promptText = `Please analyze the NFT with token ID ${tokenId} from the collection at address ${tokenAddress} on the ${network} network. Provide information about the collection name, token details, and any other relevant information.`;
146160
} else if (tokenType === "nft" || tokenType === "erc721") {
147-
promptText = `Please analyze the NFT collection at address ${tokenAddress} on the ${network} network. Provide information about the collection name, symbol, total supply if available, floor price if available, and any other relevant details about this NFT collection.`;
161+
promptText = `Please analyze the NFT collection at address ${tokenAddress} on the ${network} network. Provide information about the collection name, symbol, total supply if available, and any other relevant details.`;
148162
}
149163

150164
return {
@@ -158,5 +172,4 @@ export function registerEVMPrompts(server: McpServer) {
158172
};
159173
}
160174
);
161-
162-
}
175+
}

0 commit comments

Comments
 (0)