@blockrun/mcp 0.8.0 → 0.9.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/dist/index.js +257 -19
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
8
8
|
import {
|
|
9
9
|
LLMClient,
|
|
10
10
|
ImageClient,
|
|
11
|
+
PriceClient,
|
|
11
12
|
getOrCreateWallet,
|
|
12
13
|
getPaymentLinks,
|
|
13
14
|
formatWalletCreatedMessage,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
} from "@blockrun/llm";
|
|
16
17
|
var _client = null;
|
|
17
18
|
var _imageClient = null;
|
|
19
|
+
var _priceClient = null;
|
|
18
20
|
var _walletInfo = null;
|
|
19
21
|
function ensureWallet() {
|
|
20
22
|
if (!_walletInfo) {
|
|
@@ -43,6 +45,13 @@ function getImageClient() {
|
|
|
43
45
|
}
|
|
44
46
|
return _imageClient;
|
|
45
47
|
}
|
|
48
|
+
function getPriceClient() {
|
|
49
|
+
if (!_priceClient) {
|
|
50
|
+
const privateKey = getOrCreateWalletKey();
|
|
51
|
+
_priceClient = new PriceClient({ privateKey });
|
|
52
|
+
}
|
|
53
|
+
return _priceClient;
|
|
54
|
+
}
|
|
46
55
|
function getWalletInfo() {
|
|
47
56
|
const info = ensureWallet();
|
|
48
57
|
const links = getPaymentLinks(info.address);
|
|
@@ -103,12 +112,12 @@ var USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
|
103
112
|
var BASE_CHAIN_ID = "8453";
|
|
104
113
|
var MODEL_TIERS = {
|
|
105
114
|
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.
|
|
115
|
+
balanced: ["openai/gpt-5.4", "anthropic/claude-sonnet-4.6", "google/gemini-2.5-pro", "moonshot/kimi-k2.6", "openai/gpt-5.3", "google/gemini-3.1-pro"],
|
|
116
|
+
powerful: ["openai/gpt-5.4-pro", "anthropic/claude-opus-4.7", "anthropic/claude-opus-4.6", "openai/o3", "openai/gpt-5.4"],
|
|
108
117
|
cheap: ["zai/glm-5", "zai/glm-5-turbo", "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"],
|
|
118
|
+
reasoning: ["openai/o3", "openai/o1", "openai/o3-mini", "deepseek/deepseek-reasoner", "moonshot/kimi-k2.6", "openai/gpt-5.3-codex"],
|
|
110
119
|
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", "nvidia/glm-4.7"],
|
|
111
|
-
coding: ["zai/glm-5", "openai/gpt-5.3-codex", "nvidia/qwen3-coder-480b", "nvidia/devstral-2-123b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"],
|
|
120
|
+
coding: ["zai/glm-5", "openai/gpt-5.3-codex", "moonshot/kimi-k2.6", "nvidia/qwen3-coder-480b", "nvidia/devstral-2-123b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"],
|
|
112
121
|
glm: ["zai/glm-5", "zai/glm-5-turbo", "nvidia/glm-4.7"]
|
|
113
122
|
};
|
|
114
123
|
|
|
@@ -1099,8 +1108,235 @@ $0.001/call.`,
|
|
|
1099
1108
|
);
|
|
1100
1109
|
}
|
|
1101
1110
|
|
|
1102
|
-
// src/tools/
|
|
1111
|
+
// src/tools/price.ts
|
|
1103
1112
|
import { z as z10 } from "zod";
|
|
1113
|
+
var CATEGORY = z10.enum(["crypto", "fx", "commodity", "usstock", "stocks"]);
|
|
1114
|
+
var MARKET = z10.enum([
|
|
1115
|
+
"us",
|
|
1116
|
+
"hk",
|
|
1117
|
+
"jp",
|
|
1118
|
+
"kr",
|
|
1119
|
+
"gb",
|
|
1120
|
+
"de",
|
|
1121
|
+
"fr",
|
|
1122
|
+
"nl",
|
|
1123
|
+
"ie",
|
|
1124
|
+
"lu",
|
|
1125
|
+
"cn",
|
|
1126
|
+
"ca"
|
|
1127
|
+
]);
|
|
1128
|
+
var RESOLUTION = z10.enum(["1", "5", "15", "60", "240", "D", "W", "M"]);
|
|
1129
|
+
var SESSION = z10.enum(["pre", "post", "on"]);
|
|
1130
|
+
var ACTION = z10.enum(["price", "history", "list"]);
|
|
1131
|
+
function registerPriceTool(server) {
|
|
1132
|
+
server.registerTool(
|
|
1133
|
+
"blockrun_price",
|
|
1134
|
+
{
|
|
1135
|
+
description: `Realtime quotes and OHLC history for crypto, FX, commodities and 12 global stock markets (Pyth-backed).
|
|
1136
|
+
|
|
1137
|
+
- action="price" \u2014 realtime quote for a symbol
|
|
1138
|
+
- action="history" \u2014 OHLC bars between from/to (unix seconds)
|
|
1139
|
+
- action="list" \u2014 discovery: list available symbols (free)
|
|
1140
|
+
|
|
1141
|
+
Pricing:
|
|
1142
|
+
- crypto / fx / commodity: FREE across price, history and list
|
|
1143
|
+
- stocks / usstock: $0.001 per price or history call (list free)
|
|
1144
|
+
|
|
1145
|
+
Stocks markets: us, hk, jp, kr, gb, de, fr, nl, ie, lu, cn, ca (required when category="stocks").
|
|
1146
|
+
|
|
1147
|
+
Examples:
|
|
1148
|
+
- { action: "price", category: "crypto", symbol: "BTC-USD" }
|
|
1149
|
+
- { action: "price", category: "stocks", symbol: "AAPL", market: "us" }
|
|
1150
|
+
- { action: "history", category: "crypto", symbol: "ETH-USD", resolution: "D", from: 1700000000, to: 1710000000 }
|
|
1151
|
+
- { action: "list", category: "crypto", query: "sol" }`,
|
|
1152
|
+
inputSchema: {
|
|
1153
|
+
action: ACTION.describe("Which endpoint to hit: price, history, or list."),
|
|
1154
|
+
category: CATEGORY.describe("Market category."),
|
|
1155
|
+
symbol: z10.string().optional().describe("Ticker (required for price+history). e.g. BTC-USD, AAPL, EUR-USD."),
|
|
1156
|
+
market: MARKET.optional().describe("Stock market code \u2014 required when category='stocks'."),
|
|
1157
|
+
session: SESSION.optional().describe("Equity session hint (pre/post/on); ignored for non-equity."),
|
|
1158
|
+
resolution: RESOLUTION.optional().describe("Bar resolution for history (default D)."),
|
|
1159
|
+
from: z10.number().optional().describe("History window start (unix seconds)."),
|
|
1160
|
+
to: z10.number().optional().describe("History window end (unix seconds)."),
|
|
1161
|
+
query: z10.string().optional().describe("Free-text filter for list."),
|
|
1162
|
+
limit: z10.number().optional().describe("Max items for list (default 100, max 2000).")
|
|
1163
|
+
}
|
|
1164
|
+
},
|
|
1165
|
+
async ({ action, category, symbol, market, session, resolution, from, to, query, limit }) => {
|
|
1166
|
+
try {
|
|
1167
|
+
const priceClient = getPriceClient();
|
|
1168
|
+
if (action === "price") {
|
|
1169
|
+
if (!symbol) throw new Error("symbol is required for action='price'");
|
|
1170
|
+
const result2 = await priceClient.price(category, symbol, {
|
|
1171
|
+
market,
|
|
1172
|
+
session
|
|
1173
|
+
});
|
|
1174
|
+
return {
|
|
1175
|
+
content: [{ type: "text", text: JSON.stringify(result2, null, 2) }],
|
|
1176
|
+
structuredContent: result2
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
if (action === "history") {
|
|
1180
|
+
if (!symbol) throw new Error("symbol is required for action='history'");
|
|
1181
|
+
if (!from) throw new Error("from (unix seconds) is required for action='history'");
|
|
1182
|
+
const result2 = await priceClient.history(category, symbol, {
|
|
1183
|
+
market,
|
|
1184
|
+
session,
|
|
1185
|
+
resolution: resolution ?? "D",
|
|
1186
|
+
from,
|
|
1187
|
+
to
|
|
1188
|
+
});
|
|
1189
|
+
return {
|
|
1190
|
+
content: [{ type: "text", text: JSON.stringify(result2, null, 2) }],
|
|
1191
|
+
structuredContent: result2
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
const result = await priceClient.listSymbols(category, {
|
|
1195
|
+
market,
|
|
1196
|
+
query,
|
|
1197
|
+
limit
|
|
1198
|
+
});
|
|
1199
|
+
return {
|
|
1200
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
1201
|
+
structuredContent: result
|
|
1202
|
+
};
|
|
1203
|
+
} catch (err) {
|
|
1204
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1205
|
+
return {
|
|
1206
|
+
content: [{ type: "text", text: formatError(msg) }],
|
|
1207
|
+
isError: true
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// src/tools/twitter.ts
|
|
1215
|
+
import { z as z11 } from "zod";
|
|
1216
|
+
var ACTION2 = z11.enum([
|
|
1217
|
+
"user_lookup",
|
|
1218
|
+
"user_info",
|
|
1219
|
+
"followers",
|
|
1220
|
+
"followings",
|
|
1221
|
+
"verified_followers",
|
|
1222
|
+
"user_tweets",
|
|
1223
|
+
"user_mentions",
|
|
1224
|
+
"tweet_lookup",
|
|
1225
|
+
"tweet_replies",
|
|
1226
|
+
"tweet_thread",
|
|
1227
|
+
"search"
|
|
1228
|
+
]);
|
|
1229
|
+
function registerTwitterTool(server) {
|
|
1230
|
+
server.registerTool(
|
|
1231
|
+
"blockrun_x",
|
|
1232
|
+
{
|
|
1233
|
+
description: `Structured X/Twitter data via AttentionVC partner API.
|
|
1234
|
+
|
|
1235
|
+
Actions:
|
|
1236
|
+
- user_lookup (usernames: string | string[])
|
|
1237
|
+
- user_info (username)
|
|
1238
|
+
- followers (username, cursor?)
|
|
1239
|
+
- followings (username, cursor?)
|
|
1240
|
+
- verified_followers (user_id, cursor?)
|
|
1241
|
+
- user_tweets (username, includeReplies?, cursor?)
|
|
1242
|
+
- user_mentions (username, sinceTime?, untilTime?, cursor?)
|
|
1243
|
+
- tweet_lookup (tweet_ids: string | string[])
|
|
1244
|
+
- tweet_replies (tweet_id, cursor?, queryType?)
|
|
1245
|
+
- tweet_thread (tweet_id, cursor?)
|
|
1246
|
+
- search (query, queryType?, cursor?)
|
|
1247
|
+
|
|
1248
|
+
Paid per request via x402; prices scale with the endpoint (e.g. user_lookup ~ $0.02, followers ~ $0.05/page).`,
|
|
1249
|
+
inputSchema: {
|
|
1250
|
+
action: ACTION2,
|
|
1251
|
+
usernames: z11.union([z11.string(), z11.array(z11.string())]).optional(),
|
|
1252
|
+
username: z11.string().optional(),
|
|
1253
|
+
user_id: z11.string().optional(),
|
|
1254
|
+
tweet_id: z11.string().optional(),
|
|
1255
|
+
tweet_ids: z11.union([z11.string(), z11.array(z11.string())]).optional(),
|
|
1256
|
+
query: z11.string().optional(),
|
|
1257
|
+
queryType: z11.enum(["Latest", "Top", "Default"]).optional(),
|
|
1258
|
+
cursor: z11.string().optional(),
|
|
1259
|
+
sinceTime: z11.string().optional(),
|
|
1260
|
+
untilTime: z11.string().optional(),
|
|
1261
|
+
includeReplies: z11.boolean().optional()
|
|
1262
|
+
}
|
|
1263
|
+
},
|
|
1264
|
+
async (args) => {
|
|
1265
|
+
try {
|
|
1266
|
+
const llm = getClient();
|
|
1267
|
+
const a = args.action;
|
|
1268
|
+
const require2 = (value, name) => {
|
|
1269
|
+
if (value === void 0 || value === null || value === "") {
|
|
1270
|
+
throw new Error(`${name} is required for action='${a}'`);
|
|
1271
|
+
}
|
|
1272
|
+
return value;
|
|
1273
|
+
};
|
|
1274
|
+
let result;
|
|
1275
|
+
switch (a) {
|
|
1276
|
+
case "user_lookup":
|
|
1277
|
+
result = await llm.xUserLookup(require2(args.usernames, "usernames"));
|
|
1278
|
+
break;
|
|
1279
|
+
case "user_info":
|
|
1280
|
+
result = await llm.xUserInfo(require2(args.username, "username"));
|
|
1281
|
+
break;
|
|
1282
|
+
case "followers":
|
|
1283
|
+
result = await llm.xFollowers(require2(args.username, "username"), args.cursor);
|
|
1284
|
+
break;
|
|
1285
|
+
case "followings":
|
|
1286
|
+
result = await llm.xFollowings(require2(args.username, "username"), args.cursor);
|
|
1287
|
+
break;
|
|
1288
|
+
case "verified_followers":
|
|
1289
|
+
result = await llm.xVerifiedFollowers(require2(args.user_id, "user_id"), args.cursor);
|
|
1290
|
+
break;
|
|
1291
|
+
case "user_tweets":
|
|
1292
|
+
result = await llm.xUserTweets(
|
|
1293
|
+
require2(args.username, "username"),
|
|
1294
|
+
args.includeReplies,
|
|
1295
|
+
args.cursor
|
|
1296
|
+
);
|
|
1297
|
+
break;
|
|
1298
|
+
case "user_mentions":
|
|
1299
|
+
result = await llm.xUserMentions(
|
|
1300
|
+
require2(args.username, "username"),
|
|
1301
|
+
args.sinceTime,
|
|
1302
|
+
args.untilTime,
|
|
1303
|
+
args.cursor
|
|
1304
|
+
);
|
|
1305
|
+
break;
|
|
1306
|
+
case "tweet_lookup":
|
|
1307
|
+
result = await llm.xTweetLookup(require2(args.tweet_ids, "tweet_ids"));
|
|
1308
|
+
break;
|
|
1309
|
+
case "tweet_replies":
|
|
1310
|
+
result = await llm.xTweetReplies(
|
|
1311
|
+
require2(args.tweet_id, "tweet_id"),
|
|
1312
|
+
args.queryType,
|
|
1313
|
+
args.cursor
|
|
1314
|
+
);
|
|
1315
|
+
break;
|
|
1316
|
+
case "tweet_thread":
|
|
1317
|
+
result = await llm.xTweetThread(require2(args.tweet_id, "tweet_id"), args.cursor);
|
|
1318
|
+
break;
|
|
1319
|
+
case "search":
|
|
1320
|
+
result = await llm.xSearch(require2(args.query, "query"), args.queryType, args.cursor);
|
|
1321
|
+
break;
|
|
1322
|
+
}
|
|
1323
|
+
return {
|
|
1324
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
1325
|
+
structuredContent: result
|
|
1326
|
+
};
|
|
1327
|
+
} catch (err) {
|
|
1328
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1329
|
+
return {
|
|
1330
|
+
content: [{ type: "text", text: formatError(msg) }],
|
|
1331
|
+
isError: true
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// src/tools/dex.ts
|
|
1339
|
+
import { z as z12 } from "zod";
|
|
1104
1340
|
function registerDexTool(server) {
|
|
1105
1341
|
server.registerTool(
|
|
1106
1342
|
"blockrun_dex",
|
|
@@ -1117,10 +1353,10 @@ Examples:
|
|
|
1117
1353
|
blockrun_dex({ token: "So11...xxx" }) -> Get specific token data
|
|
1118
1354
|
blockrun_dex({ symbol: "PEPE" }) -> Search by symbol`,
|
|
1119
1355
|
inputSchema: {
|
|
1120
|
-
query:
|
|
1121
|
-
token:
|
|
1122
|
-
symbol:
|
|
1123
|
-
chain:
|
|
1356
|
+
query: z12.string().optional().describe("Search query (token name, symbol, or address)"),
|
|
1357
|
+
token: z12.string().optional().describe("Token address for direct lookup"),
|
|
1358
|
+
symbol: z12.string().optional().describe("Token symbol to search"),
|
|
1359
|
+
chain: z12.string().optional().describe("Filter by chain (ethereum, solana, base, etc.)")
|
|
1124
1360
|
}
|
|
1125
1361
|
},
|
|
1126
1362
|
async ({ query, token, symbol, chain }) => {
|
|
@@ -1181,7 +1417,7 @@ ${lines.join("\n\n")}` }],
|
|
|
1181
1417
|
}
|
|
1182
1418
|
|
|
1183
1419
|
// src/tools/modal.ts
|
|
1184
|
-
import { z as
|
|
1420
|
+
import { z as z13 } from "zod";
|
|
1185
1421
|
var MODAL_GPU_TYPES = ["T4", "L4", "A10G", "A100", "A100-80GB", "H100"];
|
|
1186
1422
|
function registerModalTool(server) {
|
|
1187
1423
|
server.registerTool(
|
|
@@ -1201,17 +1437,17 @@ Pricing:
|
|
|
1201
1437
|
- create: $0.01
|
|
1202
1438
|
- exec/status/terminate: $0.001 each`,
|
|
1203
1439
|
inputSchema: {
|
|
1204
|
-
action:
|
|
1440
|
+
action: z13.enum(["create", "exec", "status", "terminate"]).describe(
|
|
1205
1441
|
"Sandbox action to perform"
|
|
1206
1442
|
),
|
|
1207
|
-
sandbox_id:
|
|
1208
|
-
command:
|
|
1209
|
-
image:
|
|
1210
|
-
timeout:
|
|
1211
|
-
cpu:
|
|
1212
|
-
memory:
|
|
1213
|
-
gpu:
|
|
1214
|
-
setup_commands:
|
|
1443
|
+
sandbox_id: z13.string().optional().describe("Sandbox ID returned by a previous create"),
|
|
1444
|
+
command: z13.array(z13.string()).optional().describe('Command array for exec, for example ["python", "-c", "print(2+2)"]'),
|
|
1445
|
+
image: z13.string().optional().describe("Container image for create (default: python:3.11)"),
|
|
1446
|
+
timeout: z13.number().optional().describe("Timeout in seconds for create or exec"),
|
|
1447
|
+
cpu: z13.number().optional().describe("CPU cores for create"),
|
|
1448
|
+
memory: z13.number().optional().describe("Memory in MB for create"),
|
|
1449
|
+
gpu: z13.enum(MODAL_GPU_TYPES).optional().describe("Optional GPU type for create"),
|
|
1450
|
+
setup_commands: z13.array(z13.string()).optional().describe("Shell commands to run during sandbox setup")
|
|
1215
1451
|
}
|
|
1216
1452
|
},
|
|
1217
1453
|
async ({ action, sandbox_id, command, image, timeout, cpu, memory, gpu, setup_commands }) => {
|
|
@@ -1280,6 +1516,8 @@ function initializeMcpServer(server) {
|
|
|
1280
1516
|
registerSearchTool(server);
|
|
1281
1517
|
registerExaTool(server);
|
|
1282
1518
|
registerMarketsTool(server);
|
|
1519
|
+
registerPriceTool(server);
|
|
1520
|
+
registerTwitterTool(server);
|
|
1283
1521
|
registerDexTool(server);
|
|
1284
1522
|
registerModalTool(server);
|
|
1285
1523
|
server.registerResource(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
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",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"url": "https://github.com/blockrunai/blockrun-mcp/issues"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@blockrun/llm": "^1.
|
|
47
|
+
"@blockrun/llm": "^1.8.0",
|
|
48
48
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49
49
|
"open": "^11.0.0",
|
|
50
50
|
"qrcode": "^1.5.4",
|