Skip to main content
Glama
MoralisWeb3

Moralis MCP Server

Official
by MoralisWeb3

evm_getlatestblocknumber

Retrieve the current block number for a specified blockchain to synchronize transactions, monitor network activity, or verify data timestamps.

Instructions

Get the most recent block number for a specified blockchain.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chainYesThe chain to queryeth

Implementation Reference

  • The core handler function for all dynamically registered API tools, including 'evm_getlatestblocknumber'. It takes the tool definition (from OpenAPI parsing), user arguments, constructs the appropriate HTTP request to the Moralis EVM API endpoint, handles authentication with API key, executes via axios, and returns formatted JSON/text response.
    export async function executeApiTool(
      toolName: string,
      definition: McpToolDefinition,
      toolArgs: JsonObject,
      allSecuritySchemes: Record<string, any>,
      token?: string,
    ): Promise<CallToolResult> {
      try {
        // Validate arguments against the input schema
        let validatedArgs: JsonObject;
        try {
          const zodSchema = getZodSchemaFromJsonSchema(
            definition.inputSchema,
            toolName,
          );
          const argsToParse =
            typeof toolArgs === 'object' && toolArgs !== null ? toolArgs : {};
          validatedArgs = zodSchema.parse(argsToParse);
        } catch (error: unknown) {
          if (error instanceof ZodError) {
            const validationErrorMessage = `Invalid arguments for tool '${toolName}': ${error.errors.map((e) => `${e.path.join('.')} (${e.code}): ${e.message}`).join(', ')}`;
            return { content: [{ type: 'text', text: validationErrorMessage }] };
          } else {
            const errorMessage =
              error instanceof Error ? error.message : String(error);
            return {
              content: [
                {
                  type: 'text',
                  text: `Internal error during validation setup: ${errorMessage}`,
                },
              ],
            };
          }
        }
    
        // Prepare URL, query parameters, headers, and request body
        let urlPath = definition.pathTemplate;
        const queryParams: Record<string, any> = {};
        const headers: Record<string, string> = {
          Accept: 'application/json',
          'X-Moralis-Platform': 'MCP',
        };
        let requestBodyData: any = undefined;
    
        // Apply parameters to the URL path, query, or headers
        definition.executionParameters.forEach((param) => {
          const value = validatedArgs[param.name];
          if (typeof value !== 'undefined' && value !== null) {
            if (param.in === 'path') {
              urlPath = urlPath.replace(
                `{${param.name}}`,
                encodeURIComponent(String(value)),
              );
            } else if (param.in === 'query') {
              queryParams[param.name] = value;
            } else if (param.in === 'header') {
              headers[param.name.toLowerCase()] = String(value);
            }
          }
        });
    
        // Ensure all path parameters are resolved
        if (urlPath.includes('{')) {
          throw new Error(`Failed to resolve path parameters: ${urlPath}`);
        }
    
        // Construct the full URL
        const requestUrl = `${definition.baseUrl}${urlPath}`;
    
        // Handle request body if needed
        if (
          definition.requestBodyContentType &&
          typeof validatedArgs['requestBody'] !== 'undefined'
        ) {
          requestBodyData = validatedArgs['requestBody'];
          headers['content-type'] = definition.requestBodyContentType;
        }
    
        // Apply security requirements if available
        // Security requirements use OR between array items and AND within each object
        const appliedSecurity = definition.securityRequirements?.find((req) => {
          // Try each security requirement (combined with OR)
          return Object.entries(req).every(([schemeName, scopesArray]) => {
            const scheme = allSecuritySchemes[schemeName];
            if (!scheme) return false;
    
            // API Key security (header, query, cookie)
            if (scheme.type === 'apiKey') {
              return !!token || !!Config.MORALIS_API_KEY;
            }
    
            return false;
          });
        });
    
        // If we found matching security scheme(s), apply them
        if (appliedSecurity) {
          // Apply each security scheme from this requirement (combined with AND)
          for (const [schemeName, scopesArray] of Object.entries(appliedSecurity)) {
            const scheme = allSecuritySchemes[schemeName];
    
            // API Key security
            if (scheme?.type === 'apiKey') {
              const apiKey = token || Config.MORALIS_API_KEY;
              if (apiKey) {
                if (scheme.in === 'header') {
                  headers[scheme.name.toLowerCase()] = apiKey;
                  console.error(
                    `Applied API key '${schemeName}' in header '${scheme.name}'`,
                  );
                }
              }
            }
          }
        }
        // Log warning if security is required but not available
        else if (definition.securityRequirements?.length > 0) {
          // First generate a more readable representation of the security requirements
          const securityRequirementsString = definition.securityRequirements
            .map((req) => {
              const parts = Object.entries(req)
                .map(([name, scopesArray]) => {
                  const scopes = scopesArray as string[];
                  if (scopes.length === 0) return name;
                  return `${name} (scopes: ${scopes.join(', ')})`;
                })
                .join(' AND ');
              return `[${parts}]`;
            })
            .join(' OR ');
    
          console.warn(
            `Tool '${toolName}' requires security: ${securityRequirementsString}, but no suitable credentials found.`,
          );
        }
    
        // Prepare the axios request configuration
        const config: AxiosRequestConfig = {
          method: definition.method.toUpperCase(),
          url: requestUrl,
          params: queryParams,
          headers: headers,
          ...(requestBodyData !== undefined && { data: requestBodyData }),
        };
    
        // Log request info to stderr (doesn't affect MCP output)
        console.error(
          `Executing tool "${toolName}": ${config.method} ${config.url}`,
        );
    
        // Execute the request
        const response = await axios(config);
    
        // Process and format the response
        let responseText = '';
        const contentType = response.headers['content-type']?.toLowerCase() || '';
    
        // Handle JSON responses
        if (
          contentType.includes('application/json') &&
          typeof response.data === 'object' &&
          response.data !== null
        ) {
          try {
            responseText = JSON.stringify(response.data, null, 2);
          } catch (e) {
            responseText = '[Stringify Error]';
          }
        }
        // Handle string responses
        else if (typeof response.data === 'string') {
          responseText = response.data;
        }
        // Handle other response types
        else if (response.data !== undefined && response.data !== null) {
          responseText = String(response.data);
        }
        // Handle empty responses
        else {
          responseText = `(Status: ${response.status} - No body content)`;
        }
    
        // Return formatted response
        return {
          content: [
            {
              type: 'text',
              text: `API Response (Status: ${response.status}):\n${responseText}`,
            },
          ],
        };
      } catch (error: unknown) {
        // Handle errors during execution
        let errorMessage: string;
    
        // Format Axios errors specially
        if (axios.isAxiosError(error)) {
          errorMessage = formatApiError(error);
        }
        // Handle standard errors
        else if (error instanceof Error) {
          errorMessage = error.message;
        }
        // Handle unexpected error types
        else {
          errorMessage = `Unexpected error: ${String(error)}`;
        }
    
        // Log error to stderr
        console.error(
          `Error during execution of tool '${toolName}':`,
          errorMessage,
        );
    
        // Return error message to client
        return { content: [{ type: 'text', text: errorMessage }] };
      }
    }
  • src/server.ts:26-72 (registration)
    Registers EVM tools by fetching Moralis OpenAPI spec, dereferencing, extracting tool definitions with 'evm_' prefix via extractToolsFromApi, building toolDefinitionMap used for ListTools response and CallTool dispatch.
    async function mapToolDefinitions(config: SchemaConfig) {
      const spec = (await getSpec(config.specUrl)) as OpenAPIV3DocumentX;
      const api = (await SwaggerParser.dereference(spec)) as OpenAPIV3DocumentX;
    
      const tools = extractToolsFromApi(api, config.prefix);
      const blacklist = Array.isArray(api['x-mcp-blacklist'])
        ? api['x-mcp-blacklist'].map((e) => `${config.prefix}${e.toLowerCase()}`)
        : [];
    
      const toolDefinitionMap: Record<string, McpToolDefinition> = {};
      for (const tool of tools) {
        if (blacklist.includes(tool.name)) continue;
        toolDefinitionMap[tool.name] = {
          ...tool,
          baseUrl: config.baseUrl,
        };
      }
      return toolDefinitionMap;
    }
    
    export async function serverSetup(
      config: SchemaConfig | SchemaConfig[] = [
        Config.EVM_CONFIG,
        Config.SOL_CONFIG,
      ],
    ) {
      let configArray = Array.isArray(config) ? config : [config];
      if (Config.SERVER_CONFIG) configArray = [Config.SERVER_CONFIG];
    
      /**
       * MCP Server instance
       */
      const server = new Server(
        { name: Config.SERVER_NAME, version: Config.SERVER_VERSION },
        { capabilities: { tools: {}, prompts: {} } },
      );
    
      /**
       * Map of tool definitions by name
       */
      let toolDefinitionMap: Record<string, McpToolDefinition> = {};
      for (const config of configArray)
        toolDefinitionMap = {
          ...toolDefinitionMap,
          ...(await mapToolDefinitions(config)),
        };
  • Generates the inputSchema (JSON Schema) for each tool from OpenAPI operation parameters (path/query/header) and requestBody, used for MCP tool definition and Zod validation in handler.
    export function generateInputSchemaAndDetails(
      operation: OpenAPIV3.OperationObject,
    ): {
      inputSchema: JSONSchema7 | boolean;
      parameters: OpenAPIV3.ParameterObject[];
      requestBodyContentType?: string;
    } {
      const properties: { [key: string]: JSONSchema7 | boolean } = {};
      const required: string[] = [];
    
      // Process parameters
      const allParameters: OpenAPIV3.ParameterObject[] = Array.isArray(
        operation.parameters,
      )
        ? operation.parameters.map((p) => p as OpenAPIV3.ParameterObject)
        : [];
    
      allParameters.forEach((param) => {
        if (!param.name || !param.schema) return;
    
        const paramSchema = mapOpenApiSchemaToJsonSchema(
          param.schema as OpenAPIV3.SchemaObject,
        );
        if (typeof paramSchema === 'object') {
          paramSchema.description = param.description || paramSchema.description;
        }
    
        properties[param.name] = paramSchema;
        if (param.required) required.push(param.name);
      });
    
      // Process request body (if present)
      let requestBodyContentType: string | undefined = undefined;
    
      if (operation.requestBody) {
        const opRequestBody = operation.requestBody as OpenAPIV3.RequestBodyObject;
        const jsonContent = opRequestBody.content?.['application/json'];
        const firstContent = opRequestBody.content
          ? Object.entries(opRequestBody.content)[0]
          : undefined;
    
        if (jsonContent?.schema) {
          requestBodyContentType = 'application/json';
          const bodySchema = mapOpenApiSchemaToJsonSchema(
            jsonContent.schema as OpenAPIV3.SchemaObject,
          );
    
          if (typeof bodySchema === 'object') {
            bodySchema.description =
              opRequestBody.description ||
              bodySchema.description ||
              'The JSON request body.';
          }
    
          properties['requestBody'] = bodySchema;
          if (opRequestBody.required) required.push('requestBody');
        } else if (firstContent) {
          const [contentType] = firstContent;
          requestBodyContentType = contentType;
    
          properties['requestBody'] = {
            type: 'string',
            description:
              opRequestBody.description ||
              `Request body (content type: ${contentType})`,
          };
    
          if (opRequestBody.required) required.push('requestBody');
        }
      }
    
      // Combine everything into a JSON Schema
      const inputSchema: JSONSchema7 = {
        type: 'object',
        properties,
        ...(required.length > 0 && { required }),
      };
    
      return { inputSchema, parameters: allParameters, requestBodyContentType };
    }
  • src/server.ts:96-120 (registration)
    MCP CallTool request handler that looks up the tool definition by name (e.g. 'evm_getlatestblocknumber') and dispatches to the generic executeApiTool handler.
    server.setRequestHandler(
      CallToolRequestSchema,
      async (request: CallToolRequest, c): Promise<CallToolResult> => {
        const { name: toolName, arguments: toolArgs } = request.params;
        const toolDefinition = toolDefinitionMap[toolName];
        if (!toolDefinition) {
          console.error(`Error: Unknown tool requested: ${toolName}`);
          return {
            content: [
              {
                type: 'text',
                text: `Error: Unknown tool requested: ${toolName}`,
              },
            ],
          };
        }
        return executeApiTool(
          toolName,
          toolDefinition,
          toolArgs ?? {},
          securitySchemes,
          c.authInfo?.token,
        );
      },
    );
  • Configuration for EVM tools: defines 'evm_' prefix (key for tool name 'evm_getlatestblocknumber'), base API URL, and OpenAPI spec URL from which the tool is extracted.
    evm:  {
      prefix: 'evm_',
      baseUrl:
        process.env.API_BASE_URL || 'https://deep-index.moralis.io/api/v2.2',
      specUrl:
        process.env.API_SPEC_URL ||
        'https://deep-index.moralis.io/api-docs-2.2/v2.2/swagger.json',
    },
Install Server

Other 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/MoralisWeb3/moralis-mcp-server'

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