Skip to main content
Glama
README.md
# herdr-mcp

An [MCP](https://modelcontextprotocol.io) server that exposes a running
[Herdr](https://herdr.dev) session to MCP clients such as Grok Bot, Claude
Desktop, or any other app that speaks the protocol.

Herdr is a terminal workspace manager for coding agents. It organizes
terminals into workspaces, tabs and panes, recognizes the agent running in
each pane, and tracks whether it is idle, working, blocked on a dialog, or
done. This server lets a desktop assistant see all of that and act on it:
read what Claude Code or Codex is doing in your terminal, hand them a prompt,
wait for them to finish, run commands in new panes, and react to lifecycle
events as they happen.

## How it works

- Every control tool is a typed wrapper over the `herdr` CLI, so name
  resolution, `--wait` semantics and protocol compatibility stay Herdr's job.
- A background **event tap** holds one `events.subscribe` connection open on
  Herdr's Unix socket. It buffers every event with a monotonic sequence number
  and subscribes to `pane.agent_status_changed` for each pane, resubscribing
  when new panes appear. Clients poll with `events_recent` or block with
  `events_wait`.
- Mutating tools carry MCP annotations (`readOnlyHint`, `destructiveHint`) so
  clients can gate them with per-tool permissions.

## Requirements

- Herdr 0.9 or newer, with a server running for the session you want to
  expose (start it with `herdr` or `herdr server`).
- Python 3.12 or newer and [uv](https://docs.astral.sh/uv/).

## Install

```sh
git clone https://github.com/frysquint/herdr-mcp.git ~/git/herdr-mcp
cd ~/git/herdr-mcp
uv sync
uv run herdr-mcp --help
```

`uv sync` creates `.venv/bin/herdr-mcp`, an absolute entry point that needs
no shell setup. That is the path to hand to desktop clients, which often run
with a minimal `PATH`.

## Grok Bot

Open Grok Bot settings, go to **MCP servers**, add a server, and paste:

```json
{
  "mcpServers": {
    "herdr": {
      "command": "/home/USER/git/herdr-mcp/.venv/bin/herdr-mcp",
      "args": []
    }
  }
}
```

Replace `USER` with your login. Grok Bot accepts one server per paste.

If you prefer to run through uv instead of the venv entry point:

```json
{
  "mcpServers": {
    "herdr": {
      "command": "/absolute/path/to/uv",
      "args": ["run", "--project", "/home/USER/git/herdr-mcp", "herdr-mcp"]
    }
  }
}
```

## Other MCP clients

Claude Desktop, Claude Code, Codex and most others take the same
`command`/`args` shape. For Claude Code:

```sh
claude mcp add herdr -- /home/USER/git/herdr-mcp/.venv/bin/herdr-mcp
```

To serve over HTTP instead of stdio (for remote clients or several clients
sharing one tap):

```sh
uv run herdr-mcp --transport streamable-http --host 127.0.0.1 --port 8765
```

The endpoint is `http://127.0.0.1:8765/mcp`. There is no authentication; keep
it on loopback or put it behind something that authenticates.

## Configuration

All configuration is through the environment of the server process.

| Variable             | Effect                                                              |
| -------------------- | ------------------------------------------------------------------- |
| `HERDR_BIN_PATH`     | Path to the `herdr` binary. Default: first `herdr` on `PATH`.       |
| `HERDR_SESSION`      | Target a named Herdr session instead of the default one.            |
| `HERDR_SOCKET_PATH`  | Low-level override of the socket path (CLI and event tap).          |
| `HERDR_MCP_MACHINE`  | Run every command against a saved SSH machine profile (`herdr --machine`). Live events are disabled in this mode because there is no local socket for that machine. |
| `HERDR_MCP_LOG_LEVEL`| Log level written to stderr. Default `INFO`.                        |

## Tools

Read-only: `herdr_status`, `session_snapshot`, `workspace_list`,
`workspace_get`, `tab_list`, `pane_list`, `pane_get`, `pane_layout`,
`pane_process_info`, `pane_read`, `pane_wait_output`, `agent_list`,
`agent_get`, `agent_explain`, `agent_read`, `agent_wait`, `worktree_list`,
`events_status`, `events_recent`, `events_wait`.

Mutating: `workspace_create`, `workspace_focus`, `workspace_rename`,
`tab_create`, `tab_focus`, `tab_rename`, `pane_split`, `pane_run`,
`pane_send_text`, `pane_send_keys`, `pane_rename`, `agent_prompt`,
`agent_send_keys`, `agent_start`, `agent_rename`, `agent_focus`,
`worktree_create`, `notification_show`.

Destructive: `workspace_close`, `tab_close`, `pane_close`.

### Event kinds

Broadcast events from Herdr, in underscore form: `workspace_created`,
`workspace_updated`, `workspace_metadata_updated`, `workspace_renamed`,
`workspace_moved`, `workspace_reordered`, `workspace_closed`,
`workspace_focused`, `worktree_created`, `worktree_opened`,
`worktree_removed`, `tab_created`, `tab_closed`, `tab_focused`,
`tab_renamed`, `tab_moved`, `pane_created`, `pane_closed`, `pane_updated`,
`pane_focused`, `pane_moved`, `pane_exited`, `pane_agent_detected`,
`layout_updated`.

Per-pane subscription events: `pane_agent_status_changed` with
`agent_status` one of `idle`, `working`, `blocked`, `done`, `unknown`.

Synthetic events from the tap itself: `tap_connected`, `tap_disconnected`,
`tap_events_lost`. If you see `tap_events_lost`, re-read state with
`session_snapshot`; Herdr does not replay missed events.

### A typical delegation loop

1. `agent_list` to find a ready agent (status `idle` or `done`).
2. `events_recent` with `limit: 0` to learn `latest_seq`.
3. `agent_prompt` with `wait: true`, or send it with `wait: false` and then
   `events_wait` with `since_seq`, `kinds: ["pane_agent_status_changed"]`,
   `pane_id`, and `agent_status: ["done", "blocked", "idle"]`.
4. `agent_read` to collect the response. If the status was `blocked`, show the
   user the dialog text before answering it with `agent_send_keys`.

## Development

```sh
uv run pytest
uv run herdr-mcp --log-level DEBUG   # speaks MCP on stdin/stdout
```

The unit tests fake the `herdr` binary and do not need a running server.

## License

MIT. See `LICENSE`.

TDQS

B3.3/5.0

Scored across 41 tools

Disambiguation4/5

The set is strongly segmented by resource prefix (workspace_, tab_, pane_, agent_, events_, worktree_), and repeated actions such as list/get/create/close target explicit resources. The closest overlaps are pane_read vs agent_read and pane_send_keys vs agent_send_keys, plus the several input tools, but descriptions make the intended conditions clear.

Naming Consistency5/5

All names use snake_case with a resource/domain prefix, and nearly all are resource_action forms like workspace_list, pane_read, and agent_prompt. Exceptions such as herdr_status, session_snapshot, and events_status are readable status/snapshot nouns and do not break the overall convention.

Tool Count2/5

41 tools is heavy for any single MCP server; even though the terminal/workspace/agent domain is broad, many fine-grained pane/agent input, read, and wait variants could be consolidated or parameterized. The count exceeds the reasonable 3-15 range and sits in the 'too many' band.

Completeness4/5

Core lifecycle is covered: workspaces, tabs, and panes can be created, listed, renamed, focused, and closed; agents can be started, prompted, waited on, and read; events and worktrees have support. Gaps remain for pane_focus/resize, agent_stop, tab_get, and worktree_remove, though terminal access and close operations provide workarounds.

Maintenance

ActivityMaintained
ResponsivenessNo issues