Skip to main content
Workflows Library MCP Directory Realtime AI News Sponsor Tier Subscribe
Front Page / AI Tools / Deep Dive

Build a Chainlink MCP Server for Agentic Onchain Data & Cross-Chain Transactions

Chainlink for Agents (Aug 14, 2026) made verified data feeds and CCIP cross-chain settlement first-class resources for autonomous AI agents. This MCP server — chainlink-mcp — exposes those resources as governed tools: read price feeds, check token balances, inspect cross-chain transfer status, and submit CCIP transfers behind an explicit approval gate. Built with FastMCP in TypeScript with full inputSchema JSON definitions, an mcpServers config, and an OAuth 2.0 / API-key security guide.

Deepak Bagada

Deepak Bagada

CEO, SaaSNext

Aug 17, 2026 Published
|
Aug 17, 2026 Updated
|
11 Minutes Reading Time
Core Takeaways for Founders & Builders
  • chainlink-mcp exposes Chainlink's verified data feeds, token balances, and CCIP cross-chain transfers as governed MCP tools for AI agents.
  • The get_price_feed tool reads cryptographically signed, freshness-checked price data — the agent's ground truth instead of scraped web context.
  • send_cross_chain_transfer requires an explicit approved:true flag and enforces per-transfer caps, so value movement is a policy decision, not a model impulse.
  • Idempotency keys and status polling make cross-chain transfers safe to retry without double-settlement risk.
  • Security: API keys and OAuth 2.0 for reads, hardware-wallet custody for signing, and never expose private keys to the agent runtime.

By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.

When Chainlink unveiled Chainlink for Agents on August 14, 2026, it made two things first-class resources for autonomous AI agents: verified data (tamper-proof, freshness-checked price feeds) and cross-chain settlement (CCIP transfers and messaging). The infrastructure exists; what is missing is the tool surface that lets agents use it safely. This dispatch builds chainlink-mcp, a TypeScript FastMCP server that exposes those resources as governed tools — reads for data, and an explicit approval gate on anything that moves value. The latest AI news hub has tracked the agent-economy wave all year; this is the MCP surface for the agents that will actually transact onchain.

Why agents need verified onchain data

The problem with agent context is that most of it is scraped from the web — and scraped context can be stale or poisoned. For an agent making decisions about money, contracts, or supply chains, ground truth matters. Chainlink data feeds are cryptographically signed, freshness-checked, and verifiable onchain — exactly the kind of input an agent can trust. chainlink-mcp turns that into a tool call: the agent asks for the ETH/USD price feed, and gets a signed, fresh answer it can act on. That is the difference between an agent that reasons over reality and an agent that reasons over a rumor.

Architecture

flowchart TD
    A[AI agent] -->|MCP JSON-RPC| B[chainlink-mcp server]
    B --> C[get_price_feed]
    B --> D[get_balance]
    B --> E[get_transfer_status]
    B --> F[send_cross_chain_transfer]
    F --> G{Approved + cap check}
    G -- no --> H[Rejected: approval required]
    G -- yes --> I[CCIP router submit]
    I --> J[Return tx hash + status poll]
    C --> K[Chainlink Data Feeds API]
    D --> L[RPC balanceOf]

Project setup

mkdir chainlink-mcp && cd chainlink-mcp
npm init -y
npm install @modelcontextprotocol/sdk fastmcp zod dotenv
# .env
CHAINLINK_DATA_API_KEY=your_chainlink_api_key
ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/xxx
ARB_RPC_URL=https://arb-mainnet.g.alchemy.com/v2/xxx
CCIP_ROUTER_ETH=0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D
MAX_TRANSFER_USD=100
SIGNER_MNEMONIC=  # leave empty in prod; use custody service

Server code (index.ts)

import { FastMCP } from "fastmcp";
import { z } from "zod";
import { ethers } from "ethers";
import "dotenv/config";

const server = new FastMCP({
  name: "chainlink-mcp",
  version: "1.0.0",
});

// --- Tool 1: read a verified price feed ---
server.addTool({
  name: "get_price_feed",
  description: "Read the latest verified Chainlink price feed for a symbol pair. Returns price, decimals, and update timestamp.",
  inputSchema: z.object({
    pair: z.string().describe("e.g. ETH/USD, BTC/USD, LINK/USD"),
  }),
  async execute({ pair }) {
    const [base, quote] = pair.split("/");
    const feedId = `0x${base}-${quote}`; // simplified; use real feed registry
    const res = await fetch(`https://data.chain.link/feeds/${feedId}/latest`, {
      headers: { Authorization: `Bearer ${process.env.CHAINLINK_DATA_API_KEY}` },
    });
    const data = await res.json();
    return {
      pair,
      price: data.answer,
      decimals: data.decimals,
      updatedAt: data.updatedAt,
      freshnessOk: Date.now() - data.updatedAt < 3600_000, // 1h staleness gate
    };
  },
});

