Skip to content

Refactor direct_api_call to use a dispatcher for specialized handlers #238

@akolotov

Description

@akolotov

The get_address_logs tool was deprecated because it was frequently misused by LLMs, which preferred it for paginated searches over more efficient tools like get_transactions_by_address that support time-range filtering.

However, the internal logic of get_address_logs provides significant value by processing raw API responses into a more context-friendly format. This includes:

  • Smart truncation of large data fields.
  • Curation of specific, relevant fields to reduce verbosity.
  • A sophisticated response-slicing pagination strategy that serves smaller, more digestible chunks to the LLM.

Currently, when the /api/v2/addresses/{address}/logs endpoint is called via the generic direct_api_call tool, we lose this valuable processing. This issue proposes a refactoring to re-introduce this logic in a scalable and architecturally sound way.

Proposed Solution

We will introduce a "dispatcher and handler" pattern within the direct_api_call tool. This will allow direct_api_call to delegate response processing to specialized handlers for specific endpoints while maintaining a clean and minimal tool surface for the LLM.

  1. Dispatcher Module (dispatcher.py):
    A new module at blockscout_mcp_server/tools/direct_api/dispatcher.py will be created. It will manage a registry of handlers and will be responsible for matching the endpoint_path of a request to the appropriate handler.

  2. Self-Registering Handlers (handlers/):

    • A new directory, blockscout_mcp_server/tools/direct_api/handlers/, will house the specialized handler modules.
    • Handlers will use a decorator-based, self-registering pattern (e.g., @register_handler("/path/pattern")). This makes the system highly extensible, as adding a new handler will not require modifying the central dispatcher.
    • The handlers/__init__.py file will import all handler modules to ensure their registration decorators are executed.
  3. Handler Contract:

    • Each handler will be a pure response processor. Its responsibility is to receive the raw JSON response from the API, perform its specialized processing, and return a complete, strongly-typed ToolResponse object.
    • Handlers will also be responsible for extracting any required parameters (e.g., {address}) from the URL path via a regex match object passed to them by the dispatcher.
  4. direct_api_call Refactoring:

    • The direct_api_call function will be simplified. It will invoke the dispatcher after fetching the API data. If a handler is found, it will return the handler's response. Otherwise, it will proceed with its default generic processing.
    • To support this dynamic behavior, the function's return type annotation will be changed to ToolResponse[Any]. This will be documented as a principled exception to the project's general typing rules.

Tasks and Acceptance Criteria

Phase 1: Code & Architecture

  • Create blockscout_mcp_server/tools/direct_api/dispatcher.py with the handler registry, @register_handler decorator, and dispatch() function.
  • Create the blockscout_mcp_server/tools/direct_api/handlers/ directory and its __init__.py file.
  • Move the processing logic from get_address_logs.py to a new .../handlers/address_logs_handler.py file.
  • Refactor the code in address_logs_handler.py into a pure handler function that uses the @register_handler decorator and extracts the address from the path.
  • Update handlers/__init__.py to import the new handler module.
  • Modify direct_api_call.py to use the new dispatcher and change its return type annotation to ToolResponse[Any].
  • Delete the old blockscout_mcp_server/tools/address/get_address_logs.py file.

Phase 2: Testing

  • Create new unit tests in tests/tools/direct_api/test_dispatcher.py to verify the self-registration and routing logic.
  • Move and refactor the unit tests from tests/tools/address/test_get_address_logs.py to a new file under tests/tools/direct_api/handlers/ to test the handler in isolation.
  • Move and refactor the integration tests from tests/integration/address/test_get_address_logs_real.py to a new file under tests/integration/direct_api/.
  • Update the refactored integration tests to call direct_api_call and verify that the dispatcher correctly invokes the address_logs_handler.

Phase 3: Documentation & Rules

  • Create a new rule file (e.g., .cursor/rules/112-direct-api-handlers.mdc) documenting the handler pattern.
  • Amend rule 110-new-mcp-tool.mdc to add a documented exception for dispatcher tools returning ToolResponse[Any].
  • Update .cursor/AGENTS.md to list the new rule file.
  • Update testing guidelines (210-unit-testing-guidelines.mdc, 220-integration-testing-guidelines.mdc) to include instructions for testing handlers.
  • Update SPEC.md to describe the new dispatcher architecture.
  • Update the file structure diagram in AGENTS.md to reflect all new, moved, and deleted files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions