-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharbitrum-mcp.ts
116 lines (101 loc) · 4.29 KB
/
arbitrum-mcp.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import 'dotenv/config'
const server = new McpServer({
name: "Arbitrum Analytics Service",
version: "1.0.0",
});
interface GetArbitrumDataParams {
fullPrompt: string;
address?: string;
}
server.tool(
"getArbitrumData",
{
fullPrompt: z.string().describe("The complete user query about Arbitrum data"),
address: z.string().optional().describe("Optional specific address to focus on"),
},
async ({ fullPrompt, address }: GetArbitrumDataParams) => {
try {
// Get account balance if address is provided
let accountData = null;
if (address) {
const balanceResponse = await fetch(`https://api.arbiscan.io/api?module=account&action=balance&address=${address}&tag=latest&apikey=${process.env.ARBISCAN_API_KEY || ''}`);
accountData = await balanceResponse.json();
}
// Get general stats
const statsResponse = await fetch(`https://api.arbiscan.io/api?module=stats&action=ethsupply&apikey=${process.env.ARBISCAN_API_KEY || ''}`);
const statsData = await statsResponse.json();
// Get latest block number
const latestBlockResponse = await fetch(`https://api.arbiscan.io/api?module=proxy&action=eth_blockNumber&apikey=${process.env.ARBISCAN_API_KEY || ''}`);
const latestBlockData = await latestBlockResponse.json();
// Get latest block transactions using proxy API
const latestBlockNumber = latestBlockData.result;
const txListResponse = await fetch(`https://api.arbiscan.io/api?module=proxy&action=eth_getBlockByNumber&tag=${latestBlockNumber}&boolean=true&apikey=${process.env.ARBISCAN_API_KEY || ''}`);
const txListData = await txListResponse.json();
const claudeResponse = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.CLAUDE_API_KEY || '',
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-3-sonnet-20240229',
max_tokens: 1024,
messages: [
{
role: 'user',
content: `
You are an Arbitrum blockchain data assistant. Your task is to analyze Arbitrum data and respond to user queries.
Here is the data from the Arbiscan API:
${JSON.stringify({
accountData: accountData,
statsData: statsData,
latestBlock: latestBlockData,
latestBlockTransactions: txListData
}, null, 2)}
User query: ${fullPrompt}
${address ? `Address: ${address}` : ''}
Provide a well-structured response that directly addresses the user's query about the Arbitrum data.
Focus on being accurate, informative, and comprehensive.
When discussing transaction data:
1. List the transactions in chronological order (newest first)
2. Include relevant details like hash, from/to addresses (abbreviated), value, and transaction type
3. Format the response in a clear, readable way
4. Highlight any interesting patterns or notable transactions
5. Explain the context of the Arbitrum network for users who may be unfamiliar
For transaction values in Wei, convert them to ETH (1 ETH = 1e18 Wei).
Format addresses as shortened versions (e.g., 0x1234...5678).
`
}
]
})
})
const claudeJson = await claudeResponse.json()
return {
content: [
{
type: "text",
text: `${claudeJson.content[0].text}`,
},
],
};
} catch (err) {
return {
content: [
{
type: "text",
text: `Error fetching Arbitrum data: ${err}`,
},
],
};
}
},
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch(console.error);