Three names with different jobs
A Function is a reusable catalog template, identified by function_slug such as erc20.holder_balance. A Bound Function is that computation with its chain and scope parameters filled, identified by a content-addressed bound_function_id beginning sha256:. An MCP tool is a verb such as bind, materialize, or read.
Pass the returned bound-function ID unchanged. A readable name, metric phrasing, or function slug cannot stand in for it. Two phrasings may resolve to one identity; one template bound to two contracts can produce two different identities.
Scope is structural
Obtain template parameter names from inspect subject:function. Pass addresses in typed fields or params, not hidden in explanatory prose. Set chain_id explicitly. There is no default chain. Use the exact JSON field names from the deployed schema: unknown fields are rejected.
The reviewed live 0.6.0 instructions advertise Function dependencies in params: a dependency can be supplied as nested scope parameters or as a declared binding name discovered through inspect subject:function. Use only the structure and names advertised for that Function. A declared binding name is not a substitute for the returned bound_function_id in data tools.
bind takes scope, not a block range. ask returns a resolution, not a metric value series.
Every explicit block window is half-open
[from_block, to_block) includes the start and excludes the end. [100, 110) contains ten blocks; block 110 is not included. A single block n is [n, n+1).
State both ends or omit both where the tool permits omission. One end alone is invalid. Never treat block numbers as timestamps or add ranges from different chains. A materialize window may extend beyond the current chain head; that tail waits for those blocks to exist. A read or provenance request requires full coverage of its stated window.
For a wall-clock request, first discover chain landmarks. The chain card includes blocks_per_day and either head or unavailable. A block-rate estimate is not an exact timestamp-to-block conversion; define the actual block boundaries before spending. The head does not establish finality.
Schema once, values many times
A successful read returns bare values, one object per block and row key, with every attribute of that row. Obtain their types and key-part names from the Function’s row schema through inspect. Preserve declared types; do not round large integer strings through floating-point arithmetic. A sparse row, an empty result, and missing coverage are distinct states. Within fully materialized coverage, a block with no row means the Function emitted nothing there; consult its description before interpreting that absence.
Inspect the actual row schema and prefer exact integer fields for accounting when supplied. Human-readable floating-point units can lose precision above 2^53.
The optional read.key is an object of string values for a leading run of row-key parts. It filters stored rows without rebinding scope. read.attributes, read.entity, and provenance.attribute are no longer accepted. Provenance uses the bound identity and exact window.
Keep useful agent state
Persist the endpoint, chain, function slug, bound-function ID, scope parameters, requested window, selected measures, quote/payment/job IDs, settlement receipts, and source verification evidence. Store secrets separately. This small state record lets another agent resume a workflow without reconstructing intent from prose.