MCP.so
Sign In
H

Hubd

@bzdOS

About Hubd

The project tracker for teams of humans and AI agents — in plain files. MCP server + CLI, zero dependencies.

Config

Add this server to your MCP-compatible client using the configuration below.

{
  "mcpServers": {
    "hubd": {
      "command": "npx",
      "args": [
        "-y",
        "@bzdos/hubd"
      ]
    }
  }
}

Tools

38

Sync a project folder into the hub. Collects git facts automatically; pass digest (your own summary of state/next steps) and the card is rewritten.

Create or update a project card from just a name and a digest — no folder needed (unlike hub_sync). Use it to capture a project that is not a local git checkout, e.g. when harvesting a dialog. Preserves any hand-written frontmatter and Facts.

Append ONE line to ONE section of a project card, leaving everything around it untouched. This is how Gates / Metrics / Market and any hand-written section get written by a tool at all — hub_card_set only writes the digest, and the report router only reaches Decisions / Facts / Communication / Next step. For those four, a normal hub_report with DECIDE:/FACT:/COMM:/NEXT: is still the right call; use this for the rest. The section is created if missing (you get created:true back — check it, a typo is how a card grows two nearly identical headings).

Append a session report to the shared journal: what was done / broken / blocked.

Snapshot of every project at once: the latest digest of each, when it was last synced, and its open-task count, plus the most recent shared-journal entries. A project whose card has fallen behind its OWN journal carries digestStale {daysBehind, lastJournal} — the card still reads fresh while the work moved on. Best for orienting at the start of a session. For a deadline-sorted to-do list use hub_brief; for one project in depth use hub_get.

Everything about ONE project: its full card (digest + facts), recent journal entries for it, and any active soft-locks. Use after hub_status or hub_search points you at a project.

Auto-resolve which hub project YOUR working directory belongs to — call this at session start instead of hub_status/hub_get when you already know your cwd. Checks, most to least certain: a .hubd marker file (repo root, first line = project slug) · a project card's recorded sync path · the repo folder name as a last-resort guess (returned with guessed:true — never silently trust a name coincidence). Returns {project, via, root, guessed, digest, openTasks, activeClaims}; project is null with a hint if nothing matched.

Full-text search across every project card and the entire journal, archived months included. Returns each matching line with its location. START HERE whenever you know a keyword, a task id or a name but not which project owns it — searching once beats guessing project × status against hub_task_list, which is how sessions have actually wasted calls. Also the way to find where something was discussed or decided.

Add a task to the shared cross-project backlog.

ONE task by id, plus what it is blocked by and what it blocks. Use this when you know the id — do NOT go guessing project × status combinations with hub_task_list. Know a keyword but not the id? hub_search first.

List backlog tasks. Filter by project and/or status; page with limit/offset. `total` is always the full matching count, so a page never reads as the whole backlog. Looking for ONE task you can name? hub_task_get by id, or hub_search by keyword — both beat listing and scanning.

Update a task: close it (status=done), reassign, reprioritise, edit text/deadline/cat.

Compare what the hub DECLARES with what actually happened, and turn each disagreement into an incident somebody owns. Checks: a money bet whose gate date passed with no decision since · a project whose share of the journal contradicts the MODE its card declares · owner buttons nobody pressed · a card that stopped following its own journal · tasks with no project. Read-only by default; `apply` files one incident task per finding and writes ONE report. Every finding quotes the rule it enforces with the date that rule was written (HUB/rules.json -> laws), because an engine's opinion carries no weight and your own past decision does. Findings are keyed, so a weekly run never files the same incident twice. NOT a dashboard: the numbers it prints (attention share, close rates) are a thermometer and are never filed as violations.

Every rule that CAN be checked, checked — the difference between a rule the hub enforces and one that is only written down somewhere. Reports a money bet whose gate has no date, and a human-owned communicative task with no prep it depends on (the owner would have to both prepare and decide). Each finding says whether the instance actually enforces it (HUB/rules.json -> strict, opt-in and empty by default) and quotes the local rule if one is declared. Read-only, never files anything.

The ONE task to do now, and why it won — not a list. Picking from a list is work, and a session that has to pick tends to pick the easy one. A task whose dependencies are still open is never eligible, however loud it is. Says explicitly when the chosen one is the owner's to press rather than an agent's.

The day split by WHO CAN ACT: agent work ready now, the owner's buttons (owner_kind human, or assigned to a role declared in HUB/owner-roles.json), what is blocked and on what, overdue and due-soon. Different question from hub_brief (everything that is going on) and hub_inbox (what needs a decision): this one answers "what can I actually start", which a mixed list hides.

What do we know about X — ranked across project cards, their sections, decisions, the journal and tasks, instead of hub_search's flat exact-substring list or hub_get's everything-about-one-project. Scoring is deterministic and readable: term coverage first, then where the line lives (a decision outranks a passing note), then recency. EVERY hit carries the date it was true as of and a stale flag — recall's real failure mode is handing over a two-month-old fact with this morning's confidence.

