Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Nvnm

БесплатноНе проверен

Nvnm — Model Context Protocol server

GitHubEmbed

Описание

Nvnm — Model Context Protocol server

README

CI License: Apache 2.0 Latest Release Cosign Signed

A typed Model Context Protocol bridge between AI agents and the NVNM Chain (Inveniam's L2 on MANTRA). It exposes 23 curated tools — EVM reads, anchor reads, prepare-sign-submit writes, and guided onboarding — with normalized responses, per-tool authorization, and zero key custody. Intended for application developers, LLM-agent authors, and pipeline operators who need a stable, audited surface against an EVM chain rather than raw JSON-RPC.

A Go-based Model Context Protocol (MCP) server that exposes the NVNM Chain (Inveniam's L2 on MANTRA) through a curated set of typed tools, with special emphasis on the chain's built-in anchoring interface.

This is not a generic JSON-RPC passthrough. It provides stable, typed, high-value MCP tools with normalized responses designed for both human and LLM consumers.

Request Flow

The HTTP transport layers defense-in-depth middleware around the MCP SDK. Order is outermost first; each layer can short-circuit before the request reaches a tool handler.

                  ┌─────────────────────────────────────────────┐
   MCP client ──▶ │ originGuard         DNS-rebinding defense   │
                  │ failGuarded         pre-auth IP rate limit  │
                  │ limitRequestBody    body size cap           │
                  │ AuthMiddleware      apikey or fusionauth    │
                  │ rateLimitMiddleware per-client bucket       │
                  │ mcp.Server (SDK)    JSON-RPC dispatch       │
                  │ tool handler        ABI encode / decode     │
                  │ evm client          retry, breaker, trace   │
                  └──────────────────────┬──────────────────────┘
                                         ▼
                                  EVM JSON-RPC
                            (https://evm.testnet.nvnmchain.io)

Source: internal/mcp/server.go.

Documentation

This README is the technical entry point. For deeper context, follow the links below.

OSS foundation (repo root):

File Purpose
LICENSE Apache 2.0 license text
NOTICE Required attribution notice
CONTRIBUTING.md Contribution workflow, DCO, branch / PR conventions
CODE_OF_CONDUCT.md Community standards
SECURITY.md Vulnerability disclosure policy
CHANGELOG.md Per-release notes (Keep a Changelog format)

Technical references (docs/):

File Purpose
docs/ONBOARDING.md New-contributor orientation — reading order, intentional design decisions, local quality gate (start here)
docs/DESIGN.md Architecture decisions; multi-chain deployment model; target-chain reference
docs/TOOL_REFERENCE.md Per-tool schema reference for all 21 MCP tools
docs/METAMASK_GUIDE.md Signing and submitting anchor writes with MetaMask (step-by-step)
docs/standards/CODING_STANDARDS.md Go coding standards and conventions for contributors
docs/TESTING.md Layered testing strategy — unit, golden, integration, HTTP E2E, load, and Docker smoke
docs/RUNBOOK.md Operational guide — startup, env-var migration, admin REST API
docs/INCIDENT_RUNBOOK.md Per-alert investigation playbook; what to do when each Prometheus rule fires
docs/SECURITY_AUDIT.md Frozen-snapshot security assessment with remediation results
docs/OWASP_AUDIT.md OWASP Top 10:2021 audit — per-category findings and remediation status
docs/SECURITY_CONSUMER_GUIDANCE.md Threats that fall on the consuming LLM agent / application, not the server
docs/DATA_HANDLING.md Privacy-by-design technical reference (what is and isn't stored)
docs/NVNM_MCP_Privacy_Policy_Jul_2026.pdf Counsel-finalized Privacy Policy for the hosted Service (published legal artifact)
docs/TERMS.md Terms of Service for the hosted Service (Apache 2.0 governs the Software)
docs/KEY_CUSTODY_THREAT_MODEL.md Rationale for the zero-key-custody design — no agent-mediated signing
docs/LICENSE_EXCEPTIONS.md Dependency-license policy and recorded GPL/LGPL/AGPL exception dispositions

What this server is not

Cold-reader assumptions to head off up front. The server is deliberately scoped narrow.

  • Not a chain node. The server talks JSON-RPC to an upstream EVM RPC endpoint. It does not consensus, mine, or hold state beyond connection caches.
  • Not a wallet. No private keys are ever held server-side. Write tools build complete unsigned transactions and return both a raw_tx (for HSM / CLI signers) and a wallet_tx_request (for MetaMask / EIP-1193 wallets); the caller signs and broadcasts.
  • Not a custodian or escrow. The server stores no per-user balance, no document content, no off-chain user records. The only persistent state is the API key store (hashed at rest). All "onboarding state" surfaced by the wizard tools is derived from on-chain balance + nonce at call time.
  • Not an orchestrator. Tools return a next_actions hint array so agents can chain calls themselves. The server does not call other tools internally and does not run multi-step flows on the caller's behalf.

Target Chain

Property Value (testnet)
Network NVNM Chain -- Inveniam L2 (MANTRA-secured consumer chain)
EVM chain ID 787111 (0xc02a7)
Cosmos chain ID nvnm-testnet-1
Native token mantraUSD
Gas token wmantraUSD (wrapped mantraUSD, held in EVM wallets) -- pays gas fees
EVM RPC https://evm.testnet.nvnmchain.io
Cosmos RPC https://rpc.testnet.nvnmchain.io
EVM explorer https://explorer.evm.testnet.nvnmchain.io
MCP service (hosted) https://mcp-testnet.nvnmchain.io (testnet); https://mcp.nvnmchain.io (mainnet)
Anchor precompile 0x0000000000000000000000000000000000000A00

Mainnet identifiers (EVM chain ID 1611, Cosmos nvnm-1, *.nvnmchain.io endpoints) and the full testnet+mainnet reference live in docs/DESIGN.md § Target Chain. The server runs as one instance per network.

Status

Current release: v1.0.0-rc13. The server is feature-complete and security-hardened — 21 typed tools (EVM reads, anchor reads, prepare-sign-submit writes, guided onboarding) with provider-agnostic auth (API keys or FusionAuth JWTs), per-tool RBAC, optional keyless reads, pre-auth and per-client rate limiting, DNS-rebinding defense, operator-configured data-retention purge, an OWASP Top-10 self-audit, and SBOM + Cosign-signed multi-arch images. See CHANGELOG.md for the full release history and docs/SECURITY_AUDIT.md for the security assessment.

HTTP transport supports two auth providers (API keys or FusionAuth JWTs) with per-client identity flowing into all authenticated audit logs and OTel spans. Under keyless reads (MCP_KEYLESS_READS=true, the Inveniam-hosted default) only evm_send_raw_transaction authenticates and carries a per-client identifier; the anchor_prepare_* tools are auth-exempt and anonymous reads carry no client_id. API keys are stored sha256-hashed at rest and indexed by hash in memory (Phase 8.6); the validator compares hash bytes under constant time and flattens hit/miss timing with a placeholder compare on the miss path (Phase 8.7). A pre-auth IP failure-rate limiter throttles credential stuffing before the auth check runs; per-client MCP rate limiting (post-auth) returns HTTP 429 when exceeded. Per-tool authorization (RBAC) gates each handler on reader / writer / admin / automation roles. Origin-header validation (Phase 8.5) provides DNS-rebinding defense at the outermost middleware position; allowlist via NVNM_ALLOWED_ORIGINS. Write access is gated by RBAC role and ENABLE_WRITE_TOOLS; obtaining human confirmation before submitting a signed transaction is the caller/agent's responsibility (stated in the server's initialize instructions). The signature remains the security boundary — the server holds no keys and cannot alter a signed transaction. A dedicated admin REST API (default-bound to 127.0.0.1:8081) enables runtime key management without server restarts.

Write tools construct complete unsigned transactions with both raw_tx (for HSM/CLI signers) and wallet_tx_request (for MetaMask / EIP-1193 wallets); private keys never touch the server -- see Write Architecture. Phase 8.4 made EIP-1559 (type-2) the default transaction format; callers that need legacy type-0 set prefer_legacy_tx: true on the prepare-tool input. Every tool response carries a next_actions hint array (Phase 8.3) so agents can chain calls from response-embedded affordances rather than server-side orchestration. Every tool carries an MCP ToolAnnotations payload (Phase 8.2) so clients can tell read-only tools from state-changing ones without inferring spec defaults. Five Phase 8.8 onboarding tools (nvnm_overview, wallet_status, nvnm_setup_wizard, nvnm_setup_verify_hash, nvnm_setup_verify_signature) walk first-time agents through wallet generation, funding, and on-chain state derivation; the wizard's funded_active state is explicit that "has sent any transaction" is not the same as "has anchored" because the wizard reads only balance and nonce, never transaction contents. OpenTelemetry instrumentation provides traces, metrics, and health check endpoints -- see Observability.

The EVM RPC stack uses github.com/defiweb/go-eth (MIT) -- go-ethereum was removed in 2026-05-13 to comply with the project's dependency-license policy; see docs/LICENSE_EXCEPTIONS.md and docs/SECURITY_AUDIT.md for the migration record. Dependencies are vendored (vendor/) and CI builds with -mod=vendor for supply-chain safety.

Prerequisites

  • Go 1.26+
  • Access to the NVNM Chain EVM RPC endpoint
  • (Optional) golangci-lint for linting
  • (Optional) pre-commit for git hooks
  • (Optional) Docker for containerized deployment

Quick Start

# Clone and enter the project
git clone https://github.com/NVNM-Chain/nvnm-mcp-server.git
cd nvnm-mcp-server

# Install dev tools and pre-commit hooks
make setup-dev

# See all available commands
make help

# Build
make build

# Run the test suite (unit + MCP E2E; hermetic, no chain access needed)
make test

# Verify the same coverage gate CI enforces (-race + >=80% total coverage)
make coverage-check

# Configure (minimum required)
export NVNM_EVM_RPC_URL=https://evm.testnet.nvnmchain.io
export NVNM_CHAIN_ID=787111
export ANCHOR_ABI_PATH=abi/anchoring.json

# Run (stdio transport -- for local MCP client integration)
make run

# Run (HTTP transport -- for remote/production deployment)
make run-http

Connect to an MCP client

Stdio (local):

{
  "mcpServers": {
    "nvnm-chain": {
      "command": "/path/to/nvnm-mcp-server",
      "args": ["--transport", "stdio"]
    }
  }
}

HTTP (remote):

# Server runs on :8080 by default
export MCP_HTTP_ADDR=:8080
./nvnm-mcp-server --transport http

Authentication (HTTP transport)

When using HTTP transport, authentication is strongly recommended. The server supports two auth providers, selected by AUTH_PROVIDER (default: apikey).

API Key Provider (default)

export AUTH_PROVIDER=apikey  # default, can be omitted

# Create an API key for a client
make key-create NAME=my-agent

# List all keys
make key-list

# Configure the server to use keys:
export MCP_API_KEYS_FILE=.mcp-keys.json   # Multi-key file (recommended)
# OR
export MCP_API_KEY=your-secret-key         # Single key (dev/test only)

FusionAuth Provider (OAuth/JWT)

export AUTH_PROVIDER=fusionauth
export FUSIONAUTH_URL=https://auth.example.com
export FUSIONAUTH_APPLICATION_ID=your-app-uuid
# Optional:
export FUSIONAUTH_ISSUER=https://auth.example.com  # defaults to FUSIONAUTH_URL
export JWT_CLOCK_SKEW=60s                           # default 60s
export JWT_ROLES_CLAIM=roles                        # default "roles"

The automation role grants write access alongside writer and admin; it is intended for unattended pipelines.

The authenticated client ID — the API key's label, or a keyed HMAC of the JWT sub (the raw sub, which is email-reversible, is never logged) — flows into audit logs and OTel spans for authenticated requests.

Setting up the FusionAuth side

To use the fusionauth provider, configure these in your FusionAuth instance (this is what an operator/identity admin sets up; the server only validates the resulting tokens):

  1. Create an Application. Its Application ID (UUID) becomes FUSIONAUTH_APPLICATION_ID. FusionAuth issues access tokens with aud set to this ID, which the server validates against — so this lines up automatically.
  2. Define these Application Roles (exact names — the server's RBAC checks them literally): reader, writer, admin, automation. FusionAuth emits a user's application roles in the access-token roles claim once the user is registered to the Application.
  3. Register consumers to the Application and assign roles:
    • reader — read tools only
    • writer — reads + broadcast writes (evm_send_raw_transaction)
    • admin — the above + anchor_prepare_grant_role
    • automation — write access for unattended pipelines (same as writer + admin for broadcast access); assign only to non-interactive callers.
  4. JWKS is the standard <FUSIONAUTH_URL>/.well-known/jwks.json (auto-discovered unless FUSIONAUTH_JWKS_URL is set); ensure it is reachable from the server.
  5. Clients obtain a JWT from FusionAuth (interactive login, or a client-credentials / Entity grant) and present it as Authorization: Bearer <jwt>.

Gotchas:

  • The roles claim must actually populate. An empty roles array makes RBAC a no-op — writes would not be role-gated. For machine-to-machine / Entity grants you may need a JWT-populate lambda to inject roles.
  • MCP_CLIENT_ID_HMAC_KEY is required in fusionauth mode (startup fails loud without it). It keys the one-way HMAC that turns the JWT sub into the logged client_id, keeping the email-reversible sub out of logs.
  • The server validates iss (== FUSIONAUTH_ISSUER, default FUSIONAUTH_URL) and aud (== FUSIONAUTH_APPLICATION_ID) on every token; a mismatch is rejected.

Configuration

All configuration is via environment variables. No config files required.

Required

Variable Description
NVNM_EVM_RPC_URL Primary EVM JSON-RPC endpoint
NVNM_CHAIN_ID Expected chain ID (787111 for NVNM testnet, 1611 for mainnet)
NVNM_CHAIN_ENVIRONMENT Chain environment label: testnet or mainnet. Required to disambiguate the per-instance chain pin; legacy INVENIAM_* env vars are hard-rejected at startup with a pointer to docs/RUNBOOK.md#env-var-migration

Authentication (HTTP transport)

Variable Default Description
AUTH_PROVIDER apikey Auth provider: apikey or fusionauth
MCP_API_KEYS_FILE (none) Path to JSON key store file (API key mode).
MCP_API_KEY (none) Single API key for dev/test (API key mode).
FUSIONAUTH_URL (none) FusionAuth base URL (required for fusionauth mode).
FUSIONAUTH_APPLICATION_ID (none) FusionAuth application UUID (required for fusionauth mode).
FUSIONAUTH_ISSUER FUSIONAUTH_URL Expected JWT issuer (FusionAuth mode).
FUSIONAUTH_JWKS_URL auto JWKS endpoint (defaults to FUSIONAUTH_URL/.well-known/jwks.json).
JWT_CLOCK_SKEW 60s Leeway for JWT expiry checks (FusionAuth mode).
JWT_ROLES_CLAIM roles JWT claim name for roles (FusionAuth mode).

When auth is configured, HTTP requests must include Authorization: Bearer <token>.

Admin Key Management API

Variable Default Description
ADMIN_API_KEY (none) Admin bearer token. Enables the admin REST API on a separate port for runtime key CRUD.
ADMIN_API_ADDR :8081 Admin API listen address.

When set (with HTTP transport), a separate server exposes POST/GET/PATCH/DELETE /admin/keys for runtime key management. Changes take effect immediately. See docs/RUNBOOK.md for full endpoint reference.

Optional

Variable Default Description
NVNM_EVM_ARCHIVE_RPC_URL (none) Archive node RPC for historical queries
ANCHOR_ADDRESS 0x0000000000000000000000000000000000000A00 Anchor precompile address
ANCHOR_ABI_PATH (none) Path to anchor ABI JSON file
REQUEST_TIMEOUT 15s Timeout for upstream RPC calls
LOG_LEVEL info Log level: debug, info, warn, error
ENABLE_WRITE_TOOLS false Enable write (prepare) tools
MCP_RELAY_ALLOW_ANY false Authenticated-path escape hatch: when true, evm_send_raw_transaction skips the anchor-precompile relay scope and broadcasts to any destination. Default false pins the relay to the anchor precompile. No effect under keyless writes (and a boot error if combined with MCP_KEYLESS_WRITES=true). See Write Architecture.
MCP_TRANSPORT stdio Transport: stdio or http
MCP_HTTP_ADDR :8080 Listen address for HTTP transport
OTLP_INSECURE false Use TLS for the OTLP gRPC connection. Set to true only for sidecar / localhost collectors that do not support TLS.
WRITE_APPROVAL_DEFAULT Removed. Setting this env var aborts startup with a migration error. See docs/RUNBOOK.md#write-approval-removal.

Observability

Variable Default Description
OTEL_EXPORTER_OTLP_ENDPOINT (none) OTel Collector endpoint (e.g. localhost:4317). Enables OTLP trace + metric export
OTEL_SERVICE_NAME nvnm-mcp-server Service name in traces and metrics
ENABLE_PROMETHEUS true Expose /metrics endpoint on metrics port
ENABLE_STDOUT_TELEMETRY false Dump spans/metrics to stderr (dev only)
METRICS_ADDR :9090 Listen address for health + metrics endpoints

Resilience

Variable Default Description
MCP_RATE_LIMIT 60 Per-client MCP request rate limit (requests per second). Returns HTTP 429 when exceeded.
MCP_RATE_BURST 10 Per-client burst capacity for the MCP rate limiter.
RPC_MAX_RETRIES 3 Maximum retry attempts for transient RPC errors
RPC_INITIAL_BACKOFF 500ms Initial backoff duration between retries
RPC_MAX_BACKOFF 10s Maximum backoff duration between retries
RPC_RATE_LIMIT 100 Upstream RPC rate limit (requests per second)
RPC_RATE_BURST 20 Burst capacity for upstream RPC rate limiter
CIRCUIT_BREAKER_THRESHOLD 5 Consecutive failures to trip circuit breaker
CIRCUIT_BREAKER_TIMEOUT 30s Time in open state before half-open probe
OTEL_TRACE_SAMPLE_RATIO 1.0 Fraction of traces sampled (0.0-1.0)

MCP Tools

23 tools in total. First-time agents should call nvnm_overview first; it returns the canonical 6-step journey across the rest of the surface.

Phase 8.8: Onboarding (5 tools)

Tool Description
nvnm_overview Lobby tool. Chain identity, privacy-by-design property, 6-step agent journey, prereqs. No chain calls.
wallet_status Balance + nonce for an address; three-state status (unfunded / funded_unused / funded_active).
nvnm_setup_wizard Four-state guided onboarding with language-specific samples (Python / JS / Go) that store keys via keyring / .env / 0o600 files (never print them).
nvnm_setup_verify_hash Stateless challenge: caller proves they can hash a per-address challenge.
nvnm_setup_verify_signature Stateless challenge: caller proves they can EIP-191 sign the same challenge.

Phase 1: Generic EVM

Tool Description
evm_get_chain_id Chain ID, latest block number, RPC label
evm_get_block Block by number or hash, with optional full transactions
evm_get_transaction Transaction details by hash
evm_get_transaction_receipt Receipt with status, gas, logs, created contract
evm_get_balance Balance at address (wei + ether)
evm_get_code Contract bytecode at address
evm_get_logs Filtered event logs
evm_call_contract Read-only contract call with ABI decoding

Phase 2: Anchor Reads

Tool Description
anchor_info Precompile config status: address, ABI loaded, method count
anchor_get_registry Fetch a registry by numeric ID (ID-only, single-valued)
anchor_get_registries Paginated list of registries, optionally filtered by name (client-side scan finds every match, then pages over them)
anchor_get_records Flexible record query: by version, by checksum, by registry, with pagination

Phase 3: Anchor Writes

Write tools follow a prepare-sign-submit pattern. The MCP server constructs complete unsigned transactions but never holds private keys. Requires ENABLE_WRITE_TOOLS=true. See Write Architecture below.

Tool Description
anchor_prepare_add_registry Build unsigned tx to create a new registry
anchor_prepare_add_record Build unsigned tx to anchor a document (checksum + URI)
anchor_prepare_update_record_status Build unsigned tx to change a record's status (e.g. Active, Superseded, Revoked)
anchor_prepare_grant_role Build unsigned tx to grant admin/editor role
anchor_prepare_revoke_role Build unsigned tx to revoke admin/editor role
evm_send_raw_transaction Broadcast a signed transaction, return tx hash

Write Architecture (Phase 3)

The MCP server handles all blockchain complexity (ABI encoding, nonce lookup, gas estimation, transaction construction) but signing stays with the caller. This keeps private keys out of the MCP server entirely.

Flow:

  1. Prepare -- Caller invokes anchor_prepare_add_registry(from, name, description, metadata). The MCP server ABI-encodes the call, fetches the nonce for the sender address, estimates gas, and returns a complete unsigned transaction with two signing paths.

  2. Sign & Submit (choose one):

Path A -- MetaMask / browser wallet (recommended for human users):

const prepared = await callMCPTool("anchor_prepare_add_record", {
  from, registry, uri, checksum, checksum_algo, metadata // checksum_algo + metadata are required (metadata must be non-empty and not "{}")
});

// Pass wallet_tx_request directly to MetaMask
const txHash = await window.ethereum.request({
  method: "eth_sendTransaction",
  params: [prepared.wallet_tx_request],
});

// Confirm on-chain
const receipt = await callMCPTool("evm_get_transaction_receipt", { tx_hash: txHash });

MetaMask signs and broadcasts directly. The response includes wallet_tx_request with all numeric fields as 0x-prefixed hex quantities ready for EIP-1193 wallets. You do not call evm_send_raw_transaction in this path.

Path B -- Local/headless signer (CLI, HSM, automation):

prepared = mcp.call("anchor_prepare_add_record", {...})

# Sign the raw_tx bytes externally
signed_hex = my_signer.sign(prepared["raw_tx"])

# Broadcast via MCP server
result = mcp.call("evm_send_raw_transaction", {"signed_tx": signed_hex})
receipt = mcp.call("evm_get_transaction_receipt", {"tx_hash": result["tx_hash"]})

Broadcast allowlist (relay scope): evm_send_raw_transaction is a scoped anchoring relay, not a general-purpose broadcaster. The server decodes the signed transaction and rejects it unless its destination is the anchor precompile (ANCHOR_ADDRESS); other contracts, externally-owned accounts, value transfers, and contract creation are refused without broadcast. This holds on both the keyless-write and authenticated/self-host paths — the caller's signature cannot be relayed to move funds or reach arbitrary contracts. Self-hosters who need to broadcast non-anchor transactions can opt out with MCP_RELAY_ALLOW_ANY=true (authenticated path only; forbidden under keyless writes). Reads are never restricted.

  1. Verify -- Use evm_get_transaction_receipt(tx_hash) and anchor_get_records to confirm the anchor is on-chain.

This pattern means:

  • Private keys never touch the MCP server
  • Browser wallet users get native MetaMask confirmation prompts
  • Signing can happen in an HSM, Vault, hardware wallet, or any secure enclave
  • The MCP server handles all the ABI encoding, nonce, and gas estimation

Observability

The server includes vendor-agnostic observability via OpenTelemetry, with out-of-the-box support for Prometheus/Grafana and CloudWatch/X-Ray.

Endpoints

The health and metrics server runs on a separate port (default :9090), independent of the MCP transport.

Endpoint Purpose
GET /healthz Liveness probe -- returns 200 OK if the process is running
GET /readyz Readiness probe -- returns 200 OK if the EVM RPC is reachable and the ABI is loaded
GET /metrics Prometheus scrape endpoint (when ENABLE_PROMETHEUS=true)

What Gets Instrumented

  • Every MCP tool call gets a trace span and metrics (duration histogram, call counter, error counter, active request gauge)
  • Every upstream EVM RPC call gets a child trace span with method name and duration
  • Structured logs include request IDs and can be correlated with OTel traces
  • Sensitive data — the SafeAddr / SafeURL / SafeTxData helpers redact addresses, URLs, and tx data on debug log lines (internal/logging/redact.go). Note the write-audit broadcast lines (INFO/WARN) deliberately record the recovered on-chain signer, destination, and value in full — these are public on-chain data and form the write-audit trail, not debug output. See docs/DATA_HANDLING.md for the exact redaction scope.

Deployment Integration

  • Kubernetes: Liveness/readiness probes on :9090. ServiceMonitor/PodMonitor for Prometheus auto-discovery. OTel Collector as DaemonSet or sidecar.
  • AWS ECS/Fargate: ALB health check on /readyz. aws-otel-collector sidecar for CloudWatch/X-Ray. Structured JSON logs via awslogs driver.
  • Azure: Compatible with AKS probes and Azure Monitor via OTel Collector.

Development

Running make with no arguments displays the full help menu.

make help           # Show all available commands (also the default)
make build          # Build binary
make run            # Run with stdio transport
make run-http       # Run with HTTP transport
make run-local      # Build and run locally with HTTP + testnet config
make test           # Run all tests
make test-unit      # Unit tests only (-short)
make test-coverage  # Tests with -race + coverage report
make coverage-check # test-coverage + enforce the 80% total coverage gate (same as CI)
make test-verbose   # Verbose test output
make check-all      # format + vet + lint
make format         # gofmt + goimports
make vet            # go vet
make lint           # golangci-lint
make pre-commit     # Run pre-commit hooks on all files
make install-hooks  # Install pre-commit git hooks
make setup-dev      # Install dev deps + hooks
make ci             # install-dev + check-all + test-coverage
make release-check  # clean + ci + build
make info           # Show project info
make docker-build   # Build Docker image (host arch only)
make docker-buildx  # Multi-arch Docker build (amd64 + arm64) via buildx -- local manual operation
make docker-push    # Multi-arch build and push to registry -- local manual operation, requires registry login
make docker-run     # Run in Docker
make docker-smoke   # Build, run, verify healthz + MCP, tear down
make test-load      # Run k6 load tests (requires k6)
make test-integration # Integration tests against live testnet
make seed-test-data # Create test registry with phoney records on-chain
make clean          # Remove build artifacts

API Key Management

make key-create NAME=my-agent                            # Create a new API key
make key-list                                            # List all keys (ID, enabled, roles, created)
make key-disable NAME=my-agent                           # Disable a key (rejected at auth)
make key-enable NAME=my-agent                            # Re-enable a disabled key

Keys are stored in .mcp-keys.json (gitignored). Set MCP_API_KEYS_FILE=.mcp-keys.json to use them.

Local testing

The default suite is hermetic — no chain access, no credentials — and is the same one CI runs on every PR:

make test             # Unit + golden + MCP E2E tests (fast, no network)
make coverage-check   # -race + coverage report + the 80% total-coverage gate
open coverage.html    # Inspect per-line coverage after coverage-check/test-coverage

CI fails any PR whose total statement coverage drops below 80% (scripts/check_coverage.sh), so run make coverage-check before pushing. Every new feature needs unit tests for its success/error paths and, if it changes the MCP surface, E2E tests through the HTTP transport — see AGENTS.md for the full requirements.

Optional local layers:

# Postgres-backed internal/mcp tests (audit log, quotas, migrations) —
# they skip unless a DSN is set. Any disposable Postgres 16 works:
export NVNM_TEST_PG_DSN='postgres://nvnm:nvnm@localhost:5432/nvnm_test?sslmode=disable'  # pragma: allowlist secret -- throwaway local dev creds
make test

make test-integration # Live-testnet integration tests (needs network + .env credentials)
make docker-smoke     # Build image, boot container, verify healthz/readyz + MCP init

For comprehensive testing documentation, including test architecture, framework details, and latest results, see docs/TESTING.md.

Deployment

Docker

make docker-build
docker run --rm \
  -e NVNM_EVM_RPC_URL=https://evm.testnet.nvnmchain.io \
  -e NVNM_CHAIN_ID=787111 \
  -e ANCHOR_ABI_PATH=/app/abi/anchoring.json \
  -e MCP_TRANSPORT=http \
  -p 8080:8080 \
  -p 9090:9090 \
  nvnm-mcp-server

Kubernetes

Plain YAML manifests are available in deploy/k8s/:

# Apply with default namespace (nvnm-mcp; renamed from inveniam-mcp in PR #6, 2026-06-02 — see RUNBOOK § "K8s manifest migration")
kubectl apply -k deploy/k8s/

# Apply to a specific namespace
kubectl apply -k deploy/k8s/ -n your-namespace

A Helm chart is available in deploy/helm/nvnm-mcp-server/:

helm install nvnm-mcp deploy/helm/nvnm-mcp-server/ \
  --set env.NVNM_EVM_RPC_URL=https://evm.testnet.nvnmchain.io \
  --set env.NVNM_CHAIN_ID=787111

Prometheus alerting rules are in deploy/prometheus/alerts.yaml and a Grafana dashboard in deploy/grafana/dashboard.json.

AWS (ECS/Fargate)

The Docker image is designed for deployment on ECS/Fargate with HTTP transport. Configure environment variables through ECS task definitions. The server exposes health check endpoints on :9090 (/healthz, /readyz). Add an aws-otel-collector sidecar for CloudWatch/X-Ray telemetry.

MANTRA Validator Nodes

The server can run directly on MANTRA validator nodes, connecting to localhost RPC endpoints for minimal latency. Use stdio transport if co-located with an MCP client, or HTTP transport for remote access.

Project Structure

cmd/
  nvnm-mcp-server/       Entrypoint
  key-mgmt/                  API key management CLI
  query-anchor/              Anchor query dev CLI
  seed-test-data/            Test-data seeding dev CLI
internal/
  auth/                      Client identity context propagation
  config/                    Environment-based configuration
  logging/                   slog-based structured logging + redaction
  errors/                    Shared sentinel errors + error sanitization
  evm/                       Generic EVM RPC client layer + tracing wrapper
  anchor/                    Inveniam anchor adapter (with address validation)
  mcp/                       MCP tool registration, handlers, auth middleware, key store, admin API
  telemetry/                 OTel providers, MCP middleware, health server, metrics
  version/                   Canonical version constant (single source of truth)
abi/
  anchoring.json             Anchor precompile ABI
deploy/
  k8s/                       Kubernetes manifests (Deployment, Service, HPA, ServiceMonitor, NetworkPolicy)
  helm/nvnm-mcp-server/      Helm chart
  grafana/                   Grafana dashboard JSON
  prometheus/                Prometheus alerting rules
tests/
  load/                      k6 load test scripts
docs/
  DESIGN.md                       Architecture and design decisions
  SECURITY_AUDIT.md               Security assessment and remediation results
  OWASP_AUDIT.md                  OWASP Top 10 self-audit (Phase 8.12)
  DATA_HANDLING.md                Privacy-by-design technical reference
  NVNM_MCP_Privacy_Policy_Jul_2026.pdf  Finalized Privacy Policy (legal artifact)
  TERMS.md                        Terms of Service for the hosted Service
  INCIDENT_RUNBOOK.md             Per-alert investigation playbook
  KEY_CUSTODY_THREAT_MODEL.md     Rationale for zero-key-custody design
  SECURITY_CONSUMER_GUIDANCE.md   Operator-facing security guidance
  LICENSE_EXCEPTIONS.md           Project-scoped license exception register
  METAMASK_GUIDE.md               End-user MetaMask integration walkthrough
  TESTING.md                      Test framework, strategy, and results
  TOOL_REFERENCE.md               MCP tool schema reference
  RUNBOOK.md                      Operational runbook
.github/
  workflows/ci.yml           CI pipeline
  dependabot.yml             Automated dependency updates
.pre-commit-config.yaml     Pre-commit hooks
.golangci.yml               Linter configuration

License

Apache License 2.0 -- see LICENSE and NOTICE. Contributions are accepted under the same terms; see CONTRIBUTING.md.

from github.com/NVNM-Chain/nvnm-mcp-server

Установка Nvnm

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/NVNM-Chain/nvnm-mcp-server

FAQ

Nvnm MCP бесплатный?

Да, Nvnm MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Nvnm?

Нет, Nvnm работает без API-ключей и переменных окружения.

Nvnm — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Nvnm в Claude Desktop, Claude Code или Cursor?

Открой Nvnm на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Nvnm with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development