If you're referring to the MCP server published by this repository, it's **herdr-inbox** (the README calls it “herdr inbox”). **Description:** It lets Claude Code agents running in herdr ask a question once, get a receipt, and keep working instead of blocking, while the operator answers all open questions from a single popup and each answer is delivered back to the pane that asked. A couple of notes on the constraints you gave: - The name used is the repository's own project name, **herdr-inbox**, not a person or organization. - The description deliberately avoids repeating the name and focuses on what the server enables: asynchronous agent questions, non-blocking work, centralized answering, and delivery back to the originating agent. - If you want the answer as a strict JSON object only, it would be: ```json { "name": "herdr-inbox", "description": "Enables Claude Code agents running in herdr to ask a question once, receive a receipt, and continue working instead of blocking, while the operator answers all open questions from one popup and each answer is delivered back to the pane that asked." } ```
Official 1. Click on "Deploy Server".
2. Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
3. In the chat, type `@` followed by the MCP server name and your instructions, e.g., "`@If you're referring to the MCP server published by this repository, it's **herdr-inbox** (the README calls it “herdr inbox”).Description: It lets Claude Code agents running in herdr ask a question once, get a receipt, and keep working instead of blocking, while the operator answers all open questions from a single popup and each answer is delivered back to the pane that asked.
A couple of notes on the constraints you gave:
The name used is the repository's own project name, herdr-inbox, not a person or organization.
The description deliberately avoids repeating the name and focuses on what the server enables: asynchronous agent questions, non-blocking work, centralized answering, and delivery back to the originating agent.
If you want the answer as a strict JSON object only, it would be:
{
"name": "herdr-inbox",
"description": "Enables Claude Code agents running in herdr to ask a question once, receive a receipt, and continue working instead of blocking, while the operator answers all open questions from one popup and each answer is delivered back to the pane that asked."
}
```` ask the operator which database to use for this service, then continue"
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](https://glama.ai/blog/2025-07-08-how-to-install-and-use-mcp-servers).herdr inbox
Ask once. Keep working. Answer when you're ready.
An asynchronous question inbox for Claude Code agents running in herdr: every agent's open questions in one popup, every answer delivered back to the pane that asked.
Ever had an agent stop dead to ask you a question, when it could have kept going with the rest of its work? Or one that asked in chat, carried on, and then asked the same thing again three turns later because it never knew you'd seen it?
herdr-inbox makes agent questions asynchronous. It works like Claude Code's own question
prompt (same options, notes and multi-question groups), except the agent doesn't wait for you.
It files the question once, gets a receipt (Q12) and keeps working on everything that doesn't
depend on the answer. You answer whenever you're ready, from one popup that collects the open
questions of every agent in your herdr session, and the answer lands back in the right agent's
conversation.
Agents don't stall. No blocking dialog, no idle agent waiting for you to notice it.
Questions don't repeat. Asking the same thing twice just returns the existing receipt.
Nothing gets lost. Every open question from every pane is in one place, and tabs show a
❓Ncount while their agent is waiting on you.Zero per-project setup. A session hook teaches every Claude Code session to use it.
claude plugin marketplace add LeaveMyYard/herdr-inbox
claude plugin install herdr-inbox@herdr-inbox
herdr plugin install LeaveMyYard/herdr-inboxThen bind a key to the popup (Install has the snippet). The repo is two plugins at
once: a Claude Code plugin (.claude-plugin/: MCP server, hooks, the
herdr-inbox:operator-questions skill) and a herdr plugin (herdr-plugin.toml: popup, open
and sync-tokens actions, startup hook), listed on the
herdr plugin marketplace. You install both.
Answering
Press prefix+i. A group is one ask_operator call: a single question, or up to four related
ones that the agent names with a short title.
The group list
With several open groups the popup opens on a list styled like Claude Code's option list: one row
per group, named by its title (❯ 1. Invoice storage and caching · 2 questions · 4m), with the
tab label, asked_by and the question headers on a dim second line. Groups from the pane you were
in come first, then the rest oldest first; answers that could not be delivered are their own ⚠
rows. Enter opens a group, g jumps to its agent, d dismisses the whole group (y confirms).
With exactly one open group the popup skips the list and opens straight into it.
Inside a group: tabs and Submit
A group's questions are tabs under its title, followed by its own Submit tab. Answering drafts
the question and moves to the next tab. Submit reviews everything ("You have not answered all
questions" when some are blank) and sends the group's answered questions in one message; blank
ones stay open. Drafts are stored, so closing the popup loses nothing. Esc goes back to the list.
One question, with previews
A group of one question sends as soon as you select an answer. Options can be plain strings or
{label, description, preview}; a preview (plain monospace text such as a config snippet or a
git graph) is shown beside the list while that option is highlighted. There is always
Type something. (a free answer; in multi-select it is added to the picks) and
Chat about this (jumps to the asking agent's pane and leaves the question open). n adds a
note to the highlighted option, e.g. Postgres (note: keep the old schema).
While you answer
Nothing that happens in the background changes what your next key does. New groups are appended
to the list without moving your cursor, and a row that just arrived ignores Enter and digits for
1 s. Every view ignores Enter, digits and Space for 0.4 s after it appears. A group or question
closed meanwhile (withdrawn, answered elsewhere) stays as an inert placeholder ("Q12 was closed")
until you move. With no open questions the popup shows "No open questions" and closes on any key;
groups arriving then are announced, and Tab or → shows them. An undelivered answer's ⚠ row
offers Retry delivery and Stop showing it here (the agent can still fetch it with
check_answers).
Related MCP server: hermes-claude-bridge
Keys
Key | Action |
| Move the |
| Jump to that row or option |
| Open the group; select the option (single-select) or toggle it (multi-select) |
| Toggle (multi-select) |
| Add a note to the option / clear the draft |
| Next / previous tab inside a group |
| Go to the asking agent's pane |
| Dismiss the group or question ( |
| Back to the list; on the list, close without sending |
Delivery
An answer arrives in the agent's conversation as
[inbox] Q12 answered — <question>: Postgres (note: keep the old schema), or for several
[inbox] answered — Q12 <q>: A · Q13 <q>: B, only while that pane still holds the conversation
that asked. If delivery fails (agent at a dialog, pane gone, conversation changed), the asking
session's MCP server retries every 30 s, and the agent can always fetch the answer itself.
Tab marker and sidebar count
herdr has no per-tab tokens, so while a tab has open questions its label gets a ❓N prefix
(herdr tab rename), updated as the count changes and removed at 0. Your own label is never
stored: it is recovered by stripping the prefix each time, so renaming a prefixed tab is
respected. Tabs without a custom name (herdr shows their position, e.g. 6) are left alone by
default, because a rename cannot give them back automatic naming.
Optionally, every pane with open questions carries the pane token inbox_q = "?N", cleared when
the last one closes. Add $inbox_q to a row of the agent sidebar:
[ui.sidebar.agents]
rows = [["state_icon", "tab", { token = "$inbox_q", fg = "#c04a4a", bold = true }], ["agent"]]With herdr-radar, which replaces the agent rows with
its own and has no slot for other plugins' tokens yet
(hhdebb/herdr-radar#57 proposes an
extra_tokens setting), run the action Inbox: show ?N in herdr-radar's sidebar
(herdr plugin action invoke leavemyyard.herdr-inbox.radar-sidebar, or inbox radar-sidebar).
It adds the $inbox_q cell to each of radar's agent rows, inside radar's managed block only, and
reloads herdr's config. It runs only when you ask: radar rewrites its block on its configure
action, and the popup then shows a one-line hint to run it again (radar_sidebar_hint = false
turns the hint off). It leaves the file alone if it does not parse, if a row would exceed herdr's
16-token limit, or once radar's config carries $inbox_q in extra_tokens itself; a backup of
the previous file is kept as config.toml.inbox-bak.
Install
Requirements: herdr ≥ 0.9.0 (Linux or macOS); Claude Code with plugin support;
uv on PATH for both herdr and Claude Code.
Claude Code:
claude plugin marketplace add LeaveMyYard/herdr-inbox
claude plugin install herdr-inbox@herdr-inboxThis registers the MCP server (tools appear as mcp__plugin_herdr-inbox_herdr-inbox__ask_operator
etc.) and the hooks. Restart running Claude sessions (or /reload-plugins). Claude Code installs
plugins as a copy, so the MCP server keeps its Python environment in
${CLAUDE_PLUGIN_DATA}/venv-<version> (created by uv on first use, about 0.5 s from a warm cache;
older versions' venvs are removed automatically once no server uses them; after restarting
sessions that predate 0.5.3, inbox clean-venvs removes their older venvs too). The hooks need only the
system python3 (3.11+; older falls back to uv) and always exit 0. MCP server only, without hooks: run
claude mcp add --scope user herdr-inbox -- uv run --project /path/to/herdr-inbox inbox mcp from a
checkout and add docs/agent-instructions.md to your CLAUDE.md; use
one route, not both.
herdr:
herdr plugin install LeaveMyYard/herdr-inboxThe plugin is also on the herdr plugin marketplace (through the
herdr-plugin GitHub topic); installing from there is the same command. herdr runs the manifest's
[[build]] step (uv sync --frozen --no-dev) during install, after showing you what it will run.
Add --ref <tag> to pin a revision. Then bind a key in ~/.config/herdr/config.toml and run
herdr server reload-config:
[[keys.command]]
key = "prefix+i"
type = "plugin_action"
command = "leavemyyard.herdr-inbox.open"
description = "question inbox"Configuration
Settings live in config.toml in the plugin's config directory
(herdr plugin config-dir leavemyyard.herdr-inbox):
tab_prefix = "❓" # "" turns the tab prefix off
prefix_unnamed_tabs = false # true: also prefix tabs named by position (they keep the number)
radar_sidebar_hint = true # false: no popup hint when herdr-radar's rows lack $inbox_qThe popup and every Claude session read this file, and edits apply without a restart. The database
is ${XDG_STATE_HOME:-~/.local/state}/herdr-inbox/inbox.db; HERDR_INBOX_DB overrides it.
Agent tools
Tool | Purpose |
| File a question (or |
| Answers not seen yet (after a missed delivery or compaction) |
| The session's questions, to recover after |
| The agent resolved it itself |
A SessionStart hook teaches every Claude Code session to use them, so no CLAUDE.md edit is
needed. Outside herdr the hooks stay silent and ask_operator tells the agent to ask in chat.
From a shell (from a checkout, as uv run inbox ...):
inbox list [--all]
inbox answer Q12 "squash it"
inbox dismiss 12
inbox sync-tokens
inbox radar-sidebar [--remove] # $inbox_q in herdr-radar's sidebar rows (on demand)Opening the inbox from another plugin
Another plugin (or a script) can open the popup straight on one question or group:
root=$(herdr plugin list --json | jq -r '.result.plugins[] | select(.plugin_id == "leavemyyard.herdr-inbox") | .plugin_root')
uv run --quiet --frozen --no-dev --project "$root" inbox open --question Q12 # or:
# inbox open --group 7 the group (one ask_operator call)
# inbox open --pane w6:p3A that pane's oldest open group
# inbox open --session <id> that Claude session's oldest open groupRun it only on an explicit operator action (a key binding, a click), never from an event or a timer. A popup takes all keyboard input, so one that appears under the operator's typing would swallow their keys.
As a second guard, a deep-linked popup sends nothing until the operator presses Tab or →, at least half a second after it appeared. ↑/↓ don't count, since they are what shell history under the popup would send. Until then it shows "Opened from another plugin — press Tab or → to start answering", and Enter and digits do nothing.
How it works:
herdr plugin pane opencannot pass arguments to the popup. Soinbox openwrites a one-shot request (open-request.jsonnext to the database: target, time and nonce, written atomically, newest wins).It then opens the inbox's own popup. The plugin id and root are fixed to the inbox's own, never the calling plugin's.
It hands the request's nonce to that popup. Only that popup takes the request, and only within 5 s; a popup opened by hand ignores it.
The popup opens the target group on the target question, with the list behind it (Esc goes back to the list). If the target is no longer open, it shows the list with a one-line notice.
If the popup is already open,
inbox openexits with code 3 and the message "the inbox popup is already open", and writes nothing.--questiontakesQnornand--grouptakes a number; anything else is a usage error (exit 2).
Updating
herdr plugin update # herdr side (or: herdr plugin update LeaveMyYard/herdr-inbox)
claude plugin marketplace update herdr-inbox
claude plugin update herdr-inbox@herdr-inboxThen restart Claude sessions: a session started before the update keeps its old MCP server. While 0.2.x and 0.3 sessions overlap, an answer sent at the same moment as an old session's retry tick can (rarely) be delivered twice; the window closes once every session has restarted.
Uninstall
Remove the tab prefixes first (pane tokens vanish with herdr's next restart). Set
tab_prefix = "" in the config file above, then reconcile every tab:
herdr plugin action invoke leavemyyard.herdr-inbox.sync-tokensThen remove the plugins:
herdr plugin uninstall leavemyyard.herdr-inbox # or: herdr plugin unlink ... if you linked it
claude plugin uninstall herdr-inbox@herdr-inbox
claude plugin marketplace remove herdr-inboxFrom a checkout, uv run inbox sync-tokens --remove-prefixes does the first step in one command.
If you added $inbox_q to herdr-radar's rows, take it out first with inbox radar-sidebar --remove.
Remove the prefix+i binding yourself. The database stays in ~/.local/state/herdr-inbox/
until you delete it.
How it works
The MCP server (spawned per Claude session, so it inherits the pane's HERDR_PANE_ID) writes
questions to a shared SQLite database. The popup reads it, and answering calls
herdr agent prompt <pane>. Markers use herdr tab rename and herdr pane report-metadata. A
SessionStart hook injects a short usage block into each session. Details, data model and
design decisions: docs/DESIGN.md.
Limitations and known issues
Proof of concept. Interfaces may change. Claude Code only; other agents are not supported.
Answers are typed into the pane, so one that arrives while you are typing in that pane can merge with your input. Retries are skipped while the pane is focused or the agent is blocked, but the first delivery from the popup has no such guard.
A delivery whose
agent promptcall times out after herdr already submitted it is retried, so the agent can receive that answer twice.After
/clear, a restart or another agent taking over the pane, an answer is not typed anywhere (conversation changed); the agent gets it throughcheck_answers.herdr has no compare-and-set rename, so a tab rename of yours landing in the few milliseconds between our read and our rename is overwritten.
If a pane moves to another tab, the old tab's prefix is refreshed at the next
sync-tokens.Subagents are not identified (use
asked_by), and answers go to the main session's pane.Outside herdr, or from a
claudenested inside an agent's pane, nothing is filed and the agent is told to ask in chat.No blocking questions, remote or mobile answering, or multi-machine sync.
Development
uv sync
uv run pytestTests never touch a real herdr: they point HERDR_BIN_PATH at a fake that records its argv and
HERDR_INBOX_DB at a temp file. CI runs them on Linux and macOS, and validates the plugin
manifests with claude plugin validate. Keep the version identical in pyproject.toml,
herdr-plugin.toml, .claude-plugin/plugin.json and .claude-plugin/marketplace.json (a test
checks this); bump it for every release, since Claude Code keys its plugin cache by version.
The README images are captures of a real herdr, made by
uv run --with pyte --with pillow python docs/screenshots/herdr_demo.py (needs herdr ≥ 0.9,
rsvg-convert and ffmpeg). It starts an isolated herdr (its own HOME, config, socket and inbox
database under the git-ignored .scratch/), links this checkout as the plugin, runs a scripted
stand-in agent in each tab (docs/screenshots/fake_agent.py, no API calls), files the demo
questions through the plugin's own code and drives the popup with real keys; frame.py adds the
backdrop. Popup-only renders: uv run pytest tests/make_screenshots.py (needs rsvg-convert).
This server cannot be deployed
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Shared memory and mail for your AI agents. Verified with Claude Code; other MCP clients in testing.
MCP server for OnceAsk, the AI-native current-address layer for people and agents.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceMCP server that bridges coding agents (Claude Code, Codex, Gemini CLI) via ACP for pair programming, enabling agents to consult each other as tools.3-
- AlicenseNot gradedqualityCmaintenanceMCP server that enables Hermes Agent to delegate development tasks to Claude Code CLI, reusing the Claude Code subscription without additional API costs.1MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that enables Claude Code to communicate with other Claude Code agents over HTTP, allowing users to ask questions about remote codebases or delegate coding tasks.MIT
- FlicenseNot gradedqualityDmaintenanceA flexible MCP server enabling multiple Claude AI sessions to coordinate work across machines through shared state management.1-