Docs
givemeanode is on-demand GPU nodes and batch GPU jobs for AI agents, over MCP. Your agent gets a container on an H100 with a persistent encrypted disk, billed per minute. Stop it and it parks: files intact, billing stopped. The next command wakes it.
- Quick start
- Installation — Claude on the web · Claude Code · OpenAI Codex · opencode
- Nodes
- Running commands
- Long-running commands
- Files in and out
- Exposing ports
- Batch jobs
- From inside a node
- Teams and organizations
- Usage and billing
- Scopes
- Getting help
Quick start
Add the MCP server (Claude Code shown; other clients below):
claude mcp add --transport http givemeanode https://mcp.givemeanode.com
Your client opens a browser window once to sign in. Then ask your agent for a GPU:
Get me a GPU node, clone github.com/you/yourrepo on it, and run the benchmark.
That's the whole product. Behind the scenes the agent makes three tool calls:
create_node(gpu_type: "h100") → {name: "tulip", status: "provisioning", rate: "$/min"}
run_command("tulip", "nvidia-smi") → {exit_code: 0, stdout: "..."}
stop_node("tulip") → parked: files intact, billing stopped
Billing starts when the node is ready and stops when you stop it, at the
rate in the create_node response. The next run_command against a
stopped node wakes it with the disk exactly as you left it.
Installation
The server is the same for every client — streamable HTTP with OAuth 2.1 at:
https://mcp.givemeanode.com
Clients discover auth automatically; a human approves once in the browser. No API keys.
Claude on the web
Go to Settings → Connectors → Add custom connector and enter the remote MCP server URL:
https://mcp.givemeanode.com
Claude Code (CLI)
claude mcp add --transport http givemeanode https://mcp.givemeanode.com
Then approve the connection when Claude first uses it (/mcp shows
status).
OpenAI Codex
codex mcp add givemeanode --url https://mcp.givemeanode.com
Or in ~/.codex/config.toml:
[mcp_servers.givemeanode]
url = "https://mcp.givemeanode.com"
Run codex mcp login givemeanode if Codex doesn't prompt for OAuth on
first use.
opencode
In opencode.json (project or global):
{
"mcp": {
"givemeanode": {
"type": "remote",
"url": "https://mcp.givemeanode.com",
"enabled": true
}
}
}
Nodes
A node is a container on an H100 with a persistent disk. gpu_type is
h100 for one GPU or 8xh100 for a full 8-GPU machine.
create_node(name: "tulip", gpu_type: "h100")
create_node never blocks. It returns one of:
provisioning— capacity was free; the response carries the locked per-minute rate. Pollget_node("tulip")untilrunning.queued— the type is exhausted; you get a live queue position and a wait estimate. The scheduler provisions your node the moment a slot frees — pollget_node, don't re-create. Re-callingcreate_nodewith the same name is idempotent (you get the current status, never a duplicate), and passingmax_waiton a re-call extends your hold, forward-only, up to 1 hour.
The lifecycle:
stop_node("tulip") # stop paying now; disk parks, files intact
run_command("tulip", "ls") # wakes a stopped node automatically
delete_node("tulip") # destroy the disk (crypto-erase, irreversible);
# stopped nodes only — stop_node first
list_nodes() shows everything you have, get_node(name) shows one
node's state, rate, and queue position. It's the poll target while a node
is queued, provisioning, or waking.
Reproducible benchmarks: pass clock_lock: true at create. The platform
pins the GPU clock (free, immutable once set) so timings compare across
runs.
Running commands
There is no SSH. Commands run over MCP in the node's container, and logs are the interface:
run_command("tulip", "git clone https://github.com/you/yourrepo && cd yourrepo && pip install -e .")
→ {exit_code: 0, stdout: "...", stderr: "...", truncated: false}
Secrets go in env, never the command string — command lines are
recorded, env values aren't:
run_command("tulip", "huggingface-cli download meta-llama/Llama-3.1-8B",
env: {HF_TOKEN: "hf_..."})
Use short-lived, minimally scoped tokens and treat them as burned.
Long-running commands
Anything that outlives a tool-call timeout (training, a server) runs detached:
run_command("tulip", "python train.py", detach: true)
→ {command_id: "cmd_...", log_path: "..."} # returns immediately
get_command("tulip", "cmd_...") # status + incremental output
get_command("tulip", "cmd_...", offset: 4096) # just the new bytes
list_commands("tulip") # all detached commands, newest first
kill_command("tulip", "cmd_...") # TERM, then KILL after 10s
Files survive stop/wake; processes don't — exactly like tmux on a machine
you can power off. get_command never wakes a stopped node, so checking
on finished work is free.
Files in and out
Small files in (configs, entry scripts — not secrets, not datasets):
write_file("tulip", "/root/run.sh", "#!/bin/sh\npython train.py\n", executable: true)
Large inputs: pull them from inside the node with run_command — curl,
git, huggingface-cli. The node has internet access.
Results out: export_file returns a presigned download URL; a directory
arrives as a tar.
export_file("tulip", "/root/yourrepo/checkpoints")
→ {url: "https://...", expires_at: "..."}
Exposing ports
Put a port on a running node at a public HTTPS URL — TensorBoard, Jupyter, a vLLM endpoint serving a model to a judge:
run_command("tulip", "python -m vllm.entrypoints.openai.api_server --port 8000", detach: true)
expose_port("tulip", port: 8000)
→ {url: "https://<endpoint-id>.<edge>", expires_at: "..."}
Anyone holding the URL reaches the port — the URL is the secret, so treat
it like one. auth: "bearer" additionally requires an Authorization: Bearer token at the edge (the token rides the response once and is never
shown again).
Endpoints are bound to the node's current container: a stop kills them,
and a wake never resurrects them — re-call expose_port for a fresh URL.
Traffic through the endpoint is free and does not keep the node awake; the
server process (a detached command) is what holds the node running.
list_endpoints(node) shows what's live, unexpose_port(node, port)
takes it down.
Batch jobs
Nodes are interactive; jobs are fire-and-forget. submit_job builds your
image, queues fairly against your org's share, runs your command, and
bills only the running attempt — queued and preempted time is free:
submit_job(
gpu_model: "h100",
command: "python eval.py",
context: {"Dockerfile": "FROM pytorch/pytorch\nCOPY eval.py .", "eval.py": "..."},
idempotency_key: "eval-2026-07-25")
→ {job_id: "job_...", rate: "$/min", cost_ceiling: "..."}
Or skip the build with a prebuilt image ref instead of context.
idempotency_key makes resubmission safe: the same key returns the same
job.
Inside the container, declare results instead of grepping logs: write your
verdict as JSON to $GMN_RESULT_PATH and put files worth keeping in
$GMN_OUTPUT_DIR. Both come back on get_job when the attempt completes
— the result inline, the output dir as a download URL.
get_job("job_...") # status; add stream:"run" for logs
list_jobs(label: "lr-sweep", summary: true) # rollup with every declared result
cancel_job("job_...") # immediate; queued/building stops free
Sweeps
Up to 256 variants of one job in one call — one build, N runs:
submit_jobs(
shared: {gpu_model: "h100", context: {...}},
variants: [{env: {LR: "1e-4"}}, {env: {LR: "3e-4"}}, {env: {LR: "1e-3"}}],
label: "lr-sweep",
idempotency_key: "lr-sweep-1")
Validation is all-or-nothing; list_jobs(label: ..., summary: true) is
the comparison table when they finish.
Large build contexts
Inline contexts cap at 4 MiB. Past that, presign an upload:
create_context(sha256: "...", size_bytes: 123456789) → upload URL
# PUT the tar to the URL, then:
finalize_context(context_id)
submit_job(gpu_model: "h100", command: "...", context_id: "...", idempotency_key: "...")
From inside a node
Code running on a node can introspect and stop itself with no credential —
identity is placement. Fixed address http://169.254.42.1 (also
metadata.givemeanode.internal); every request needs the header
Metadata-Flavor: givemeanode:
curl -s -H 'Metadata-Flavor: givemeanode' http://169.254.42.1/v1/node
curl -s -H 'Metadata-Flavor: givemeanode' http://169.254.42.1/v1/events
curl -s -X POST -H 'Metadata-Flavor: givemeanode' http://169.254.42.1/v1/stop
/v1/node is identity and money (name, state, rate, grace window);
/v1/events carries structured notices with deadlines (machine
retirement, spend-cap warnings) — a checkpoint-aware training script polls
it like cloud spot metadata. POST /v1/stop ends the node from inside
with stop_node semantics: a training run's last line can be that curl.
Teams and organizations
Every account is an org of one until you invite someone:
invite_member(email: "student@lab.edu", role: "member")
Roles: admin (everything), billing (money pages), member (their own
nodes and usage). The same management lives in the browser at
/team — roster, invites, role changes, workspaces
with spend caps, and a stop button for any org node (the
runaway-student-node case, also stop_org_node over MCP).
Members of a workspace share its nodes. switch_active_org(org) picks
where your next node bills if you belong to several.
Usage and billing
Per-minute rates, listed on the front page. A node bills
while running or idling in its grace window; stopped nodes cost nothing.
The rate in every create_node/get_node response is the rate you pay.
get_usage() # this month's spend per node
get_usage(month: "2026-06")
get_billing() # dunning state, MTD spend, caps
In the browser: /usage is the rendered ledger
(per-workspace, per-member, per-node; CSV export at /usage.csv), and
/billing is the Stripe portal — invoices,
receipts, payment method.
Referrals: claim a code at /referrals (or
claim_referral_code over MCP); activations and credits earned are listed
there and on list_referrals().
Scopes
Authorizing the server is a consent checklist (OAuth scopes); the tool
list a connection sees is exactly its grant. Each scope comes in two
strengths: the bare word grants read and write, a :read suffix grants
the read-only slice.
infra— your infrastructure: nodes (lifecycle, exec, files, ports) and batch jobsorg— your organization: spend and billing, members, invites, roles, caps, referrals
A token that names no scopes acts with your full authority. Give a
CI agent infra and nothing else; give a finance script org:read.
Getting help
- Status and incident history: status.givemeanode.com
- A human: /contact
- Report abuse: abuse@givemeanode.com
- These docs, as plain markdown for agents: /llms.txt