@blockrun/mcp 0.21.5 → 0.22.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 (3) hide show
  1. package/README.md +56 -4
  2. package/dist/index.js +130 -51
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -14,6 +14,15 @@ Wallet auto-created. Fund with $5 USDC. Ask Claude anything.
14
14
 
15
15
  ---
16
16
 
17
+ ## Documentation
18
+
19
+ Full docs: **https://blockrun.ai/docs**
20
+
21
+ - MCP tools & setup: https://blockrun.ai/docs/mcp/blockrun-mcp
22
+ - All BlockRun SDKs & APIs: https://blockrun.ai/docs
23
+
24
+ ---
25
+
17
26
  ## What changes
18
27
 
19
28
  Before BlockRun, Claude can't answer:
@@ -84,6 +93,25 @@ claude mcp add blockrun -s user -- npx -y @blockrun/mcp@latest
84
93
  The `-s user` flag installs globally (available in every project). The `--` separator
85
94
  ensures `-y` is passed to `npx`, not parsed by `claude mcp add`.
86
95
 
96
+ **Tool profiles** — expose a trimmed tool set so the client loads fewer schemas into
97
+ context. Pass `--profile <name>` (or set `BLOCKRUN_MCP_PROFILE`); omit it for the full set.
98
+
99
+ | Profile | Tools |
100
+ |---------|-------|
101
+ | `full` *(default)* | everything |
102
+ | `media` | `wallet` `models` `image` `video` `realface` `music` `speech` |
103
+ | `trading` | `wallet` `price` `dex` `markets` `surf` `defi` `rpc` |
104
+ | `research` | `wallet` `models` `chat` `search` `exa` `surf` |
105
+ | `chat` | `wallet` `models` `chat` |
106
+
107
+ ```bash
108
+ # e.g. a media-only install
109
+ claude mcp add blockrun-media -s user -- npx -y @blockrun/mcp@latest --profile media
110
+ # or a trading-only install
111
+ claude mcp add blockrun-trading -s user -- npx -y @blockrun/mcp@latest --profile trading
112
+ ```
113
+ Equivalent via env: `BLOCKRUN_MCP_PROFILE=trading`. An unknown profile name falls back to `full`. `modal` and `phone` are available in the `full` profile only.
114
+
87
115
  **Claude Desktop** — add to `claude_desktop_config.json`:
88
116
  ```json
89
117
  {
@@ -117,7 +145,7 @@ ensures `-y` is passed to `npx`, not parsed by `claude mcp add`.
117
145
 
118
146
  ## Fund your wallet
119
147
 
120
- Run `blockrun_wallet` to see your address. Send USDC on Base.
148
+ Run `blockrun_wallet` to see your address. The server pays on **Base** by default. Send USDC on Base:
121
149
 
122
150
  | Method | Steps |
123
151
  |--------|-------|
@@ -126,6 +154,24 @@ Run `blockrun_wallet` to see your address. Send USDC on Base.
126
154
 
127
155
  $5 covers ~5,000 market queries, ~500 Exa searches, ~250 image generations, or ~10 Seedance 1.5-pro clips (5s @ 720p+audio, ~$0.46 each).
128
156
 
157
+ ### Pay on Solana
158
+
159
+ Prefer to pay in USDC on Solana? It's two tool calls — no env vars, no file editing, no restart:
160
+
161
+ ```
162
+ blockrun_wallet action:"chain" chain:"solana" # provisions + activates the Solana wallet
163
+ blockrun_wallet action:"setup" # shows the Solana address + funding QR
164
+ ```
165
+
166
+ Then send USDC (SPL) on the **Solana** network — from Coinbase (pick "Solana"), Phantom, Solflare, or Backpack. Switch back anytime with `blockrun_wallet action:"chain" chain:"base"`. The server keeps both wallets; switching just changes which one pays.
167
+
168
+ **Base-only — these fall back to Base regardless of active chain:**
169
+
170
+ - 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.
171
+ - `blockrun_chat routing:"smart"` (ClawRouter) and native Anthropic (`claude-*`) passthrough — on Solana, pass `model:` or `mode:` explicitly.
172
+
173
+ > 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.
174
+
129
175
  ---
130
176
 
131
177
  ## Tools
@@ -261,10 +307,16 @@ Chain selection priority (see `src/utils/wallet.ts`):
261
307
 
262
308
  **Switching chains:**
263
309
 
264
- - Base Solana: `echo solana > ~/.blockrun/.chain`, then set `SOLANA_WALLET_KEY` or create `~/.blockrun/.solana-session`
265
- - Solana → Base: `echo base > ~/.blockrun/.chain` (the existing `.session` is reused, so it's the same Base wallet)
310
+ The recommended way is the tool itself it provisions both wallets, applies instantly (no restart), and shows the funding QR:
311
+
312
+ ```
313
+ blockrun_wallet action:"chain" chain:"solana" # or chain:"base"
314
+ blockrun_wallet action:"setup" # funding instructions for the active chain
315
+ ```
316
+
317
+ *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.
266
318
 
267
- 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. In Solana mode they fail before creating or charging a Base wallet.
319
+ 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.
268
320
 
269
321
  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.
270
322
 
package/dist/index.js CHANGED
@@ -388,6 +388,14 @@ Call this to set spending limits before spawning child agents.
388
388
 
389
389
  The server holds TWO wallets \u2014 one on Base, one on Solana \u2014 but pays on ONE
390
390
  active chain at a time. status shows both addresses/balances and which is active.
391
+ Default chain is Base.
392
+
393
+ To pay on Solana (no env vars, no file editing, no restart):
394
+ 1. action:"chain" chain:"solana" \u2192 provisions + activates the Solana wallet
395
+ 2. action:"setup" \u2192 Solana address + funding QR (send USDC SPL on Solana)
396
+ Switch back with action:"chain" chain:"base". Base-only \u2014 these ignore Solana and
397
+ need Base: blockrun_image, blockrun_music, blockrun_speech, blockrun_video, paid
398
+ blockrun_price, blockrun_chat routing:"smart", and native Anthropic (claude-*).
391
399
 
392
400
  Actions:
393
401
  - status (default): Both wallet addresses + USDC balances, active chain, session spending
@@ -3022,58 +3030,127 @@ Use blockrun_price (free) for plain spot quotes, blockrun_dex (free) for DEX pai
3022
3030
  );
3023
3031
  }
3024
3032
 
3033
+ // src/profiles.ts
3034
+ var ALL_TOOLS = [
3035
+ "wallet",
3036
+ "chat",
3037
+ "models",
3038
+ "image",
3039
+ "music",
3040
+ "speech",
3041
+ "video",
3042
+ "realface",
3043
+ "search",
3044
+ "exa",
3045
+ "markets",
3046
+ "price",
3047
+ "dex",
3048
+ "modal",
3049
+ "phone",
3050
+ "surf",
3051
+ "rpc",
3052
+ "defi"
3053
+ ];
3054
+ var PROFILES = {
3055
+ full: "all",
3056
+ // Generative media: image/video/realface plus the other media-generation
3057
+ // tools (music, speech), with wallet (funding/balance — media calls cost
3058
+ // USDC) and models (discover what's available).
3059
+ media: ["wallet", "models", "image", "video", "realface", "music", "speech"],
3060
+ // Markets & on-chain data: prediction markets, realtime prices, DEX/CEX
3061
+ // data, DeFi metrics, and raw RPC, plus the wallet for balance/funding.
3062
+ trading: ["wallet", "price", "dex", "markets", "surf", "defi", "rpc"],
3063
+ // Web research & analysis: live search, neural search, Surf's news/SQL,
3064
+ // and chat for synthesis, plus wallet and the model catalogue.
3065
+ research: ["wallet", "models", "chat", "search", "exa", "surf"],
3066
+ // Minimal LLM gateway: just chat + model discovery + wallet.
3067
+ chat: ["wallet", "models", "chat"]
3068
+ };
3069
+ var DEFAULT_PROFILE = "full";
3070
+ function resolveProfileName(argv = process.argv.slice(2), env = process.env) {
3071
+ for (let i = 0; i < argv.length; i++) {
3072
+ const arg = argv[i];
3073
+ if (arg === "--profile") return (argv[i + 1] ?? DEFAULT_PROFILE).toLowerCase();
3074
+ if (arg.startsWith("--profile=")) return arg.slice("--profile=".length).toLowerCase();
3075
+ }
3076
+ if (env.BLOCKRUN_MCP_PROFILE) return env.BLOCKRUN_MCP_PROFILE.toLowerCase();
3077
+ return DEFAULT_PROFILE;
3078
+ }
3079
+ function resolveTools(argv, env) {
3080
+ const requested = resolveProfileName(argv, env);
3081
+ const spec = PROFILES[requested];
3082
+ if (!spec) {
3083
+ return { profile: DEFAULT_PROFILE, tools: new Set(ALL_TOOLS) };
3084
+ }
3085
+ return {
3086
+ profile: requested,
3087
+ tools: new Set(spec === "all" ? ALL_TOOLS : spec)
3088
+ };
3089
+ }
3090
+
3025
3091
  // src/mcp-handler.ts
3026
- function initializeMcpServer(server) {
3092
+ function initializeMcpServer(server, profileArgs) {
3027
3093
  const budget = { limit: null, spent: 0, calls: 0, agents: /* @__PURE__ */ new Map() };
3028
3094
  const modelCache = { models: null };
3029
- registerWalletTool(server, budget);
3030
- registerChatTool(server, budget);
3031
- registerModelsTool(server, modelCache);
3032
- registerImageTool(server, budget);
3033
- registerMusicTool(server, budget);
3034
- registerSpeechTool(server, budget);
3035
- registerVideoTool(server, budget);
3036
- registerRealfaceTool(server, budget);
3037
- registerSearchTool(server, budget);
3038
- registerExaTool(server, budget);
3039
- registerMarketsTool(server, budget);
3040
- registerPriceTool(server, budget);
3041
- registerDexTool(server);
3042
- registerModalTool(server, budget);
3043
- registerPhoneTool(server, budget);
3044
- registerSurfTool(server, budget);
3045
- registerRpcTool(server, budget);
3046
- registerDefiTool(server, budget);
3047
- server.registerResource(
3048
- "wallet",
3049
- "blockrun://wallet",
3050
- { description: "Wallet address and status", mimeType: "application/json" },
3051
- async () => {
3052
- const info = await getWalletInfo();
3053
- return {
3054
- contents: [{
3055
- uri: "blockrun://wallet",
3056
- mimeType: "application/json",
3057
- text: JSON.stringify(info, null, 2)
3058
- }]
3059
- };
3060
- }
3061
- );
3062
- server.registerResource(
3063
- "models",
3064
- "blockrun://models",
3065
- { description: "Available AI models with pricing", mimeType: "application/json" },
3066
- async () => {
3067
- const models = await loadModels(getClient(), modelCache);
3068
- return {
3069
- contents: [{
3070
- uri: "blockrun://models",
3071
- mimeType: "application/json",
3072
- text: JSON.stringify(models, null, 2)
3073
- }]
3074
- };
3075
- }
3076
- );
3095
+ const { profile, tools } = resolveTools(profileArgs?.argv, profileArgs?.env);
3096
+ const registrars = {
3097
+ wallet: () => registerWalletTool(server, budget),
3098
+ chat: () => registerChatTool(server, budget),
3099
+ models: () => registerModelsTool(server, modelCache),
3100
+ image: () => registerImageTool(server, budget),
3101
+ music: () => registerMusicTool(server, budget),
3102
+ speech: () => registerSpeechTool(server, budget),
3103
+ video: () => registerVideoTool(server, budget),
3104
+ realface: () => registerRealfaceTool(server, budget),
3105
+ search: () => registerSearchTool(server, budget),
3106
+ exa: () => registerExaTool(server, budget),
3107
+ markets: () => registerMarketsTool(server, budget),
3108
+ price: () => registerPriceTool(server, budget),
3109
+ dex: () => registerDexTool(server),
3110
+ modal: () => registerModalTool(server, budget),
3111
+ phone: () => registerPhoneTool(server, budget),
3112
+ surf: () => registerSurfTool(server, budget),
3113
+ rpc: () => registerRpcTool(server, budget),
3114
+ defi: () => registerDefiTool(server, budget)
3115
+ };
3116
+ for (const [name, register] of Object.entries(registrars)) {
3117
+ if (tools.has(name)) register();
3118
+ }
3119
+ if (tools.has("wallet")) {
3120
+ server.registerResource(
3121
+ "wallet",
3122
+ "blockrun://wallet",
3123
+ { description: "Wallet address and status", mimeType: "application/json" },
3124
+ async () => {
3125
+ const info = await getWalletInfo();
3126
+ return {
3127
+ contents: [{
3128
+ uri: "blockrun://wallet",
3129
+ mimeType: "application/json",
3130
+ text: JSON.stringify(info, null, 2)
3131
+ }]
3132
+ };
3133
+ }
3134
+ );
3135
+ }
3136
+ if (tools.has("models")) {
3137
+ server.registerResource(
3138
+ "models",
3139
+ "blockrun://models",
3140
+ { description: "Available AI models with pricing", mimeType: "application/json" },
3141
+ async () => {
3142
+ const models = await loadModels(getClient(), modelCache);
3143
+ return {
3144
+ contents: [{
3145
+ uri: "blockrun://models",
3146
+ mimeType: "application/json",
3147
+ text: JSON.stringify(models, null, 2)
3148
+ }]
3149
+ };
3150
+ }
3151
+ );
3152
+ }
3153
+ return { profile, tools: [...tools] };
3077
3154
  }
3078
3155
 
3079
3156
  // src/utils/key-leak-scanner.ts
@@ -3173,6 +3250,7 @@ function printHelp() {
3173
3250
  "Options:",
3174
3251
  " -h, --help Show this help message",
3175
3252
  " -v, --version Print the package version",
3253
+ ` --profile <name> Tool profile to expose: ${Object.keys(PROFILES).join(" | ")} (default: full)`,
3176
3254
  "",
3177
3255
  "When no metadata flag is provided, the server starts on stdio for MCP clients.",
3178
3256
  ""
@@ -3211,10 +3289,11 @@ async function main() {
3211
3289
  name: "blockrun-mcp",
3212
3290
  version: VERSION
3213
3291
  });
3214
- initializeMcpServer(server);
3292
+ const { profile, tools } = initializeMcpServer(server);
3215
3293
  const transport = new StdioServerTransport();
3216
3294
  await server.connect(transport);
3217
- console.error(`BlockRun MCP Server started (v${VERSION}) \u2014 stdio transport`);
3295
+ const profileNote = profile === "full" ? `${tools.length} tools` : `profile "${profile}" \u2014 ${tools.length} tools: ${tools.join(", ")}`;
3296
+ console.error(`BlockRun MCP Server started (v${VERSION}) \u2014 stdio transport \u2014 ${profileNote}`);
3218
3297
  checkForUpdate();
3219
3298
  }
3220
3299
  main().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/mcp",
3
- "version": "0.21.5",
3
+ "version": "0.22.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",
@@ -18,6 +18,7 @@
18
18
  "dev": "tsx watch src/index.ts",
19
19
  "start": "node dist/index.js",
20
20
  "typecheck": "tsc --noEmit",
21
+ "test": "tsx --test test/*.test.ts",
21
22
  "prepublishOnly": "npm run build"
22
23
  },
23
24
  "keywords": [