@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.
- package/README.md +4 -4
- package/dist/index.js +24 -12
- 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 ≥
|
|
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 (
|
|
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:
|
|
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:
|
|
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
|
-
|
|
825
|
-
|
|
826
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|