Skip to main content
Glama

contract_get_function_args

Parse a contract's ABI or use nearblocks.io API to retrieve function call arguments for NEAR blockchain. Checks recent method executions to identify likely inputs. Experimental tool.

Instructions

Get the arguments of a function call by parsing the contract's ABI or by using the nearblocks.io API (as a fallback). This function API checks recent execution results of the contract's method being queried to determine the likely arguments of the function call. Warning: This tool is experimental and is not garunteed to get the correct arguments.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contractIdYes
methodNameYes
networkIdNomainnet

Implementation Reference

  • Registration of the 'contract_get_function_args' MCP tool, including name, description, input schema, and handler function.
    mcp.tool(
      'contract_get_function_args',
      noLeadingWhitespace`
      Get the arguments of a function call by parsing the contract's ABI or by using the nearblocks.io API (as a fallback).
      This function API checks recent execution results of the contract's method being queried
      to determine the likely arguments of the function call.
      Warning: This tool is experimental and is not garunteed to get the correct arguments.`,
      {
        contractId: z.string(),
        methodName: z.string(),
        networkId: z.enum(['testnet', 'mainnet']).default('mainnet'),
      },
      async (args, _) => {
        const connection = await connect({
          networkId: args.networkId,
          nodeUrl: getEndpointsByNetwork(args.networkId)[0]!,
        });
        const contractAccountResult: Result<Account, Error> = await getAccount(
          args.contractId,
          connection,
        );
        if (!contractAccountResult.ok) {
          return {
            content: [
              { type: 'text', text: `Error: ${contractAccountResult.error}` },
            ],
          };
        }
    
        const contractMethods = await getContractMethods(
          args.contractId,
          connection,
        );
        if (!contractMethods.ok) {
          return {
            content: [
              {
                type: 'text',
                text: `Error: ${contractMethods.error}`,
              },
            ],
          };
        }
        if (contractMethods.value.length === 0) {
          return {
            content: [
              {
                type: 'text',
                text: `No methods found for contract ${args.contractId}`,
              },
            ],
          };
        }
        if (!contractMethods.value.includes(args.methodName)) {
          return {
            content: [
              {
                type: 'text',
                text: `Method ${args.methodName} not found for contract ${args.contractId}`,
              },
            ],
          };
        }
    
        const parsedContractABIResult = await getContractABI(
          contractAccountResult.value,
          args.contractId,
        );
    
        // if the contract ABI is not found, ignore, only return if
        // the contract ABI is found
        if (parsedContractABIResult.ok) {
          const abi = parsedContractABIResult.value;
          const method = abi.body.functions.find(
            (method) => method.name === args.methodName,
          );
          if (!method) {
            return {
              content: [
                {
                  type: 'text',
                  text: `Method ${args.methodName} not found in contract ${args.contractId}`,
                },
              ],
            };
          }
          return {
            content: [
              {
                type: 'text',
                text: stringify_bigint({
                  ...method,
                  args: method.params?.args || {},
                }),
              },
            ],
          };
        }
    
        // TODO: This function uses near blocks api which is rate limited
        //       and will fail if we call it too many times. We should
        //       use another method to get the contract methods.
        const parsedContractMethodsResult: Result<JsonSchema7Type, Error> =
          await (async () => {
            try {
              const parsedMethod = await getParsedContractMethod(
                args.contractId,
                args.methodName,
              );
              if (!parsedMethod.ok) {
                return parsedMethod;
              }
              const zodArgsResult = json_to_zod(
                parsedMethod.value.action.length > 0
                  ? parsedMethod.value.action[0]?.args.args_json
                  : {},
              );
              if (!zodArgsResult.ok) {
                return zodArgsResult;
              }
              const jsonSchema = zodToJsonSchema(zodArgsResult.value);
              return {
                ok: true,
                value: jsonSchema,
              };
            } catch (e) {
              return { ok: false, error: new Error(e as string) };
            }
          })();
        if (!parsedContractMethodsResult.ok) {
          return {
            content: [
              {
                type: 'text',
                text: `Error Parsing Contract Methods: ${parsedContractMethodsResult.error}`,
              },
            ],
          };
        }
        const parsedContractMethods = parsedContractMethodsResult.value;
    
        return {
          content: [
            {
              type: 'text',
              text: stringify_bigint(parsedContractMethods),
            },
          ],
        };
      },
    );
  • The main handler function for the tool. Connects to NEAR, validates contract account and method existence, attempts to fetch ABI via __contract_abi for params, falls back to parsing recent tx args from nearblocks.io API using getParsedContractMethod and json_to_zod.
    async (args, _) => {
      const connection = await connect({
        networkId: args.networkId,
        nodeUrl: getEndpointsByNetwork(args.networkId)[0]!,
      });
      const contractAccountResult: Result<Account, Error> = await getAccount(
        args.contractId,
        connection,
      );
      if (!contractAccountResult.ok) {
        return {
          content: [
            { type: 'text', text: `Error: ${contractAccountResult.error}` },
          ],
        };
      }
    
      const contractMethods = await getContractMethods(
        args.contractId,
        connection,
      );
      if (!contractMethods.ok) {
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${contractMethods.error}`,
            },
          ],
        };
      }
      if (contractMethods.value.length === 0) {
        return {
          content: [
            {
              type: 'text',
              text: `No methods found for contract ${args.contractId}`,
            },
          ],
        };
      }
      if (!contractMethods.value.includes(args.methodName)) {
        return {
          content: [
            {
              type: 'text',
              text: `Method ${args.methodName} not found for contract ${args.contractId}`,
            },
          ],
        };
      }
    
      const parsedContractABIResult = await getContractABI(
        contractAccountResult.value,
        args.contractId,
      );
    
      // if the contract ABI is not found, ignore, only return if
      // the contract ABI is found
      if (parsedContractABIResult.ok) {
        const abi = parsedContractABIResult.value;
        const method = abi.body.functions.find(
          (method) => method.name === args.methodName,
        );
        if (!method) {
          return {
            content: [
              {
                type: 'text',
                text: `Method ${args.methodName} not found in contract ${args.contractId}`,
              },
            ],
          };
        }
        return {
          content: [
            {
              type: 'text',
              text: stringify_bigint({
                ...method,
                args: method.params?.args || {},
              }),
            },
          ],
        };
      }
    
      // TODO: This function uses near blocks api which is rate limited
      //       and will fail if we call it too many times. We should
      //       use another method to get the contract methods.
      const parsedContractMethodsResult: Result<JsonSchema7Type, Error> =
        await (async () => {
          try {
            const parsedMethod = await getParsedContractMethod(
              args.contractId,
              args.methodName,
            );
            if (!parsedMethod.ok) {
              return parsedMethod;
            }
            const zodArgsResult = json_to_zod(
              parsedMethod.value.action.length > 0
                ? parsedMethod.value.action[0]?.args.args_json
                : {},
            );
            if (!zodArgsResult.ok) {
              return zodArgsResult;
            }
            const jsonSchema = zodToJsonSchema(zodArgsResult.value);
            return {
              ok: true,
              value: jsonSchema,
            };
          } catch (e) {
            return { ok: false, error: new Error(e as string) };
          }
        })();
      if (!parsedContractMethodsResult.ok) {
        return {
          content: [
            {
              type: 'text',
              text: `Error Parsing Contract Methods: ${parsedContractMethodsResult.error}`,
            },
          ],
        };
      }
      const parsedContractMethods = parsedContractMethodsResult.value;
    
      return {
        content: [
          {
            type: 'text',
            text: stringify_bigint(parsedContractMethods),
          },
        ],
      };
    },
  • Zod input schema defining parameters: contractId (string), methodName (string), networkId (testnet/mainnet, default mainnet).
      contractId: z.string(),
      methodName: z.string(),
      networkId: z.enum(['testnet', 'mainnet']).default('mainnet'),
    },
  • Helper function to retrieve and parse the contract's ABI from the __contract_abi view method, used as primary source for function arguments.
    const getContractABI = async (
      account: Account,
      contractAccountId: string,
    ): Promise<Result<AbiRoot, Error>> => {
      try {
        const contractABICompressed: unknown = await account.viewFunction({
          contractId: contractAccountId,
          methodName: '__contract_abi',
          args: {},
          parse: (value) => value,
        });
    
        const decoder = new ZSTDDecoder();
        await decoder.init();
        const contractABI = new TextDecoder().decode(
          decoder.decode(contractABICompressed as Buffer),
        );
        return {
          ok: true,
          value: JSON.parse(contractABI) as AbiRoot,
        };
      } catch (e) {
        return { ok: false, error: new Error(e as string) };
      }
    };
  • Fallback helper: Queries nearblocks.io API for recent executions of the method to infer argument structure from args_json.
    export const getParsedContractMethod = async (
      contractId: string,
      methodName: string,
    ): Promise<Result<ParsedMethod, Error>> => {
      try {
        const url = `https://api.nearblocks.io/v1/account/${contractId}/contract/${methodName}`;
        const response = await fetch(url);
        const responseJson = (await response.json()) as unknown;
        const parsedMethod = ParsedMethodSchema.safeParse(responseJson);
        if (!parsedMethod.success) {
          return {
            ok: false,
            error: new Error(
              `Error parsing args for contract ${contractId}, method ${methodName}. Got: ${JSON.stringify(
                responseJson,
                null,
                2,
              )}`,
            ),
          };
        }
        return {
          ok: true,
          value: parsedMethod.data,
        };
      } catch (error) {
        return {
          ok: false,
          error: new Error(
            `Error parsing contract method ${methodName} for contract ${contractId}: ${String(error)}`,
          ),
        };
      }

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/nearai/near-mcp'

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