Neo N3 MCP Server
About
Integrates with the Neo N3 blockchain for wallet management, asset transfers, contract interactions, and blockchain queries.
Details
- Author
- r3e-network
- Categories
- Developer Tools
Jump to
Setup
Install Neo N3 MCP Server in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/r3e-network/neo-n3-mcp
Follow the installation instructions in the repository README, then restart your MCP client.
@r3e/neo-mcpis an MCP server for Neo N3 blockchain queries and controlled, auditable transaction submission. It ships three entrypoints:
The two HTTP servers are unrelated and configured separately. SeeRemote MCP 2026 HTTPanddocs/remote-mcp-transport.md.
Current version:4.0.2. Node.js>=22is required. Version 4 speaks only MCP2026-07-28; clients using the removed initialization/session protocol are rejected rather than downgraded.
Example Claude Desktop or Cursor configuration:
{ "mcpServers": { "neo-n3": { "command": "npx", "args": ["-y", "@r3e/neo-mcp"], "env": { "NEO_NETWORK": "testnet", "NEO_TESTNET_RPC": "https://testnet1.neo.coz.io:443", "LOG_LEVEL": "info" } } } }
The package root exports the MCP server, HTTP server, services, network enums, and validated configuration:
import { NeoNetwork, NeoService } from '@r3e/neo-mcp'; const neo = new NeoService( 'https://testnet1.neo.coz.io:443', NeoNetwork.TESTNET, ); const blockCount = await neo.getBlockCount(); console.log({ blockCount, height: Math.max(0, blockCount - 1) });
NeoMcpServerexposesrun()andclose()for applications that manage the stdio transport lifecycle themselves.
The aliasesNEO_MAINNET_RPC_URL,NEO_TESTNET_RPC_URL, andNEO_NETWORK_MODEremain supported.
Remote RPC endpoints must use HTTPS. Plain HTTP is accepted for loopback RPC endpoints; settingNEO_ALLOW_INSECURE_RPC=trueexplicitly permits remote plaintext HTTP and should be limited to controlled development environments.
WhenNEO_NETWORK=both, read-only MCP calls without an explicit network use mainnet. Every state-changing call requires an explicit network and an idempotency key. The HTTP entrypoint rejectsboth; setNEO_NETWORK=mainnetorNEO_NETWORK=testnet.
Writes are disabled by default. To enable them, create an owner-only signer file outside the repository and configure durable state:
install -m 0600 /dev/stdin /run/secrets/neo-signer-wif export NEO_ENABLE_WRITES=true export NEO_SIGNER_WIF_FILE=/run/secrets/neo-signer-wif export NEO_WRITE_STATE_DIR=/var/lib/neo-mcp/write-operations export NEO_MCP_REQUEST_STATE_KEY="$(openssl rand -hex 32)" export HTTP_WRITE_APPROVAL_API_KEY="$(openssl rand -hex 32)"
The MCP and HTTP request schemas never accept WIFs, private keys, or passwords. MCP writes use the2026-07-28input_requiredflow. The server signs the opaquerequestState, binds it totools/call, expires it after ten minutes, and executes only after the re-entered response accepts the exact intent fingerprint. HTTP writes return a pending intent and require a separate approval request authenticated byHTTP_WRITE_APPROVAL_API_KEY.
Account intelligence remains evidence-first:analyze_account_graphexposes the replayable, network-scoped transfer graph and curated metadata only. The backend's deterministic exchange-sweep, coordinated-signer, community-affinity, and graph-similarity detector queue is deliberately not exposed as public identity data; pending candidates require human review before they can become curated metadata.
As of 2026-08-01, both production network detector timers have completed their detector rerun successfully. The resulting pending queue is operational review evidence only and is not returned byanalyze_account_graph.
This is a bespoke REST/JSON API, not an MCP transport. MCP clients cannot connect to it; they use the stdio entrypoint or theremote MCP transport.
npm ci npm run build export HTTP_API_KEY="$(openssl rand -hex 32)" NEO_NETWORK=mainnet npm run start:http
The server listens on127.0.0.1:3000by default. A non-loopbackHTTP_HOSTrequiresHTTP_API_KEY, and every configured API key must contain at least 32 bytes. When a key is configured, send it as a bearer token on every route exceptGET /liveandGET /health:
curl http://127.0.0.1:3000/live curl http://127.0.0.1:3000/health curl -H "Authorization: Bearer $HTTP_API_KEY" \ http://127.0.0.1:3000/api/blockchain/height
The HTTP listener does not terminate TLS. Plaintext HTTP is supported only on loopback or a trusted host-local proxy network. Remote clients must use HTTPS through a TLS-terminating reverse proxy or load balancer; direct remote plaintext HTTP is unsupported because bearer tokens traverse requests.
The height endpoint distinguishes the node's block count from the latest block index:
{ "blockCount": 12346, "height": 12345 }
HTTP_CORS_ORIGINSis an optional exact-origin allowlist. For example:
HTTP_CORS_ORIGINS=https://console.example.com,https://admin.example.com
Origins must use HTTP or HTTPS and cannot contain paths, credentials, query strings, or fragments. Wildcard CORS is not supported.
POST and PUT bodies must be JSON objects. The default body limit is 1 MiB and can be changed withHTTP_MAX_BODY_BYTES. A write request creates an immutable pending intent:
curl -X POST http://127.0.0.1:3000/api/transfers \ -H "Authorization: Bearer $HTTP_API_KEY" \ -H "Idempotency-Key: transfer-2026-07-11-001" \ -H 'Content-Type: application/json' \ -d '{"network":"mainnet","toAddress":"Nb...","asset":"NEO","amount":"1"}'
Approve only after comparing the returned fingerprint with the intended request:
curl -X POST http://127.0.0.1:3000/api/write-intents/INTENT_ID/approve \ -H "Authorization: Bearer $HTTP_WRITE_APPROVAL_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"fingerprint":"RETURNED_64_HEX_FINGERPRINT"}'
SeeAPI.mdfor the tool and route reference.
The stateless MCP 2026-07-28 HTTP transport serves the same read-only MCP tools as the stdio entrypoint to remote clients. It is a separate process from the REST API, listens on its own port, and has its own configuration and bearer token.
npm ci npm run build export MCP_HTTP_BEARER="$(openssl rand -hex 32)" NEO_NETWORK=mainnet npm run start:mcp-http
The server listens on127.0.0.1:3001by default and exposes:
A non-loopbackMCP_HTTP_HOSTrequiresMCP_HTTP_BEARERand rejects a token shorter than 32 bytes, mirroring theHTTP_API_KEYrule for the REST entrypoint. When a token is configured, clients sendAuthorization: Bearer <token>on every request toMCP_HTTP_PATH;/healthzstays unauthenticated so probes can reach it.
import { Client, StreamableHTTPClientTransport, } from '@modelcontextprotocol/client'; const transport = new StreamableHTTPClientTransport(new URL('http://127.0.0.1:3001/mcp'), { authProvider: { token: async () => process.env.MCP_HTTP_BEARER }, }); const client = new Client( { name: 'my-client', version: '2.0.0' }, { capabilities: {}, versionNegotiation: { mode: { pin: '2026-07-28' } }, }, ); await client.connect(transport); const { tools } = await client.listTools();
Like the REST listener, this listener serves plaintext HTTP and does not terminate TLS. Remote clients must reach it through a TLS-terminating reverse proxy. Requests are stateless, so replicas do not need sticky routing.
See[remote-mcp-transport.mdfor the full configuration reference, an end-to-end local run against the Neo Explorer agent, production deployment guidance, and troubleshooting.
The production Compose file isdocker/docker-compose.yml. It defines two services from the same image:neo-mcpruns the REST API on port 3000, andneo-mcp-httpruns the remote MCP transport on port 3001. Each requires its own token, binds the host port to127.0.0.1by default, and persists wallet records in its own volume:
export HTTP_API_KEY="$(openssl rand -hex 32)" export MCP_HTTP_BEARER="$(openssl rand -hex 32)" docker compose -f docker/docker-compose.yml up -d
…
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





