Install
$ agentstack add skill-blockscout-agent-skills-blockscout-analysis ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Blockscout Analysis
Analyze blockchain activity and build scripts, tools, and applications that query on-chain data. All data access goes through the Blockscout MCP Server — via native MCP tool calls, the MCP REST API, or both.
Infrastructure
Blockscout MCP Server
The server is the sole runtime data source. It is multichain — almost all tools accept a chain_id parameter. Use get_chains_list to discover supported chains. Always pass its query parameter — a case-insensitive substring match by chain name, ecosystem, or native currency — so the call returns only the relevant chains instead of the full registry. Fall back to a no-argument call only when a query returns no matches.
| Access method | URL | Use case | |---------------|-----|----------| | Native MCP | https://mcp.blockscout.com/mcp | Direct tool calls from the agent | | REST API | https://mcp.blockscout.com/v1/{tool_name}?params | HTTP GET calls from scripts |
Response format equivalence: Native MCP tool calls and REST API calls to the same tool return identical JSON response structures. When writing scripts targeting the REST API, use native MCP tool calls to probe and validate the expected response shape.
Available tools (16): unlock_blockchain_analysis, get_chains_list, get_address_info, get_address_by_ens_name, get_tokens_by_address, nft_tokens_by_address, get_transactions_by_address, get_token_transfers_by_address, get_block_info, get_block_number, get_transaction_info, get_contract_abi, inspect_contract_code, read_contract, lookup_token_by_symbol, direct_api_call.
Dedicated MCP tools return LLM-friendly, enriched responses (pre-filtered, with guidance for next steps). The exception is direct_api_call, which proxies raw Blockscout API responses without optimization or filtering. direct_api_call enforces a 100,000-character response size limit (413 error when exceeded). Native MCP calls strictly enforce this limit. REST API callers can bypass it with the X-Blockscout-Allow-Large-Response: true header — but scripts using this bypass must still apply [response transformation](#response-transformation).
Transient errors
The Blockscout MCP server proxies requests to upstream indexers and chain nodes, so any single call may surface a transient upstream failure even when the underlying data is fine. Treat 5xx responses as retryable:
- Retry on 5xx (especially
500 Internal Server Error): retry the same call up to 3 times before giving up or reporting failure to the user. A short pause between retries is fine but not required — the upstream condition is usually momentary. - Do not retry on 4xx. 4xx responses are deterministic (bad parameters, unknown resource, oversized response). Retrying does not change the outcome.
413fromdirect_api_callspecifically means the response exceeded the 100,000-character limit. Either narrow the query or, from a script, setX-Blockscout-Allow-Large-Response: trueand apply [response transformation](#response-transformation) before passing data to the LLM.- Applies to both access methods. The same rule governs native MCP tool calls and scripts hitting the MCP REST API — when a script wraps HTTP requests, build the retry into the wrapper rather than treating a 5xx as a hard failure on the first call.
unlock_blockchain_analysis prerequisite
Before any other Blockscout MCP tool call, the agent must call unlock_blockchain_analysis. This is a hard skill-level prerequisite for every MCP client and every access method (native MCP or REST API).
- Call it once per session, not before every tool call. One successful call at the start of the session covers all subsequent Blockscout MCP tool use in that session.
- No client carve-outs. The requirement applies even to clients (e.g., Claude Code) that read server-side tool instructions reliably.
MCP tool discovery
- MCP server configured: Tool names and descriptions are already in the agent's context. The agent may still consult the API reference files for parameter details.
- MCP server not configured: Discover tools and their schemas via
GET https://mcp.blockscout.com/v1/tools.
MCP pagination
When a tool response includes a pagination field, additional pages of data are available. The response's pagination.next_call holds the complete next request — tool name and all required parameters (including the cursor). Use that next-call shape directly rather than reconstructing the call by hand: this avoids drift between what the agent assembles and what the server expects, and keeps the cursor (a single Base64URL-encoded token) the only piece of state the agent has to carry between pages.
- Native MCP: invoke the tool named in
pagination.next_callwith itsparamsas-is. - Scripts (REST API): translate
pagination.next_callinto the next HTTP GET —cursorbecomes a?cursor=...query parameter, the rest of the original query parameters stay unchanged.
Pages contain ~10 items each. When the user asks for comprehensive data or "all" results, continue following pagination.next_call until the data is exhausted or a reasonable limit is reached — do not stop after the first page.
Chainscout (chain registry)
Chainscout (https://chains.blockscout.com/api) is a separate service for resolving a chain ID to its Blockscout explorer URL. Access it via direct HTTP requests (e.g., WebFetch, curl, or from a script) — not via direct_api_call, which does not proxy calls to the Chainscout service.
Chain IDs must first be obtained from the get_chains_list MCP tool. See references/chainscout-api.md for the endpoint details.
Decision Framework
Data source priority
All data access goes through the Blockscout MCP Server. Prefer sources in this order:
- Dedicated MCP tools — LLM-friendly, enriched, no auth. Prefer when a tool directly answers the data need.
direct_api_call— for Blockscout API endpoints not covered by dedicated tools. Consultreferences/blockscout-api-index.mdto discover available endpoints.- Chainscout — only for resolving a chain ID to its Blockscout instance URL.
When a data need can be fulfilled by either a dedicated MCP tool or direct_api_call, always prefer the dedicated tool. Choose direct_api_call instead when no dedicated tool covers the endpoint, or when the dedicated tool is known — from its description or schema — not to return a field required for the task. Make this choice upfront; do not call a dedicated tool and then fall back to direct_api_call for the same data.
No redundant calls: Once a tool or endpoint is selected for a data need, do not call alternative tools for the same data.
Execution strategy
Choose the execution method based on task complexity, determinism, and whether semantic reasoning is required:
| Signal | Strategy | When to use | |--------|----------|-------------| | Simple lookup, 1-3 calls, no post-processing | Direct tool calls | Answer is returned directly by an MCP tool. E.g., get a block number, resolve an ENS name, fetch address info. | | Deterministic multi-step flow with loops, date ranges, aggregation, or branching | Script (MCP REST API via HTTP) | Logic is well-defined and would be inefficient as a sequence of LLM-driven calls. E.g., iterate over months for APY changes, paginate through holders, scan transaction history with filtering. | | Simple retrieval but output requires math, normalization, or filtering | Hybrid (tool call + script) | Raw data needs decimal normalization, USD conversion, sorting, deduplication, or threshold filtering. E.g., get balances via MCP then normalize and filter in a script. | | Semantic understanding, code analysis, or subjective judgment needed | LLM reasoning over tool results | Cannot be answered by a deterministic algorithm — needs contract code interpretation, token authenticity verification, transaction classification, or code flow tracing. | | Large data volume with known filtering criteria | Script with direct_api_call | Process many pages with programmatic filters. Use direct_api_call via MCP REST API for paginated endpoints. |
Combination patterns: Real-world queries often combine strategies. E.g., direct tool calls to resolve an ENS name, then a script to iterate chains and normalize balances, with the LLM interpreting which tokens are stablecoins.
Probe-then-script: When the execution strategy is "Script" but the agent needs to understand response structures before writing the script, call the relevant MCP tools natively with representative parameters first. Use the observed response structure to write the script targeting the REST API. Do not fall back to third-party data sources (e.g., direct RPC endpoints, third-party libraries) when the MCP REST API covers the data need.
Query patterns
Analysis tasks come in a small set of recognizable shapes — filter data to a time window, locate the moment of a state transition, and so on. For each of these shapes the correct way to assemble Blockscout MCP calls is not obvious from the individual tool descriptions, so the skill codifies the pattern explicitly. When a task matches a shape below, follow the pattern instead of improvising — improvised approaches in these areas are a common source of either wasted calls or confidently wrong answers.
Time-bounded queries
When the task constrains the answer to a time range (before/after a date, between two dates, "in the last N days"), start with the transaction-level tools that accept time filters: get_transactions_by_address and get_token_transfers_by_address, using the age_from and age_to parameters. Retrieve associated data (logs, internal token transfers, receipt details) from the transactions returned by those calls, not by trying to time-filter other endpoints directly.
The reason is mechanical: most other Blockscout endpoints have no time-filter parameter. Without age_from/age_to, the only way to honor a time bound on those endpoints is to paginate from one end of history until the timestamps fall inside the requested window — that grows linearly with chain history and burns a lot of calls. Starting from the time-filtered endpoints scopes the work to the actual window.
Carve-out — "find the block at this moment". When the task is to convert a wall-clock instant into a block number (or to anchor a follow-up query to a block boundary), use get_block_number(datetime=...) directly. This is the cheapest and most accurate path; do not bisect transaction history to discover a block boundary that the server can return in one call.
For tasks asking when a state transition happened (e.g., "in which block did X change") rather than for data inside a window, see [Locating historical state changes](#locating-historical-state-changes).
Locating historical state changes
Some tasks ask for the moment of an on-chain state transition rather than the values themselves: "in which block did the supply first exceed N", "when did this address first become a holder", "find the transaction after which the contract was paused", "at what block did role X get granted". Pagination is the wrong tool for these — scanning history grows linearly with transactions, while bisection over block numbers grows logarithmically. Use binary search.
Monotonicity precondition (mandatory). Binary search returns a correct answer only when the predicate is monotonic over the bracketed range — once it flips, it stays flipped. The classic safe cases are "first block where the predicate becomes true" (and stays true) or "last block where it remained false". Non-monotonic predicates are not eligible for binary search. Concretely:
- Paused/unpaused toggles, balances that go up and down, repeated threshold crossings, role grants followed by role revokes — none of these can be located with a single bisection, because the midpoint check tells you whether the predicate holds there, not which crossing you have hit.
- For genuinely non-monotonic predicates, use event/log scanning (
/api/v2/transactions/{hash}/logsviadirect_api_call, orget_transactions_by_address/get_token_transfers_by_addresswith a time filter and post-filtering for the event of interest). - Sometimes the task can be re-cast: the first occurrence of a non-monotonic event is still a monotonic question ("first block at which the count of pause events is ≥ 1"). If you can split the range into segments that are individually monotonic — known deployments, known event boundaries — bisecting each segment is also fine. Otherwise scan.
If you are not sure the predicate is monotonic, say so and scan; a wrong "first block" answer from a misapplied bisection is worse than a slower correct one.
Pattern: bracket → bisect → probe.
- Bracket the search range with two block numbers,
loandhi, where the predicate is known (or assumed) to hold one value atloand the other athi. Sources:
- Time-stated bound →
get_block_number(datetime=...). - Open-ended bound → chain tip (current block via
get_block_number()), contract deployment block, or genesis (0). - If the contract did not exist at
lo, narrowloto the deployment block before starting.
- Bisect by block number — never by transaction count, position in a paginated list, or any other index. Block numbers are dense and uniform across what binary search needs.
- Probe the midpoint with the smallest deterministic check that answers the predicate:
- On-chain state at a block →
read_contractwith the relevant function andblockparameter. - Indexed Blockscout field at a block →
direct_api_callagainst the appropriate endpoint with a block scope. - Block-level facts (timestamp, base fee, miner) →
get_block_info.
Choose the probe so that one call decides the bisection direction; avoid probes that need follow-up calls to interpret.
Termination. Stop when hi - lo is 1 (or whatever resolution the task accepts). Be explicit about which boundary the task asks for:
- First block where the predicate holds → return
hiwhen the bisection settles with the predicatefalseatloandtrueathi. - Last block where it did not hold → return
lofrom the same settled bracket. - The exact transaction that flipped the state → after the block is found, do one more pass within that block (its transaction list and event logs) to pick out the flipping tx.
Edge cases.
- Very recent history. The last handful of blocks can reorg; a probe there may return a different answer minutes later. If the task touches the chain tip, mention the reorg risk in the answer or wait for additional confirmations before reporting a definitive block.
- Contract not yet deployed at the probe block.
read_contractat a pre-deployment block fails deterministically. Treat this as evidence that the deployment block is between the currentloand the probe, and narrowloupward instead of recording a "false" reading. - Non-uniform block times across chains. L2s and PoS chains have variable block times. This does not affect correctness — the bisection runs on block numbers, not time.
Complete portfolio queries
When the task asks for a portfolio, net worth, total assets, holdings, or "top tokens by value" for an address, query both value surfaces before answering:
get_address_info— native-coin balance (ETH/MATIC/etc.) and its USD valuation.get_tokens_by_address— ERC-20 holdings.
These surfaces live in different parts of the data model and are returned by different tools; one tool does not subsume the other. For most addresses the largest position is in the native coin, so an answer built only from get_tokens_by_address is dominated by what was not queried. When ranking or selecting top tokens by USD value, include the native-coin bal
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: blockscout
- Source: blockscout/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.