@blockrun/mcp 0.20.0 → 0.21.1
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 +2 -1
- package/dist/index.js +182 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -135,7 +135,7 @@ $5 covers ~5,000 market queries, ~500 Exa searches, ~250 image generations, or ~
|
|
|
135
135
|
| `blockrun_chat` | 66+ LLMs (GPT, Claude, Gemini, DeepSeek, Kimi K2.6, GLM, NVIDIA free tier, ...) with `mode` tier routing | per token |
|
|
136
136
|
| `blockrun_image` | GPT Image 1/2, Nano Banana / Pro (up to 4K), Grok Imagine, CogView-4 — generation + img2img editing | $0.015–0.15 |
|
|
137
137
|
| `blockrun_video` | Sora 2 + xAI Grok Imagine Video + ByteDance Seedance 1.5/2.0/2.0-fast (720p + audio defaults); RealFace asset → real-person video | $0.05–0.30/sec |
|
|
138
|
-
| `blockrun_realface` | Enroll a real person (phone liveness
|
|
138
|
+
| `blockrun_realface` | Enroll a real person (phone liveness) or an AI character (Virtual Portrait, no liveness) as a `ta_xxxx` asset for Seedance 2.0 video | free; $0.01 to enroll |
|
|
139
139
|
| `blockrun_music` | MiniMax music generation | per track |
|
|
140
140
|
| `blockrun_speech` | ElevenLabs text-to-speech (Flash/Turbo/Multilingual/v3, 8 voice aliases) + cinematic sound effects; free voice listing | $0.05–0.10/1k chars; $0.0525/effect |
|
|
141
141
|
| `blockrun_price` | Pyth-backed realtime + OHLC — crypto / FX / commodity (free), 12 stock markets (paid) | free or $0.001/call |
|
|
@@ -145,6 +145,7 @@ $5 covers ~5,000 market queries, ~500 Exa searches, ~250 image generations, or ~
|
|
|
145
145
|
| `blockrun_search` | Grok Live Search — web + news with citations | $0.025 × max_results (default 10) |
|
|
146
146
|
| `blockrun_dex` | Live DEX prices via DexScreener | free |
|
|
147
147
|
| `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 |
|
|
148
|
+
| `blockrun_defi` | DefiLlama — protocol TVL, chain TVL, yield pools (APY), token prices | $0.001–0.005/call |
|
|
148
149
|
| `blockrun_modal` | Isolated code execution in a BlockRun-hosted Modal sandbox — disposable container, optional GPU (T4 → H100) | $0.01 create; $0.001/op |
|
|
149
150
|
| `blockrun_phone` | Outbound AI voice calls (Bland) + wallet-owned US/CA numbers (Twilio), carrier + fraud lookups | $0.54/call; $5/number |
|
|
150
151
|
| `blockrun_models` | Live catalogue of every LLM/image/video/music model + pricing | free |
|
package/dist/index.js
CHANGED
|
@@ -231,11 +231,14 @@ var MODEL_TIERS = {
|
|
|
231
231
|
fast: ["google/gemini-3.5-flash", "google/gemini-2.5-flash", "google/gemini-3.1-flash-lite", "openai/gpt-5-mini", "deepseek/deepseek-chat", "google/gemini-3-flash-preview"],
|
|
232
232
|
balanced: ["openai/gpt-5.5", "anthropic/claude-sonnet-4.6", "google/gemini-3.1-pro", "moonshot/kimi-k2.6", "openai/gpt-5.3", "openai/gpt-5.4"],
|
|
233
233
|
powerful: ["anthropic/claude-opus-4.8", "openai/gpt-5.4-pro", "anthropic/claude-opus-4.7", "anthropic/claude-opus-4.6", "openai/o3", "openai/gpt-5.4"],
|
|
234
|
-
cheap: ["zai/glm-5", "zai/glm-5-turbo", "nvidia/gpt-oss-120b", "nvidia/deepseek-
|
|
234
|
+
cheap: ["zai/glm-5", "zai/glm-5-turbo", "nvidia/gpt-oss-120b", "nvidia/deepseek-v4-flash", "google/gemini-2.5-flash", "deepseek/deepseek-chat", "openai/gpt-5.4-nano"],
|
|
235
235
|
reasoning: ["anthropic/claude-opus-4.8", "openai/o3", "openai/o1", "openai/o3-mini", "deepseek/deepseek-reasoner", "moonshot/kimi-k2.6", "openai/gpt-5.3-codex"],
|
|
236
|
-
|
|
236
|
+
// 2026-06-07 sweep: dropped qwen3-next (NVIDIA EOL, 410), mistral-small-4-119b
|
|
237
|
+
// (timing out), deepseek-v3.2 + glm-4.7 (NIM hung). All redirect server-side
|
|
238
|
+
// anyway; these are the free models actually serving themselves.
|
|
239
|
+
free: ["nvidia/llama-4-maverick", "nvidia/qwen3-coder-480b", "nvidia/deepseek-v4-flash", "nvidia/gpt-oss-120b", "nvidia/gpt-oss-20b"],
|
|
237
240
|
coding: ["anthropic/claude-opus-4.8", "zai/glm-5", "openai/gpt-5.3-codex", "moonshot/kimi-k2.6", "nvidia/qwen3-coder-480b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"],
|
|
238
|
-
glm: ["zai/glm-5", "zai/glm-5-turbo"
|
|
241
|
+
glm: ["zai/glm-5", "zai/glm-5-turbo"]
|
|
239
242
|
};
|
|
240
243
|
|
|
241
244
|
// src/utils/qr.ts
|
|
@@ -1907,6 +1910,46 @@ async function fetchWithTimeout4(url, options, timeoutMs) {
|
|
|
1907
1910
|
clearTimeout(id);
|
|
1908
1911
|
}
|
|
1909
1912
|
}
|
|
1913
|
+
async function payAndPostJson(url, reqBody, fallbackDescription) {
|
|
1914
|
+
const privateKey = getOrCreateWalletKey();
|
|
1915
|
+
const account = privateKeyToAccount4(privateKey);
|
|
1916
|
+
const resp402 = await fetchWithTimeout4(url, {
|
|
1917
|
+
method: "POST",
|
|
1918
|
+
headers: { "Content-Type": "application/json" },
|
|
1919
|
+
body: reqBody
|
|
1920
|
+
}, 15e3);
|
|
1921
|
+
if (resp402.status !== 402) {
|
|
1922
|
+
const data2 = await resp402.json().catch(() => ({}));
|
|
1923
|
+
throw new Error(`Expected 402, got ${resp402.status}: ${data2.message || data2.error || JSON.stringify(data2)}`);
|
|
1924
|
+
}
|
|
1925
|
+
const prHeader = resp402.headers.get("payment-required") || resp402.headers.get("PAYMENT-REQUIRED");
|
|
1926
|
+
if (!prHeader) throw new Error("No PAYMENT-REQUIRED header in 402 response");
|
|
1927
|
+
const paymentRequired = parsePaymentRequired4(prHeader);
|
|
1928
|
+
const details = extractPaymentDetails4(paymentRequired);
|
|
1929
|
+
const paymentPayload = await createPaymentPayload4(
|
|
1930
|
+
privateKey,
|
|
1931
|
+
account.address,
|
|
1932
|
+
details.recipient,
|
|
1933
|
+
details.amount,
|
|
1934
|
+
details.network || "eip155:8453",
|
|
1935
|
+
{
|
|
1936
|
+
resourceUrl: details.resource?.url || url,
|
|
1937
|
+
resourceDescription: details.resource?.description || fallbackDescription,
|
|
1938
|
+
maxTimeoutSeconds: Math.max(details.maxTimeoutSeconds || 0, 120),
|
|
1939
|
+
extra: details.extra
|
|
1940
|
+
}
|
|
1941
|
+
);
|
|
1942
|
+
const resp = await fetchWithTimeout4(url, {
|
|
1943
|
+
method: "POST",
|
|
1944
|
+
headers: {
|
|
1945
|
+
"Content-Type": "application/json",
|
|
1946
|
+
"PAYMENT-SIGNATURE": paymentPayload
|
|
1947
|
+
},
|
|
1948
|
+
body: reqBody
|
|
1949
|
+
}, 9e4);
|
|
1950
|
+
const data = await resp.json().catch(() => ({}));
|
|
1951
|
+
return { status: resp.status, data };
|
|
1952
|
+
}
|
|
1910
1953
|
function registerRealfaceTool(server, budget) {
|
|
1911
1954
|
server.registerTool(
|
|
1912
1955
|
"blockrun_realface",
|
|
@@ -1919,7 +1962,8 @@ Actions:
|
|
|
1919
1962
|
- init: FREE. Create an asset group + a phone H5 link. The tool renders the link as a QR code and opens it; the real person scans it on their phone and completes the ~1 min liveness check. Pass group_id to refresh an expired link.
|
|
1920
1963
|
- status: FREE. Poll a group until status:"active" (ready_to_finalize:true). The H5 link is valid ~120s \u2014 re-init if it expires.
|
|
1921
1964
|
- enroll: PAID ($0.01 USDC, Base only). After the group is active, upload a clear front-facing photo (image_url) of the SAME person. Returns the ta_xxxx asset id.
|
|
1922
|
-
-
|
|
1965
|
+
- portrait: PAID ($0.01 USDC, Base only). Virtual Portrait \u2014 enroll an AI-GENERATED character from an image URL directly, NO liveness needed (one step: name + image_url \u2192 ta_xxxx). For fictional/AI characters only; for a real person use the init\u2192status\u2192enroll liveness flow.
|
|
1966
|
+
- list: FREE. List the RealFace + Virtual Portrait assets enrolled by this wallet (their ta_xxxx ids + names) so you can pick one for blockrun_video.
|
|
1923
1967
|
|
|
1924
1968
|
Typical flow:
|
|
1925
1969
|
1. blockrun_realface action:"init" name:"Alice" \u2192 scan QR on phone, do liveness
|
|
@@ -1929,10 +1973,10 @@ Typical flow:
|
|
|
1929
1973
|
|
|
1930
1974
|
Privacy: BlockRun does not store face/liveness data \u2014 only the asset id, name, and the photo URL you supply.`,
|
|
1931
1975
|
inputSchema: {
|
|
1932
|
-
action: z8.enum(["init", "status", "enroll", "list"]).describe("What to do"),
|
|
1933
|
-
name: z8.string().min(1).max(64).optional().describe("Display name for the person (required for init and
|
|
1934
|
-
group_id: z8.string().regex(/^legacy_rf_\d+$/).optional().describe("Asset-group id from init (required for status and enroll; pass to init to refresh an expired H5 link)."),
|
|
1935
|
-
image_url: z8.string().url().optional().describe("Public HTTPS URL to a clear front-facing face
|
|
1976
|
+
action: z8.enum(["init", "status", "enroll", "portrait", "list"]).describe("What to do"),
|
|
1977
|
+
name: z8.string().min(1).max(64).optional().describe("Display name for the person/character (required for init, enroll, and portrait)."),
|
|
1978
|
+
group_id: z8.string().regex(/^legacy_rf_\d+$/).optional().describe("Asset-group id from init (required for status and enroll; pass to init to refresh an expired H5 link). Not used by portrait."),
|
|
1979
|
+
image_url: z8.string().url().optional().describe("Public HTTPS URL to a clear front-facing face image (JPG/PNG/WEBP, \u226410MB). Required for enroll and portrait."),
|
|
1936
1980
|
agent_id: z8.string().optional().describe("Agent identifier for budget tracking and enforcement (enroll only).")
|
|
1937
1981
|
}
|
|
1938
1982
|
},
|
|
@@ -2022,30 +2066,88 @@ QR opened for scanning (${qrPath}).`;
|
|
|
2022
2066
|
}
|
|
2023
2067
|
if (action === "list") {
|
|
2024
2068
|
const account = privateKeyToAccount4(getOrCreateWalletKey());
|
|
2025
|
-
const
|
|
2026
|
-
method: "GET"
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2069
|
+
const [rfResp, vpResp] = await Promise.all([
|
|
2070
|
+
fetchWithTimeout4(`${BLOCKRUN_API4}/v1/wallet/${account.address}/realfaces`, { method: "GET" }, 3e4),
|
|
2071
|
+
fetchWithTimeout4(`${BLOCKRUN_API4}/v1/wallet/${account.address}/portraits`, { method: "GET" }, 3e4).catch(() => null)
|
|
2072
|
+
]);
|
|
2073
|
+
const data = await rfResp.json().catch(() => ({}));
|
|
2074
|
+
if (!rfResp.ok) {
|
|
2075
|
+
return { content: [{ type: "text", text: formatError(`list failed (${rfResp.status}): ${data.error || JSON.stringify(data)}`) }], isError: true };
|
|
2031
2076
|
}
|
|
2032
2077
|
const faces = Array.isArray(data.realfaces) ? data.realfaces : [];
|
|
2033
|
-
|
|
2078
|
+
let portraits = [];
|
|
2079
|
+
if (vpResp?.ok) {
|
|
2080
|
+
const vpData = await vpResp.json().catch(() => ({}));
|
|
2081
|
+
portraits = Array.isArray(vpData.portraits) ? vpData.portraits : [];
|
|
2082
|
+
}
|
|
2083
|
+
if (faces.length === 0 && portraits.length === 0) {
|
|
2034
2084
|
return {
|
|
2035
|
-
content: [{ type: "text", text: `No RealFace assets enrolled for ${account.address}.
|
|
2036
|
-
Enroll one: blockrun_realface action:"init" name:"\u2026".` }],
|
|
2037
|
-
structuredContent: { wallet: account.address, realfaces: [], count: 0 }
|
|
2085
|
+
content: [{ type: "text", text: `No RealFace or Virtual Portrait assets enrolled for ${account.address}.
|
|
2086
|
+
Enroll one: blockrun_realface action:"init" name:"\u2026" (real person) or action:"portrait" name:"\u2026" image_url:"https://\u2026" (AI character).` }],
|
|
2087
|
+
structuredContent: { wallet: account.address, realfaces: [], portraits: [], count: 0 }
|
|
2038
2088
|
};
|
|
2039
2089
|
}
|
|
2090
|
+
const first = faces[0] ?? portraits[0];
|
|
2040
2091
|
const lines = [
|
|
2041
|
-
`
|
|
2042
|
-
...faces.map((f) => ` \u2022 ${f.assetId} \u2014 "${f.name}"${f.createdAt ? ` (${f.createdAt})` : ""}`),
|
|
2092
|
+
`Assets for ${account.address} (${faces.length} RealFace, ${portraits.length} Virtual Portrait):`,
|
|
2093
|
+
...faces.map((f) => ` \u2022 ${f.assetId} \u2014 "${f.name}" [realface]${f.createdAt ? ` (${f.createdAt})` : ""}`),
|
|
2094
|
+
...portraits.map((p) => ` \u2022 ${p.assetId} \u2014 "${p.name}" [portrait]${p.createdAt ? ` (${p.createdAt})` : ""}`),
|
|
2043
2095
|
``,
|
|
2044
|
-
`Use one: blockrun_video model:"bytedance/seedance-2.0" real_face_asset_id:"${
|
|
2096
|
+
`Use one: blockrun_video model:"bytedance/seedance-2.0" real_face_asset_id:"${first.assetId}" prompt:"\u2026".`
|
|
2045
2097
|
];
|
|
2046
2098
|
return {
|
|
2047
2099
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
2048
|
-
structuredContent: { wallet: account.address, realfaces: faces, count: faces.length }
|
|
2100
|
+
structuredContent: { wallet: account.address, realfaces: faces, portraits, count: faces.length + portraits.length }
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
if (action === "portrait") {
|
|
2104
|
+
if (getChain() !== "base") {
|
|
2105
|
+
return { content: [{ type: "text", text: formatError("blockrun_realface portrait settles on Base only. Switch BlockRun to Base (run blockrun_wallet with action:chain chain:base) and fund the Base wallet with USDC.") }], isError: true };
|
|
2106
|
+
}
|
|
2107
|
+
if (!name || !image_url) {
|
|
2108
|
+
return { content: [{ type: "text", text: formatError("portrait requires name and image_url (public HTTPS URL of an AI-generated character image).") }], isError: true };
|
|
2109
|
+
}
|
|
2110
|
+
const budgetCheck = checkBudget(budget, agent_id, ENROLLMENT_PRICE_USD);
|
|
2111
|
+
if (!budgetCheck.allowed) {
|
|
2112
|
+
return { content: [{ type: "text", text: `${budgetCheck.reason}. Use blockrun_wallet action:"report" to see usage or action:"delegate" to increase agent budget.` }], isError: true };
|
|
2113
|
+
}
|
|
2114
|
+
const { status, data } = await payAndPostJson(
|
|
2115
|
+
`${BLOCKRUN_API4}/v1/portrait/enroll`,
|
|
2116
|
+
JSON.stringify({ name, image_url }),
|
|
2117
|
+
"BlockRun Virtual Portrait enrollment"
|
|
2118
|
+
);
|
|
2119
|
+
if (status === 402) {
|
|
2120
|
+
throw new Error("Payment rejected. Check your wallet balance.");
|
|
2121
|
+
}
|
|
2122
|
+
if (status === 422) {
|
|
2123
|
+
return { content: [{ type: "text", text: formatError(`Portrait rejected \u2014 ${data.hint || data.message || "use a clear front-facing character image"}. No payment taken.`) }], isError: true };
|
|
2124
|
+
}
|
|
2125
|
+
if (status < 200 || status >= 300) {
|
|
2126
|
+
throw new Error(`Portrait enroll error ${status}: ${data.error || JSON.stringify(data)}`);
|
|
2127
|
+
}
|
|
2128
|
+
const assetId = data.asset_id;
|
|
2129
|
+
if (!assetId) throw new Error(`Portrait response missing asset_id: ${JSON.stringify(data)}`);
|
|
2130
|
+
recordSpending(budget, ENROLLMENT_PRICE_USD, agent_id);
|
|
2131
|
+
const txHash = data.settlement?.tx_hash || void 0;
|
|
2132
|
+
const lines = [
|
|
2133
|
+
`\u2705 Virtual Portrait enrolled!`,
|
|
2134
|
+
`Asset ID: ${assetId}`,
|
|
2135
|
+
`Name: ${data.name || name}`,
|
|
2136
|
+
`Cost: $${ENROLLMENT_PRICE_USD.toFixed(2)} USDC`,
|
|
2137
|
+
...txHash ? [`Tx: ${txHash}`] : [],
|
|
2138
|
+
``,
|
|
2139
|
+
`Use it: blockrun_video model:"bytedance/seedance-2.0" real_face_asset_id:"${assetId}" prompt:"\u2026".`
|
|
2140
|
+
];
|
|
2141
|
+
return {
|
|
2142
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
2143
|
+
structuredContent: {
|
|
2144
|
+
asset_id: assetId,
|
|
2145
|
+
group_id: data.group_id,
|
|
2146
|
+
name: data.name || name,
|
|
2147
|
+
image_url: data.image_url,
|
|
2148
|
+
price_usd: ENROLLMENT_PRICE_USD,
|
|
2149
|
+
...txHash ? { txHash } : {}
|
|
2150
|
+
}
|
|
2049
2151
|
};
|
|
2050
2152
|
}
|
|
2051
2153
|
if (action === "enroll") {
|
|
@@ -2874,6 +2976,63 @@ Prefer blockrun_price (free quotes), blockrun_dex (free DEX data), or blockrun_s
|
|
|
2874
2976
|
);
|
|
2875
2977
|
}
|
|
2876
2978
|
|
|
2979
|
+
// src/tools/defi.ts
|
|
2980
|
+
import { z as z18 } from "zod";
|
|
2981
|
+
function estimateDefiCost(path5) {
|
|
2982
|
+
return path5.startsWith("prices") ? 1e-3 : 5e-3;
|
|
2983
|
+
}
|
|
2984
|
+
function registerDefiTool(server, budget) {
|
|
2985
|
+
server.registerTool(
|
|
2986
|
+
"blockrun_defi",
|
|
2987
|
+
{
|
|
2988
|
+
description: `DeFi fundamentals via DefiLlama \u2014 protocol TVL, chain TVL, yield pools (APY), token prices. Pays per call in USDC, no API key.
|
|
2989
|
+
|
|
2990
|
+
Paths (GET only):
|
|
2991
|
+
- protocols ($0.005) \u2014 all DeFi protocols ranked by TVL
|
|
2992
|
+
- protocol/{slug} ($0.005) \u2014 one protocol's TVL history + chain breakdown, e.g. protocol/aave-v3
|
|
2993
|
+
- chains ($0.005) \u2014 TVL by chain
|
|
2994
|
+
- yields ($0.005) \u2014 yield pools with APY + TVL (large; filter client-side)
|
|
2995
|
+
- prices/{coins} ($0.001) \u2014 token prices, coins like 'base:0x833589...,coingecko:ethereum'
|
|
2996
|
+
|
|
2997
|
+
Examples:
|
|
2998
|
+
blockrun_defi({ path: "protocol/uniswap-v3" })
|
|
2999
|
+
blockrun_defi({ path: "prices/coingecko:bitcoin,coingecko:ethereum" })
|
|
3000
|
+
blockrun_defi({ path: "chains" })
|
|
3001
|
+
|
|
3002
|
+
Use blockrun_price (free) for plain spot quotes, blockrun_dex (free) for DEX pairs, blockrun_surf for labeled on-chain data \u2014 this tool is for protocol/TVL/yield fundamentals.`,
|
|
3003
|
+
inputSchema: {
|
|
3004
|
+
path: z18.string().describe("Endpoint under /v1/defillama/, e.g. 'protocols', 'protocol/aave-v3', 'chains', 'yields', 'prices/coingecko:ethereum'"),
|
|
3005
|
+
agent_id: z18.string().optional().describe("Agent identifier for budget tracking and enforcement.")
|
|
3006
|
+
}
|
|
3007
|
+
},
|
|
3008
|
+
async ({ path: path5, agent_id }) => {
|
|
3009
|
+
try {
|
|
3010
|
+
const cleanPath = path5.replace(/^\/+/, "").replace(/^v1\/defillama\//, "").replace(/^api\/v1\/defillama\//, "");
|
|
3011
|
+
const estimatedCost = estimateDefiCost(cleanPath);
|
|
3012
|
+
const budgetCheck = checkBudget(budget, agent_id, estimatedCost);
|
|
3013
|
+
if (!budgetCheck.allowed) {
|
|
3014
|
+
return {
|
|
3015
|
+
content: [{ type: "text", text: `${budgetCheck.reason}. Use blockrun_wallet action:"report" to see usage or action:"delegate" to increase agent budget.` }],
|
|
3016
|
+
isError: true
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
const client = getClient();
|
|
3020
|
+
const result = await client.getWithPaymentRaw(`/v1/defillama/${cleanPath}`);
|
|
3021
|
+
recordSpending(budget, estimatedCost, agent_id);
|
|
3022
|
+
return {
|
|
3023
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
3024
|
+
structuredContent: typeof result === "object" && result !== null && !Array.isArray(result) ? result : { result }
|
|
3025
|
+
};
|
|
3026
|
+
} catch (err) {
|
|
3027
|
+
return {
|
|
3028
|
+
content: [{ type: "text", text: formatError(extractErrorMessage(err)) }],
|
|
3029
|
+
isError: true
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
);
|
|
3034
|
+
}
|
|
3035
|
+
|
|
2877
3036
|
// src/mcp-handler.ts
|
|
2878
3037
|
function initializeMcpServer(server) {
|
|
2879
3038
|
const budget = { limit: null, spent: 0, calls: 0, agents: /* @__PURE__ */ new Map() };
|
|
@@ -2895,6 +3054,7 @@ function initializeMcpServer(server) {
|
|
|
2895
3054
|
registerPhoneTool(server, budget);
|
|
2896
3055
|
registerSurfTool(server, budget);
|
|
2897
3056
|
registerRpcTool(server, budget);
|
|
3057
|
+
registerDefiTool(server, budget);
|
|
2898
3058
|
server.registerResource(
|
|
2899
3059
|
"wallet",
|
|
2900
3060
|
"blockrun://wallet",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
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",
|