# Use blockchain RPC in LangChain agents with BlockVectra

> Original page: https://docs.blockvectra.com/en/guides/langchain/

A LangChain agent reads live blockchain data through one tool that POSTs JSON-RPC to `https://api.blockvectra.com/v1/eth_mainnet/public`. That endpoint needs no API key or sign-up for the methods in each chain's `public.methods`. A key adds the rest, and the Free Plan gives 30,000,000 CU per 30-day window. Checked 2026-10-10.

```python
import httpx
from langchain.agents import create_agent
from langchain.tools import tool

RPC = "https://api.blockvectra.com/v1/eth_mainnet/public"

@tool
def eth_block_number() -> str:
    """Return the latest Ethereum mainnet block number as a hex string."""
    body = {"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber", "params": []}
    return httpx.post(RPC, json=body, timeout=10).json()["result"]

agent = create_agent("claude-sonnet-5", tools=[eth_block_number])
result = agent.invoke({"messages": [{"role": "user", "content": "What is the latest block?"}]})
print(result["messages"][-1].content)
```

Install with `pip install langchain httpx`; the model string and its provider key follow the [LangChain quickstart](https://docs.langchain.com/oss/python/langchain/quickstart). The tool uses LangChain's [`@tool` decorator](https://docs.langchain.com/oss/python/langchain/tools) and [`create_agent`](https://reference.langchain.com/python/langchain/agents/factory/create_agent).

## The same tool in TypeScript

```typescript
import * as z from "zod";
import { createAgent, tool } from "langchain";

const ethBlockNumber = tool(
  async () => {
    const res = await fetch("https://api.blockvectra.com/v1/eth_mainnet/public", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }),
    });
    return (await res.json()).result as string;
  },
  { name: "eth_block_number", description: "Latest Ethereum mainnet block number (hex).", schema: z.object({}) },
);

const agent = createAgent({ model: "claude-sonnet-5", tools: [ethBlockNumber] });
```

See the LangChain JS [tools guide](https://docs.langchain.com/oss/javascript/langchain/tools) for the `tool()` signature.

## Call any method with an API key

Methods outside `public.methods`, such as `eth_getLogs`, need a key. Read it from the environment and send it in the `x-api-key` header; the chain slug (`eth_mainnet`, `base_mainnet`, and so on) comes from `GET /v1/chains`:

```python
import os
import httpx
from langchain.tools import tool

@tool
def rpc_call(chain: str, method: str, params: list) -> dict:
    """Call a JSON-RPC method on a BlockVectra chain slug such as base_mainnet."""
    headers = {"x-api-key": os.environ["BLOCKVECTRA_API_KEY"]}
    body = {"jsonrpc": "2.0", "id": 1, "method": method, "params": params}
    return httpx.post(f"https://api.blockvectra.com/v1/{chain}", json=body, headers=headers, timeout=15).json()
```

Returning the whole JSON-RPC response lets the model read an `error` object and change its next call. To create the key without a browser, run the four-step flow in the [programmatic sign-up guide](https://docs.blockvectra.com/en/guides/programmatic-signup/): challenge, signature, login, then `POST /keys`. Developers can also [create a key in the console](https://console.blockvectra.com/login/?next=%2Fkeys%2F).

## Add the docs MCP server

LangChain agents connect to MCP servers through `MCPAdapter`. Point it at `https://docs.blockvectra.com/mcp` to give the agent `list_chains`, `get_status`, `rpc_call`, `read_doc` and the other tools listed on the [MCP server page](https://docs.blockvectra.com/en/guides/mcp-server/). Connecting needs no key.

```python
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter

async def main():
    async with MCPAdapter("https://docs.blockvectra.com/mcp") as adapter:
        tools = await adapter.list_tools()
        agent = create_agent("claude-sonnet-5", tools)
        return await agent.ainvoke({"messages": [{"role": "user", "content": "List the supported chains."}]})
```

Install with `pip install "langchain[mcp]"` (`langchain>=1.4.0`, in beta). To use keyed tools, pass the key as a bearer token: `MCPAdapter(Client(url, auth=os.environ["BLOCKVECTRA_API_KEY"]))` with `from fastmcp.client import Client`, as in LangChain's [MCP authentication guide](https://docs.langchain.com/oss/python/langchain/mcp/auth).

In TypeScript, install `@langchain/mcp-adapters@^2.0.0` and pass a headers map:

```typescript
import { MCPAdapter } from "@langchain/mcp-adapters";
import { createAgent } from "langchain";

const adapter = new MCPAdapter({
  servers: {
    blockvectra: {
      url: "https://docs.blockvectra.com/mcp",
      headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! },
    },
  },
});

try {
  const agent = createAgent({ model: "claude-sonnet-5", tools: await adapter.listTools() });
  // agent.invoke(...)
} finally {
  await adapter.close();
}
```

Drop the `headers` line to connect keyless. Official references: [LangChain MCP (Python)](https://docs.langchain.com/oss/python/langchain/mcp) and [LangChain MCP (JavaScript)](https://docs.langchain.com/oss/javascript/langchain/mcp).

## Errors your tool will see

| Response                              | Meaning                                       | What the agent should do                                                |
| ------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------- |
| HTTP 401, `-32024`, `missing_api_key` | Keyed URL called without a key                | Send the key in `x-api-key` or the path                                 |
| HTTP 401, `-32024`, `invalid_api_key` | Key unknown, disabled or revoked              | Check the key in the console; a new key takes a few seconds to activate |
| `-32601`, `method_not_public`         | Method is not in the chain's `public.methods` | Use a keyed URL instead of `/public`                                    |
| `-32601`, method not available        | Method is not enabled on that chain           | Check `methods.allow` in `GET /v1/chains`                               |

Each error carries `data.reason` and a `docs_url`; the full list is on the [errors page](https://docs.blockvectra.com/en/errors/).

## Common questions

**Does the public endpoint work for `eth_getLogs`?** No. It serves only the methods in the chain's `public.methods`; `eth_getLogs` and the Data API need an API key.

**Can the agent pass the API key as a tool argument?** No. Keep it in the environment or the MCP client headers; the MCP server rejects keys in tool arguments.

**Can the tool target another chain?** Yes. Replace `eth_mainnet` with any chain slug that has a `public.url` in `GET /v1/chains`.

## Next steps

* [Agent framework overview](https://docs.blockvectra.com/en/guides/agent-frameworks/) for ElizaOS, viem, wagmi and Coinbase AgentKit.
* [Connect an AI agent](https://docs.blockvectra.com/en/guides/ai-agents/) to discover endpoints with MCP, llms.txt and OpenAPI.
* [Billing rules](https://docs.blockvectra.com/en/guides/billing-rules/) for CU metering, rate limits and non-billed errors.