// --- Tool 2: read a token balance ---
server.addTool({
  name: "get_balance",
  description: "Read the ERC-20 or native token balance of an address on a given chain.",
  inputSchema: z.object({
    chain: z.enum(["ethereum", "arbitrum"]),
    address: z.string(),
    token: z.string().optional().describe("Token address; omit for native balance"),
  }),
  async execute({ chain, address, token }) {
    const rpc = chain === "ethereum" ? process.env.ETH_RPC_URL : process.env.ARB_RPC_URL;
    const provider = new ethers.JsonRpcProvider(rpc);
    if (!token) {
      const bal = await provider.getBalance(address);
      return { chain, address, balance: ethers.formatEther(bal), token: "native" };
    }
    const erc20 = new ethers.Contract(token, ["function balanceOf(address) view returns (uint256)"], provider);
    const bal = await erc20.balanceOf(address);
    return { chain, address, token, balance: bal.toString() };
  },
});

// --- Tool 3: check a CCIP transfer status ---
server.addTool({
  name: "get_transfer_status",
  description: "Poll the status of a previously submitted CCIP cross-chain transfer by message id.",
  inputSchema: z.object({
    messageId: z.string(),
  }),
  async execute({ messageId }) {
    // Query CCIP router / explorer for message status
    return { messageId, status: "pending", note: "Poll until finalized before resubmitting" };
  },
});

// --- Tool 4: submit a CCIP transfer (approval-gated) ---
server.addTool({
  name: "send_cross_chain_transfer",
  description: "Submit a CCIP cross-chain token transfer. REQUIRES approved:true and amount within cap.",
  inputSchema: z.object({
    approved: z.boolean(),
    fromChain: z.enum(["ethereum", "arbitrum"]),
    toChain: z.enum(["ethereum", "arbitrum"]),
    token: z.string(),
    amount: z.number().positive(),
    receiver: z.string(),
    idempotencyKey: z.string(),
  }),
  async execute({ approved, fromChain, toChain, token, amount, receiver, idempotencyKey }) {
    const capUsd = parseFloat(process.env.MAX_TRANSFER_USD || "100");
    if (!approved) return { status: "rejected", reason: "approved must be true to move value" };
    if (amount > capUsd) return { status: "rejected", reason: `amount ${amount} exceeds cap ${capUsd}` };
    // Real implementation: build CCIP message via router, sign with custody key
    return {
      status: "submitted",
      messageId: ethers.id(idempotencyKey),
      note: "Poll get_transfer_status before sending another transfer for the same key",
    };
  },
});

server.start({ transportType: "stdio" });

inputSchema JSON definitions

The same tools expressed as raw JSON Schema for MCP client manifests:

{
  "get_price_feed": {
    "type": "object",
    "properties": {
      "pair": { "type": "string", "description": "e.g. ETH/USD, BTC/USD" }
    },
    "required": ["pair"]
  },
  "send_cross_chain_transfer": {
    "type": "object",
    "properties": {
      "approved": { "type": "boolean", "description": "Must be true to move value" },
      "fromChain": { "type": "string", "enum": ["ethereum", "arbitrum"] },
      "toChain": { "type": "string", "enum": ["ethereum", "arbitrum"] },
      "token": { "type": "string" },
      "amount": { "type": "number", "exclusiveMinimum": 0 },
      "receiver": { "type": "string" },
      "idempotencyKey": { "type": "string" }
    },
    "required": ["approved", "fromChain", "toChain", "token", "amount", "receiver", "idempotencyKey"]
  }
}

mcpServers config

{
  "mcpServers": {
    "chainlink": {
      "command": "node",
      "args": ["/path/to/chainlink-mcp/dist/index.js"],
      "env": {
        "CHAINLINK_DATA_API_KEY": "${CHAINLINK_DATA_API_KEY}",
        "ETH_RPC_URL": "${ETH_RPC_URL}",
        "ARB_RPC_URL": "${ARB_RPC_URL}",
        "MAX_TRANSFER_USD": "100"
      }
    }
  }
}

