Multi-chain MCP server for the ERC-8004 Agent Registry Standard. Supports Solana and EVM chains (Ethereum, Base, Polygon, BSC, Monad).
- Node.js >= 20.0.0
npmif you want to pack/exec the local tarballbunonly for local development and tests
This repo should currently be treated as local-first. The package flow is tested locally, but do not assume the package is already published on npm.
Run from the repo:
bun install
bun run build
node dist/index.jsIf you want to test the packaged behavior locally:
npm pack
npm exec --yes --package /absolute/path/to/quantulabs-8004-mcp-<version>.tgz 8004-mcp- Multi-chain: Solana + EVM (Base, Ethereum, Polygon, BSC, Monad)
- Cross-chain discovery:
agent_searchsearches all deployed chains by default unless you scopechain - Unified API: Same tools work across chains with automatic routing
- Wallet Management: Encrypted local storage with auto-lock
- Local Cache: SQLite with FTS5 for fast agent search
- ATOM Reputation: Full integration with Solana's reputation system
- IPFS Support: Studio MCP upload endpoint by default, with optional Pinata, Filecoin, or custom node overrides
Reads work out of the box with the built-in defaults. A .env file is optional and only needed if you want to override network, RPC, or IPFS settings. IPFS uploads use the Studio MCP upload endpoint by default.
Advanced override note:
- set
PINATA_JWTif you want8004-mcpto use your own Pinata credentials instead of the Studio MCP upload endpoint - set
IPFS_UPLOAD_URLonly if you want to point the MCP to a different backend upload endpoint
cp .env.example .env
# Edit only the values you want to override
node dist/index.jsSee .env.example for all available options.
claude mcp add 8004 node /absolute/path/to/8004-mcp/dist/index.jsWorks on Windows, Mac, and Linux. No cmd /c or -- needed.
With environment variables:
claude mcp add 8004 -e NETWORK_MODE=testnet -e SOLANA_CLUSTER=devnet node /absolute/path/to/8004-mcp/dist/index.jsEdit ~/.claude.json (or %USERPROFILE%\.claude.json on Windows):
{
"mcpServers": {
"8004": {
"command": "node",
"args": ["/absolute/path/to/8004-mcp/dist/index.js"],
"env": {
"NETWORK_MODE": "testnet",
"SOLANA_CLUSTER": "devnet"
}
}
}
}Search across all blockchains without specifying a chain:
> Find the agent named "DataAnalyst Pro"
Found 2 agents named "DataAnalyst Pro" on Ethereum Sepolia:
- eth:11155111:461 - Owner: 0xfb49...
- eth:11155111:460 - Owner: 0x6fd8...
> Search for agents with "Yoda" in the name
Found 4 agents:
- eth:11155111:523 - "Yoda 27 Jan"
- eth:11155111:468 - "Yoda 3"
- eth:11155111:467 - "Yoda Dash 1"
- eth:11155111:465 - "Yoda PG 2 IPFS"
All owned by 0xad55...
> Show me details about agent eth:11155111:474
Agent: 8004 Test Agent
- Chain: Ethereum Sepolia
- Owner: 0x9ca4...
- Description: This is an explanation of my test agent
- Created: 2026-01-27
Cross-chain discovery is the default behavior of
agent_search. If you omitchain, the MCP searches every deployed chain in the current network mode.
> Find me MCP-compatible agents across all chains
Searching deployed chains in testnet mode:
- Solana devnet
- Ethereum Sepolia
- Base Sepolia
- BSC Chapel
- Monad Testnet
Top matches:
1. sol:...
2. eth:11155111:...
3. base:84532:...
Note: Trust tiers and ATOM reputation metrics are only available on Solana.
> What's the reputation of sol:6YMAwDYygQEo1BGDavNaKhhfy52yzZ6SoBsa2wdgXthJ?
Trust Tier: Unrated (0/4)
Quality Score: 2440
Total Feedbacks: 29
Average Score: 24.4
Trust tiers remain Solana-only, but leaderboard reads are available on deployed EVM chains too.
> Show me the top 5 agents by reputation
Top 5 Solana agents:
1. sol:9j7cTX... - Score: 5586 (34 feedbacks)
2. sol:5heKjG... - Score: 5544 (35 feedbacks)
3. sol:HnGRPf... - Score: 3364 (50 feedbacks)
4. sol:6YMAwD... - Score: 2440 (30 feedbacks)
5. sol:Arskmk... - Score: 2440 (30 feedbacks)
> Give a score of 90 to agent sol:7xKXtG8vN2... with comment "Fast execution"
First I need to unlock a wallet...
Feedback submitted! Transaction: 4xR7m...
> Register a new agent called "MyBot" with MCP endpoint https://mybot.com/mcp
1. Uploading registration via Studio backend...
2. Registering on-chain...
Agent registered!
- ID: sol:NewAgentPubkey...
- Name: MyBot
- Transaction: 5tY8n...
> Create a new Solana wallet called "trading-wallet"
Wallet created:
- Name: trading-wallet
- Address: 8xM2k...
- Chain: Solana
Fund this address to start using it for transactions.
> Switch to mainnet
Using network_set with mode "mainnet"...
Switched to mainnet. Active chains:
- Solana: mainnet-beta
- Base: mainnet (chainId: 8453)
- Ethereum: mainnet (chainId: 1)
For programmatic access from autonomous agents, AI frameworks, or custom applications:
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({
command: 'node',
args: ['/absolute/path/to/8004-mcp/dist/index.js'],
env: { ...process.env, NETWORK_MODE: 'testnet', SOLANA_CLUSTER: 'devnet' },
});
const client = new Client(
{ name: 'my-agent', version: '1.0.0' },
{ capabilities: {} }
);
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log(`${tools.tools.length} tools available`);
// Search agents
const result = await client.callTool({
name: 'agent_search',
arguments: { hasMcp: true, limit: 5 } // Omit `chain` to search all deployed chains
});
console.log(result.content[0].text);
// Get agent details
const agent = await client.callTool({
name: 'agent_get',
arguments: { id: 'eth:11155111:738' }
});
console.log(agent.content[0].text);Use skipSend: true to get unsigned transactions without broadcasting:
// Initialize the wallet store once, then create a wallet
await client.callTool({
name: 'wallet_store_init',
arguments: {
password: 'my-secure-password'
}
});
await client.callTool({
name: 'wallet_create',
arguments: {
name: 'test-wallet',
chainType: 'solana'
}
});
// Register agent (dry run - returns unsigned tx)
const result = await client.callTool({
name: 'agent_register',
arguments: {
name: 'My Test Agent',
description: 'A test agent',
chain: 'sol',
skipSend: true // Returns unsigned tx, no funds needed
}
});
// Returns: { unsigned: true, transaction: "base64...", message: "..." }
// Give feedback (dry run)
const feedback = await client.callTool({
name: 'feedback_give',
arguments: {
id: 'sol:AgentPubkey...',
value: 85,
tag1: 'uptime',
tag2: 'day',
skipSend: true
}
});npm install @modelcontextprotocol/sdk- TOOLS.md - Complete tool reference (86+ tools)
- skill.md - AI agent integration guide (search tips, workflows, write ops)
Agents are identified using global IDs that include chain info:
| Chain | Format | Example |
|---|---|---|
| Solana | sol:<pubkey> |
sol:7xKXtG8vN2mPQr... |
| Ethereum | eth:<chainId>:<tokenId> |
eth:11155111:738 (Sepolia) |
| Base | base:<chainId>:<tokenId> |
base:84532:42 (Sepolia) |
| Polygon | poly:<chainId>:<tokenId> |
poly:80002:456 |
| BSC | bsc:<chainId>:<tokenId> |
bsc:97:123 |
| Monad | monad:<chainId>:<tokenId> |
monad:10143:789 |
Note: When using agent_get, you can pass either:
- Full globalId:
eth:11155111:738 - Raw tokenId with chain param:
{ id: "738", chain: "eth" }
The MCP supports the x402 payment protocol extension for reputation (8004-reputation). This allows linking feedback to actual payment transactions, creating verifiable proof-of-payment reputation.
- Server announces identity: When returning 402 Payment Required, include agent identity in CAIP-2 format
- Client pays: Standard x402 payment flow
- Feedback with proof: Both parties can submit feedback linked to the payment transaction
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({
command: 'node',
args: ['/absolute/path/to/8004-mcp/dist/index.js'],
});
const mcpClient = new Client(
{ name: 'my-app', version: '1.0.0' },
{ capabilities: {} }
);
await mcpClient.connect(transport);// Build identity for PaymentRequired response
const result = await mcpClient.callTool({
name: 'x402_identity_build',
arguments: { agentId: 'sol:AgentPubkey...' }
});
const identity = JSON.parse(result.content[0].text);
// Returns: { identity: { agentRegistry: "solana:EtWTRA...:HHCVWc...", agentId: "..." } }
// Add to PaymentRequired headers
const paymentRequired = {
...standardX402Fields,
extensions: {
'8004-reputation': identity.identity
}
};// After receiving PaymentResponse, parse the proof
const proofResult = await mcpClient.callTool({
name: 'x402_proof_parse',
arguments: { paymentResponse: base64EncodedPaymentResponse }
});
const proof = JSON.parse(proofResult.content[0].text);
// Option A: Auto-store on IPFS (works out of the box via the Studio MCP upload endpoint)
await mcpClient.callTool({
name: 'x402_feedback_submit',
arguments: {
agentId: 'sol:AgentPubkey...',
value: 8500,
valueDecimals: 2,
score: 85,
tag1: 'x402-resource-delivered',
tag2: 'exact-svm',
endpoint: 'https://agent.example.com/api',
proofOfPayment: proof.proofOfPayment,
storeOnIpfs: true
}
});
// Option B: Manual storage - build file first, store yourself
const buildResult = await mcpClient.callTool({
name: 'x402_feedback_build',
arguments: {
agentId: 'base:84532:123',
value: 9000,
valueDecimals: 2,
score: 90,
tag1: 'x402-resource-delivered',
tag2: 'exact-evm',
proofOfPayment: proof.proofOfPayment
}
});
// Store buildResult.feedbackFile on Arweave, your IPFS, etc.
const myUri = 'ar://abc123...';
// Then submit with your URI
await mcpClient.callTool({
name: 'x402_feedback_submit',
arguments: {
agentId: 'base:84532:123',
value: 9000,
valueDecimals: 2,
score: 90,
tag1: 'x402-resource-delivered',
tag2: 'exact-evm',
proofOfPayment: proof.proofOfPayment,
feedbackUri: myUri,
storeOnIpfs: false
}
});Feedback files must be stored for the x402 protocol. Two options:
- Auto IPFS (
storeOnIpfs: true): Works with the Studio MCP upload endpoint out of the box. Useipfs_configureonly if you want to override it. - Manual storage (
feedbackUri): Usex402_feedback_buildto get the file, store it yourself (Arweave, your IPFS, HTTP), then pass the URI
Supported URI schemes: ipfs://, ar://, https://, http://
Example feedback file structure:
{
"agentRegistry": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1:HHCVWcqs...",
"agentId": "AgentPubkey...",
"clientAddress": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1:ClientPubkey...",
"createdAt": "2026-01-23T12:00:00Z",
"score": 85,
"tag1": "x402-resource-delivered",
"tag2": "exact-svm",
"endpoint": "https://agent.example.com/api",
"proofOfPayment": {
"fromAddress": "ClientPubkey...",
"toAddress": "AgentPubkey...",
"chainId": "EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
"txHash": "5xR7mN2k..."
}
}See TOOLS.md for more details on x402 tools.
If you see cmd C:/ instead of cmd /c, the command was parsed incorrectly.
Wrong (causes Windows parsing bug):
claude mcp add 8004 -- cmd /c node C:/absolute/path/to/8004-mcp/dist/index.jsCorrect:
claude mcp add 8004 node C:/absolute/path/to/8004-mcp/dist/index.js- Check logs:
claude mcp logs 8004 - Verify the local build exists:
node /absolute/path/to/8004-mcp/dist/index.js - Restart Claude Code after adding the server
git clone https://github.com/QuantuLabs/8004-mcp.git
cd 8004-mcp
bun install
bun run build
bun run testNote: Registries supported by the 8004-solana SDK and agent0-ts SDK are automatically included in this MCP. No action needed for those chains.
Want to add your own ERC-8004 compatible registry to the MCP? Open an issue on GitHub with the following requirements:
-
Open Source: Your registry must be public and open source
- Provide link to your GitHub repository
-
Indexer: Provide an open source indexer or equivalent data access method
- We need a way to query agents efficiently
- Subgraph, REST API, or RPC-based indexing supported
-
Documentation: Complete API documentation including:
- All contract methods and events
- Data structures and types
- Example requests/responses
-
API Compatibility: We recommend following the 8004-solana SDK API patterns:
getAgent(id)- Get agent detailsagentExists(id)- Check existencesearchAgents(params)- Search with filtersgiveFeedback(input)- Submit feedbackgetFeedback(agentId, client, index)- Read feedbacklistFeedbacks(query)- List feedbacksgetReputationSummary(id)- Get reputation
MIT