piherder-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@piherder-mcpshow me the current server inventory"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
PiHerder MCP
stdio process that lets Cursor, Claude, Codex, Windsurf, Continue, Goose, and other MCP clients call a PiHerder instance through the existing bearer API.
It runs on the computer that runs the agent. It is not part of the PiHerder image. PiHerder v1.10.0 also serves POST /mcp on the herder, including browser sign-in. This adapter does not use that sign-in. It is the air-gapped fallback for a machine that cannot reach that URL. The public demo is not a target.
Adapter 0.4.2 calls the PiHerder bearer API. trigger_job accepts the same list as hosted /mcp on PiHerder v1.10.0, including container_start, container_stop, container_restart, and container_redeploy. start_move, read_discovery, and start_discovery match the hosted tools on the v1.11 train. list_discovery_devices, rename_discovery_device, set_discovery_device_state, link_discovery_device, unlink_discovery_device, purge_discovery_device, purge_stale_discovery_devices, and scan_discovery_device tidy LAN Discovery devices. The two purge calls send confirm=true on the request. MCP registry name: io.github.bjorngluck/piherder-mcp (see server.json). Herder notes: PiHerder v1.10.0. Adapter notes: v0.4.2 · CHANGELOG.md. PyPI package: 0.4.2.
Install
Full steps and scope notes: Agents (MCP).
export PIHERDER_URL='https://piherder.example.com'
export PIHERDER_TOKEN='ph_…'
uvx piherder-mcpRequires uv (uvx). The package is on PyPI. uvx piherder-mcp installs the latest published release, 0.4.2. A machine that cached 0.4.1 needs uvx --refresh piherder-mcp.
Git fallback (pin a branch or commit):
uvx --from git+https://github.com/bjorngluck/piherder-mcp.git piherder-mcpAuth and tokens
In PiHerder 1.9.0: Settings → API management → Create new token → MCP agent. Details: API tokens.
readis required.jobs,edit, andfilesadd the write tools. A token withoutreadexits on stderr.Set
PIHERDER_URLandPIHERDER_TOKENfor the MCP process.
${PIHERDER_TOKEN} often does not expand inside client JSON env blocks. Many clients pass that string literally. Prefer one of:
Export
PIHERDER_TOKENin the host environment and omit it from the clientenvobject (if the client inherits the parent env), orUse the client's secret / env UI when it has one, or
Paste the token once into the client config and keep that file out of git.
Samples in clients/ use a ph_… placeholder — replace it, or remove the key and rely on the host env. Do not commit real tokens.
Related MCP server: Puppet Enterprise MCP Server
Clients
Samples: clients/ (Cursor, Claude Desktop, Codex, Grok, Windsurf, Continue, Goose, Windows cmd /c). Path notes: clients/README.md.
Claude Desktop config locations:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Minimal Cursor / Claude-shaped entry:
{
"mcpServers": {
"piherder": {
"command": "uvx",
"args": ["piherder-mcp"],
"env": {
"PIHERDER_URL": "https://piherder.example.com",
"PIHERDER_TOKEN": "ph_…"
}
}
}
}The same operating note is in skills/piherder/SKILL.md (Grok), clients/cursor/piherder.mdc (Cursor), CLAUDE.md, and AGENTS.md.
Tools
A token with read, jobs, edit, and files has these 27 tools. A missing scope hides that group. A token without read exits on stderr and lists nothing.
Tool | Scope | What it does |
|
| Token health, scopes, and allowed features. |
|
| Fleet heartbeat from the database. Does not SSH. Call this before a change. |
|
| Servers. |
|
| One server, including its feature flags. |
|
| Stored Docker inventory. Omit |
|
| Stored service up/down chips. Does not poll Uptime Kuma or Nginx Proxy Manager. |
|
| Jobs. Optional |
|
| One job. |
|
| Read saved LAN Discovery ranges and recent scans. |
|
| Page devices. Optional |
|
| Start one job type from the table below. |
|
| Start a stop-first Move. |
|
| Start a scan of the saved LAN Discovery ranges. |
|
| Scan one device inside those ranges. |
|
| Toggle |
|
| Set the operator name. Kind and map role stay. |
|
| Set |
|
| Link a device to a fleet server. |
|
| Unlink a device. It becomes known. |
|
| Delete one device. |
|
| Delete offline devices. |
|
| List a fleet-jail directory. |
|
| Download one fleet-jail file. Capped around 256 KiB. The result says when it was cut. |
|
| Upload text. |
|
| Create a directory. |
|
| Rename inside the current directory. |
|
| Delete one file or an empty directory. Not recursive. |
Read tools set readOnlyHint. set_features, trigger_job, start_move, start_discovery, scan_discovery_device, rename_discovery_device, set_discovery_device_state, link_discovery_device, unlink_discovery_device, purge_discovery_device, purge_stale_discovery_devices, write_file, mkdir, rename_file, and delete_file set destructiveHint.
trigger_job types
server_id and job_type are required. source_filter, service, and os_steps are optional on the tool. For container_start, container_stop, container_restart, and container_redeploy, service (compose service name) and source_filter (compose project directory) are both required and are sent on POST /api/v1/servers/{id}/jobs. HTTP 202 means accepted. HTTP 409 means that job is already active: poll get_job and do not start another. The host feature flag and any feature:* scope still apply. The jobs scope is still required. Docker stays behind the server docker flag and feature:docker when the token is feature-restricted.
| Host feature | Arguments |
| backup |
|
| backup | Prune backups. |
| os_patch |
|
| os_patch | Check for OS package updates. |
| os_patch | Reboot the host. |
| docker | Update containers. |
| docker | Check for container image updates. |
| docker |
|
| docker |
|
| docker |
|
| docker |
|
| docker |
|
| docker | On this list because the jobs POST accepts it. This call has no template slug or variable values, so a catalog deploy still starts from the template UI. |
| docker | Same as |
| docker |
|
| docker | Same required |
| docker | Same required |
| docker | Same required |
Not accepted on trigger_job: docker_stack_down, docker_stack_remove, template_drift_check, Move (service_migrate), undo (service_migrate_undo), and dest-up recover (service_migrate_dest_recover). SSH, the console, and token admin are not tools. A Move is start_move. A LAN Discovery scan is read_discovery and start_discovery. A device scan is scan_discovery_device. Adapter 0.3.1 did not send start_move, read_discovery, or start_discovery. Adapter 0.4.0 did not send the device tools. This package does.
Move
start_move takes server_id (the source), dest_server_id, project (the compose project name, not a directory), and confirm: true. It calls POST /api/v1/servers/{id}/moves. The source stack is left stopped. There is no undo. 409 means a stack, Move, or backup is already running. Poll get_job. That route is on PiHerder 1.10.0.
LAN Discovery
read_discovery lists saved ranges and the latest scan. Pass integration_id for recent scans, or integration_id and run_id for one scan.
start_discovery takes integration_id and confirm: true. Optional intensity is discovery, inventory, detailed, or deep. The body is confirm and intensity only. The scan uses the ranges saved on that integration. The agent does not choose the ranges. Vulnerability scripts stay off.
list_discovery_devices pages devices. state is new, known, linked, ignored, or stale. rename_discovery_device sets the operator name and leaves kind and map role alone. set_discovery_device_state sets known, new, or ignored. A linked device cannot be marked new. link_discovery_device and unlink_discovery_device tie a device to a fleet server. purge_discovery_device and purge_stale_discovery_devices need confirm: true and send confirm=true on the request. A linked device cannot be purged. Offline purge removes only stale rows. There is no undo. scan_discovery_device scans one device whose address sits inside the saved ranges. Default intensity is deep. Vulnerability scripts stay off.
These tools call /api/v1/discovery. A herder without that route returns 404. Device routes need the v1.11 herder that exposes them.
Wiki
Topic | Page |
PiHerder v1.10.0 | |
PiHerder v1.9.0 | |
Adapter 0.4.2 | |
Install, clients, scopes | |
Token scopes and allowlist | |
Jobs the token can start | |
Fleet-jail files |
Do not vendor this tree inside the PiHerder Docker image.
Publishing (maintainers)
piherder-mcp 0.1.1 was the first PyPI release. 0.4.2 is the current package. Prior package: 0.4.1. Notes: docs/RELEASE_v0.4.2.md. The adapter badge reads the latest GitHub Release. The PyPI badge reads the latest package. The PiHerder badge is hand-typed v1.10.0 and links to the v1.10.0 notes.
Trusted Publisher is already set: GitHub Environment pypi, workflow release.yml, owner bjorngluck, repository piherder-mcp. Later versions reuse it. github-release and publish-pypi still run independently after the build, so a green GitHub Release is not proof the package is on PyPI.
Package version is
piherder_mcp.__version__.pyproject.tomlreads it. CI checksserver.json, the Continue sample, the changelog heading, and the README adapter line.Write
docs/RELEASE_vX.Y.Z.mdon that commit. The release workflow uses it as the GitHub Release body. Tag and push:git tag -a vX.Y.Z <sha> -m "piherder-mcp X.Y.Z" && git push origin vX.Y.Z.Confirm the Release has wheel and sdist assets and the
publish-pypijob succeeded, then check pypi.org/project/piherder-mcp.Optional: publish
server.jsonto the MCP registry; keep the README<!-- mcp-name: … -->marker in sync withserver.jsonname(the version test checks the marker).Suggested GitHub topics:
mcp,model-context-protocol,piherder,python,stdio,uvx.
See CHANGELOG.md. Workflow comments in .github/workflows/release.yml repeat the Trusted Publisher fields.
Tests
pip install -e ".[dev]"
pytest -qTests mock HTTP. They do not call a live herder. CI runs Python 3.10–3.12.
Support
Optional. Nothing here is required to install the adapter.
github.com/sponsors/bjorngluck · buymeacoffee.com/bjorngluck · Support the project
This server cannot be deployed
Maintenance
Related MCP Connectors
Build, validate, deploy — HTTP APIs, cron jobs, webhooks and MCP tools — from your AI client. Air Pipe MCP token as a bearer credential, e.g. 'Authorization: Bearer <token>'. Create one at https://app.airpipe.io/
Deploy and manage Jade Hosting projects from AI clients. Jade account and OAuth required.
Your apps, skills, MCP servers and keys from ahel.ai, served to Claude, ChatGPT, Cursor and Codex.
MCP server that lets AI assistants use all OneSchema features exposed via the public API.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to manage and monitor Hetzner Cloud infrastructure, including servers, firewalls, networks, and snapshots, while keeping the API token local and secure.MIT
- FlicenseNot gradedqualityDmaintenanceExposes the full Puppet Enterprise API to AI assistants, enabling management of Puppet infrastructure through natural language.-
- AlicenseBqualityAmaintenanceGives AI assistants read (and optionally write) access to a NetBox instance, covering DCIM, IPAM, circuits, virtualization, tenancy, and more.10021 npm1MIT
- AlicenseNot gradedqualityAmaintenanceTurns any Linux server into an AI-agent-accessible machine over HTTPS, allowing MCP clients like ChatGPT, Claude, and Grok to securely control files, run shell commands, inspect system state, query SQLite, and work with git behind a bearer token.136 npm4MIT