Retry & idempotency rules

  • get_price_feed retries twice on 5xx; a stale feed (freshnessOk false) is returned with the staleness flag, never silently replaced.
  • get_balance retries twice with backoff on RPC timeouts.
  • send_cross_chain_transfer is idempotent by key: the same idempotencyKey returns the same messageId, never double-settles. Retries must reuse the key.
  • get_transfer_status is the only way to confirm settlement; never resubmit a transfer whose status is pending.

Security guide

The security model has three layers. Reads (price feeds, balances) use an API key or OAuth 2.0 — an agent can read market data freely. Value movement is the hard surface: send_cross_chain_transfer requires an explicit approval flag, enforces a per-transfer cap from MAX_TRANSFER_USD, and uses an idempotency key so a confused or looping agent cannot double-settle. Signing is the last line: private keys must live in a hardware wallet or custody service, never in the agent runtime's environment — the MCP server signs via a custody API, and the agent never touches the key. Add a human approval step in front of the tool for amounts above your risk tolerance, and log every transfer to an audit store. The same approval-gate discipline is documented across the AI workflows library and the MCP directory for every value-touching agent tool.

The bottom line

chainlink-mcp turns Chainlink for Agents into a governed tool surface: verified price data and balances as safe reads, and CCIP cross-chain transfers behind an explicit approval gate with caps and idempotency. Agents get ground truth and the ability to settle — and the governance layer keeps value movement a policy decision. The tooling patterns are in the MCP directory; track the agent-economy wave on latest AI news.

Frequently Asked Questions

What is chainlink-mcp?

A TypeScript FastMCP server exposing Chainlink price feeds, token balance checks, CCIP transfer status, and cross-chain transfers as governed tools an AI agent can call through the Model Context Protocol.

Why expose Chainlink data to agents?

Chainlink for Agents (Aug 14, 2026) made verified data and CCIP settlement first-class agent resources. Verified feeds give agents tamper-proof ground truth instead of scraped, poisonable web context.

How do agents send cross-chain transfers safely?

The send_cross_chain_transfer tool requires an explicit approved:true flag, enforces a per-transfer cap, uses an idempotency key to prevent double settlement, and returns a status the agent can poll.

What security model does it use?

Read tools use API keys or OAuth 2.0; value-moving tools require explicit approval, enforce caps, and sign via a hardware wallet or custody service — private keys never reach the agent runtime.

How do I configure it?

Set CHAINLINK_DATA_API_KEY and RPC URLs in .env, run with npx @modelcontextprotocol/server-chainlink or the built server, and add the mcpServers block to your client config.

Closing thoughts

Chainlink for Agents gave the agent economy verified data and cross-chain settlement; chainlink-mcp gives it a governed tool surface. Verified reads, approval-gated transfers, caps, and idempotency are the pattern for any agent that will touch value onchain. The tooling is in the MCP directory; the agent-economy coverage is on latest AI news.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

Frequently Asked Questions
A TypeScript FastMCP server exposing Chainlink price feeds, token balance checks, CCIP transfer status, and cross-chain transfers as governed tools an AI agent can call through the Model Context Protocol.
Chainlink for Agents (Aug 14, 2026) made verified data and CCIP settlement first-class agent resources. Verified feeds give agents tamper-proof ground truth instead of scraped, poisonable web context.
The send_cross_chain_transfer tool requires an explicit approved:true flag, enforces a per-transfer cap, uses an idempotency key to prevent double settlement, and returns a status the agent can poll.
Read tools use API keys or OAuth 2.0; value-moving tools require explicit approval, enforce caps, and sign via a hardware wallet or custody service — private keys never reach the agent runtime.
Set CHAINLINK_DATA_API_KEY and RPC URLs in .env, run with npx @modelcontextprotocol/server-chainlink or the built server, and add the mcpServers block to your client config.
Deepak Bagada
Author Profile

Deepak Bagada

CEO, SaaSNext

Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.

Related Intelligence Analysis

Briefing AI Tools

Vercel AI SDK Tool Calling React: 5 Steps (2026)

Vercel AI SDK tool calling React integration is a programming pattern that executes server-side functions based on large language model decisions and streams the results to a React frontend. By combining streamText with...

Deepak Bagada Deepak Bagada
12m read
Breaking AI Tools

Fact-Density vs. Word Count: The New SEO for 2026

Fact Density is the ratio of verifiable, unique information to the total word count of a piece of content. In 2026, AI search engines like Perplexity and Gemini prioritize high fact density over traditional word count. A...

Deepak Bagada Deepak Bagada
4m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc