Skip to content
TraceFast Docs

Connect an AI agent over MCP

Create an API key →

TraceFast runs a Model Context Protocol server: an AI agent calls TraceFast's Ethereum data as tools. Each tool is one method of the REST API — the same data, the same bounds, the same refusals — and it is called under your plan: with an API key, or by signing in with your TraceFast account. A tool call counts against a rate limit and your account's daily quota exactly like a REST call; listing the tools does not count.

Address:     https://tracefast.xyz/mcp
Transport:   Streamable HTTP, one POST per request
Protocol:    2026-07-28; 2025-11-25 clients are served too
Credential:  a TraceFast API key, or sign-in with your TraceFast account

Connect a client

There are two ways in. Claude Code, Cursor, your own agent and claude.ai organizations send an API key in a request header; a personal claude.ai account signs in with your TraceFast account instead — see below.

The key goes in one request header. Use the first one; the second exists for clients that can only send a bearer token:

HeaderWhen
X-Api-Key: tf_live_…the client lets you set a header
Authorization: Bearer tf_live_…the client can only send a bearer token

Keys are created in the TraceFast app on a paid plan — see Managing API keys. Every paid plan can connect; the plan decides which tools answer (see Tools).

Claude Code

claude mcp add --transport http tracefast https://tracefast.xyz/mcp \
  --header "X-Api-Key: $TRACEFAST_API_KEY"

The shell expands the variable, so the key is saved in your Claude Code configuration. Add --scope user to have TraceFast in every project; /mcp inside Claude Code shows whether it is connected.

To share the server through a repository without committing the key, put it in the project's .mcp.json — Claude Code reads ${TRACEFAST_API_KEY} from the environment of each person who opens the project:

{
  "mcpServers": {
    "tracefast": {
      "type": "http",
      "url": "https://tracefast.xyz/mcp",
      "headers": { "X-Api-Key": "${TRACEFAST_API_KEY}" }
    }
  }
}

Cursor

In ~/.cursor/mcp.json for every project, or .cursor/mcp.json for one:

{
  "mcpServers": {
    "tracefast": {
      "url": "https://tracefast.xyz/mcp",
      "headers": { "X-Api-Key": "${env:TRACEFAST_API_KEY}" }
    }
  }
}

claude.ai on a Team or Enterprise plan

An organization Owner adds TraceFast once, for the whole organization:

  1. Open Organization settings → Connectors and click Add custom connector.
  2. Enter the URL https://tracefast.xyz/mcp.
  3. Open Request headers, choose x-api-key and paste the key.

Members then turn the connector on in their own connector settings.

  • One key for everyone. Every member's calls go through the key the Owner entered: they share its rate limit and your account's daily quota, and show in its usage as one.
  • Request headers are a claude.ai beta open to a limited set of organizations. If the dialog has no Request headers section, your organization cannot connect TraceFast with a key yet.

claude.ai on a personal account

A personal account connects without a key, by signing in with your TraceFast account:

  1. In claude.ai open Settings → Connectors and click Add custom connector.
  2. Name it TraceFast and enter the URL https://tracefast.xyz/mcp.
  3. Keep what the dialog detects: authentication Sign in now, OAuth client Register automatically. Leave Request headers empty — a key there turns every call into a call with that key.
  4. Click Connect, sign in to TraceFast, and read the consent screen: it names the access asked for (tracefast:read), your plan and the address it returns to. Click Allow.

The connector stays connected and renews its sign-in on its own. The dialog also offers your own OAuth client or Claude's published identity; neither is needed.

  • Your plan decides the tools. A tool above your plan answers with a plan refusal.
  • One budget for every agent you sign in. They share one rate limit and one concurrency cap, and their calls count toward your account's daily quota, which your API keys share too.
  • To disconnect, remove the app under Settings → Connected apps in TraceFast.

A client that connects with neither a key nor a sign-in gets 401 with a WWW-Authenticate header pointing at TraceFast sign-in (resource_metadata, scope tracefast:read). A client that supports MCP sign-in starts it; one that does not reports an authentication error — give it the key header.

Your own agent

Any MCP client with the Streamable HTTP transport that can set a request header works. MCP SDKs negotiate the protocol version and set the protocol headers themselves.

Call the server from a backend or a local process. A request that carries a browser Origin header is refused, and the endpoint answers no CORS preflight — it cannot be called from a web page.

Calling it by hand

For raw HTTP — curl, a test — protocol 2026-07-28 needs no handshake and no session, but every request must carry:

  • the header MCP-Protocol-Version: 2026-07-28, matching the body;
  • the header Mcp-Method with the JSON-RPC method, and on tools/call also Mcp-Name with the tool name;
  • params._meta with both io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. An empty object is a valid clientCapabilities.

A request without one of the _meta keys is refused with HTTP 400 and JSON-RPC error -32602; error.data.missing lists the keys that were absent. SDK clients add them on their own — this matters only when you write the body yourself.

List the tools:

curl -s https://tracefast.xyz/mcp \
  -H "X-Api-Key: $TRACEFAST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/list" \
  -d '{
    "jsonrpc": "2.0", "id": 1, "method": "tools/list",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'

The list is one page, the same for every account, and carries ttlMs: 3600000 with cacheScope: public: a client may keep it for an hour. It is large — each tool comes with its full input and output schemas. Protocol calls such as server/discover and tools/list do not count toward your plan's rate or daily quota; only tool calls do.

Call a tool:

curl -s https://tracefast.xyz/mcp \
  -H "X-Api-Key: $TRACEFAST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: get_latest_block" \
  -d '{
    "jsonrpc": "2.0", "id": 2, "method": "tools/call",
    "params": {
      "name": "get_latest_block",
      "arguments": {},
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'

Results

A tool that answers returns its REST response whole in structuredContent, and the same JSON as one text block for clients that read only text:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "structuredContent": {
      "data": { "number": 26091151, "hash": "0xfdd109390c63bb9efa2d86af53b7b06769d7c2151d9a7f95b69e2f076a5b12f7", "…": "…" },
      "meta": {
        "chain": "ethereum",
        "timestamp": 1790781616092,
        "cached": false,
        "asOfBlock": 26091151,
        "docs": "https://docs.tracefast.xyz/api/block-latest"
      },
      "links": { "web": "https://tracefast.xyz/blocks/26091151" }
    },
    "content": [{ "type": "text", "text": "{\"data\":{…},\"meta\":{…},\"links\":{…}}" }],
    "isError": false
  }
}
  • data and meta are the method's REST answer — see Conventions. meta.asOfBlock is the block the answer is valid at, meta.cached says whether it came from the response cache, meta.docs links the method page. Not every source reaches the chain head at the same moment: see Data freshness.
  • links.web is the TraceFast page of what the answer is about — the entity page of an address or token, the page of a transaction or a block — so an agent can hand its user a link. resolve_entity links its best match, and carries no links when nothing matched.
  • List tools return a small page by default — smaller than the REST method's — and take limit up to the maximum their description states. A larger limit is refused, never cut. Tools with a cursor argument continue with the nextCursor inside data; the others answer in one call.

Refusals

A call can be refused at four points, and each looks different:

Refused byWhat the agent receivesFor example
the credential or a limitHTTP 401 or 429 with the REST refusal body — no tool runsapi_key_required, invalid_api_key, a 429 with bucket
the planHTTP 200: a tool result with isError: true and error.code forbiddenplan_scope_missing
the protocola JSON-RPC error with an integer codea missing _meta key, an unknown tool or argument
the dataHTTP 200: a tool result with isError: truenot_found, block_not_available, bad_request

The key and the limits

These come from the credential check, before any tool runs, in the same envelope as on REST. With no credential the 401 also carries a WWW-Authenticate header that points at TraceFast sign-in:

{
  "error": {
    "code": "auth_failed",
    "message": "authentication failed: sign in with your TraceFast account (OAuth) or send an API key",
    "reason": "api_key_required"
  }
}
  • 401 api_key_required — neither a key nor a valid sign-in was sent: no credential, a header value that is not a TraceFast key, or a sign-in that is invalid or expired. Sign in again, or send the key.
  • 401 invalid_api_key — the value is not a valid key. A disabled, expired or revoked key has its own reason.
  • 429 — a rate limit or the daily quota; bucket names which one, and Retry-After says when to try again where waiting helps. Tool calls share the key's request rate with its REST calls: on a plan with a low rate, two calls sent back to back can get 429 with bucket: base. Pace them.

Every reason and bucket is explained on API keys, with the limits under rate limits and quotas.

The plan

A tool your plan or your key does not open is not an HTTP error on MCP — REST answers 403 for the same thing. It is a tool result on HTTP 200 with isError: true, so the agent can read why and tell its user:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "resultType": "complete",
    "structuredContent": {
      "error": {
        "code": "forbidden",
        "message": "forbidden: your plan does not include this method — see https://tracefast.xyz/pricing for the plans that do",
        "reason": "plan_scope_missing",
        "details": { "upgrade": "https://tracefast.xyz/pricing" },
        "requestId": "…"
      }
    },
    "content": [{ "type": "text", "text": "{\"error\":{…}}" }],
    "isError": true
  }
}
reasonWhat happenedWhat to do
plan_scope_missingthe tool needs a higher plan than yours; details.upgrade links the plansupgrade the plan — the key itself is fine
key_scope_missingyour plan opens the tool, but the key was issued without itissue or rotate a key that includes it
endpoint_group_not_allowedthis key may not call this toolcheck the plan and the key's permissions
account_suspendedthe account is suspendedcontact support

tools/list is the same for every account, so an agent sees tools its plan does not open; the plan each tool needs is in Tools.

The protocol

A request the server cannot take as MCP gets a JSON-RPC error with an integer code, on HTTP 400 in protocol 2026-07-28:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "request _meta is missing: io.modelcontextprotocol/clientCapabilities",
    "data": {
      "missing": ["io.modelcontextprotocol/clientCapabilities"],
      "requestId": "01a0f2e6-f020-7e20-b144-c1ebe68220f4"
    }
  }
}
codeMeaning
-32602invalid params: an unknown tool; an argument the tool does not take, a missing required argument or a value of the wrong type — error.data.argument names it; a missing _meta key — error.data.missing lists them
-32020Mcp-Method, Mcp-Name or MCP-Protocol-Version disagrees with the body, is repeated, or is missing
-32022the protocol version is not served; error.data.supported lists the ones that are
-32601the method does not exist — the server offers tools only, no resources, prompts or subscriptions
-32600not a single JSON-RPC 2.0 request — a batch is refused; also a body over 16 KiB, an HTTP method other than POST and a browser Origin
-32700the body is not JSON

error.data.requestId identifies the request — quote it when you contact support. A client on protocol 2025-11-25 receives the same errors on HTTP 200, as that version expects.

The data

A tool the data refuses — a malformed address, a block the method cannot answer yet, a limit above the tool's maximum — is not an HTTP error. It is an ordinary result on HTTP 200 with isError: true, and structuredContent holds the refusal the REST method gives:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resultType": "complete",
    "structuredContent": {
      "error": {
        "code": "not_found",
        "message": "no block at height 99999999",
        "requestId": "01a0f2e6-efec-73f2-9992-615a0b686e86"
      }
    },
    "content": [{ "type": "text", "text": "{\"error\":{…}}" }],
    "isError": true
  }
}

Branch on error.code and details.reason exactly as on REST — the registry is under Errors. A block_not_available means "not built yet" or "not visible right now", never "does not exist": see Data freshness.

Tools

The list below is generated from the server's own tools/list. Each tool is one method of the REST API: the same arguments under the same names, the same data and the same refusals — its method page is the reference. The heading is the lowest plan that opens the tool; higher plans include it (plans).

Enriched Data

ToolWhat it answers
get_blockOne block
get_block_authorizationsEIP-7702 authorizations of one block
get_block_transactionsTransactions of one block
get_block_withdrawalsValidator withdrawals of one block
get_contractOne contract
get_contract_bytecodeBytecode of a contract
get_contract_proxyImplementations of a proxy contract
get_contract_selectorsFunction selectors of a contract
get_entity_activityActivity of an address
get_entity_balance_historyNative balance history of an address
get_entity_daily_activityDaily activity of an address
get_entity_overviewOne address
get_latest_blockThe latest block
get_tokenOne token contract
get_token_statsToken statistics of the network
get_token_transfersTransfers of a token
get_transactionOne transaction
get_transaction_eventsEvent logs of a transaction
get_transaction_failuresWhy a transaction reverted

Intelligence

ToolWhat it answers
get_block_addressesAccounts touched by one block
get_block_proposersBlock-proposal leaderboard
get_entity_attribute_historyAttribute history of an address
get_entity_attribute_proofProof of one attribute of an address
get_entity_attributesAttributes of an address
get_entity_attributes_at_blockAttributes of an address at a block
get_entity_counterpartiesAddress counterparties
get_entity_portfolioPortfolio of an address
get_entity_relation_historyRelation history of an address
get_entity_relation_proofProof of one relation of an address
get_entity_relationsRelations of an address
get_entity_relations_at_blockRelations of an address at a block
get_entity_token_balanceBalance of one token on an address
get_token_holdersTop holders of a token
get_validator_queue_historyValidator queues over time
get_validator_queuesValidator queues now
get_validator_withdrawalsWithdrawals of a validator
resolve_entityResolve a name, symbol or address

Investigation

ToolWhat it answers
get_blacklist_eventsBlacklist events about one address
get_blacklist_statusWhich issuer contracts list one address
get_contract_eventsEvents emitted by a contract
get_entity_internal_transfersInternal transfers of an address
get_entity_token_transfersToken transfers of an address
get_entity_transactionsTransactions of an address
get_trace_framesCall frames of a transaction, paged
get_transaction_storage_writesStorage writes of a transaction
get_transaction_traceExecution trace of a transaction

Last updated 01 Oct 2026, 13:38 UTC · verified against TraceFast v1.0.135 · Markdown