@blockrun/mcp 0.6.6 → 0.6.7
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/dist/index.js +82 -149
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,70 +5,29 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
6
|
|
|
7
7
|
// src/utils/wallet.ts
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var WALLET_FILE = path.join(WALLET_DIR, ".session");
|
|
17
|
-
var QR_FILE = path.join(WALLET_DIR, "qr.png");
|
|
18
|
-
var USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
19
|
-
var BASE_CHAIN_ID = "8453";
|
|
20
|
-
var BASE_RPC_URLS = [
|
|
21
|
-
"https://mainnet.base.org",
|
|
22
|
-
"https://base.llamarpc.com",
|
|
23
|
-
"https://1rpc.io/base"
|
|
24
|
-
];
|
|
25
|
-
var MODEL_TIERS = {
|
|
26
|
-
fast: ["google/gemini-2.5-flash", "google/gemini-3.1-flash-lite", "openai/gpt-5-mini", "deepseek/deepseek-chat", "google/gemini-3-flash-preview"],
|
|
27
|
-
balanced: ["openai/gpt-5.4", "anthropic/claude-sonnet-4.6", "google/gemini-2.5-pro", "openai/gpt-5.3", "google/gemini-3.1-pro"],
|
|
28
|
-
powerful: ["openai/gpt-5.4-pro", "anthropic/claude-opus-4.6", "anthropic/claude-opus-4.5", "openai/o3", "openai/gpt-5.4"],
|
|
29
|
-
cheap: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "google/gemini-2.5-flash", "deepseek/deepseek-chat", "openai/gpt-5.4-nano"],
|
|
30
|
-
reasoning: ["openai/o3", "openai/o1", "openai/o3-mini", "deepseek/deepseek-reasoner", "openai/gpt-5.3-codex"],
|
|
31
|
-
free: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "nvidia/nemotron-ultra-253b", "nvidia/nemotron-super-49b", "nvidia/qwen3-coder-480b", "nvidia/llama-4-maverick", "nvidia/gpt-oss-20b"],
|
|
32
|
-
coding: ["openai/gpt-5.3-codex", "nvidia/qwen3-coder-480b", "nvidia/devstral-2-123b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"]
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// src/utils/wallet.ts
|
|
36
|
-
var _walletWasCreated = false;
|
|
37
|
-
var _walletAddress = null;
|
|
8
|
+
import {
|
|
9
|
+
LLMClient,
|
|
10
|
+
ImageClient,
|
|
11
|
+
getOrCreateWallet,
|
|
12
|
+
getPaymentLinks,
|
|
13
|
+
formatWalletCreatedMessage,
|
|
14
|
+
formatNeedsFundingMessage
|
|
15
|
+
} from "@blockrun/llm";
|
|
38
16
|
var _client = null;
|
|
39
17
|
var _imageClient = null;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
if (fs.existsSync(WALLET_FILE)) {
|
|
48
|
-
try {
|
|
49
|
-
const savedKey = fs.readFileSync(WALLET_FILE, "utf-8").trim();
|
|
50
|
-
if (savedKey.startsWith("0x") && savedKey.length === 66) {
|
|
51
|
-
const account2 = privateKeyToAccount(savedKey);
|
|
52
|
-
_walletAddress = account2.address;
|
|
53
|
-
return savedKey;
|
|
54
|
-
}
|
|
55
|
-
} catch {
|
|
18
|
+
var _walletInfo = null;
|
|
19
|
+
function ensureWallet() {
|
|
20
|
+
if (!_walletInfo) {
|
|
21
|
+
_walletInfo = getOrCreateWallet();
|
|
22
|
+
if (_walletInfo.isNew) {
|
|
23
|
+
console.error(formatWalletCreatedMessage(_walletInfo.address));
|
|
56
24
|
}
|
|
57
25
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!fs.existsSync(WALLET_DIR)) {
|
|
64
|
-
fs.mkdirSync(WALLET_DIR, { recursive: true, mode: 448 });
|
|
65
|
-
}
|
|
66
|
-
fs.writeFileSync(WALLET_FILE, newKey, { mode: 384 });
|
|
67
|
-
console.error(`[BlockRun] New wallet created and saved to ${WALLET_FILE}`);
|
|
68
|
-
} catch (err) {
|
|
69
|
-
console.error(`[BlockRun] Warning: Could not save wallet to file: ${err}`);
|
|
70
|
-
}
|
|
71
|
-
return newKey;
|
|
26
|
+
return _walletInfo;
|
|
27
|
+
}
|
|
28
|
+
function getOrCreateWalletKey() {
|
|
29
|
+
const info = ensureWallet();
|
|
30
|
+
return info.privateKey;
|
|
72
31
|
}
|
|
73
32
|
function getClient() {
|
|
74
33
|
if (!_client) {
|
|
@@ -85,28 +44,29 @@ function getImageClient() {
|
|
|
85
44
|
return _imageClient;
|
|
86
45
|
}
|
|
87
46
|
function getWalletInfo() {
|
|
88
|
-
const
|
|
89
|
-
const
|
|
47
|
+
const info = ensureWallet();
|
|
48
|
+
const links = getPaymentLinks(info.address);
|
|
90
49
|
return {
|
|
91
|
-
address,
|
|
50
|
+
address: info.address,
|
|
92
51
|
network: "Base",
|
|
93
52
|
chainId: 8453,
|
|
94
53
|
currency: "USDC",
|
|
95
|
-
isNew:
|
|
96
|
-
basescanUrl:
|
|
54
|
+
isNew: info.isNew,
|
|
55
|
+
basescanUrl: links.basescan,
|
|
56
|
+
fundingUrl: links.blockrun
|
|
97
57
|
};
|
|
98
58
|
}
|
|
99
59
|
async function getUsdcBalance(address) {
|
|
60
|
+
const USDC_ADDRESS2 = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
61
|
+
const BASE_RPC_URLS = [
|
|
62
|
+
"https://mainnet.base.org",
|
|
63
|
+
"https://base.llamarpc.com",
|
|
64
|
+
"https://1rpc.io/base"
|
|
65
|
+
];
|
|
100
66
|
const data = {
|
|
101
67
|
jsonrpc: "2.0",
|
|
102
68
|
method: "eth_call",
|
|
103
|
-
params: [
|
|
104
|
-
{
|
|
105
|
-
to: USDC_ADDRESS,
|
|
106
|
-
data: `0x70a08231000000000000000000000000${address.slice(2)}`
|
|
107
|
-
},
|
|
108
|
-
"latest"
|
|
109
|
-
],
|
|
69
|
+
params: [{ to: USDC_ADDRESS2, data: `0x70a08231000000000000000000000000${address.slice(2)}` }, "latest"],
|
|
110
70
|
id: 1
|
|
111
71
|
};
|
|
112
72
|
for (const rpcUrl of BASE_RPC_URLS) {
|
|
@@ -117,9 +77,7 @@ async function getUsdcBalance(address) {
|
|
|
117
77
|
body: JSON.stringify(data)
|
|
118
78
|
});
|
|
119
79
|
const result = await response.json();
|
|
120
|
-
if (result.result)
|
|
121
|
-
return parseInt(result.result, 16) / 1e6;
|
|
122
|
-
}
|
|
80
|
+
if (result.result) return parseInt(result.result, 16) / 1e6;
|
|
123
81
|
} catch {
|
|
124
82
|
continue;
|
|
125
83
|
}
|
|
@@ -133,15 +91,35 @@ import { z } from "zod";
|
|
|
133
91
|
// src/utils/qr.ts
|
|
134
92
|
import QRCode from "qrcode";
|
|
135
93
|
import open from "open";
|
|
136
|
-
import * as
|
|
94
|
+
import * as fs from "fs";
|
|
95
|
+
|
|
96
|
+
// src/utils/constants.ts
|
|
97
|
+
import * as path from "path";
|
|
98
|
+
import * as os from "os";
|
|
99
|
+
var WALLET_DIR = path.join(os.homedir(), ".blockrun");
|
|
100
|
+
var WALLET_FILE = path.join(WALLET_DIR, ".session");
|
|
101
|
+
var QR_FILE = path.join(WALLET_DIR, "qr.png");
|
|
102
|
+
var USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
103
|
+
var BASE_CHAIN_ID = "8453";
|
|
104
|
+
var MODEL_TIERS = {
|
|
105
|
+
fast: ["google/gemini-2.5-flash", "google/gemini-3.1-flash-lite", "openai/gpt-5-mini", "deepseek/deepseek-chat", "google/gemini-3-flash-preview"],
|
|
106
|
+
balanced: ["openai/gpt-5.4", "anthropic/claude-sonnet-4.6", "google/gemini-2.5-pro", "openai/gpt-5.3", "google/gemini-3.1-pro"],
|
|
107
|
+
powerful: ["openai/gpt-5.4-pro", "anthropic/claude-opus-4.6", "anthropic/claude-opus-4.5", "openai/o3", "openai/gpt-5.4"],
|
|
108
|
+
cheap: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "google/gemini-2.5-flash", "deepseek/deepseek-chat", "openai/gpt-5.4-nano"],
|
|
109
|
+
reasoning: ["openai/o3", "openai/o1", "openai/o3-mini", "deepseek/deepseek-reasoner", "openai/gpt-5.3-codex"],
|
|
110
|
+
free: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "nvidia/nemotron-ultra-253b", "nvidia/nemotron-super-49b", "nvidia/qwen3-coder-480b", "nvidia/llama-4-maverick", "nvidia/gpt-oss-20b"],
|
|
111
|
+
coding: ["openai/gpt-5.3-codex", "nvidia/qwen3-coder-480b", "nvidia/devstral-2-123b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"]
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/utils/qr.ts
|
|
137
115
|
function getEip681Uri(address, amountUsdc = 1) {
|
|
138
116
|
const amountWei = Math.floor(amountUsdc * 1e6);
|
|
139
117
|
return `ethereum:${USDC_ADDRESS}@${BASE_CHAIN_ID}/transfer?address=${address}&uint256=${amountWei}`;
|
|
140
118
|
}
|
|
141
119
|
async function generateQrPng(address) {
|
|
142
120
|
const eip681Uri = getEip681Uri(address);
|
|
143
|
-
if (!
|
|
144
|
-
|
|
121
|
+
if (!fs.existsSync(WALLET_DIR)) {
|
|
122
|
+
fs.mkdirSync(WALLET_DIR, { recursive: true, mode: 448 });
|
|
145
123
|
}
|
|
146
124
|
await QRCode.toFile(QR_FILE, eip681Uri, {
|
|
147
125
|
type: "png",
|
|
@@ -675,52 +653,8 @@ Error: ${errMsg}` }],
|
|
|
675
653
|
);
|
|
676
654
|
}
|
|
677
655
|
|
|
678
|
-
// src/tools/twitter.ts
|
|
679
|
-
import { z as z5 } from "zod";
|
|
680
|
-
function registerTwitterTool(server, budget) {
|
|
681
|
-
server.registerTool(
|
|
682
|
-
"blockrun_twitter",
|
|
683
|
-
{
|
|
684
|
-
description: `Search real-time X/Twitter via Grok. Use for trending topics, @handles, breaking news.`,
|
|
685
|
-
inputSchema: {
|
|
686
|
-
query: z5.string().describe("Search query (can include @handles, topics)"),
|
|
687
|
-
max_results: z5.number().optional().default(10).describe("Max results (1-25)")
|
|
688
|
-
}
|
|
689
|
-
},
|
|
690
|
-
async ({ query, max_results }) => {
|
|
691
|
-
const budgetCheck = checkBudget(budget);
|
|
692
|
-
if (!budgetCheck.allowed) {
|
|
693
|
-
return {
|
|
694
|
-
content: [{ type: "text", text: `Budget limit reached ($${budget.spent.toFixed(4)} of $${budget.limit?.toFixed(2)}). Use blockrun_wallet with action: "budget" to adjust.` }],
|
|
695
|
-
isError: true
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
try {
|
|
699
|
-
const llm = getClient();
|
|
700
|
-
const response = await llm.chat("xai/grok-3", query, {
|
|
701
|
-
system: `Real-time X/Twitter search. Focus on recent posts, key accounts, engagement. Max results: ${max_results}`,
|
|
702
|
-
search: true
|
|
703
|
-
});
|
|
704
|
-
recordSpending(budget, 2e-3);
|
|
705
|
-
return {
|
|
706
|
-
content: [{ type: "text", text: `[X/Twitter via Grok]
|
|
707
|
-
|
|
708
|
-
${response}` }],
|
|
709
|
-
structuredContent: { query, model: "xai/grok-3", response }
|
|
710
|
-
};
|
|
711
|
-
} catch (error) {
|
|
712
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
713
|
-
return {
|
|
714
|
-
content: [{ type: "text", text: formatError(errorMessage) }],
|
|
715
|
-
isError: true
|
|
716
|
-
};
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
656
|
// src/tools/search.ts
|
|
723
|
-
import { z as
|
|
657
|
+
import { z as z5 } from "zod";
|
|
724
658
|
function registerSearchTool(server) {
|
|
725
659
|
server.registerTool(
|
|
726
660
|
"blockrun_search",
|
|
@@ -732,11 +666,11 @@ Pricing: ~$0.01/search
|
|
|
732
666
|
|
|
733
667
|
Returns a summary with cited sources.`,
|
|
734
668
|
inputSchema: {
|
|
735
|
-
query:
|
|
736
|
-
sources:
|
|
737
|
-
max_results:
|
|
738
|
-
from_date:
|
|
739
|
-
to_date:
|
|
669
|
+
query: z5.string().describe("Search query"),
|
|
670
|
+
sources: z5.array(z5.enum(["web", "x", "news"])).optional().describe("Sources to search (default: web + x + news)"),
|
|
671
|
+
max_results: z5.number().optional().default(10).describe("Max results per source (1-20)"),
|
|
672
|
+
from_date: z5.string().optional().describe("Start date filter (YYYY-MM-DD)"),
|
|
673
|
+
to_date: z5.string().optional().describe("End date filter (YYYY-MM-DD)")
|
|
740
674
|
}
|
|
741
675
|
},
|
|
742
676
|
async ({ query, sources, max_results, from_date, to_date }) => {
|
|
@@ -764,7 +698,7 @@ Returns a summary with cited sources.`,
|
|
|
764
698
|
}
|
|
765
699
|
|
|
766
700
|
// src/tools/exa.ts
|
|
767
|
-
import { z as
|
|
701
|
+
import { z as z6 } from "zod";
|
|
768
702
|
function registerExaTool(server) {
|
|
769
703
|
server.registerTool(
|
|
770
704
|
"blockrun_exa",
|
|
@@ -777,14 +711,14 @@ Actions:
|
|
|
777
711
|
- contents: Fetch full Markdown text from URLs, ready for LLM context ($0.002/URL)
|
|
778
712
|
- similar: Find pages semantically similar to a given URL ($0.01/call)`,
|
|
779
713
|
inputSchema: {
|
|
780
|
-
action:
|
|
781
|
-
query:
|
|
782
|
-
url:
|
|
783
|
-
urls:
|
|
784
|
-
num_results:
|
|
785
|
-
category:
|
|
786
|
-
include_domains:
|
|
787
|
-
exclude_domains:
|
|
714
|
+
action: z6.enum(["search", "answer", "contents", "similar"]).describe("Action to perform"),
|
|
715
|
+
query: z6.string().optional().describe("Natural language query (for search/answer)"),
|
|
716
|
+
url: z6.string().optional().describe("Reference URL to find similar pages (for similar action)"),
|
|
717
|
+
urls: z6.array(z6.string()).optional().describe("URLs to fetch content from (for contents action, up to 100)"),
|
|
718
|
+
num_results: z6.number().optional().describe("Number of results to return (default: 10)"),
|
|
719
|
+
category: z6.string().optional().describe("Category filter: 'news', 'research paper', 'company', 'tweet', 'github', 'pdf'"),
|
|
720
|
+
include_domains: z6.array(z6.string()).optional().describe("Only search within these domains"),
|
|
721
|
+
exclude_domains: z6.array(z6.string()).optional().describe("Exclude these domains from results")
|
|
788
722
|
}
|
|
789
723
|
},
|
|
790
724
|
async ({ action, query, url, urls, num_results, category, include_domains, exclude_domains }) => {
|
|
@@ -837,7 +771,7 @@ Actions:
|
|
|
837
771
|
}
|
|
838
772
|
|
|
839
773
|
// src/tools/markets.ts
|
|
840
|
-
import { z as
|
|
774
|
+
import { z as z7 } from "zod";
|
|
841
775
|
function registerMarketsTool(server) {
|
|
842
776
|
server.registerTool(
|
|
843
777
|
"blockrun_markets",
|
|
@@ -852,9 +786,9 @@ Example paths:
|
|
|
852
786
|
|
|
853
787
|
$0.001/call.`,
|
|
854
788
|
inputSchema: {
|
|
855
|
-
path:
|
|
856
|
-
params:
|
|
857
|
-
body:
|
|
789
|
+
path: z7.string().describe("Endpoint path, e.g. 'polymarket/events', 'kalshi/markets/KXBTC-25MAR14'"),
|
|
790
|
+
params: z7.record(z7.string(), z7.string()).optional().describe("Query parameters for GET requests"),
|
|
791
|
+
body: z7.any().optional().describe("JSON body for POST queries (triggers pmQuery)")
|
|
858
792
|
}
|
|
859
793
|
},
|
|
860
794
|
async ({ path: path2, params, body }) => {
|
|
@@ -877,7 +811,7 @@ $0.001/call.`,
|
|
|
877
811
|
}
|
|
878
812
|
|
|
879
813
|
// src/tools/dex.ts
|
|
880
|
-
import { z as
|
|
814
|
+
import { z as z8 } from "zod";
|
|
881
815
|
function registerDexTool(server) {
|
|
882
816
|
server.registerTool(
|
|
883
817
|
"blockrun_dex",
|
|
@@ -894,10 +828,10 @@ Examples:
|
|
|
894
828
|
blockrun_dex({ token: "So11...xxx" }) -> Get specific token data
|
|
895
829
|
blockrun_dex({ symbol: "PEPE" }) -> Search by symbol`,
|
|
896
830
|
inputSchema: {
|
|
897
|
-
query:
|
|
898
|
-
token:
|
|
899
|
-
symbol:
|
|
900
|
-
chain:
|
|
831
|
+
query: z8.string().optional().describe("Search query (token name, symbol, or address)"),
|
|
832
|
+
token: z8.string().optional().describe("Token address for direct lookup"),
|
|
833
|
+
symbol: z8.string().optional().describe("Token symbol to search"),
|
|
834
|
+
chain: z8.string().optional().describe("Filter by chain (ethereum, solana, base, etc.)")
|
|
901
835
|
}
|
|
902
836
|
},
|
|
903
837
|
async ({ query, token, symbol, chain }) => {
|
|
@@ -965,7 +899,6 @@ function initializeMcpServer(server) {
|
|
|
965
899
|
registerChatTool(server, budget);
|
|
966
900
|
registerModelsTool(server, modelCache);
|
|
967
901
|
registerImageTool(server);
|
|
968
|
-
registerTwitterTool(server, budget);
|
|
969
902
|
registerSearchTool(server);
|
|
970
903
|
registerExaTool(server);
|
|
971
904
|
registerMarketsTool(server);
|
|
@@ -1009,12 +942,12 @@ function initializeMcpServer(server) {
|
|
|
1009
942
|
async function main() {
|
|
1010
943
|
const server = new McpServer({
|
|
1011
944
|
name: "blockrun-mcp",
|
|
1012
|
-
version: "0.6.
|
|
945
|
+
version: "0.6.6"
|
|
1013
946
|
});
|
|
1014
947
|
initializeMcpServer(server);
|
|
1015
948
|
const transport = new StdioServerTransport();
|
|
1016
949
|
await server.connect(transport);
|
|
1017
|
-
console.error("BlockRun MCP Server started (v0.6.
|
|
950
|
+
console.error("BlockRun MCP Server started (v0.6.6) \u2014 stdio transport");
|
|
1018
951
|
}
|
|
1019
952
|
main().catch((error) => {
|
|
1020
953
|
console.error("Fatal error:", error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"mcpName": "io.github.BlockRunAI/blockrun-mcp",
|
|
5
5
|
"description": "BlockRun MCP Server - Give your AI agent web search, deep research, prediction markets, crypto data, X/Twitter intelligence. Paid via x402 micropayments.",
|
|
6
6
|
"type": "module",
|