# How the Arbitrum MCP Server Resolves Chain Names to RPC URLs

> Learn how the Arbitrum MCP Server resolves chain names to RPC URLs using a four-step algorithm a direct lookup cached service custom endpoint or a default URL discover the inner workings

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

---

**The Arbitrum MCP Server resolves chain names to RPC URLs through a four-step resolution algorithm in `ArbitrumMCPServer.resolveRpcUrl` that checks for direct URLs, queries a cached `ChainLookupService` for known chains, falls back to treating the input as a custom endpoint, or uses a default RPC URL.**

When interacting with the dewanshparashar/arbitrum-mcp repository, tools like **arbos_version**, **node_health**, and **list_chains** accept a `chainName` parameter that must be converted into a concrete JSON-RPC endpoint. The server handles this translation seamlessly through a centralized resolution mechanism that supports both well-known Arbitrum chains and custom endpoints.

## Resolution Algorithm in `ArbitrumMCPServer.resolveRpcUrl`

The primary resolution logic lives in [`src/index.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/index.ts) within the `ArbitrumMCPServer.resolveRpcUrl` method (lines 54-71). This method implements a priority-based lookup system that processes user input through four distinct stages.

### Step 1: Direct URL Detection

If the supplied string starts with `http://` or `https://`, the server returns it unchanged. This shortcut allows users to bypass the lookup system entirely and provide raw RPC endpoints directly.

### Step 2: Chain Lookup via `ChainLookupService`

When the input is not a URL, the server delegates to the singleton `ChainLookupService` obtained via `ChainLookupService.getInstance()`. The service method `findChainByName(chainNameOrUrl)` searches a cached list of chain descriptors for matching `name` or `slug` fields.

The underlying data originates from `ChainLookupService.fetchChainsData()` in [`src/services/chain-lookup.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/services/chain-lookup.ts), which merges two sources:

- **Core Arbitrum chains**: Arbitrum One and Nova, defined in-code via `@arbitrum/sdk` through the `getCoreArbitrumChains` function (lines 79-147)
- **Orbit chains**: Loaded from the public JSON file at `https://raw.githubusercontent.com/OffchainLabs/arbitrum-token-bridge/master/packages/arb-token-bridge-ui/src/util/orbitChainsData.json`

The combined array is stored in `this.chainsData` with a **5-minute cache TTL** (`CACHE_TTL`). If a match is found, the method returns the chain's `rpcUrl` field.

### Step 3: Fallback to Custom URL

If the lookup fails to find a known chain, the server assumes the input string is a custom RPC URL and returns it as-is. This provides flexibility for private or development networks not listed in the official registries.

### Step 4: Default RPC URL

When no `chainName` argument is supplied, the method falls back to `this.defaultRpcUrl`, ensuring the server always has a valid endpoint for instantiating clients like `NitroNodeClient`, `ArbitrumChainClient`, or `EthereumAccountClient`.

## The `ChainLookupService` Implementation

Located in [`src/services/chain-lookup.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/services/chain-lookup.ts), the `ChainLookupService` acts as the authoritative source for chain metadata across the Arbitrum ecosystem.

### Core Arbitrum Chains

The `getCoreArbitrumChains` function (lines 79-147) constructs descriptors for Arbitrum One and Nova, including their hard-coded RPC URLs. These foundational chains are always available regardless of external network requests.

### Orbit Chains from Remote JSON

The service fetches dynamic chain data from the OffchainLabs Arbitrum token bridge repository. This JSON contains names, slugs, RPC URLs, and bridge addresses for all Orbit-deployed chains, enabling immediate support for new chains without code modifications.

### Caching Strategy

To minimize external requests, the service caches the merged chain data for five minutes. Subsequent lookups during this window hit the local cache, significantly improving response times for tools like **list_chains** that enumerate available networks.

## Practical Code Examples

### Resolving Chain Names Directly

```typescript
import { ArbitrumMCPServer } from './index.js';

async function demo() {
  const server = new ArbitrumMCPServer();

  // Resolve a known chain name
  const rpc1 = await (server as any).resolveRpcUrl('Arbitrum One');
  console.log(rpc1); // → https://arb1.arbitrum.io/rpc

  // Resolve a custom URL (passed through unchanged)
  const rpc2 = await (server as any).resolveRpcUrl('https://my-custom-node.io/rpc');
  console.log(rpc2); // → https://my-custom-node.io/rpc
}
demo();

```

*The `resolveRpcUrl` method is defined in [`src/index.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/index.ts) (lines 54-71).*

### Using the MCP Tool Interface

When calling tools via an MCP client, the resolution happens automatically:

```json
{
  "name": "arbos_version",
  "arguments": {
    "chainName": "Xai"
  }
}

```

Internally, the server executes:

```typescript
const rpcUrl = await this.resolveRpcUrl(args.chainName);
const client = new NitroNodeClient(rpcUrl);
const version = await client.getArbOSVersion();

```

The name **"Xai"** is matched against cached `OrbitChainData`, returning the appropriate RPC URL (e.g., `https://xai-chain.net/rpc`) for the `NitroNodeClient` instantiation.

### Refreshing Chain Data at Runtime

```typescript
await server.chainLookupService.fetchChainsData(); // forces refresh
// after the fetch you can call findChainByName on the new entry
const custom = await server.chainLookupService.findChainByName('my-chain');
console.log(custom?.rpcUrl);

```

Because `fetchChainsData` pulls the latest JSON from the Orbit repository, newly added chains become available immediately without restarting the server.

## Key Source Files and Functions

- **[`src/index.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/index.ts)** – `ArbitrumMCPServer.resolveRpcUrl`: Central resolution logic handling URL detection, name lookup, fallback mechanisms, and default handling.
- **[`src/services/chain-lookup.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/services/chain-lookup.ts)** – `ChainLookupService`: Singleton service managing chain metadata, cache lifecycle, and the `findChainByName` lookup method.
- **[`src/services/chain-lookup.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/services/chain-lookup.ts)** – `getCoreArbitrumChains`: In-code definitions for Arbitrum One and Nova including hard-coded RPC endpoints.
- **Orbit chains JSON**: External registry at `https://raw.githubusercontent.com/OffchainLabs/arbitrum-token-bridge/master/packages/arb-token-bridge-ui/src/util/orbitChainsData.json` containing Orbit chain configurations.

## Summary

- **`ArbitrumMCPServer.resolveRpcUrl`** in [`src/index.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/index.ts) implements a four-stage resolution algorithm prioritizing direct URLs, known chain lookups, custom endpoints, and default fallbacks.
- **`ChainLookupService`** maintains a merged registry of core Arbitrum chains and Orbit chains, caching results for five minutes to optimize performance.
- The system supports **human-readable names** (e.g., "Arbitrum One", "Nova"), **slugs** (e.g., "arbitrum-nova"), **raw URLs**, and **custom endpoints** through a unified interface.
- Chain data automatically updates by fetching the latest Orbit chains JSON from the OffchainLabs repository, requiring no code changes to support new networks.

## Frequently Asked Questions

### What happens if I provide a full HTTP URL as the chainName?

If the input string begins with `http://` or `https://`, `ArbitrumMCPServer.resolveRpcUrl` returns it immediately without modification. This bypasses the `ChainLookupService` entirely, allowing direct connection to any compatible JSON-RPC endpoint.

### How often does the Arbitrum MCP Server refresh its chain list?

The `ChainLookupService` caches chain data for **5 minutes** (`CACHE_TTL`). After this period expires, the next lookup triggers `fetchChainsData()` to reload core chains and refetch the Orbit chains JSON from the remote repository.

### Can I use chain slugs instead of full names?

Yes. The `findChainByName` method in `ChainLookupService` searches both the `name` and `slug` fields of each chain descriptor. You can use identifiers like **"arbitrum-nova"** or **"Xai"** interchangeably with their full canonical names.

### Where are the core Arbitrum One and Nova RPC URLs defined?

These are hard-coded within the `getCoreArbitrumChains` function in [`src/services/chain-lookup.ts`](https://github.com/dewanshparashar/arbitrum-mcp/blob/main/src/services/chain-lookup.ts) (lines 79-147), which uses the `@arbitrum/sdk` package to construct the chain descriptors with their official RPC endpoints.