Skip to content

MCP agent access

Bitsmith exposes an MCP endpoint so an AI agent (such as Claude or another MCP client) can operate your server: create and control virtual machines and LXC containers, manage apps and folders, configure the reverse proxy, and read storage and health. MCP (Model Context Protocol) is the standard those tools use to call into a system like Bitsmith.

Access is gated by tokens you create. Each token carries only the scopes you grant, can be revoked at any time, and every action it takes is recorded in your Activity log. The same tools are also callable over plain HTTP without an MCP client: see the API.

The Access tokens page: the token form and the scope checklist

  1. Open Access tokens (under System, Agent access).
  2. Give the token a name, for example “claude-on-laptop”, so you can recognize it later.
  3. Choose its scopes (see Scopes below for what each grants). Grant only what the agent needs.
  4. Create the token. Bitsmith shows a ready-to-paste client configuration once. Copy it now; the secret isn’t shown again.
  5. Paste the configuration into your MCP client. It points at your server’s /mcp endpoint with the token in an Authorization header.

The Access tokens page lists every token with its scopes and when it was last used. Revoke a token to cut off an agent immediately, without affecting your own sign-in or other tokens.

The generated configuration uses your server’s address over plain HTTP by default, because MCP clients can’t click through the self-signed certificate a browser can. On a home network that’s the same exposure as the rest of the local interface. If you reach your server over Tailscale or a VPN, that traffic is already encrypted; if you’ve set up a trusted certificate, use the https URL instead.

Because a token can change real things on your server, prefer narrow scopes, name tokens so you know which agent holds which, and revoke any you’re unsure about. The Activity log shows exactly what each agent did.

An MCP token carries one or more scopes, and each scope grants a set of tools the agent can call. Grant the narrowest set that covers what you want the agent to do. Scope names follow a domain.level pattern, so new capabilities slot in predictably.

ScopeWhat it grants
vm.readList and inspect virtual machines, images, host status, and background tasks.
vm.manageCreate, configure, start, stop, and delete virtual machines.
vm.execRun commands inside virtual machines through the QEMU guest agent.
apps.readList installed apps and read their container logs.
apps.manageStart, stop, and restart installed apps.
storage.readList storage pools and their health.
system.readRead host health and the system summary.
lxc.readList and inspect LXC containers and images.
lxc.manageCreate, configure, start, stop, and delete LXC containers.
lxc.execRun commands inside LXC containers through lxc-attach.
files.readList folders and read folder contents.
files.manageCreate, rename, delete folders and move, copy, or delete entries inside folders.
connections.readList connected locations, browse their contents, and discover SMB shares on the network.
connections.manageConnect, disconnect, reconnect, and remove connected locations, and create, move, copy, or delete entries inside them.
proxy.readRead the reverse-proxy configuration.
proxy.manageAdd, modify, and delete reverse-proxy entries.
sandbox.readList and inspect sandboxes owned by this token, and follow template builds.
sandbox.manageCreate, run work in, and destroy sandboxes owned by this token, and build the VM templates they boot from.

Read scopes are safe to hand out freely; an agent with only read scopes can look but not change. Manage and exec scopes let an agent change your server, so grant them deliberately. The sandbox.* scopes go the other way: the agent owns its own throwaway VMs on the server and can’t touch yours.

  • Virtual machines (vm.read / vm.manage): list and get VMs, browse the catalog and on-disk images and ISOs, create a VM from an image, clone it, update its cloud-init or CPU and memory, start, stop, suspend, and resume it, delete it, wait for its IP or for it to be ready, and get its SSH connection details, move an image or ISO between storage pools, and check host readiness and the memory headroom left for new VMs. Data disks can be added, grown, and removed with add_disk_to_virtual_machine, resize_disk_on_virtual_machine (grow only), and remove_disk_from_virtual_machine; the root disk is grown with the VM’s Increase storage action.
  • Warm states and template builds (vm.manage; readable with vm.read): save_vm_warm_state freezes a running VM’s memory and disk into a reusable state, create_vm_from_warm_state starts a new VM from it, and list_vm_warm_states and delete_vm_warm_state manage them. capture_vm_as_template turns a VM’s disk into a reusable image. build_template and get_template_build build a template from a base image and a cloud-init script, and are also callable with sandbox.manage and sandbox.read.
  • Run commands in a VM (vm.exec): run_command_in_vm runs a shell command inside a guest through the QEMU guest agent. This works without a network path to the VM, which makes it useful for first-boot setup or rescue. For ongoing work, agents are pointed at SSH instead.
  • LXC containers (lxc.read / lxc.manage): list and get containers, read their stats, create one from a cached or catalog template, clone it, start, stop, restart, freeze, and unfreeze it, rename it, change its resources and network, set its disk limit, move its rootfs, delete it, and check the LXC host’s runtime status. Template tools: download_lxc_image, delete_lxc_image, move_lxc_image. Run commands in a container with run_command_in_lxc_container (lxc.exec).
  • Apps (apps.read / apps.manage): list apps and app templates, read an app’s logs and stats, list containers the server found that Bitsmith doesn’t manage, start, stop, or restart an app, install and uninstall one, update its compose content and folder assignments, and move its data to another storage pool.
  • Files and folders (files.read / files.manage): list folders and their contents, search them, and create, rename, move, copy, or delete folders and entries inside them. Every tool that takes a path also accepts a target object (src_target / dst_target for move_entry and copy_entry) of the form {"kind": "folder" | "connection", "id": "...", "path": "sub/path"}, so the same tool reads or writes a managed folder or a connected network share; the older folder_id and sub_path arguments keep working. copy_entry takes one target of each kind, which is how data moves between a share and a folder. A connection target needs connections.read or connections.manage on top of the file scope.
  • Connected storage (connections.read / connections.manage): list connected locations with their mount status and last observed reachability, get one, and discover_smb (hosts on the network without host, a host’s shares with it); connect a new share (credentials go to the secret store and are never returned), disconnect, reconnect, or remove a location. Browsing and changing files on a share goes through the file tools with a target of kind connection; see Connected storage.
  • Reverse proxy (proxy.read / proxy.manage): read the full config, certificate status, and available upstreams; add, update, and remove base domains and entries; enable or disable the proxy; set ACME settings, VIP, and DNS forwarding; toggle HTTP/3; renew certificates; and move the proxy between paired servers; see Reverse proxy.
  • Sandboxes (sandbox.read / sandbox.manage): the token owns its own throwaway VMs instead of touching the operator’s: list and inspect its sandboxes, create one, suspend and resume it, and destroy it. wait_for_sandbox blocks until it is running or settled.
  • Storage, system, and tasks (storage.read / system.read / vm.read): list storage pools and their health, read host CPU and memory health, summarize VM and LXC CPU and memory allocation against host capacity, search the activity log, and read the log lines a background task produced.

Every action that changes something is written to the Activity log under an “agent” category, attributed to the token’s name, with the arguments it was called with. Read calls aren’t logged, since agents poll often and the noise would bury the real changes. This means you can always answer “what did my agent do” after the fact, and an agent with system.read can answer it for itself.