Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Smoke-test the built server via the MCP stdio handshake:
(printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1"}}}\n{"jsonrpc":"2.0","method":"notifications/initialized"}\n{"jsonrpc":"2.0","id":2,"method":"tools/list"}\n'; sleep 2) | node dist/index.js 2>/dev/null
```

Should return 18 tools including `blockrun_surf` and any new one you add.
Should return <!-- br:mcp.tools -->19<!-- /br:mcp.tools --> tools including `blockrun_surf` and any new one you add.

To test locally with Claude Code, point it at your dev build:

Expand Down
6 changes: 3 additions & 3 deletions skills/crypto-data/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: crypto-data
description: Use for any crypto data question — token/coin prices, FX, commodities, stocks, OHLC history, DEX pairs and liquidity, DeFi TVL, yield/APY pools, on-chain SQL, wallet labels and net worth, social mindshare, news, or raw JSON-RPC against a chain. Routes across five tools that overlap heavily, so it also says which one to use and which are FREE — blockrun_price (crypto/FX/commodities free, Pyth), blockrun_dex (free, DexScreener), blockrun_defi (DefiLlama TVL + yields), blockrun_surf (83 endpoints — on-chain SQL, 100M+ wallet labels, social), blockrun_rpc (40+ chains). No API keys, pay-per-call in USDC via x402.
description: Use for any crypto data question — token/coin prices, FX, commodities, stocks, OHLC history, DEX pairs and liquidity, DeFi TVL, yield/APY pools, on-chain SQL, wallet labels and net worth, social mindshare, news, or raw JSON-RPC against a chain. Routes across five tools that overlap heavily, so it also says which one to use and which are FREE — blockrun_price (crypto/FX/commodities free, Pyth), blockrun_dex (free, DexScreener), blockrun_defi (DefiLlama TVL + yields), blockrun_surf (83 endpoints — on-chain SQL, 100M+ wallet labels, social), blockrun_rpc (40 chains). No API keys, pay-per-call in USDC via x402.
triggers:
- "crypto price"
- "token price"
Expand Down Expand Up @@ -62,7 +62,7 @@ Five tools cover crypto data and they overlap. **Pick by cost first** — two of
| **DEX pair, liquidity, volume, contract** | `blockrun_dex` | **FREE** |
| Stock quote / history (12 markets) | `blockrun_price` category:"stocks" | $0.0030 |
| Token price by contract address | `blockrun_defi` path:"prices/{coins}" | $0.0030 |
| Raw JSON-RPC on 40+ chains | `blockrun_rpc` | $0.0040 |
| Raw JSON-RPC on <!-- br:chains.rpc -->40<!-- /br:chains.rpc --> chains | `blockrun_rpc` | $0.0040 |
| Protocol TVL, chain TVL, yields/APY | `blockrun_defi` | $0.0070 |
| **Everything below** (on-chain SQL, wallet labels, social, news, unlocks, liquidations, ETF flows) | `blockrun_surf` | $0.0095 |
| Raw SQL over 80+ ClickHouse tables | `blockrun_surf` path:"onchain/sql" | $0.0095 |
Expand Down Expand Up @@ -136,7 +136,7 @@ blockrun_surf({ path: "onchain/sql", body: {

## blockrun_rpc — raw chain access

40+ chains, one endpoint, no node, no key. $0.0040/call (batches charge per element, plus one flat fee per request). See [`skills/rpc/SKILL.md`](../rpc/SKILL.md).
<!-- br:chains.rpc -->40<!-- /br:chains.rpc --> chains, one endpoint, no node, no key. $0.0040/call (batches charge per element, plus one flat fee per request). See [`skills/rpc/SKILL.md`](../rpc/SKILL.md).

```ts
blockrun_rpc({ network: "base", method: "eth_blockNumber", params: [] })
Expand Down
4 changes: 2 additions & 2 deletions skills/rpc/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: rpc
description: Use when the user needs raw blockchain JSON-RPC access — contract reads (eth_call), native balances, blocks, transactions, logs, gas estimates, or any chain-native RPC method across 40+ chains. One endpoint per chain via BlockRun's Tatum-backed gateway, $0.0040 per call, no node, no API key. Prefer blockrun_price / blockrun_dex / blockrun_surf when they already cover the question.
description: Use when the user needs raw blockchain JSON-RPC access — contract reads (eth_call), native balances, blocks, transactions, logs, gas estimates, or any chain-native RPC method across 40 chains. One endpoint per chain via BlockRun's Tatum-backed gateway, $0.0040 per call, no node, no API key. Prefer blockrun_price / blockrun_dex / blockrun_surf when they already cover the question.
triggers:
- "rpc"
- "json-rpc"
Expand All @@ -16,7 +16,7 @@ triggers:
- "tatum"
---

# Multi-chain RPC — 40+ chains, one tool
# Multi-chain RPC — every supported chain, one tool

`blockrun_rpc` POSTs a standard JSON-RPC 2.0 body to `/v1/rpc/{network}`. Flat **$0.0040 per call** ($0.002 base + the $0.002 transaction fee). A JSON-RPC **batch array charges per element but pays the flat fee only once** — $0.002 × n + $0.002, so a batch of 3 costs $0.0080 where three separate calls cost $0.0120. Batch whenever you can. Settlement in USDC via x402. Responses are cached briefly server-side for identical read calls (`X-Cache: HIT` is free of upstream latency but still billed).

Expand Down
17 changes: 16 additions & 1 deletion test/brand-numbers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { ALL_TOOLS, PROFILES, resolveTools } from "../src/profiles.js";

const published = JSON.parse(
readFileSync(new URL("../brand-numbers.json", import.meta.url), "utf8"),
) as { mcp: { tools: number } };
) as { mcp: { tools: number }; chains: { rpc: number } };

test("ships the advertised number of tools", () => {
assert.equal(ALL_TOOLS.length, published.mcp.tools);
Expand Down Expand Up @@ -53,3 +53,18 @@ test("no profile advertises a tool that does not exist", () => {
}
}
});

test("skills frontmatter states the published chain count", () => {
// A skill's YAML frontmatter becomes the description an agent reads when
// deciding whether to load it. A marker there is not inert — it would be
// part of the string — so these are literals, asserted instead.
const n = published.chains.rpc;
for (const f of ["skills/rpc/SKILL.md", "skills/crypto-data/SKILL.md"]) {
const text = readFileSync(new URL(`../${f}`, import.meta.url), "utf8");
const frontmatter = text.slice(0, text.indexOf("\n---", 4));
assert.ok(
frontmatter.includes(`${n} chains`),
`${f} frontmatter must say "${n} chains"`,
);
}
});
Loading