---
description: Guidelines for creating specialized handlers for the direct_api_call tool.
globs:
alwaysApply: false
---
# `direct_api_call` Handler Guidelines
This document outlines the pattern for creating specialized response handlers that are invoked by the `direct_api_call` tool's dispatcher.
## Purpose
Handlers allow for custom processing of specific API endpoints to provide richer, more structured, and context-aware responses than the default generic JSON output of `direct_api_call`.
## Handler Contract
A handler MUST adhere to the following contract:
1. **Location**: It must be located in a new module within the `blockscout_mcp_server/tools/direct_api/handlers/` directory.
2. **Registration**: It must use the `@register_handler` decorator from `...tools.direct_api.dispatcher` to associate itself with a URL path regex.
3. **Signature**: It must be an `async` function that accepts a `match: re.Match` object as its first argument, followed by keyword arguments including `response_json: dict` and other context passed by the dispatcher.
4. **Responsibility**: It is responsible for processing the `response_json` and returning a complete, strongly-typed `ToolResponse[SpecificModel]` object. It is also responsible for extracting any path parameters it needs from the `match` object (e.g., `address = match.group("address")`).
5. **Activation**: Handlers are automatically discovered and imported at startup via the dynamic module loading in `blockscout_mcp_server/tools/direct_api/handlers/__init__.py`. No manual import is required.
6. **Regex Matching**: The dispatcher uses `fullmatch`. Ensure your pattern matches the entire `endpoint_path` (for example, anchor the regex or include trailing slash handling when required).
## Parameter Guidelines
**All handlers must declare ALL dispatcher parameters.** The dispatcher passes all context parameters as keyword arguments, and Python will raise a `TypeError` if any parameter is missing from the handler signature.
**Required parameters for all handlers:**
- `match: re.Match` - **Always required** - Contains regex match groups for path parameters
- `response_json: dict` - **Always required** - The raw JSON response from the API
- `query_params: dict | None` - **Always required** - Query parameters from the original request (use `# noqa: ARG001` if unused)
- `chain_id: str` - **Always required** - The blockchain chain identifier
- `base_url: str` - **Always required** - The base URL of the Blockscout instance
- `ctx: Context` - **Always required** - The MCP context for progress reporting (use `# noqa: ARG001` if unused)
**Example:**
```python
@register_handler(r"^/api/v2/my_endpoint/(?P<id>\d+)/?$")
async def handle_my_endpoint(
*,
match: re.Match[str],
response_json: dict[str, Any],
chain_id: str,
base_url: str,
ctx: Context, # noqa: ARG001 - reserved for future use
query_params: dict[str, Any] | None = None, # noqa: ARG001 - not used by this endpoint
) -> ToolResponse[MyModel]:
item_id = match.group("id")
# ... process response_json ...
return build_tool_response(data=processed_data)
```