Skip to content

Fully local — mcidrac + a local model on a DGX Spark

Everything mcidrac touches is sensitive in a quiet way: BMC credentials, service tags, SEL contents, the shape of your network. Point a cloud model at it and all of that becomes someone else’s inference log. A DGX Spark — the GB10 Grace Blackwell desktop with 128 GB of unified memory — is enough machine to close that loop entirely: the model runs on your desk, mcidrac runs beside it, and the whole conversation about your servers stays on your LAN.

The pieces are a local model served by Ollama, opencode as the MCP-speaking agent, and mcidrac as the tool provider.

Follow the Spark site’s run a local LLM how-to — Ollama has native ARM64 + CUDA support and exposes an OpenAI-compatible API on port 11434.

Model choice is not a matter of taste here. These tools power-cycle servers, so the only property that matters is reliable tool calling: the model must emit valid JSON arguments, respect required parameters, and stop when a tool says stop. opencode also wants a 64k+ context window, and MCP tool results (an inventory dump, a SEL page) are chunky.

Two reasonable starting points, both comfortable in the Spark’s memory budget at 4-bit (~0.5 bytes per parameter, per the Spark site’s unified memory explainer):

Terminal window
ollama pull qwen3-coder:30b # MoE, few active params — fast, agentic-tuned
ollama pull gpt-oss:120b # more headroom, still fits at ~60 GB

Don’t take my word — or anyone’s benchmark — for whether your pick is good enough. Step 4 measures it against fake hardware.

Terminal window
curl -LsSf https://astral.sh/uv/install.sh | sh # if uv isn't there yet
uv tool install mcidrac
curl -fsSL https://opencode.ai/install | bash

mcidrac is pure Python with one dependency, so arm64 is a non-event — nothing to compile, no wheels to fight.

~/.config/opencode/opencode.json — the provider block points opencode at Ollama, and the mcp block spawns mcidrac over stdio:

{
"$schema": "https://opencode.ai/config.json",
"model": "ollama/qwen3-coder:30b",
"provider": {
"ollama": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama (local)",
"options": { "baseURL": "http://127.0.0.1:11434/v1" },
"models": { "qwen3-coder:30b": { "name": "Qwen3 Coder 30B" } }
}
},
"mcp": {
"idrac": {
"type": "local",
"command": ["uvx", "mcidrac", "--transport", "stdio"],
"enabled": true,
"environment": {
"MCIDRAC_CONFIG": "/home/YOU/.config/mcidrac/mockup.toml",
"R740_LAB_PASS": "your-idrac-password"
}
}
}
}

Note what MCIDRAC_CONFIG is pointing at: the mockup registry, not your real one. That’s deliberate, and it’s the next step.

This is the part other setups can’t offer. mcidrac ships an integration harness that serves Dell’s real iDRAC9 and iDRAC10 Redfish captures as six fake BMCs, plus a behavioral simulator for the write paths — see the mockup lab. Point your local model at those and let it flail with zero consequences:

Terminal window
git clone https://git.supported.systems/warehack.ing/mcidrac.git
cd mcidrac && scripts/mockup-up.sh all
cp .mockup/idracs.toml ~/.config/mcidrac/mockup.toml

Then start opencode and work the model through a real session:

“List my iDRACs, then give me a health summary of each one.”

“Which box has the most memory, and what’s its service tag?”

“Mount http://192.0.2.50/test.iso on r660xs, then unmount it.”

What you’re watching for is not whether the answers are pretty. It’s whether the model calls the right tool with valid arguments, passes the idrac name it was given rather than inventing one, reads the result before narrating it, and stops cleanly instead of looping. A model that garbles arguments against a fake R660xs would garble them against your real R740 — you just get to find out for free.

If it stumbles: try a larger quantization, raise num_ctx in Ollama (tool results are big), or move up a model tier. This is a measurement, not a vibe.

Once the model has earned it, point MCIDRAC_CONFIG at your real registry (see configuration) and restart opencode.

Two habits worth keeping:

Start read-only. Ask for health checks, inventories, SEL tails, and firmware audits for a while before you let it touch power or media. The safety model explains what the server refuses on its own — wrong-box SCP imports, unverified boot configs — but a local model is a new operator, and new operators earn write access.

Keep a human in the loop for destructive calls. Every destructive tool carries the MCP destructiveHint annotation, and opencode’s permission settings can require confirmation before an agent acts. Configure it to ask, at least until you trust the pairing.

If you want the Spark to serve other machines’ clients too, run mcidrac as a persistent HTTP service instead of a per-session stdio process. A user-level systemd unit does it without root:

~/.config/systemd/user/mcidrac.service
[Unit]
Description=mcidrac — Dell iDRAC MCP server
After=network-online.target
[Service]
EnvironmentFile=%h/.config/mcidrac/env
ExecStart=%h/.local/bin/mcidrac --transport http --host 127.0.0.1 --port 7903
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
Terminal window
sudo loginctl enable-linger "$USER" # survive logout
systemctl --user daemon-reload && systemctl --user enable --now mcidrac

Put credentials in ~/.config/mcidrac/env (mode 0600), one VAR=value per line.

The HTTP transport has no authentication — network reachability is authorization, and this process holds credentials that can power off your servers. Hence the 127.0.0.1 bind. Reach it from elsewhere over an SSH tunnel, or over Tailscale as the Spark site’s network access guide recommends:

Terminal window
ssh -N -L 7903:127.0.0.1:7903 spark &
claude mcp add idrac --transport http http://127.0.0.1:7903/mcp

A bonus of centralizing: the per-host session cap lives in the server process, so however many clients connect, the iDRAC still sees at most three concurrent sessions from mcidrac (architecture).

An air-gapped rack still leaks through its management plane the moment you paste a SEL dump into a cloud chat window. This setup closes that: the model, the tools, the credentials, and the hardware all sit inside one boundary you control — and the only thing crossing it is your own curiosity.

More Spark operational lore — networking, clustering units, recovery — lives at dgx-spark.warehack.ing.