Skip to main content
Glama
Bankless

Bankless Onchain MCP Server

Official
by Bankless

read_contract

Extract and decode blockchain contract states by specifying contract address, method, and expected output types. Ensures accurate data retrieval for nested structures and tuples.

Instructions

Read contract state from a blockchain. important:

In case of a tuple, don't use type tuple, but specify the inner types (found in the source) in order. For nested structs, include the substructs types. Example: struct DataTypeA { DataTypeB b; //the liquidity index. Expressed in ray uint128 liquidityIndex; } struct DataTypeB { address token; } results in outputs for function with return type DataTypeA (tuple in abi): outputs: [{"type": "address"}, {"type": "uint128"}]

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contractYesThe contract address
inputsYesInput parameters for the method call
methodYesThe contract method to call
networkYesThe blockchain network (e.g., "ethereum", "base")
outputsYesExpected output types for the method call. In case of a tuple, don't use type tuple, but specify the inner types (found in the source) in order. For nested structs, include the substructs types. Example: struct DataTypeA { DataTypeB b; //the liquidity index. Expressed in ray uint128 liquidityIndex; } struct DataTypeB { address token; } results in outputs for function with return type DataTypeA (tuple in abi): outputs: [{"type": "address"}, {"type": "uint128"}]

Implementation Reference

  • src/index.ts:63-81 (registration)
    Registration of the 'read_contract' tool in the MCP server's list of tools, specifying name, description, and input schema.
    name: "read_contract", description: `Read contract state from a blockchain. important: In case of a tuple, don't use type tuple, but specify the inner types (found in the source) in order. For nested structs, include the substructs types. Example: struct DataTypeA { DataTypeB b; //the liquidity index. Expressed in ray uint128 liquidityIndex; } struct DataTypeB { address token; } results in outputs for function with return type DataTypeA (tuple in abi): outputs: [{"type": "address"}, {"type": "uint128"}]`, inputSchema: zodToJsonSchema(contracts.ReadContractSchema), },
  • Zod schema defining the input structure for the read_contract tool, including network, contract, method, inputs, and outputs.
    export const ReadContractSchema = z.object({ network: z.string().describe('The blockchain network (e.g., "ethereum", "base")'), contract: z.string().describe('The contract address'), method: z.string().describe('The contract method to call'), inputs: z.array(InputSchema).describe('Input parameters for the method call'), outputs: z.array(OutputSchema).describe(`Expected output types for the method call. In case of a tuple, don't use type tuple, but specify the inner types (found in the source) in order. For nested structs, include the substructs types. Example: struct DataTypeA { DataTypeB b; //the liquidity index. Expressed in ray uint128 liquidityIndex; } struct DataTypeB { address token; } results in outputs for function with return type DataTypeA (tuple in abi): outputs: [{"type": "address"}, {"type": "uint128"}] `) });
  • MCP CallToolRequest handler case for 'read_contract', parses arguments, calls the implementation function, and formats response.
    case "read_contract": { const args = contracts.ReadContractSchema.parse(request.params.arguments); const result = await contracts.readContractState( args.network, args.contract, args.method, args.inputs, args.outputs ); return { content: [{type: "text", text: JSON.stringify(result, null, 2)}], }; }
  • Core implementation of the read_contract tool: processes outputs, authenticates with API token, makes POST request to Bankless API to read contract state, handles various errors.
    export async function readContractState( network: string, contract: string, method: string, inputs: z.infer<typeof InputSchema>[], outputs: z.infer<typeof OutputSchema>[] ): Promise<ContractCallResult[]> { const token = process.env.BANKLESS_API_TOKEN; if (!token) { throw new BanklessAuthenticationError('BANKLESS_API_TOKEN environment variable is not set'); } const endpoint = `${BASE_URL}/chains/${network}/contract/read`; const cleanedOutputs = processOutputs(outputs); try { const response = await axios.post( endpoint, { contract, method, inputs, outputs: cleanedOutputs }, { headers: { 'Content-Type': 'application/json', 'X-BANKLESS-TOKEN': `${token}` } } ); return response.data; } catch (error) { if (axios.isAxiosError(error)) { const statusCode = error.response?.status || 'unknown'; const errorMessage = error.response?.data?.message || error.message; if (statusCode === 401 || statusCode === 403) { throw new BanklessAuthenticationError(`Authentication Failed: ${errorMessage}`); } else if (statusCode === 404) { throw new BanklessResourceNotFoundError(`Not Found: ${errorMessage}`); } else if (statusCode === 422) { throw new BanklessValidationError(`Validation Error: ${errorMessage}`, error.response?.data); } else if (statusCode === 429) { // Extract reset timestamp or default to 60 seconds from now const resetAt = new Date(); resetAt.setSeconds(resetAt.getSeconds() + 60); throw new BanklessRateLimitError(`Rate Limit Exceeded: ${errorMessage}`, resetAt); } throw new Error(`Bankless API Error (${statusCode}): ${errorMessage}`); } throw new Error(`Failed to read contract state: ${error instanceof Error ? error.message : String(error)}`); } }
  • Helper function to process output schemas, flattening tuples recursively for the API request.
    export function processOutputs(outputs: OutputSchemaType[]) { if (!outputs || !Array.isArray(outputs)) { return []; } const result: OutputSchemaType[] = []; for (const output of outputs) { const processed = processOutput(output); result.push(...processed); } return result; }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bankless/onchain-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server