@blockrun/mcp 0.24.1 → 0.24.2

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 (3) hide show
  1. package/README.md +4 -4
  2. package/dist/index.js +24 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -77,7 +77,7 @@ Prompts and a worked example for these are in [`skills/image-prompting/SKILL.md`
77
77
 
78
78
  ## Prerequisites
79
79
 
80
- - **Node.js ≥ 18** (`node -v`)
80
+ - **Node.js ≥ 20.19** (`node -v`)
81
81
  - **~$5 USDC** on Base or Solana (the server auto-creates a wallet on first run; see [Fund your wallet](#fund-your-wallet))
82
82
  - **An MCP client**: Claude Code, Claude Desktop, Cursor, Windsurf, or ChatGPT Desktop
83
83
 
@@ -175,7 +175,7 @@ Then send USDC (SPL) on the **Solana** network — from Coinbase (pick "Solana")
175
175
 
176
176
  **Base-only — these fall back to Base regardless of active chain:**
177
177
 
178
- - Tools: `blockrun_image`, `blockrun_music`, `blockrun_speech`, `blockrun_video`, paid stock `blockrun_price`. In Solana mode they return a "switch to Base" message instead of charging.
178
+ - Tools: `blockrun_image`, `blockrun_music`, `blockrun_speech`, `blockrun_video`, paid `blockrun_realface` (enroll/portrait), paid stock `blockrun_price`. In Solana mode they return a "switch to Base" message instead of charging.
179
179
  - `blockrun_chat routing:"smart"` (ClawRouter) and native Anthropic (`claude-*`) passthrough — on Solana, pass `model:` or `mode:` explicitly.
180
180
 
181
181
  > Advanced: chain selection can also be forced before startup via files/env (`~/.blockrun/.chain`, `SOLANA_WALLET_KEY`) — see [Environment Variables](#environment-variables). The `action:"chain"` command above is the recommended path.
@@ -196,7 +196,7 @@ Then send USDC (SPL) on the **Solana** network — from Coinbase (pick "Solana")
196
196
  | `blockrun_markets` | Polymarket (markets, candles, trades, orderbooks, leaderboards, smart-wallet PnL/clusters, UMA oracle), Kalshi, Limitless, Opinion, Predict.Fun, dFlow, Binance Futures, cross-platform match + search | $0.001–0.005/query |
197
197
  | `blockrun_surf` | Surf (asksurf.ai) — 84 endpoints: CEX market data, on-chain SQL (13 chains, 80+ ClickHouse tables), 100M+ labeled wallets, Polymarket + Kalshi side-by-side, social mindshare, news, search, Surf-1.5 chat with citations | $0.001–0.02/call |
198
198
  | `blockrun_exa` | Neural web search (Exa) — research, competitors, papers, URL content | $0.01/query |
199
- | `blockrun_search` | Grok Live Search — web + news with citations | $0.025 × max_results (default 10) |
199
+ | `blockrun_search` | Grok Live Search — web + X/Twitter + news with citations | $0.025 × max_results (default 10) |
200
200
  | `blockrun_dex` | Live DEX prices via DexScreener | free |
201
201
  | `blockrun_rpc` | Raw JSON-RPC on 40+ chains (Ethereum, Base, Solana, Bitcoin, Sui, NEAR, ...) via Tatum gateway — eth_call, balances, blocks, logs | $0.002/call |
202
202
  | `blockrun_defi` | DefiLlama — protocol TVL, chain TVL, yield pools (APY), token prices | $0.001–0.005/call |
@@ -330,7 +330,7 @@ blockrun_wallet action:"setup" # funding instructions for the a
330
330
 
331
331
  *Advanced (force a chain before startup, e.g. in CI):* `echo solana > ~/.blockrun/.chain` then set `SOLANA_WALLET_KEY` or create `~/.blockrun/.solana-session`; `echo base > ~/.blockrun/.chain` reuses the existing `.session` (same Base wallet). These edit the same preference file that `action:"chain"` writes — prefer the tool unless you need pre-startup control.
332
332
 
333
- Some media and paid market-data tools still settle on Base only: `blockrun_image`, `blockrun_music`, `blockrun_speech`, `blockrun_video`, and paid stock `blockrun_price` calls — plus `blockrun_chat routing:"smart"` and native Anthropic (`claude-*`) passthrough. In Solana mode these return a "switch to Base" message instead of charging.
333
+ Some media and paid market-data tools still settle on Base only: `blockrun_image`, `blockrun_music`, `blockrun_speech`, `blockrun_video`, paid `blockrun_realface` (enroll/portrait), and paid stock `blockrun_price` calls — plus `blockrun_chat routing:"smart"` and native Anthropic (`claude-*`) passthrough. In Solana mode these return a "switch to Base" message instead of charging.
334
334
 
335
335
  The server also runs a non-blocking npm registry check at startup and prints an `Update available` notice to stderr when a newer `@blockrun/mcp` version exists. Upgrade by re-running the install command — no manual `npm update` needed.
336
336
 
package/dist/index.js CHANGED
@@ -20,7 +20,8 @@ import {
20
20
  loadSolanaWallet,
21
21
  getPaymentLinks,
22
22
  formatWalletCreatedMessage,
23
- formatNeedsFundingMessage
23
+ formatNeedsFundingMessage,
24
+ SOLANA_WALLET_FILE_PATH
24
25
  } from "@blockrun/llm";
25
26
 
26
27
  // src/utils/constants.ts
@@ -79,7 +80,9 @@ function getChain() {
79
80
  if (preferred) return preferred;
80
81
  if (process.env.SOLANA_WALLET_KEY) return "solana";
81
82
  try {
82
- if (loadSolanaWallet()) return "solana";
83
+ if (fs.existsSync(SOLANA_WALLET_FILE_PATH) && fs.readFileSync(SOLANA_WALLET_FILE_PATH, "utf-8").trim()) {
84
+ return "solana";
85
+ }
83
86
  } catch {
84
87
  }
85
88
  return "base";
@@ -804,11 +807,14 @@ function isAnthropicModel(model) {
804
807
  return /^anthropic\//i.test(id) || /^claude-/i.test(id);
805
808
  }
806
809
  function parseDataUri(url) {
807
- const match = /^data:(image\/(?:jpeg|png|gif|webp));base64,(.+)$/i.exec(url.trim());
810
+ const match = /^data:image\/([a-z0-9.+-]+)(?:;[^;,]+)*;base64,(.+)$/i.exec(url.trim());
808
811
  if (!match) return null;
812
+ let subtype = match[1].toLowerCase();
813
+ if (subtype === "jpg") subtype = "jpeg";
814
+ if (!["jpeg", "png", "gif", "webp"].includes(subtype)) return null;
809
815
  return {
810
816
  type: "base64",
811
- media_type: match[1].toLowerCase(),
817
+ media_type: `image/${subtype}`,
812
818
  data: match[2]
813
819
  };
814
820
  }
@@ -821,9 +827,13 @@ function toAnthropicContent(content) {
821
827
  } else if (part.type === "image_url") {
822
828
  const url = part.image_url?.url;
823
829
  if (!url) continue;
824
- const base64 = parseDataUri(url);
825
- const source = base64 ? base64 : { type: "url", url };
826
- blocks.push({ type: "image", source });
830
+ if (/^data:/i.test(url)) {
831
+ const base64 = parseDataUri(url);
832
+ if (!base64) continue;
833
+ blocks.push({ type: "image", source: base64 });
834
+ } else {
835
+ blocks.push({ type: "image", source: { type: "url", url } });
836
+ }
827
837
  }
828
838
  }
829
839
  return blocks;
@@ -859,7 +869,9 @@ async function handleAnthropicNative(args) {
859
869
  if (text) systemParts.push(text);
860
870
  continue;
861
871
  }
862
- apiMessages.push({ role: m.role, content: toAnthropicContent(m.content) });
872
+ const content2 = toAnthropicContent(m.content);
873
+ if (Array.isArray(content2) && content2.length === 0) continue;
874
+ apiMessages.push({ role: m.role, content: content2 });
863
875
  }
864
876
  if (responseFormat?.type === "json_object") {
865
877
  systemParts.push("Respond with only valid JSON. Do not wrap it in markdown code fences or add any prose before or after.");
@@ -930,10 +942,10 @@ ${thinkingText}` });
930
942
  }
931
943
 
932
944
  // src/tools/chat.ts
933
- function estimateChatCost(maxTokens, mode, model, routing, routingProfile) {
945
+ function estimateChatCost(maxTokens, mode, model, routing, routingProfile, thinkingBudget) {
934
946
  if (mode === "free") return 0;
935
947
  if (model?.startsWith("nvidia/")) return 0;
936
- const out = Math.max(maxTokens ?? 1024, 256);
948
+ const out = Math.max((maxTokens ?? 1024) + (thinkingBudget ?? 0), 256);
937
949
  const frontierReserve = Math.max(0.01, out / 1e6 * 20);
938
950
  if (routing === "smart") {
939
951
  switch (routingProfile) {
@@ -986,7 +998,7 @@ Run blockrun_models to see all available models with pricing.`,
986
998
  stop: z2.array(z2.string()).max(4).optional().describe("Up to 4 stop sequences; generation halts when any is produced"),
987
999
  thinking: z2.object({
988
1000
  type: z2.literal("enabled"),
989
- budget_tokens: z2.number().min(1).describe("Tokens Claude may spend reasoning before answering. max_tokens is auto-raised above this if needed.")
1001
+ budget_tokens: z2.number().int().min(1).max(1e5).describe("Tokens Claude may spend reasoning before answering (1\u2013100000). max_tokens is auto-raised above this if needed; counts toward the budget reserve.")
990
1002
  }).optional().describe("Anthropic extended thinking. Only honored for anthropic/claude-* models \u2014 these go direct to the native /v1/messages endpoint and the response includes verbatim type:'thinking' blocks with their original signature. Ignored for non-Claude models (no native thinking channel)."),
991
1003
  agent_id: z2.string().optional().describe("Agent identifier. If a budget was delegated for this agent_id via blockrun_wallet action:'delegate', spending is tracked and enforced. The agent is hard-stopped when its budget is exhausted."),
992
1004
  messages: z2.array(z2.object({
@@ -1004,7 +1016,7 @@ Run blockrun_models to see all available models with pricing.`,
1004
1016
  async ({ message, model, mode, routing, routing_profile, system, max_tokens, temperature, response_format, stop, thinking, agent_id, messages }) => {
1005
1017
  const llm = buildClient();
1006
1018
  const responseFormat = response_format ? { type: response_format } : void 0;
1007
- const estimatedCost = estimateChatCost(max_tokens, mode, model, routing, routing_profile);
1019
+ const estimatedCost = estimateChatCost(max_tokens, mode, model, routing, routing_profile, thinking?.budget_tokens);
1008
1020
  const gate = reserveBudget(budget, agent_id, estimatedCost);
1009
1021
  if (!gate.allowed) {
1010
1022
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/mcp",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
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",