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:
- 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.
- 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.
- 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.
- 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:
-
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"
}
]
-
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
-
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.
-
Update Chain Resolution Logic:
- The
get_blockscout_base_url method within the ChainResolver class will implement the following resolution order:
- Check for the
chain_id in the user-defined self.custom_chains.
- If not found, check the
self.cache.
- If not in the cache, fall back to querying the public Chainscout API.
- The result from the Chainscout API (both success and "not found") will be stored in the cache.
-
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.
-
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.
The current implementation of the MCP server is tightly coupled with the Chainscout service for resolving
chain_idto a Blockscout instance URL. This creates several significant limitations:http://localhost:4000).chain_id: 1), and users who primarily work with other chains cannot change this behavior.Proposed Solution
To address these limitations, we propose introducing two new environment variables to give users control over chain configuration:
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" } ]BLOCKSCOUT_DEFAULT_CHAIN_ID: This variable will allow users to specify a defaultchain_idto be used when no chain is specified in a prompt. It will default to"1"to maintain backward compatibility.Implementation Details
Create a
ChainResolverClass:ChainResolver, will be created in its own module:blockscout_mcp_server/tools/chain_resolver.py.BLOCKSCOUT_CUSTOM_CHAINS_JSON_PATHvariable.self.custom_chains).self.cache) for results from Chainscout.Update Chain Resolution Logic:
get_blockscout_base_urlmethod within theChainResolverclass will implement the following resolution order:chain_idin the user-definedself.custom_chains.self.cache.Validate Default Chain ID at Startup:
BLOCKSCOUT_DEFAULT_CHAIN_IDwill be treated as a critical configuration parameter.ChainResolverinstance will be created and will immediately attempt to resolve the configureddefault_chain_id.Dynamically Generate Instructions:
__get_instructions__tool will be updated.constants.py.ChainResolverto look up the name of the configureddefault_chain_id.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
BLOCKSCOUT_CUSTOM_CHAINS_JSON_PATH.BLOCKSCOUT_DEFAULT_CHAIN_IDenvironment variable.BLOCKSCOUT_DEFAULT_CHAIN_IDis set to an unresolvable chain ID.__get_instructions__tool dynamically and correctly informs the AI agent of the configured default chain.ChainResolverclass in a separate module.