Guide

Agents

The same ten read-only tools over MCP and Pi and OMP. How a provider gets chosen for a tool call. What stays out of the answer until asked for.

Eleven tools, three surfaces

The MCP server, the Pi extension and the OMP extension register the same eleven tools, and every one of them goes through withProvider() with the operation's capability, so selection, keys and the one retry behave as in the CLI. Cancelling works too. The MCP request's signal and the one Pi and OMP hand to execute reach ENS resolution and the explorer request, so an interrupted call stops right away instead of waiting out the request timeout.

ToolReadsInput
explorers_providersevery registered provider with its capabilities and endpointnone
explorers_balancenative balance for one address or a list of up to twentyaddress or address[]
explorers_tx_historynormalized transactions involving an addressaddress, paging options, tags and raw on MCP
explorers_tx_detailone transaction by hash, OP_RETURN and inscriptions includedhash, raw on MCP
explorers_utxosfifty unspent outputs unless limit says otherwise, Bitcoin familyaddress, limit
explorers_pubkeythe public key an address has shown, and the txid that showed itaddress
explorers_contractverification, compiler, creator, proxy and token metadataaddress, abi and sourceCode on MCP
explorers_tokensfifty token holdings unless limit says otherwise, zeros droppedaddress, nonZeroOnly, limit
explorers_token_transfersfungible transfers involving an address, one token or alladdress, token, paging options
explorers_gasfee suggestions in the provider's unitnone
explorers_blockone block by numberblockNumber

Every tool takes an optional chain and provider. Addresses and ENS names get resolved before the read, so a model can pass vitalik.eth where it would pass hex. The answer is { provider, data } as JSON text, with provider naming the backend that actually answered, which after a retry isn't always the first candidate.

What stays out until asked

Over MCP the heavy fields don't travel by default. explorers_tx_history and explorers_tx_detail drop raw unless the call says raw: true, and explorers_contract drops abi and sourceCode unless the call says abi: true or sourceCode: true. A provider's own transaction record dwarfs the normalized fields, and an ABI runs to tens of kilobytes. A model that wants to know whether a contract is verified shouldn't pay for its source, and one that needs every input of a Bitcoin transaction can ask. The Pi and OMP extensions render a short text summary and keep the full object in the tool's details instead.

explorers_tokens lists fifty holdings unless limit says otherwise, at most a hundred, in the explorer's own order, which on Blockscout puts the priced ones first by USD value. total counts every holding the list was cut from, zeros excluded unless nonZeroOnly is false, so a model can tell a wallet with fifty tokens from one that has been airdropped at six thousand times without paying for the list; the Pi and OMP text says 6766 tokens … 50 listed for the same read. getTokenBalances() in the library still returns everything.

explorers_utxos cuts the same way, at fifty outputs unless limit says otherwise, with total counting all of them. An address that collects dust makes this matter. The genesis address on Bitcoin SV comes back from WhatsOnChain as ten thousand outputs, 1.8 MB of JSON, while fifty of them are 9 kB. The Pi and OMP header counts every output and sums the confirmed ones, so the balance you read off it doesn't shrink with the list.

MCP

shell
explorers mcp
claude mcp add explorers --scope user -- npx -y @agntn/explorers mcp

Or in a client's config:

json
{
  "mcpServers": {
    "explorers": { "command": "npx", "args": ["-y", "@agntn/explorers", "mcp"] }
  }
}

The server speaks MCP over stdio. Bringing your own transport? @agntn/explorers/mcp hands you the same server, no stdio attached:

ts
import { createMcpServer } from "@agntn/explorers/mcp";

await createMcpServer().connect(transport);

It shares the registry with the main entry. A provider you register() there shows up in explorers_providers too. One registry, not two that politely ignore each other.

All eleven tools carry readOnlyHint: true, because that's what they are: nothing here signs, sends or holds a key on the model's behalf.

Keys stay in the process

Keys come from the agent's process environment, ETHERSCAN_API_KEY and the rest, never from a tool argument. A model can choose a provider and a chain, it can't supply a credential, and an error that reaches it has the key redacted already. A provider that needs a key the process doesn't have fails with an AuthError naming the provider, which a model can read and a session can survive.

Pi and OMP

shell
omp install @agntn/explorers
pi install npm:@agntn/explorers

The package declares both extensions in package.json. Installing the OMP extension doesn't replace or reuse the Pi one; they're separate entrypoints that register the same eleven tools and render their calls and results in the terminal. From a source checkout, omp install . links the local package.

What the answer is

The tools return the normalized objects, not prose. The Explorer shows the same objects for any public address, a quick way to check a model's summary of a wallet against the source.

Transaction data, token names and contract names come from public chains and the explorers that index them. Anyone can deploy a token called whatever they like. Report what the data says, and don't let a functionName or a symbol become an instruction.