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

> Discover the ChainLookupService in Arbitrum MCP Server. This guide explains how it centralizes chain metadata, RPC endpoints, and contract addresses for MCP tool handlers.

- Repository: [Dewansh/arbitrum-mcp](https://github.com/dewanshparashar/arbitrum-mcp)
- Tags: deep-dive
- Published: 2026-02-28

---

**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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/index.ts) (line 35) and wires it into tool handlers.

### Listing Available Chains

```typescript
// 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

```typescript
// 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

```typescript
// 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:

```typescript
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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/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`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/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.