Skip to content

Let an AI agent run DedNets

DedNets ships an MCP server: point an AI coding agent at it and the agent can enroll a machine, publish a service at a public HTTPS URL, and wire up a watchdog, using the same API you would. It runs locally, out of the dednetsctl binary, and talks only to your Console with a token you mint and can revoke. (Since v0.4.1.)

The MCP server is a subcommand of dednetsctl. Let npx fetch it for you, download the CLI yourself, or install it with Homebrew.

Using Claude Code? Install the plugin in step 3 and skip this step entirely: it brings its own binary resolution.

You want Use Because
Nothing installed system-wide npx -y @dednets/mcp (Option A) follows your Console automatically, verified by sha256
A real, upgradable CLI on your PATH brew install dednets/tap/dednetsctl (Option C) one command, brew upgrade later; pinned to a version you choose
No Node and no Homebrew, or Windows curl from /dist (Option B) works anywhere, and you manage upgrades

(Since v0.4.1. Needs Node 20.9 or newer, and a Console publishing v0.4.1 or newer.)

Terminal window
npx -y @dednets/mcp --probe-only

That downloads dednetsctl from your Console (DEDNETS_CONSOLE, default https://console.dednets.com), checks it against the sha256 that Console publishes, caches it under ~/.cache/dednets (%LOCALAPPDATA%\dednets\cache on Windows) and exits without starting anything. Nothing is installed system-wide, and the CLI always follows the Console you point at, including a self-hosted one.

Run it once before wiring up an agent so the first session does not wait for the download. Then use the npx configuration in step 3. If it prints dednets mcp failed: console_too_old, that Console has not been upgraded to v0.4.1 yet; use Option B against it, or ask whoever operates it to upgrade.

Claude Code users should prefer the plugin (step 3) and can skip this step. Haunted Terminal users already have the CLI in the app bundle.

Download it from your Console and put it on your PATH:

Terminal window
# macOS (Apple Silicon)
curl -fsSLo dednetsctl https://console.dednets.com/dist/darwin-arm64/dednetsctl
# macOS (Intel): .../dist/darwin-amd64/dednetsctl
# Linux: .../dist/linux-arm64/dednetsctl or .../dist/linux-amd64/dednetsctl
chmod +x dednetsctl && sudo mv dednetsctl /usr/local/bin/
dednetsctl mcp -h # prints the flags; nothing is started

On Windows, in PowerShell (curl there is an alias for Invoke-WebRequest and takes different arguments, so call it by its real name):

Terminal window
$dir = "$env:LOCALAPPDATA\DedNets"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
Invoke-WebRequest -Uri https://console.dednets.com/dist/windows-amd64/dednetsctl.exe `
-OutFile "$dir\dednetsctl.exe"
& "$dir\dednetsctl.exe" mcp -h

The CLI is called dednetsctl since v0.4.1 (it was dedmeshctl). There is no alias, and the old /dist/<platform>/dedmeshctl URLs no longer resolve, so re-download it with the command above if you still have the old binary.

Builds are published for macOS (Apple Silicon and Intel), Linux (amd64, arm64) and Windows (amd64, as dednetsctl.exe). (Windows and Intel-Mac builds since v0.4.1.) Windows gets the CLI, not the host agent: a Windows machine can drive your DedNets account, and the hosts you enroll still run Linux or macOS.

The Windows build is cross-compiled and unit-tested, and has not been run on a Windows machine by us. mcp itself is the portable part of the CLI: it writes no files, opens no unix sockets and reads no config directory. Two areas are built but unverified there: the mTLS client-identity commands (login, client enroll, attach) write their key and certificate with POSIX file modes Windows ignores, and attach never puts the console into raw or virtual-terminal input mode, so interactive use would be line-buffered and locally echoed. Colored output (view) needs Windows Terminal or PowerShell 7; legacy conhost.exe shows the escape codes literally.

(Since v0.4.1.)

Terminal window
brew install dednets/tap/dednetsctl
dednetsctl mcp -h # prints the flags; nothing is started

The formula covers macOS (Apple Silicon and Intel) and Linux (arm64 and amd64), and installs a single binary. There is no Homebrew formula for Windows: use Option B there.

A Homebrew install pins one CLI version, the one the formula was cut from, and brew upgrade dednetsctl moves it. That is the difference from Option A, where the CLI follows whichever Console you point at. Against an older self-hosted Console a pinned CLI is exactly the case the version-skew warning below is for, so expect it and read it rather than filing it as a bug.

In the Console, go to Settings > API tokens > Create token. Name it after the agent (claude-code), tick the scopes you want it to have, and copy the dak_… secret: it is shown exactly once.

For the full onboarding journey below, tick Read-only, Manage hosts, Manage services and Manage watchdogs. For a token that can only look, tick just Read-only. What each scope unlocks: API tokens and scopes.

The agent holds this token. Give it the least you need, and revoke it from the same page when you are done.

(Since v0.4.1. macOS and Linux; on Windows use the manual configuration below.)

Terminal window
# 1. tell Claude Code where your Console is and how to authenticate
export DEDNETS_CONSOLE=https://console.dednets.com # omit if you use the hosted Console
export DEDNETS_TOKEN=... # Console > Settings > API tokens
# 2. install the plugin
claude plugin marketplace add dednets/dednets-claude-plugin
claude plugin install dednets@dednets

The plugin finds the CLI for you, in this order: $DEDNETSCTL, the Haunted Terminal app bundle, then dednetsctl on your PATH. If you have the Haunted Terminal, you can skip step 1 of this page entirely. It also brings a skill that walks the parts the MCP tools cannot do themselves, such as running an enroll command on the machine being enrolled.

Both variables are read when Claude Code starts, so restart it after changing either one. /mcp then lists dednets.

Your Console’s Use with AI button shows these same three paths (plugin, npx, curl) with your Console’s URL already filled in. (Since v0.4.1.)

(Since v0.4.1.) If you took Option A in step 1, name npx as the command and skip the binary entirely:

{
"mcpServers": {
"dednets": {
"command": "npx",
"args": ["-y", "@dednets/mcp"],
"env": {
"DEDNETS_CONSOLE": "https://console.dednets.com",
"DEDNETS_TOKEN": "dak_your_token_here"
}
}
}
}

Add "-read-only" to args after the package name for a look-but-do-not-touch server.

Create .mcp.json in the project you work from:

{
"mcpServers": {
"dednets": {
"command": "dednetsctl",
"args": ["mcp"],
"env": {
"DEDNETS_CONSOLE": "https://console.dednets.com",
"DEDNETS_TOKEN": "dak_your_token_here"
}
}
}
}

Or add it from the command line:

Terminal window
claude mcp add dednets \
--env DEDNETS_CONSOLE=https://console.dednets.com \
--env DEDNETS_TOKEN=dak_your_token_here \
-- dednetsctl mcp

Then /mcp inside Claude Code should list dednets as connected.

The same block goes in the app’s config file, which differs per OS. Claude Desktop does not inherit your shell PATH, so give the absolute command path in both cases, and restart the app after editing the file. That applies to npx too: use the output of which npx (often /usr/local/bin/npx or a path under ~/.nvm/) rather than the bare word. (Since v0.4.1.)

~/Library/Application Support/Claude/claude_desktop_config.json:

{
"mcpServers": {
"dednets": {
"command": "/usr/local/bin/dednetsctl",
"args": ["mcp"],
"env": {
"DEDNETS_CONSOLE": "https://console.dednets.com",
"DEDNETS_TOKEN": "dak_your_token_here"
}
}
}
}

%APPDATA%\Claude\claude_desktop_config.json. Give the expanded absolute path to the .exe (the config file is not a shell: environment variables such as %LOCALAPPDATA% are not expanded inside it), and remember that JSON needs every backslash doubled. (Since v0.4.1.)

{
"mcpServers": {
"dednets": {
"command": "C:\\Users\\you\\AppData\\Local\\DedNets\\dednetsctl.exe",
"args": ["mcp"],
"env": {
"DEDNETS_CONSOLE": "https://console.dednets.com",
"DEDNETS_TOKEN": "dak_your_token_here"
}
}
}
}
Setting Value
Transport stdio
Command dednetsctl, or dednetsctl.exe on Windows (absolute path if the client does not use your PATH)
Args ["mcp"], or ["mcp", "-read-only"] to publish only the read tools
Env DEDNETS_CONSOLE (your Console base URL), DEDNETS_TOKEN (your dak_… token)

With npx instead, the command is npx and the args are ["-y", "@dednets/mcp"] (add "-read-only" after that for the read tools only). The environment is the same. (Since v0.4.1.)

Ask the agent: “list my DedNets hosts”. It should call host_list and answer with your fleet. If it says it has no such tool, see Troubleshooting.

Ask for It does Needs scope
“add this machine to my network” enrolls a host, then hands you the exact install command to run on it Manage hosts
“which of my hosts are online?” lists the fleet with versions and status Read-only
“give this container a public HTTPS URL” publishes an app and returns the https://… address Manage services
“open port 25565 for my game server” a raw public port, or a port on your own gateway host Manage services
“let host A reach host B’s database” a proxy port; nothing becomes public Manage services
“is my service healthy?” status, uptime and health-check state for one target Read-only
“alert me if my nightly backup stops running” creates a watchdog and gives you the cron wiring Manage watchdogs
“why did my watchdog alert last night?” recent transitions, uptime buckets, likely causes Read-only

The server also ships whole workflows as MCP prompts. In Claude Code they appear as slash commands after / (type /dednets to filter); other clients list them in a prompt picker. Each one is a checklist the agent follows, and each takes optional arguments. (Since v0.4.1.)

Command Does Arguments
/dednets:onboard_host enrolls a machine and waits for it to come online host, flavor
/dednets:review_fleet read-only review of every host and what it serves kind
/dednets:publish_app exports a service and hands back the public address app, host, proto
/dednets:remove_host shows what breaks, then revokes after you confirm host
/dednets:troubleshoot_watchdog reads a monitor’s history and names likely causes watchdog, range

Arguments are optional: run the command with none and it asks you for what it needs. With -read-only only review_fleet and troubleshoot_watchdog are offered, because the others need a tool that changes something.

Prefer starting from the Console? The Hosts page has a Use with AI button (since v0.4.1) that opens this same setup plus ready-made prompts for adding, reviewing, and removing hosts - the same text these slash commands use. Copy one straight into your agent.

The agent cannot mint or revoke API tokens, change your account, or touch anyone else’s resources, whatever you ask it for.

This is a real run, not an illustration. The prompt was “deploy this machine as a new mesh host, run an HTTP service on it, expose it at a public URL, and configure a watchdog for it”, given to an agent that had the DedNets tools and a shell on a fresh Linux VM, and nothing else. What it did:

  1. Enrolled the host. It picked the systemd install flavor (the VM had no Docker) and got a one-time join token plus a ready-to-run command.
  2. Ran the install command on the machine itself, over its shell. This is the step the agent cannot do on your behalf without access: it needs a shell on the target machine, or you paste the command yourself.
  3. Waited for the host to come online, checking the fleet.
  4. Started a small HTTP service on 127.0.0.1:8080 as a systemd unit, then published it as app demo with proto: http and public: true. That returned an https://demo-<username>.<domain> address which answered 200 end to end.
  5. Created a watchdog (5 minute period, 60 second grace) and wired a cron entry that pings start, runs the check, then pings success or fail. The watchdog read up on the next ping.

It took about 50 turns and a few minutes. Give the agent shell access to the target machine, or be ready to paste one install command yourself.

  • The agent has no DedNets tools. Either the config file is not where the client reads it, or dednetsctl is not on the client’s PATH (Claude Desktop: use the absolute path). Restart the client after editing the config.
  • “no token” on startup. DEDNETS_TOKEN is missing from the env block. The server refuses to start without it.
  • A call was refused for scope. The error names the scope to add. You cannot widen an existing token: mint a new one with the extra scope and update the config.
  • Everything 404s or answers nonsense. DEDNETS_CONSOLE must be the full base URL including the scheme (https://console.dednets.com).
  • A call fails with console_outdated, or the log warns about versions (since v0.4.1). The dednetsctl binary and the Console are on different releases. On its first tool call the server prints one line on stderr naming both versions and keeps running; a call that needs an endpoint the Console does not have then fails with a fix: line instead of a bare 404. Fix it from whichever side you control: ask the Console operator to upgrade, or reinstall the CLI from that Console - curl -fsSLO https://<console>/dist/darwin-arm64/dednetsctl (or the linux-… / darwin-amd64 / windows-amd64/dednetsctl.exe path for your machine). The same version with a different -<sha> suffix is not skew and is never reported.
  • My Homebrew CLI and my Console disagree on the version (since v0.4.1). Expected: brew install pins the release the formula was cut from, so a Console on a different release produces exactly the skew warning above. Run brew upgrade dednetsctl. If the Console is the older side, upgrade it, or switch to npx -y @dednets/mcp (Option A), which follows the Console.
  • brew install dednets/tap/dednetsctl says there is no available formula. That tap has not published a formula yet, or you have an old cached copy of it: brew update and retry.
  • The install command the agent gives me fails to download. Install commands are generated for a console reachable over HTTPS on port 443. A self-hosted console on another port hands out a command whose download URL does not resolve; enroll that host from the Console’s own Deploy a daemon wizard instead.
  • I want a look-but-do-not-touch setup. Add "-read-only" to args: only the read tools are published, so no tool call can change anything.
  • npx says console_too_old (since v0.4.1). That Console publishes a release older than v0.4.1, from before the CLI was renamed, so there is no dednetsctl for npx to fetch. Ask whoever operates it to upgrade, or install the CLI yourself with Option B in step 1 and point your client at the binary.
  • npx says checksum_mismatch (since v0.4.1). The bytes downloaded did not match the sha256 that Console publishes. Nothing was run and the download was deleted. A Console being redeployed at that exact moment explains it, so retry once; if it repeats, do not use that download and tell whoever operates the Console.
  • The first npx run is slow. It is fetching a CLI of roughly 12 MB and verifying it. Every later run reuses the cached copy until the Console publishes a new version. Run npx -y @dednets/mcp --probe-only once to warm it before an agent host starts the server.
  • Windows: the client shows no DedNets server at all. Download the .exe path (windows-amd64/dednetsctl.exe); the suffix-less file is not published and Windows would not run it. In claude_desktop_config.json every backslash in the path must be doubled, or the JSON is invalid and the client drops the whole server entry without saying so.