Skip to content

Decouple Chain Resolution from Chainscout and Allow User-Defined Configuration #152

Description

@akolotov

The current implementation of the MCP server is tightly coupled with the Chainscout service for resolving chain_id to a Blockscout instance URL. This creates several significant limitations:

  1. Single Point of Failure: If the Chainscout API is unavailable, the MCP server becomes non-functional for any chain not present in the local cache, even if the target Blockscout instances are operational.
  2. Lack of Flexibility: Users cannot use the server with chains that are not indexed by Chainscout, such as:
    • Custom testnets.
    • Local development networks (e.g., a Blockscout instance running at http://localhost:4000).
    • Private or enterprise chains.
  3. No User-Defined Default: The default chain is hard-coded to "Ethereum Mainnet" (chain_id: 1), and users who primarily work with other chains cannot change this behavior.
  4. Performance: The first request for any new chain incurs the latency of an additional network call to Chainscout.

Proposed Solution

To address these limitations, we propose introducing two new environment variables to give users control over chain configuration:

  1. BLOCKSCOUT_CUSTOM_CHAINS_JSON_PATH: This variable will hold the absolute path to a user-provided JSON file. This file will allow users to define a list of custom chains, bypassing the need for Chainscout. The structure of the file will be a simple list of objects:

    [
      {
        "name": "My Local Testnet",
        "chain_id": "31337",
        "url": "http://localhost:4000"
      },
      {
        "name": "My Private Chain",
        "chain_id": "12345",
        "url": "https://explorer.my-private-chain.com"
      }
    ]
  2. BLOCKSCOUT_DEFAULT_CHAIN_ID: This variable will allow users to specify a default chain_id to be used when no chain is specified in a prompt. It will default to "1" to maintain backward compatibility.

Implementation Details

  1. Create a ChainResolver Class:

    • A new stateful class, ChainResolver, will be created in its own module: blockscout_mcp_server/tools/chain_resolver.py.
    • This class will encapsulate all logic for chain resolution.
    • On initialization, it will:
      • Read the BLOCKSCOUT_CUSTOM_CHAINS_JSON_PATH variable.
      • If the path is set, load and parse the JSON file into an instance variable (e.g., self.custom_chains).
      • Maintain an in-memory cache (self.cache) for results from Chainscout.
  2. Update Chain Resolution Logic:

    • The get_blockscout_base_url method within the ChainResolver class will implement the following resolution order:
      1. Check for the chain_id in the user-defined self.custom_chains.
      2. If not found, check the self.cache.
      3. If not in the cache, fall back to querying the public Chainscout API.
      4. The result from the Chainscout API (both success and "not found") will be stored in the cache.
  3. Validate Default Chain ID at Startup:

    • The BLOCKSCOUT_DEFAULT_CHAIN_ID will be treated as a critical configuration parameter.
    • During server startup, the ChainResolver instance will be created and will immediately attempt to resolve the configured default_chain_id.
    • If the ID cannot be resolved (i.e., it's not found in the custom JSON file or on Chainscout), the server will log a fatal error and exit, preventing it from starting in a misconfigured state.
  4. Dynamically Generate Instructions:

    • The __get_instructions__ tool will be updated.
    • The static, hard-coded rule about "Ethereum Mainnet" will be removed from constants.py.
    • The tool will use the ChainResolver to look up the name of the configured default_chain_id.
    • It will then dynamically generate the instruction for the AI agent (e.g., If no chain is specified..., assume "My Custom Chain" (chain_id: 12345) as the default.) and add it to the rules sent to the agent.

Acceptance Criteria

  • The server correctly loads and uses custom chain configurations from the file specified by BLOCKSCOUT_CUSTOM_CHAINS_JSON_PATH.
  • The server can resolve chains from the custom file without making any external calls to Chainscout.
  • The server successfully falls back to using the Chainscout API for chains not defined in the custom file.
  • The server's default chain can be configured via the BLOCKSCOUT_DEFAULT_CHAIN_ID environment variable.
  • The server fails to start with a clear error message if the BLOCKSCOUT_DEFAULT_CHAIN_ID is set to an unresolvable chain ID.
  • The __get_instructions__ tool dynamically and correctly informs the AI agent of the configured default chain.
  • The new implementation is encapsulated within a ChainResolver class in a separate module.

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