@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.
Files changed (2) hide show
  1. package/dist/index.js +257 -19
  2. 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.6", "anthropic/claude-opus-4.5", "openai/o3", "openai/gpt-5.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/dex.ts
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: z10.string().optional().describe("Search query (token name, symbol, or address)"),
1121
- token: z10.string().optional().describe("Token address for direct lookup"),
1122
- symbol: z10.string().optional().describe("Token symbol to search"),
1123
- chain: z10.string().optional().describe("Filter by chain (ethereum, solana, base, etc.)")
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 z11 } from "zod";
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: z11.enum(["create", "exec", "status", "terminate"]).describe(
1440
+ action: z13.enum(["create", "exec", "status", "terminate"]).describe(
1205
1441
  "Sandbox action to perform"
1206
1442
  ),
1207
- sandbox_id: z11.string().optional().describe("Sandbox ID returned by a previous create"),
1208
- command: z11.array(z11.string()).optional().describe('Command array for exec, for example ["python", "-c", "print(2+2)"]'),
1209
- image: z11.string().optional().describe("Container image for create (default: python:3.11)"),
1210
- timeout: z11.number().optional().describe("Timeout in seconds for create or exec"),
1211
- cpu: z11.number().optional().describe("CPU cores for create"),
1212
- memory: z11.number().optional().describe("Memory in MB for create"),
1213
- gpu: z11.enum(MODAL_GPU_TYPES).optional().describe("Optional GPU type for create"),
1214
- setup_commands: z11.array(z11.string()).optional().describe("Shell commands to run during sandbox setup")
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.8.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.5.0",
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",