Chunk MCP Server
Official# Chunk MCP Server
Production-ready MCP server exposing Chunk MedianFeeds tools over stdio.
- Network: Chunk testnet (default RPC: `https://rpc.chunknet.org`)
- Contract: MedianFeeds (default): `0x78D02A47fA898ffF4B37A9B414Eace5eed3e7fAD`
Requirements
- Node.js 18+ (ESM modules)
Quickstart
- Install
- `cd mcp-server`
- `npm install`
- Build
- `npm run build`
- Run (stdio transport)
- `npm start`
Configuration
- Environment variables
- `CHUNK_RPC` — JSON-RPC endpoint (default: `https://rpc.chunknet.org`)
- `CHUNK_MEDIAN_ADDR` — MedianFeeds contract address (default: `0x78D02A47fA898ffF4B37A9B414Eace5eed3e7fAD`)
- `METRICS_CACHE_TTL_MS` — metrics cache TTL in milliseconds (default: 30000)
Production .env (overrides optional)
```bash
CHUNK_RPC=https://rpc.chunknet.org
CHUNK_MEDIAN_ADDR=0x78D02A47fA898ffF4B37A9B414Eace5eed3e7fAD
METRICS_CACHE_TTL_MS=30000
```
Notes: You can omit `.env` entirely — these are the built-in defaults.
Tools
- `list_metrics` — List metric definitions from MedianFeeds
- Args: `{ chain?, rpcUrl?, contractAddress?, currency?, tagIncludes?, nameContains?, limit?, offset? }`
- `quote_metrics` — Get last quotes for given metric names
- Args: `{ names: string[], chain?, rpcUrl?, contractAddress?, format?: 'raw'|'int'|'decimal'|'all', decimals?: number }`
- `get_signed_root` — Get current signed Merkle tree root (epoch)
- Args: `{ chain?, rpcUrl?, contractAddress? }`
- `get_metrics_count` — Total metrics count
- `has_metric` — Check if a metric exists by name
- `get_metrics_map` — Mapping `name -> id` (index-based)
- `quote_by_ids` — Quote metrics by numeric ids
- Args: `{ ids: number[], chain?, rpcUrl?, contractAddress?, format?, decimals? }`
- `quote_metrics_at_block` — Quote metrics at specific block number
- Args: `{ names: string[], blockNumber: number, chain?, rpcUrl?, contractAddress?, format?, decimals? }`
- `quote_metrics_at_epoch_end` — Quote metrics at the end of an epoch
- Args: `{ names: string[], epochDuration?: number, epochId?: number, chain?, rpcUrl?, contractAddress?, format?, decimals? }`
- `quote_metrics_at_timestamp` — Quote metrics at specific UNIX timestamp (seconds)
- Args: `{ names: string[], timestamp: number, chain?, rpcUrl?, contractAddress?, format?, decimals? }`
- `get_health` — RPC health info `{ chainId, blockNumber }`
- `check_staleness` — Check if metrics are stale w.r.t `maxAgeSeconds`
- `check_thresholds` — Threshold checks for rules of form `{ name, op: 'lt'|'lte'|'gt'|'gte'|'eq'|'neq', value: string|number }`
Formatting
- Raw values are returned as on-chain 2**112-scaled integers.
- Use `format: 'decimal'` and `decimals` to get human-friendly strings with rounding.
Resources
- `chunk://median/{chain}/metrics` — JSON array of metrics for a chain (`chunk` supported)
- `chunk://median/{chain}/metric/{name}` — JSON object with the latest quote for a metric
Subscriptions
- The server registers `resources.subscribe` capability.
- On epoch changes, `resources/updated` notifications are sent for subscribed URIs.
Client Example (Node.js)
```js
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({
command: 'node',
args: ['dist/server.js'],
env: process.env,
});
const client = new Client({ name: 'chunk-mcp', version: '0.1.0' });
await client.connect(transport);
const list = await client.callTool({ name: 'list_metrics', arguments: { limit: 5 } });
const names = list.structuredContent.metrics.map(m => m.name).slice(0, 2);
const quotes = await client.callTool({ name: 'quote_metrics', arguments: { names, format: 'decimal', decimals: 6 } });
console.log(quotes.structuredContent.quotes);
await client.close();
```
Claude Desktop (MCP) configuration (example)
- Configure a stdio MCP server:
```json
{
"mcpServers": {
"chunk-mcp": {
"command": "node",
"args": ["dist/server.js"],
"env": {
"CHUNK_RPC": "https://rpc.chunknet.org",
"CHUNK_MEDIAN_ADDR": "0x78D02A47fA898ffF4B37A9B414Eace5eed3e7fAD"
}
}
}
}
```
Operational Notes
- Timeouts and RPC limits depend on your provider.
- Handle network errors and transient failures with retries on the client side.
- For production, pin a stable RPC endpoint and contract address.
Project Structure
- `src/server.js` — source (ESM)
- `dist/server.js` — bundled build (after `npm run build`)
- No tests are included in this directory by design.
TDQS
Scored across 14 tools
The quote_metrics, quote_by_ids, quote_metrics_at_block, quote_metrics_at_epoch_end, and quote_metrics_at_timestamp tools all return quotes and are easily confused. Additionally, ids_for_names and get_metrics_map both resolve names to IDs, creating ambiguity in tool selection.
Most tools follow a consistent verb_noun pattern (get_*, check_*, list_*, quote_*), but ids_for_names deviates with a noun-preposition-noun structure. The mix of get and check for health-related actions is a minor inconsistency.
14 tools is within the typical well-scoped range but slightly heavy for the domain. The multiple time-based quote variants could be consolidated, but the count is still reasonable for a comprehensive metrics oracle.
The server covers health checks, metric listing, quoting (current and historical), ID mapping, and existence checks. However, there is no direct get_metric_by_id tool, and the time-based quote tools are somewhat redundant with each other, leaving minor coverage gaps.