Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
The 1scan MCP server provides 13 blockchain query tools with consistent naming, clear verb-based patterns (all start with 'get_'), and documented input schemas. However, critical gaps remain: (1) Output schemas are not documented anywhere, LLMs cannot predict what fields will be returned, forcing them to guess at response structure; (2) Parameter descriptions are minimal and generic ('The blockchain chain ID', 'The account address'), they lack usage context, constraints, and LLM-optimized guidance; (3) Error handling is invisible, no recovery guidance, no indication of retryable vs fatal errors; (4) Tool descriptions are terse (10-25 chars on average) and fail to answer WHEN to use each tool vs similar alternatives. The server follows basic naming conventions well but falls short on description depth and schema documentation required for confident LLM tool selection.
Tools (13)
execute_contract_methodread onlyauth50/100
Get the result of a read contract function
get_account_balanceread onlyauth48/100
Get the balance of an account on a specific chain
get_block_by_numberread onlyauth48/100
Get block information for a given block number
get_block_rewardsread onlyauth48/100
Get block rewards by block number
get_contract_abiread onlyauth48/100
Get the ABI for a verified contract
get_contract_source_coderead onlyauth48/100
Get the source code of a verified contract
get_erc721_transfersread onlyauth50/100
Get ERC721 token transfers by address with optional contract filter, block range, and pagination
Output schemas are completely undocumented. None of the 13 tools declare what fields their responses will contain. LLMs cannot predict response structure, forcing them to guess which fields are available for downstream chaining or parsing.
Tool descriptions are critically short (10-25 chars) and lack context. Examples: 'Get the balance of an account on a specific chain' (54 chars) answers WHAT but not WHEN to call it vs get_token_balance, or what format the return value is. Descriptions fall well below the 50-200 char LLM-optimized baseline and do not guide tool selection.
Add documented output schemas to all 13 tools. Specify the JSON structure and field types agents will receive. Example for get_account_balance: 'Returns {status: string, message: string, result: string (balance in wei)}' so LLMs know what fields to extract.
Expand tool descriptions to 100-150 characters and answer: WHAT does it do? WHEN should the LLM call it vs similar tools? WHAT does it return? Example: 'Get the native token balance (in wei) for an account on the specified blockchain. Use this for ETH/native tokens; use get_token_balance for ERC20 tokens. Returns {status, message, result}.'
Add parameter constraints and format guidance to all descriptions. For chain_id: 'The blockchain chain ID (e.g. 1=Ethereum, 137=Polygon, 42161=Arbitrum; or ethereum, polygon, arbitrum)'. For address: 'A valid 0x-prefixed Ethereum address (42 chars total, e.g. 0x1234567890123456789012345678901234567890)'. For block_number: 'Block number as decimal string (e.g. "18500000") or "latest", "earliest", "pending".'
Document pagination behavior explicitly. For tools with page/offset params: 'Returns paginated results; page=1, offset=20 (default). Max offset is 10000. If result count equals offset, more pages may exist, increment page and retry. Returns {status, message, result: [{...}], total_records: int}.'
Add error handling guidance to descriptions. Example: 'If chain_id is invalid or not configured, returns {status: "0", message: "no configuration found for chain X"}. If all API keys are rate-limited, wait 1+ second and retry with a different address or chain. These errors are retryable.'
Spec posture evidence
Inferred effective spec: <=2025-11-25.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
Parameter descriptions are generic boilerplate lacking constraints and format guidance. 'The blockchain chain ID' does not tell an LLM what format chain_id should take (e.g. '1' for Ethereum, '137' for Polygon, 'ethereum', 'polygon'?), what values are valid, or if it is case-sensitive. This invites hallucinated invalid values.
No error handling guidance. The source code shows error paths (e.g. 'all API keys for chain %s are rate limited', 'no configuration found for chain %s') but tool definitions include no recovery guidance. LLMs cannot distinguish between transient (retry later) and permanent (try different parameters) failures.
Pagination parameters (start_block, end_block, page, offset) on get_transactions_by_address and similar tools are marked optional and have no descriptions explaining their purpose, constraints (e.g. max page size), or default behavior. An LLM cannot determine if omitting 'page' returns all results or defaults to page 1.
Parameter 'method_abi' on execute_contract_method expects a string representation of an ABI definition. No description explains the format (JSON string? Stringified? Example?), encoding, or validation rules. This is a complex structured input with zero guidance.
Naming ambiguity: get_transactions_by_address vs get_internal_transactions_by_address vs get_token_transfers_by_address are distinct tools but descriptions do not clarify when to use each. What is the difference between 'internal transactions' and regular transactions? When would an LLM choose one over the other?
Clarify the semantic difference between transaction types in descriptions. get_transactions_by_address: 'All external transactions (EOA to EOA, EOA to contract). Use this to see all contract interactions.' get_internal_transactions_by_address: 'Internal contract-to-contract calls and value transfers. Use to trace internal execution flows.' get_token_transfers_by_address: 'ERC20 token transfer events only. Use to see token movements.'
For execute_contract_method, document the method_abi format and provide an example. 'method_abi is a JSON string describing the contract function signature. Example: {"name": "balanceOf", "inputs": [{"name": "account", "type": "address"}], "outputs": [{"name": "balance", "type": "uint256"}], "type": "function", "stateMutability": "view"}. method_params is a JSON string of parameter values, e.g. {"account": "0x1234..."}'
Add enum constraints for chain_id. Instead of free-form string, declare: chain_id enum: ['1', '10', '137', '42161', 'ethereum', 'optimism', 'polygon', 'arbitrum', ...] so LLMs can see valid options without hallucinating unsupported chains.
Declare input validation and return clear actionable error messages. If address is not a valid 0x address, return: 'Invalid address format: received "abc123", must be 0x-prefixed 42-character hex string (e.g. 0x1234567890123456789012345678901234567890)'. This enables LLM self-correction.
Add a per-tool 'When to use' section in descriptions. Example for get_contract_source_code: 'Use this when you need to audit contract logic, understand function behavior, or verify deployment details. Requires the contract to be verified on a block explorer (Etherscan, Polygonscan, etc.). If source code is not available, returns {status: "0", message: "not found"}, in this case, suggest checking the contract on a block explorer manually or using get_contract_abi to inspect the function signatures.'