Record what only YOU can see about a piece of work: seconds, tokens, cost, model. The hub cannot observe any of these, so they arrive here explicitly and are reported back as SUPPLIED, never mixed with what the hub measured itself. At least one number is required — an empty entry would record a $0 session.

What the work cost, over a window, per project and per agent — with a hard line between SUPPLIED (seconds/tokens/money, reported by clients through hub_usage_add, since the hub cannot see them) and MEASURED (closed-task spans and journal events, the hub's own arithmetic). The split is the point: a cost number that mixes an observed span with a guessed rate gets quoted later as if someone had counted.

The team constitution (AGENTS.md) over MCP: read it, or append an amendment. hubd mechanics live in the generated HUBD.md — this is the file where the rules YOU set live. An amendment is APPENDED under one dated, attributed heading and never edits a line already there: rewriting a rule destroys the record of what it used to say, which is exactly what hub_audit needs to quote.

The operator card: facts and preferences about the HUMAN — rhythm, what framing works, and the Boundaries section listing what is never collected. Belongs to no project and changes slower than any of them. Agents READ Boundaries and never edit it. Returns a scaffold and how to create it if there is no card yet.

Morning brief across all projects: open tasks (deadlines first), journal since N hours, stale cards, cards whose digest trails their own journal (staleDigests — the misleading kind of stale), active claims, per-role queue depth with last-seen agent (broadcast roles are flagged fanout instead of a depth — their cursors are per-reader), and a buttons rollup ("N buttons waiting, oldest X days" — pending items in a human-owner queue, see HUB/owner-roles.json).

The board as data: open tasks split into queued (unassigned) and in-progress (assigned), plus done-in-the-last-day and recent journal — the same view the read-only web kanban renders. Each task carries blocked and overdue flags.

Soft-lock a work area so other agents see it (e.g. area="public/index.html"). Not enforced — informational.

Release a soft-lock. Pass id, or project+area+agent.

Record that an agent is alive — call it each work cycle (right after hub_report, before the next hub_queue_wait) so MCP/headless agents show up in hub_presence the same way screen-scraped ones do, no human bridge needed. Overwrites this agent's one presence record; freshness is judged at read time from ttlMin (default 15min), the same pattern hub_claim uses.

The fleet roster: every agent that has called hub_heartbeat, each flagged alive/stale from its own ttlMin. hub_brief's queue section pairs with this ("N queued for role X, agent last-seen T") — visibility into delivery without screen-scraping to check who is even listening.

Create or update a resource — an infrastructure/topology entity: host, vm, service, endpoint, or provider. Structured attributes (type, address, os, provider, status) and typed relationships go in fields, NOT prose. Use this instead of describing infra inside a card digest.

List resource cards (hosts, vms, services, endpoints, providers). Optionally filter by type.

One resource card plus its inbound and outbound typed relationships.

The typed relationship graph across projects AND resources: who runs where, what depends on / deploys to / exposes what. Edges are frontmatter [[links]] keyed by relation (runs_on, depends_on, deploys_to, exposes, part_of, ...). Returns nodes, edges, and dangling links. Filter by project or type.

One-time orientation for an agent that has never worked with this hub before: what hubd is, which channel to use for what (claim vs task vs report vs queue — the #1 mistake), how to write a report. Call this FIRST, before anything else, the first time you connect.

Personalized "what did I miss" — journal activity since YOUR OWN last hub_whatsnew call (tracked per agent name), not a fixed time window like hub_brief. Call this at the start of a session/sweep instead of re-reading hub_status/hub_brief from scratch; a never-seen agent gets a 24h window on its first call.

What needs a DECISION right now, distilled from hubd data (not a time window like hub_brief): blocked reports, overdue open tasks, unassigned open tasks, and claim locks whose TTL expired but were never released. Returns {empty:true} when nothing needs attention — poll this instead of re-reading hub_status/hub_brief every cycle.

Deterministic dependency-graph plan over tasks' depends_on — the probable trajectory as a critical PATH, not an ML forecast. Returns: ready (doable now, no open deps), blocked (with waitingOn ids), layers (Kahn topo-order — what unlocks when), criticalPath (longest dependency chain = ordering bound), cycles (dependency loops to fix). Use to see "given deps, what is the actual order / what is the critical path to a milestone". Weight is task-count now; weighted by real durations once logd records them.

Append a message to a role's queue (queues/<role>.<node>.queue.md) for cross-agent/cross-node handoffs. Delivered to whoever calls hub_queue_wait (or `hub queue wait`) for that role, here or on a mesh-synced peer node.

Block until new content lands in <role>'s queue (this node's file plus any mesh-synced peer files for that role), then return it — a real long-poll, not a snapshot you have to re-poll. Returns {changed:false} if nothing arrives within timeout. If a delivered block names a task (see hub_queue_send), the ids come back as `tasks` — report the outcome onto those tasks, or the message is the only place the blocker ever existed. Local/stdio only (not available on the shared HTTP server). Use this instead of a sleep-and-recheck loop when waiting on an agent to report back via hub_queue_send.

Subscribe to EVERY role's queue at once and block until new content lands in ANY of them — for an orchestrator reacting to whichever agent reports first, instead of calling hub_queue_wait per role or ssh-ing into each host to poll. Returns {changed:true, events:[{role,node,text}, ...]} tagging which role/node each event came from, or {changed:false} on timeout. Uses its own offset bookkeeping — does NOT consume/steal messages from a role's own hub_queue_wait consumer, it only taps. Local/stdio only.

Overview

What is Hubd?

Hubd is a project tracker for teams of humans and AI agents, using plain files (markdown and JSONL). It provides a shared headquarters—a journal, task queues, cross-project tasks, and a read-only kanban—that agents and humans can coordinate through without relying on a single orchestrator or chat platform. It is designed for teams running multiple agent sessions across different tools and vendors.

How to use Hubd?

Install the binaries globally with npm i -g @bzdos/hubd (includes both hubd the MCP server and hub the CLI). Run hub init to scaffold a team folder, then hub doctor to check the setup. Connect an MCP client using claude mcp add --scope user hubd -- npx -y @bzdos/hubd. For agents without MCP, paste a prompt from the prompts/ folder. Use the CLI commands hub status, hub brief, and hub serve to interact with the data. The daemon (hubd) serves agents via JSON‑RPC 2.0 over stdio or optionally HTTP; the CLI serves humans.

Key features of Hubd

  • Journal (INBOX.md) – append‑only team log read and written by agents and humans.
  • Per‑role message queues – agents block on wait until work arrives; one live consumer per role.
  • Project cards and cross‑project tasks with owners and soft locks.
  • Read‑only kanban – cards move by agent actions; humans only edit rules (AGENTS.md).
  • Harvest – one pasted prompt converts any working dialog into project digests and tasks.
  • Works with or without MCP – direct file access when MCP is unavailable.
  • Zero dependencies; no AI inside – intelligence comes from agents, not the server.
  • Multi‑machine sync via git; remote access over HTTP (token‑gated, multi‑tenant).

Use cases of Hubd

  • Coordinating several coding agents from different vendors on the same project without manual context sharing.
  • Managing a team of agents and humans with shared task queues, locks, and a daily standup pattern (journal + brief).
  • Running a long‑lived project where agents hand off work across sessions and timezones.
  • Replacing a human coordination layer with plain files that any tool can read or write.

FAQ from Hubd

How is Hubd different from an orchestrator?

Hubd manages work (projects, tasks, queues, history) but does not launch agents or stream their output. Orchestrators run agents; Hubd runs projects. They complement each other.

Where does my data live?

All data is stored in HUBD_DIR (default ~/.hubd), plain markdown and JSONL files you own. For multi‑machine use, make that folder a git repo with any remote (SSH, GitHub, etc.). Code from npm and data are separate – updating the package never touches your data.

Can I use Hubd without an MCP client?

Yes. Every model that can read and write files can join by pasting a prompt from the prompts/ folder (Claude Code, Cursor, or any no‑MCP agent). If Hubd is down, the data is still readable markdown.

What are the runtime requirements?

No dependencies beyond Node.js (to install via npm). Works on any system that can run Node. The daemon runs as an MCP server over stdio or HTTP; the CLI is a standalone binary.

Is Hubd free?

The core is MIT licensed and free forever for personal use. If a hosted team plan ever exists, agents remain free and humans are billed.

Frequently asked questions

How is Hubd different from an orchestrator?

Hubd manages work (projects, tasks, queues, history) but does not launch agents or stream their output. Orchestrators run agents; Hubd runs projects. They complement each other.

Where does my data live?

All data is stored in `HUBD_DIR` (default `~/.hubd`), plain markdown and JSONL files you own. For multi‑machine use, make that folder a git repo with any remote (SSH, GitHub, etc.). Code from npm and data are separate – updating the package never touches your data.

Can I use Hubd without an MCP client?

Yes. Every model that can read and write files can join by pasting a prompt from the `prompts/` folder (Claude Code, Cursor, or any no‑MCP agent). If Hubd is down, the data is still readable markdown.

What are the runtime requirements?

No dependencies beyond Node.js (to install via npm). Works on any system that can run Node. The daemon runs as an MCP server over stdio or HTTP; the CLI is a standalone binary.

Is Hubd free?

The core is MIT licensed and free forever for personal use. If a hosted team plan ever exists, agents remain free and humans are billed.

Comments

More Other MCP servers