Skip to main content Skip to navigation Skip to footer

MCP Server Setup

Connect AI agents to Rediacc infrastructure using the Model Context Protocol (MCP) server.

Overview

Look, rdc mcp serve starts a local MCP (Model Context Protocol) server that AI agents use to manage your infrastructure. The server uses stdio transport. The agent spawns it as a subprocess and communicates via JSON-RPC.

Prerequisites: rdc installed and configured with at least one machine.

Claude Code

Add to your project’s .mcp.json:

{
  "mcpServers": {
    "rdc": {
      "command": "rdc",
      "args": ["mcp", "serve"]
    }
  }
}

Or with a named config:

{
  "mcpServers": {
    "rdc": {
      "command": "rdc",
      "args": ["mcp", "serve", "--config", "production"]
    }
  }
}

Cursor

Open Settings → MCP Servers → Add Server:

  • Name: rdc
  • Command: rdc mcp serve
  • Transport: stdio

Available Tools

Read Tools (safe, no side effects)

ToolDescription
machine_queryGet system info, containers, services, and resource usage for a machine
machine_containersList Docker containers with status, health, resource usage, labels, and auto-route domain
machine_servicesList rediacc-managed systemd services (name, state, sub-state, restart count, memory, owning repository)
machine_reposList deployed repositories (name, GUID, size, mount status, Docker state, container count, disk usage, modified date, Rediaccfile present)
machine_healthRun health check on a machine (system, containers, services, storage)
machine_listList all configured machines
config_repositoriesList configured repositories with name-to-GUID mappings
config_show_infraShow infrastructure configuration for a machine (base domain, public IPs, TLS, Cloudflare zone)
config_providersList configured cloud providers for machine provisioning
agent_capabilitiesList all available rdc CLI commands with their arguments and options
repo_secret_listList secret names + delivery modes for a repository (never values, never digests). Read-safe.
repo_secret_getGet a secret’s SHA-256 digest + delivery mode. Plaintext value is never returned by design. Use this to verify a secret exists or has been rotated.

Write Tools (destructive)

ToolDescription
repo_createCreate a new encrypted repository on a machine
repo_upDeploy/update a repository (runs Rediaccfile up, starts containers). Use mount for first deploy or after pull
repo_downStop repository containers. Does NOT unmount by default. Use unmount to also close the LUKS container
repo_deleteDelete a repository (destroys containers, volumes, encrypted image). Credential archived for recovery
repo_forkCreate a CoW fork with new GUID and networkId (fully independent copy, online forking supported)
backup_pushPush repository backup to storage or another machine (same GUID — backup/migration, not fork)
backup_pullPull repository backup from storage or machine. After pull, deploy with repo_up (mount=true)
machine_provisionProvision a new machine on a cloud provider using OpenTofu
machine_deprovisionDestroy a cloud-provisioned machine and remove from config
config_add_providerAdd a cloud provider configuration for machine provisioning
config_remove_providerRemove a cloud provider configuration
term_execExecute a command on a remote machine via SSH

Example Workflows

Check machine status:

“What’s the status of my production machine?”

The agent calls machine_query → returns system info, running containers, services, and resource usage.

Deploy an application:

“Deploy gitlab on my staging machine”

The agent calls repo_up with name: "gitlab" and machine: "staging" → deploys the repository, returns success/failure.

Debug a failing service:

“My nextcloud is slow, figure out what’s wrong”

The agent calls machine_healthmachine_containersterm_exec to read logs → identifies the issue and suggests a fix.

Configuration Options

OptionDefaultDescription
--config <name>(default config)Named config to use for all commands
--timeout <ms>120000Default command timeout in milliseconds

Security

The MCP server enforces two layers of protection:

Fork-only mode (default)

By default, the server runs in fork-only mode: write tools (repo_up, repo_down, repo_delete, backup_push, backup_pull, term_exec) can only operate on fork repositories. Agents cannot touch grand (original) repositories. By design.

Per-repo secrets are CLI-only by design. repo_secret_set and repo_secret_unset are intentionally not exposed as MCP tools. Writes require a --current <previous-value> precondition (or --rotate-secret to acknowledge an unverified rotation), and that ceremony needs human eyes-on. Agents that need to suggest a secret rotation should call repo_secret_get to confirm the digest, then relay the operator-facing CLI command to the user via the structured next.options[].run field in the JSON error envelope. See AI Agent Safety for the full pattern, and Repositories § Secrets for the user-facing how-to.

To allow an agent to modify grand repos, export REDIACC_ALLOW_GRAND_REPO in your terminal before starting the agent that hosts the MCP server:

export REDIACC_ALLOW_GRAND_REPO='gitlab'   # one repo
# or 'repo1,repo2,repo3' (whitespace around entries is ignored), or '*' for all repos
claude   # or cursor, gemini, etc.

The override is verified against the process ancestry: it only counts when it was already present in the environment of the agent process itself, which means you exported it before the agent (and the MCP server it spawned) started. An agent cannot grant itself access by setting the variable mid-session. There is deliberately no server flag for this: a flag in the MCP server arguments carries no proof of who put it there, while the ancestry check does. Machine-level access (such as term connect -m <machine> without a repo) still requires *; a list of repo names does not unlock it.

Per-repo SSH keys and server-side sandbox

Each repository has its own SSH key pair. The public key is deployed to authorized_keys with a command= prefix that forces all SSH sessions through renet sandbox-gateway <repo-name>, a server-side ForceCommand that cannot be bypassed by any client, including VS Code.

How it works:

  1. rdc repo create or rdc repo fork generates a unique ed25519 key pair per repo
  2. The public key is deployed to the remote with command="renet sandbox-gateway <name>"
  3. Every SSH connection using that key goes through the gateway, which applies:
    • Landlock LSM, kernel-level filesystem restrictions to the repo’s mount path
    • OverlayFS home overlay, writes to $HOME captured per-repo, reads fall through to real home
    • Per-repo TMPDIR at <datastore>/.interim/sandbox/<name>/tmp/
    • Docker access via the repo’s isolated Docker socket
    • Privilege drop to the universal user (rediacc)
  4. The repo’s .envrc is loaded automatically for Docker and environment setup

Allowed RW: repo mount path, per-repo sandbox workspace, home directory (via overlay), Docker socket Allowed RO: system paths (/usr, /bin, /etc, /proc, /sys) Blocked: other repos’ mount paths, system files outside allowlist

VS Code integration: Each repo gets its own VS Code server installation at <datastore>/.interim/sandbox/<name>/.vscode-server/. Multiple repos can be open simultaneously with independent sandboxed environments, no server sharing between repos.

This prevents lateral movement. Even if an agent gains shell access to a fork, it cannot read or modify other repositories on the same machine. Machine-level SSH (without a repository) uses the team key and is not sandboxed.

Architecture

The MCP server is stateless. Each tool call spawns rdc as an isolated child process with --output json --yes --quiet flags. This means:

  • No state leaks between tool calls
  • Uses your existing rdc configuration and SSH keys
  • Errors in one command don’t affect others