Minimal, fast, and extensible MCP servers for interactions with JSON-RPC blockchain nodes. Support EVM and Solana blockchains.
π Extra feature: tools for pump.fun bonding curve calculations and analysis.
π€ Run the auto-generation script to generate MCP tools for other blockchains using OpenAPI specifications.
uv run scripts/generate_mcp_tools.py <openapi_path> <output_dir> <blockchain_name>
# Example
uv run scripts/generate_mcp_tools.py scripts/openapi_specs/ethereum.json scripts/generated evm
git clone https://github.com/chainstacklabs/rpc-nodes-mcp.git
cd rpc-nodes-mcp
Mode | Command |
---|---|
Base | uv pip install -r pyproject.toml |
Dev | uv pip install -r pyproject.toml -e '.[dev]' |
Test | uv pip install -r pyproject.toml -e '.[test]' |
ARBITRUM_RPC_URL=
BASE_RPC_URL=
BINANCE_SMART_CHAIN_RPC_URL=
ETHEREUM_RPC_URL=
SONIC_RPC_URL=
SOLANA_RPC_URL=
OPENAI_API_KEY=
Note: OPENAI_API_KEY
is only required for tests with scripts/run_mcp_client_example.py
.
npx @modelcontextprotocol/inspector uv run src/main_evm.py
For more details, visit Model Context Inspector.
A client example that interacts with the MCP server (requires OPENAI_API_KEY
environment variable):
uv run scripts/run_mcp_client_example.py
Tool for auto-generating MCP interfaces and implementations (only tools currently) based on OpenAPI spec (see Chainstack open-source docs):
uv run scripts/generate_mcp_tools.py scripts/openapi_specs/ethereum.json scripts/generated evm
Note: auto-generated tools require further improvements, see here.
The mcp.json
file contains MCP server configurations. For VS Code users, place this file in the .vscode
folder within your project directory. GitHub Copilot in Agent Mode will automatically discover and launch the configured servers.
The claude_desktop_config.json
file contains MCP server configurations. For Claude Desktop users, place this file in the Claude Desktop data folder. Claude Desktop will automatically discover and launch the configured servers.
uv location errors: specify the full path to uv
in the mcp.json
file. To get the full path, run where uv
command.
environment variables: double check you created .env
file in the MCP servers folder and required endpoints.
The project uses a modular adapter pattern with automatic registration:
src/
βββ common/ # Shared utilities (RPC client, logging, config)
βββ servers/
β βββ evm/ # EVM-compatible blockchain support
β β βββ chains/ # Individual chain implementations
β β βββ common/ # Shared EVM logic
β β βββ tools/ # MCP tool definitions
β β βββ evm.py # Base EVM adapter
β βββ solana/ # Solana-specific implementation
β βββ chains/
β βββ common/
β βββ tools/
β βββ solana.py
- Adapter registry: automatically registers blockchain adapters
- Abstract interfaces: define contracts for blockchain operations
- RPC client: handles HTTP requests to blockchain nodes with error handling and logging
- MCP tools: expose JSON-RPC methods as AI-accessible tools
- Auto-generation (experimental): scripts to generate new tools from OpenAPI specifications
- Registration: chain adapters register themselves automatically when imported
- Routing: client dispatcher routes requests to appropriate adapters based on chain name
- RPC Communication: HttpxRpcClient handles JSON-RPC requests with proper error handling
- Tool Exposure: MCP tools wrap adapter methods for AI consumption
- Update the interface (
src/servers/evm/common/interfaces.py
):
@abstractmethod
async def new_method(self, param1: str, param2: str) -> str: ...
- Implement in base adapter (
src/servers/evm/evm.py
):
async def new_method(self, param1: str, param2: str) -> str:
return await self.rpc_client.post("new_method", [param1, param2], self.rpc_url)
- Add client router (
src/servers/evm/common/client.py
):
async def new_method(chain, param1, param2):
return await _adapter(chain).new_method(param1, param2)
- Create MCP tool (
src/servers/evm/tools/json_rpc_methods.py
):
@mcp.tool(
name="new_method",
description="Description of what this method does...",
annotations={"title": "New Method", "readOnlyHint": True},
)
async def new_method(chain: str, param1: str, param2: str) -> CallToolResult:
try:
return _ok(await client.new_method(chain.lower(), param1, param2))
except Exception as e:
return _err(str(e))
Create new utility functions in src/servers/*/tools/utilities.py
:
@mcp.tool(
name="convert_something",
description="Converts something to something else",
annotations={"title": "Convert Something", "readOnlyHint": True},
)
def convert_something(value: str) -> CallToolResult:
try:
result = your_conversion_logic(value)
return _ok(result)
except Exception as e:
return _err(str(e))
- Create chain file (
src/servers/evm/chains/newchain.py
):
from common.config import settings
from common.interfaces import RpcClient
from servers.evm.common.adapter_registry import register_adapter
from servers.evm.evm import EvmAdapter
@register_adapter("newchain")
class NewChainAdapter(EvmAdapter):
def __init__(self, rpc_client: RpcClient = None):
super().__init__(rpc_url=settings.NEWCHAIN_RPC_URL, rpc_client=rpc_client)
- Add environment variable to
.env
:
NEWCHAIN_RPC_URL=https://your-rpc-endpoint.com
- Import in main (
src/main_evm.py
): The auto-discovery mechanism will automatically import your new chain.
- Create adapter interface (
src/servers/newchain/common/interfaces.py
) - Implement base adapter (
src/servers/newchain/newchain.py
) - Create chain registration (
src/servers/newchain/chains/newchain.py
) - Add client dispatcher (
src/servers/newchain/common/client.py
) - Create MCP tools (
src/servers/newchain/tools/
) - Create main entry point (
src/main_newchain.py
)