Server has 21 tools across blocks, bridge, contracts, deployment, and domains. Most tools have descriptions and input schemas, but quality varies. Naming is generally clear and action-verb based. Descriptions are present but often terse (15-50 chars for many tools). Schemas are visible for all tools with proper JSON Schema structure, but several issues emerge: (1) Parameter descriptions vary in quality, some are clear, others minimal. (2) No output schemas documented, critical for tools like get_block_by_hash or read_contract that return complex data. (3) Error handling is not evident in the tool definitions. (4) High-risk operations (execute_bridge, write_contract, deploy_contract, deploy_create2) accept private keys as parameters, a CRITICAL SECURITY violation. (5) Some parameters like 'abi' in read_contract and write_contract lack format guidance. (6) No evidence of idempotency hints or retry guidance. Tools are individually well-named but collectively lack composition guidance.
CRITICAL: Private keys exposed as tool parameters. Tools execute_bridge, write_contract, deploy_contract, deploy_create2 accept privateKey as input. This is a fundamental security violation, private keys must never appear in tool parameters as they will be logged, traced, and persisted in agent histories.
No output schemas documented for any tool. The rubric requires documented return types for A+ tools. Tools like get_block_by_hash, read_contract, and get_block_with_transactions likely return complex nested objects (block data, transaction arrays, etc.) but the output structure is not specified in the tool definitions provided.
URGENT: Refactor all private-key-handling tools (execute_bridge, write_contract, deploy_contract, deploy_create2) to use server-side secret injection. Accept a 'wallet_name' or 'account_id' parameter instead, and resolve credentials from environment or secure vault inside the tool handler. Never expose secrets in tool parameters.
Document output schemas for all tools. For each tool, specify the response structure (object fields, types, example). E.g., get_block_by_hash returns {blockHash, timestamp, gasUsed, transactions: [{hash, from, to, value}], ...}. This enables LLMs to extract the right data and chain tools efficiently.
Expand descriptions from terse one-liners to 50 - 150 chars explaining WHAT, WHEN, and key details. E.g., 'Get a block by hash: retrieve full block data from the blockchain using its 32-byte hash. Use this when you have a block hash and need timestamps, gas data, or transactions. Prefer get_block_by_number if you have a block height instead.'
Add enum constraints for the 'network' parameter. Define allowed values (ethereum, bsc, polygon, arbitrum, optimism, base, avalanche, opbnb, linea, etc.) and declare in schema as enum. This prevents hallucinated network names and clarifies supported chains.
For 'blockNumber', 'startBlock', 'endBlock' parameters: specify format explicitly. E.g., 'Block number as a decimal string (e.g., "12345") or 0x-prefixed hex (e.g., "0x3039"). Will be parsed as BigInt.' Include min/max bounds if applicable.
Document ABI format requirements for read_contract and write_contract. Specify that 'abi' must be a JSON array of Solidity ABI entries, each with {type, name, inputs[], outputs[], ...}. Optionally provide a link to Solidity ABI spec or an example.
Descriptions too terse and lack WHEN/WHY guidance. Many descriptions are 50 - 60 characters with no context on when to use the tool vs alternatives. E.g., 'Get a block by hash' vs 'Retrieve a block from the blockchain by its 32-byte hash. Use this to look up a specific block when you know its hash; use get_block_by_number for height-based lookups.'
Parameter 'abi' in read_contract and write_contract has no format guidance. Description says 'The ABI of the smart contract function, as a JSON array' but does not explain the ABI schema format (is it the standard Solidity ABI JSON? What fields are required? Can it be a string or must it be an array object?). LLMs cannot construct valid ABIs from vague descriptions.
No error handling or recovery guidance. None of the tools specify what errors can occur, how to interpret them, or what the agent should do next. E.g., execute_bridge should document: 'Fails if token not supported on source chain; fails if insufficient balance; fails if private key invalid. In all cases, no funds are transferred.' This guides retry vs user-fixable decisions.
No idempotency hints or safe-to-retry guidance. Tools like get_block_by_hash are clearly idempotent (read-only), but this is not declared via toolAnnotations (readOnlyHint). Tools like deploy_contract are irreversible but have no idempotentHint=false or destructiveHint=true declaration.
Parameter 'blockNumber' and 'startBlock' described as strings but semantically integers. Descriptions should specify: 'Block number as a string (e.g., "12345") or hex string (e.g., "0x3039"). Will be converted to a BigInt for RPC calls.' Without this, LLMs may pass decimal strings, hex without 0x prefix, or other invalid formats.
Network parameter lacks enum constraint. Description says 'e.g., ethereum, bsc, polygon' but does not list all valid values or declare them as an enum. LLMs will hallucinate network names like 'eth', 'bnb', 'polygon-mainnet', etc., causing failures. All 21 tools accept 'network' but none constrain it formally.
No composition guidance for multi-step flows. E.g., if a user wants to 'call a contract and get the block it was included in', there's no documentation suggesting: search for tx → get_block_by_number with the tx's blockNumber. Or for bridges: get_bridge_quote → verify token approved → execute_bridge. LLMs spend extra reasoning cycles on trial-and-error instead of following documented patterns.
No rate limiting or result cap documentation. Tools like get_block_range could return thousands of blocks if endBlock is set far ahead of startBlock. No documented limit (e.g., max 1000 blocks per call) means agents could request gigabytes of data, exhausting context windows and costs.
get_block_rangeget_block_receipts
Add error recovery guidance to high-risk tools. E.g., execute_bridge: 'Returns error if token unsupported, balance insufficient, or private key invalid. In all cases, no funds are moved. User should verify balance and bridge support before retrying.' Categorize errors as retryable, user-fixable, or fatal.
Declare tool annotations (toolAnnotations) for all tools. Mark read-only tools with readOnlyHint=true (is_contract, get_block_*, read_contract, resolve_ens_name, etc.). Mark destructive/irreversible tools with destructiveHint=true and idempotentHint=false (deploy_contract, deploy_create2, execute_bridge, write_contract).
Document composition patterns in descriptions. E.g., read_contract: 'Common flow: (1) resolve a contract address via search or deployment logs, (2) call read_contract with its ABI and function name, (3) extract data from response. If you need to modify state, use write_contract instead.' This guides multi-step planning.
Add pagination and result limits to get_block_range and get_block_receipts. Specify max results per call (e.g., max 1000 blocks, max 500 receipts) and include a cursor/offset in the response for fetching the next page. Document in descriptions: 'Returns up to 100 blocks per call. Use startBlock and endBlock to iterate.'
For optional parameters (e.g., blockNumber defaulting to 'latest', recipient defaulting to sender), explicitly state defaults in descriptions. E.g., 'blockNumber (optional, defaults to latest block)', 'recipient (optional, defaults to the sender address derived from privateKey)'.
Validate network names early and return actionable errors. Instead of a generic 'Invalid network', return 'Invalid network: got "polygon-mainnet", did you mean "polygon"? Supported: ethereum, bsc, polygon, arbitrum, optimism, base, avalanche, opbnb, linea.'
For tools accepting fees or gas parameters (deploy_contract, execute_bridge), document gas estimation and fee ranges. E.g., 'gasLimit: optional, defaults to auto-estimated. Typical values: 100000 - 500000 for contract deployment. Set higher for complex constructors.'
Ensure consistent parameter naming across tools. If get_block_by_number uses 'blockNumber', other block lookups should too (not 'block_height', 'block_id', or 'height'). Mismatched names force LLMs to re-resolve parameter types, wasting reasoning cycles.