What Is the ChainLookupService in Arbitrum MCP Server? A Complete Guide

The ChainLookupService is a singleton helper class that centralizes all knowledge about Arbitrum and Orbit chains, providing cached metadata, RPC endpoints, and contract addresses to MCP tool handlers.

The ChainLookupService acts as the single source of truth for chain metadata in the dewanshparashar/arbitrum-mcp repository. It decouples chain data management from the rest of the server, enabling every tool to resolve human-readable chain names to exact RPC endpoints, bridge contracts, and other chain-specific details without hard-coding them.

Core Responsibilities of the ChainLookupService

Aggregating Chain Metadata from Multiple Sources

The service combines static core Arbitrum networks with dynamic Orbit chain data. In src/services/chain-lookup.ts, the getCoreArbitrumChains() method (lines 79-112) builds the foundation using getArbitrumNetwork from the Arbitrum SDK, while fetchChainsData() (lines 55-68) pulls the latest Orbit chain catalogue from a hosted JSON file.

Implementing a 5-Minute Cache Strategy

To avoid repeated network calls, the service implements a time-based cache. The CACHE_TTL constant (line 63) defines a 5-minute expiration, and the lastFetched timestamp (line 62) guards the cache in ensureChainsData(). This ensures that chain data remains fresh while minimizing external dependencies.

Providing Fast Lookup Methods

The service exposes several query methods for tool handlers:

  • findChainByName() – Exact match by chain name
  • findChainById() – Lookup by numeric chain ID
  • searchChains() – Fuzzy search across names and IDs
  • listChainNames() – Returns all available chain identifiers

These methods are implemented in lines 84-124 of src/services/chain-lookup.ts.

How the ChainLookupService Integrates with MCP Tools

The server creates a singleton instance via ChainLookupService.getInstance() in src/index.ts (line 35) and wires it into tool handlers.

Listing Available Chains

// Tool handler for "list_chains"
const chainNames = await this.chainLookupService.listChainNames();
return {
  content: [{ type: "text", text: `Available chains:\n${chainNames.join("\n")}` }],
};

Searching for Chains

// Tool handler for "search_chains"
const results = await this.chainLookupService.searchChains(args.query);
if (results.length) {
  const list = results.map(c => `${c.name} (ID: ${c.chainId})`).join("\n");
  return { content: [{ type: "text", text: `Found chains:\n${list}` }] };
}

Retrieving Chain Metadata

// Tool handler for "chain_info"
const info = await this.chainLookupService.findChainByName(args.chainName);
if (!info) {
  return { content: [{ type: "text", text: `Chain "${args.chainName}" not found` }] };
}
return { content: [{ type: "text", text: JSON.stringify(info, null, 2) }] };

Resolving RPC URLs for Other Tools

Many tools rely on a helper method that uses the lookup service to resolve chain names to RPC endpoints:

private async resolveRpcUrl(chainNameOrUrl?: string): Promise<string> {
  if (chainNameOrUrl?.startsWith("http")) return chainNameOrUrl;
  const chain = await this.chainLookupService.findChainByName(chainNameOrUrl!);
  if (chain?.rpcUrl) return chain.rpcUrl;
  return chainNameOrUrl!; // fallback to custom URL
}

This pattern supports tools like node_health and latest_block that require RPC connections but accept human-readable chain names as input.

Key Implementation Details

The ChainLookupService is defined in src/services/chain-lookup.ts and implements the OrbitChainData interface (lines 4-57), which structures metadata including:

  • Network identifiers: chainId, name, slug
  • Infrastructure: rpcUrl, explorerUrl
  • Contracts: bridge, inbox, sequencerInbox, rollup
  • Tokenomics: nativeToken details
  • UI metadata: color, logoUrl

The service depends on @arbitrum/sdk (declared in package.json) for core network definitions and fetches extended Orbit chain data from a hosted JSON catalogue to ensure the server recognizes new chains without code changes.

Summary

  • The ChainLookupService is a singleton class in src/services/chain-lookup.ts that centralizes Arbitrum and Orbit chain metadata.
  • It caches data for 5 minutes, combining static SDK data with dynamic remote catalogues to minimize network requests.
  • It provides lookup methods (findChainByName, searchChains, etc.) that enable MCP tools to resolve human-readable names to technical chain data.
  • It acts as the single source of truth for RPC URLs, contract addresses, and explorer links, decoupling chain configuration from tool implementation.

Frequently Asked Questions

How does the ChainLookupService handle new Orbit chains?

The service fetches the latest Orbit chain catalogue from a hosted JSON file via fetchChainsData(). This allows the MCP server to recognize new chains immediately without requiring code updates or redeployment, as the remote data source is queried at runtime and cached for 5 minutes.

What happens if the remote chain catalogue is unavailable?

If the remote fetch fails, the service falls back to the core Arbitrum chains loaded via getCoreArbitrumChains(), which uses the @arbitrum/sdk package. While new Orbit chains won't be available during the outage, essential Arbitrum One and Nova functionality remains operational.

Can I use the ChainLookupService to query custom RPC endpoints?

Yes, while the service primarily manages known chains from its catalogue, the server uses a resolveRpcUrl() helper that accepts either a chain name (looked up via the service) or a direct HTTP URL. If you provide a custom RPC URL starting with "http", it bypasses the lookup and uses your endpoint directly.

Where is the ChainLookupService instantiated in the application?

The service follows the singleton pattern and is instantiated once in src/index.ts at line 35 using ChainLookupService.getInstance(). This single instance is then shared across all MCP tool handlers, ensuring consistent data and cache state throughout the server's lifecycle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →