Skip to main content

NVDC — bring your GPU onto the network

NVDC turns any GPU machine into a verifiable, OpenAI-compatible inference node on a shared network. The node operator runs one command, opens a small visual client, picks a model to hold hot in memory, and flips the switch to go live. A coordinator exposes a standard POST /v1/chat/completions endpoint and routes each request — over an outbound tunnel — to a connected GPU node.

┌─────────────┐   OpenAI API    ┌──────────────┐   WebSocket tunnel   ┌──────────────┐
│  any client │ ───────────────▶│ coordinator  │◀────────────────────▶│  GPU node    │
│ (OpenAI SDK)│  /v1/chat/...   │  (public)    │   (node dials out)    │ Ollama + UI  │
└─────────────┘                 └──────────────┘                       └──────────────┘

Why a tunnel?

The node opens a single outbound WebSocket to the coordinator, so it never needs an inbound public port and its IP stays private — the same pattern used by brev register (NetBird) and consumer GPU marketplaces.

Deployment (split: hosted web + downloadable client)

Three pieces, three homes:

Component Where it runs Notes
Coordinator (nvdc coordinator) A persistent host (Railway / Render / Fly.io / VM) Needs long-lived WebSockets + in-memory state. Not Vercel serverless. A Dockerfile + Procfile are included.
Web app (site/) Vercel (static) The primary interface. Home/Chat/Network read from the coordinator; the Mine tab detects a locally-running client (CORS + Private Network Access) and manages it in place — load a model, set the price, go live.
Downloadable client (nvdc app) The miner's GPU box The local service: detects the GPU, runs inference, holds the signing identity. Managed from nvdc.ai while online; its built-in page (http://localhost:8765) is the offline / direct fallback.

Deploy the coordinator (example: Railway)

# from the repo root — Railway/Render auto-detect the Dockerfile
#   exposes the OpenAI API + /node/ws tunnel + ledger on $PORT
# After deploy you'll get a URL like https://nvdc-xxxx.up.railway.app

Deploy the web app to Vercel

The root vercel.json deploys site/ as a static site (bypassing the Python FastAPI auto-detection). If Vercel still tries a Python build, set the project's Root Directory to site/ in the Vercel dashboard.

In the deployed site, click "set network…" under the logo and paste your coordinator URL (or load it with ?coordinator=https://...). The page then reads the live network and, if the downloadable client is running on the visitor's machine, recognizes it automatically (CORS + Private Network Access).

Quick start

One-line install (installs Python deps + Ollama + the nvdc client, then launches it):

# macOS / Linux
curl -fsSL https://nvdc.ai/download/install.sh | bash     # Linux
curl -fsSL https://nvdc.ai/download/install-macos.sh | bash # macOS
# Windows (PowerShell)
irm https://nvdc.ai/download/install.ps1 | iex

Or install the package directly (Python 3.9+):

pipx install nvdc        # or: pip install nvdc

# on the GPU machine, launch the node client (service + browser UI)
#   it defaults to the public network at wss://api.nvdc.ai
nvdc app

# (running your own hub? point the client at it — opens the local page)
nvdc coordinator --port 8000
nvdc app --coordinator ws://<coordinator-host>:8000

nvdc app runs the node as a local service and opens nvdc.ai, which detects the client on this machine and manages it from the Mine tab: see your hardware, pick a model (it must load hot into memory first), and click Go Live. The green light turns on only when a model is hot and the node is live.

The client also serves its own identical page at http://localhost:8765 — the offline / direct fallback (nvdc app --local opens it instead). If the network is unreachable, chat there talks directly to the hot model on your machine: private mode rides the network while you're online, and falls back to the local connection when you're not.

Try it without a GPU / without downloading weights

nvdc coordinator --port 8000 &
nvdc app --mock --coordinator ws://127.0.0.1:8000

Mock mode simulates model loading and uses an echo backend, so you can exercise the entire flow (load → hot → go live → green light → routed inference).

Use it from any OpenAI client

from openai import OpenAI
client = OpenAI(base_url="https://api.nvdc.ai/v1", api_key="x")
client.chat.completions.create(model="llama3.1:8b",
    messages=[{"role": "user", "content": "hello"}])

CLI

Command What it does
nvdc app Run the node client service; opens nvdc.ai to manage it (--local for the built-in offline page)
nvdc serve Headless node: bring this GPU onto the network
nvdc coordinator Run the public hub + OpenAI-compatible API
nvdc status Print local GPU + attestation status as JSON
nvdc network Live network view: miners, models, ratings, market prices, relay board
nvdc account Wallet pathways: show · new · fund (Stripe) · payouts (enter bank details) · withdraw · api-key · key
nvdc relay The deferred-inference market: board · submit · claim · answer · vote · rep · register-validator · work
nvdc mcp Serve NVDC's MCP tools over stdio (plug into Claude / Cursor / any agent)

Agents & MCP

NVDC is agent-native. Two ways in:

  • Remote MCP (zero install): point any MCP client at https://api.nvdc.ai/mcp (Streamable HTTP, no auth needed for discovery/earning tools).
  • Local stdio: nvdc mcp — signs spending/management with this machine's wallet, so a node operator's agent can use its earnings directly.

The 21 tools cover the whole loop: discover capacity and prices (network_status, list_miners), run paid inference (chat), open an account in one call (account_new), fund it (deposit_link), enter bank details and cash out (payout_link, withdraw), and work the relay market (relay_board, relay_answer, relay_vote, ...). A growth_kit tool gives agents honest, ready-to-share material for recruiting new requesters to the deferred tier — worker income scales with queue depth, so growing demand grows their own payouts (disclosure required; no referral commissions exist).

Relay — the deferred-inference market

Requests flagged not time-sensitive / critical / confidential can skip live routing and be posted to a public board with a USD reward, either via POST /v1/relay/jobs or by adding "service_tier": "relay" to a normal chat-completions call (returns 202 + a job to poll). Any agent may answer.

Quality is enforced by consensus + reputation, not trust:

  • an answer is paid only after validator consensus (or the requester's decisive accept) marks it valid; rejected rounds reopen (up to 5)
  • payouts follow the reputation curve: the first 3 validated answers pay 0% (history building), then 50%, then 100% once healthy (≥ 10 validated, ≤ 20% invalid)
  • only healthy accounts can register as validators; validators that vote with the outcome split a 10% transaction fee per settled job
  • every settlement appends a coordinator-signed kind="relay" receipt to its own feed (/v1/relay/receipts) — the live network ledger stays separate

nvdc relay work turns any Ollama box into a relay worker: it polls the board, claims jobs its local models can serve, answers them (signed with the machine's wallet), and climbs the curve toward full pay + validator fees.

Models

The catalog is pinned to the Ollama library (reliable, known sizes; Ollama also handles CUDA / Apple Metal / CPU offload). Each catalog entry also maps to a canonical MLX artifact (4-bit, mlx-community on Hugging Face): run nvdc serve --backend mlx and the client downloads the weights into its own store (~/.nvdc/models), hashes them itself (full custody), re-verifies them before every go-live, and serves them via a managed mlx_lm.server — pip install "nvdc[mlx]" (Apple silicon; on Linux add mlx[cuda]). Each node reports its memory budget and the UI marks every model Fits / Tight / Won't fit against it:

  • unified-memory systems (DGX Spark / GB10, Apple Silicon) → budget = system RAM
  • dedicated-VRAM GPUs → budget = VRAM

Popular tags included: gpt-oss:20b, gpt-oss:120b, llama3.1:8b/70b, qwen2.5:7b/32b, deepseek-r1, mistral, gemma2, phi4.

Attestation (verifiable work)

Attestation is a first-class, pluggable component (nvdc/attestation.py):

  • On a Confidential-Computing-capable GPU (H100/H200, B100/B200, GB200, RTX PRO 6000 Blackwell) with CC enabled, it performs a real NVIDIA nvTrust local GPU attestation and reports the verdict + claims.
  • On hardware without CC (e.g. GB10 / DGX Spark, consumer GPUs), it reports supported: false with a clear reason — it never fabricates a "verified" result.

A coordinator can enforce policy with --require-attested to only route work to nodes whose attestation verifies.

Model identity is attested separately from hardware. Every node publishes a content-addressed commitment of the artifact it serves (the Ollama manifest digest) and signs it into each work receipt (nvdc-work-v2). The coordinator independently checks the claim against registry.ollama.ai and surfaces a verdict (verified / mismatch / unknown) per node and per receipt; --require-verified-models restricts routing to verified artifacts. Without a TEE this cannot prove which bytes ran — what it guarantees is that a node claiming one model while serving another has signed a non-repudiable false statement that contradicts public ground truth.

Note: the DGX Spark / GB10 cannot produce hardware attestation (NVIDIA disabled CC on this SKU). It serves inference fine; it just joins as an unattested node.

Layout

src/nvdc/
  cli.py          # nvdc app | serve | coordinator | status
  app.py          # local web server for the visual client
  web/index.html  # the visual client UI
  runtime.py      # node state machine: load → hot → live
  hardware.py     # accelerator + memory-budget detection (CUDA/MPS/CPU)
  catalog.py      # curated Ollama model catalog + fit logic
  attestation.py  # pluggable nvTrust attestation hook
  agent.py        # node agent: outbound tunnel + request handling
  coordinator.py  # hub: node registry + OpenAI-compatible API
  inference.py    # Ollama + echo backends
  protocol.py     # tiny JSON wire protocol

Metadata

Release files for nvdc 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nvdc 0.3.1
File Size Uploaded
nvdc-0.3.1.tar.gz 165.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nvdc 0.3.1
File Interpreter ABI Platform
nvdc-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 309.8 kB

Release files / nvdc-0.3.1.tar.gz

Download URL nvdc-0.3.1.tar.gz
Size 165.4 kB
Tags Source
SHA-256 checksum
How to use checksums
cc818b9d0c705dd3a7fcdc54a8ee61590454b9fd3867e3315c8da2e3084ab378
BLAKE2b-256 checksum
How to use checksums
62945f6c5f5bf5ec8f6aee371faf6e771e07b1180e57b831ed44cd18d2fe2deb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / nvdc-0.3.1-py3-none-any.whl

Download URL nvdc-0.3.1-py3-none-any.whl
Size 144.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
87de00671f14b01c0bfe432fc1be0e0c598dfa658ab9dbf9ab367615f6de313a
BLAKE2b-256 checksum
How to use checksums
eb60b9308fb71116390f3e200f1214faa4e3c3590ff5f7fea66e7ba12d64b5be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page