Skip to main content
Glama
MoralisWeb3

Moralis MCP Server

Official
by MoralisWeb3

evm_gettokenscore

Analyze token performance by retrieving comprehensive metrics including price, volume, liquidity, transaction counts, and supply data for informed blockchain investment decisions.

Instructions

Retrieve a score for a specific token along with detailed metrics including price, volume, liquidity, transaction counts, and supply information.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chainNoThe chain to queryeth
tokenAddressYesThe token address to query

Implementation Reference

  • The core handler function that implements the logic for executing any API-based tool, including 'evm_gettokenscore'. It validates input using Zod from the tool's schema, constructs the HTTP request using the pathTemplate, method, parameters from the OpenAPI-derived definition, adds authentication, sends via axios to the Moralis API, and formats the 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:97-120 (registration)
    Registers the CallToolRequest handler on the MCP server, which looks up the dynamic tool definition for 'evm_gettokenscore' and dispatches to the executeApiTool handler.
      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,
        );
      },
    );
  • src/server.ts:26-44 (registration)
    Dynamically loads the OpenAPI spec for EVM tools, extracts all tools with 'evm_' prefix (including evm_gettokenscore), builds toolDefinitionMap used for registration and execution.
    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;
    }
  • Parses OpenAPI document to extract tool definitions, including schema/inputSchema for 'evm_gettokenscore' based on its operation parameters and requestBody.
    export function extractToolsFromApi(
      api: OpenAPIV3DocumentX,
      prefix?: string
    ): McpToolDefinition[] {
      const tools: McpToolDefinition[] = [];
      const usedNames = new Set<string>();
      const globalSecurity = api.security || [];
    
      if (!api.paths) return tools;
    
      for (const [path, pathItem] of Object.entries(api.paths)) {
        if (!pathItem) continue;
    
        for (const method of Object.values(OpenAPIV3.HttpMethods)) {
          const operation = pathItem[method];
          if (!operation) continue;
    
          // Generate a unique name for the tool
          let baseName = operation.operationId || generateOperationId(method, path);
          if (!baseName) continue;
    
          // Sanitize the name to be MCP-compatible (only a-z, 0-9, _, -)
          baseName = baseName
            .replace(/\./g, '_')
            .replace(/[^a-z0-9_-]/gi, '_')
            .toLowerCase();
    
          let finalToolName = baseName;
          let counter = 1;
          while (usedNames.has(finalToolName)) {
            finalToolName = `${baseName}_${counter++}`;
          }
          usedNames.add(finalToolName);
    
          // Get or create a description
          const description =
            operation.description ||
            operation.summary ||
            `Executes ${method.toUpperCase()} ${path}`;
    
          const prompt = operation['x-mcp-prompt'];
    
          // Generate input schema and extract parameters
          const { inputSchema, parameters, requestBodyContentType } =
            generateInputSchemaAndDetails(operation);
    
          // Extract parameter details for execution
          const executionParameters = parameters.map((p) => ({
            name: p.name,
            in: p.in,
          }));
    
          // Determine security requirements
          const securityRequirements =
            operation.security === null
              ? globalSecurity
              : operation.security || globalSecurity;
    
          // Create the tool definition
          tools.push({
            name: prefix + finalToolName,
            description,
            inputSchema,
            method,
            pathTemplate: path,
            parameters,
            executionParameters,
            requestBodyContentType,
            securityRequirements,
            operationId: baseName,
            prompt,
          });
        }
      }
    
      return tools;
    }
  • Configuration for EVM tools, providing the prefix 'evm_' (so gettokenscore becomes evm_gettokenscore) and URLs to the API endpoint and OpenAPI spec from which the tool is derived.
    const configs: Record<string, SchemaConfig> = {
      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