Skip to main content
Glama
blockscout

Blockscout MCP Server

Official

direct_api_call

Call raw Blockscout API endpoints to retrieve blockchain data for specific chains, supporting pagination and query parameters for advanced data access.

Instructions

Call a raw Blockscout API endpoint for advanced or chain-specific data.

Do not include query strings in ``endpoint_path``; pass all query parameters via ``query_params`` to avoid double-encoding. **SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages. Returns: ToolResponse[Any]: Must return ToolResponse[Any] (not ToolResponse[BaseModel]) because specialized handlers can return lists or other types that don't inherit from BaseModel. The dispatcher system supports flexible data structures.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chain_idYesThe ID of the blockchain
endpoint_pathYesThe Blockscout API path to call (e.g., '/api/v2/stats'); do not include query strings.
query_paramsNoOptional query parameters forwarded to the Blockscout API.
cursorNoThe pagination cursor from a previous response to get the next page of results.

Implementation Reference

  • Main execution logic for the 'direct_api_call' tool: resolves Blockscout URL, makes API request with pagination support, dispatches to specialized handlers if applicable, and returns structured ToolResponse.
    @log_tool_invocation async def direct_api_call( chain_id: Annotated[str, Field(description="The ID of the blockchain")], endpoint_path: Annotated[ str, Field( description="The Blockscout API path to call (e.g., '/api/v2/stats'); do not include query strings.", ), ], ctx: Context, query_params: Annotated[ dict[str, Any] | None, Field(description="Optional query parameters forwarded to the Blockscout API."), ] = None, cursor: Annotated[ str | None, Field(description="The pagination cursor from a previous response to get the next page of results."), ] = None, ) -> ToolResponse[Any]: """Call a raw Blockscout API endpoint for advanced or chain-specific data. Do not include query strings in ``endpoint_path``; pass all query parameters via ``query_params`` to avoid double-encoding. **SUPPORTS PAGINATION**: If response includes 'pagination' field, use the provided next_call to get additional pages. Returns: ToolResponse[Any]: Must return ToolResponse[Any] (not ToolResponse[BaseModel]) because specialized handlers can return lists or other types that don't inherit from BaseModel. The dispatcher system supports flexible data structures. """ await report_and_log_progress( ctx, progress=0.0, total=2.0, message=f"Resolving Blockscout URL for chain {chain_id}...", ) base_url = await get_blockscout_base_url(chain_id) if endpoint_path != "/" and endpoint_path.endswith("/"): endpoint_path = endpoint_path.rstrip("/") if "?" in endpoint_path: raise ValueError("Do not include query parameters in endpoint_path. Use query_params instead.") params = dict(query_params) if query_params else {} apply_cursor_to_params(cursor, params) await report_and_log_progress( ctx, progress=1.0, total=2.0, message="Fetching data from Blockscout API...", ) response_json = await make_blockscout_request(base_url=base_url, api_path=endpoint_path, params=params) handler_response = await dispatcher.dispatch( endpoint_path=endpoint_path, query_params=query_params, response_json=response_json, chain_id=chain_id, base_url=base_url, ctx=ctx, ) if handler_response is not None: await report_and_log_progress( ctx, progress=2.0, total=2.0, message="Successfully fetched data.", ) return handler_response pagination = None next_page_params = response_json.get("next_page_params") if next_page_params: next_cursor = encode_cursor(next_page_params) next_call_params = { "chain_id": chain_id, "endpoint_path": endpoint_path, "cursor": next_cursor, } if query_params: next_call_params["query_params"] = query_params pagination = PaginationInfo(next_call=NextCallInfo(tool_name="direct_api_call", params=next_call_params)) await report_and_log_progress( ctx, progress=2.0, total=2.0, message="Successfully fetched data.", ) data = DirectApiData.model_validate(response_json) return build_tool_response(data=data, pagination=pagination)
  • Registers the 'direct_api_call' tool with the FastMCP server instance.
    mcp.tool( structured_output=False, annotations=create_tool_annotations("Direct Blockscout API Call"), )(direct_api_call)
  • Dispatcher utility that routes API responses to registered specialized handlers based on endpoint path regex matching.
    async def dispatch( endpoint_path: str, **kwargs: Any, ) -> Any | None: """Find and execute the first matching handler for the given endpoint path. Args: endpoint_path: The API path that was requested. **kwargs: Additional context forwarded to the handler. Note: precedence follows registration order. Keep regex patterns disjoint or register the most specific handler first when overlap is unavoidable. Returns: Any | None: Must return Any (not ToolResponse[BaseModel]) because some handlers can return lists or other types that don't inherit from BaseModel. The handler is responsible for returning properly structured ToolResponse objects. """ for path_regex, handler in HANDLER_REGISTRY: match = path_regex.fullmatch(endpoint_path) if match: return await handler(match=match, **kwargs) return None
  • Generic output schema used by direct_api_call and other tools for standardized responses including data, notes, instructions, and pagination.
    class ToolResponse(BaseModel, Generic[T]): """A standardized, structured response for all MCP tools, generic over the data payload type.""" data: T = Field(description="The main data payload of the tool's response.") data_description: list[str] | None = Field( None, description="A list of notes explaining the structure, fields, or conventions of the 'data' payload.", ) notes: list[str] | None = Field( None, description=( "A list of important contextual notes, such as warnings about data truncation or data quality issues." ), ) instructions: list[str] | None = Field( None, description="A list of suggested follow-up actions or instructions for the LLM to plan its next steps.", ) pagination: PaginationInfo | None = Field( None, description="Pagination information, present only if the 'data' is a single page of a larger result set.", )
  • Pydantic model for validating and wrapping raw direct API response data, allowing extra fields.
    class DirectApiData(BaseModel): """Generic container for direct API responses.""" model_config = ConfigDict(extra="allow")

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/blockscout/mcp-server'

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