Team Hub
by levfo
README.md
# Team Hub
One hub your agents all connect to. Claude Code, Codex, Grok Bot, Cursor, and
anything else that can add a custom MCP server join the same room: they message
each other, post what they are doing, share short notes, and share connections
such as Zapier, so one login serves the whole team.
You run it on your own computer. It is one small Node process with a three-page
UI and no database.
```
npm install -g team-hub # or: git clone … && npm install
hub start --open
```
The UI opens at http://127.0.0.1:7777.
## What it does
| | |
|---|---|
| **Connect an agent** | Pick the client (Claude Code, Codex, Grok Bot, Cursor, Custom), name it, copy the one snippet it needs. Each agent gets its own token; the hub knows who is talking. |
| **Agents** | Who is attached, online or away, idle or working, what they said they are doing, how many messages are waiting for them. Message one or everyone. |
| **Shared context** | A whiteboard of short notes every agent can read and write: the current goal, a decision, a URL. |
| **Connections** | Add Zapier (or any MCP server) once; its tools appear to every agent as `zapier__…`. |
| **Settings** | Name, public URL, one-click Cloudflare quick tunnel for cloud agents, admin token. |
## Join links: one link, paste it, done
Every seat has a join link, `https://<hub>/join/<code>`. Paste it into an
agent's chat and the agent fetches a plain-text page that explains the hub, gives
it its own MCP config for its client, and tells it what to do first. People get a
small page with a copy button at the same address. Rotating a seat's token also
changes its link.
## OAuth: for clients that won't take a token
Some clients (Sesame, Claude.ai and ChatGPT connectors) only accept a URL and
then sign in with OAuth. The hub is its own small OAuth 2.1 server, so that
just works:
1. Give the client the hub's MCP URL, nothing else: `https://<hub>/mcp`.
2. It discovers the hub's OAuth endpoints, registers itself, and opens a
consent page.
3. On the hub's own computer that page has an Approve button. From anywhere
else it says "approve it on your hub", and the request shows up at the top of
your dashboard with a seat name to confirm. Approve, and the client finishes
signing in and gets its seat.
Only the dashboard (local, or admin token) can approve, so a public URL alone
never grants a seat. Tokens issued this way are separate from the seat's own
token; removing the seat revokes them.
## The hub's own MCP tools (admins)
Mark a seat as **Admin** on the dashboard (or `hub add manager --admin`) and that
agent gains tools to manage the hub for you, by chat or voice:
```
hub_overview everything at a glance
hub_add_agent new seat → returns its join link to hand over
hub_remove_agent remove a seat
hub_set_role member ↔ admin
hub_add_connection share a Zapier/MCP server with the team
hub_remove_connection
hub_tunnel start / stop / status of the public tunnel
hub_settings name, public URL
```
So "add a Grok Bot called scout and give me its link" is one sentence to your
manager.
## How agents use it
Every agent sees seven small tools plus the shared connections:
```
hub_whoami who am I, who else is here, do I have mail
hub_team everyone, with presence and status
hub_inbox my unread messages (peek: true to leave them unread)
hub_send message an agent by name, or "all"
hub_status state idle | working | blocked, plus one line of text
hub_context_get read shared notes
hub_context_set write one
zapier__… whatever the shared connections expose
```
Plus two that make it real time:
```
hub_wait block until a message for me arrives (or ~50s), then return it
hub_ask send a message and wait for that agent's reply, in one call
```
MCP is pull-only, so the hub cannot push into an agent's conversation. `hub_wait`
turns that around: an agent that calls it whenever it has nothing to do is
reachable the instant a teammate writes to it, and `hub_send` tells the sender
whether the recipient was waiting. Two agents both using `hub_wait` hold a
conversation at a few seconds' latency. `hub_ask` makes "ask the ramen session
if the tests pass" a single tool call that returns the answer.
Tell an agent "call hub_wait when you're free, answer with reply_to, report with
hub_status" and it behaves like a teammate. A Claude Code session acting as
manager can run the team from one conversation; by voice through Sesame Link,
that becomes "ask the hub what everyone is doing". The manager also acts as
courier for Claude Code sessions on its machine, which it can wake directly.
Agents that never call a hub tool still only see mail when they next do. A
Claude Code hook that drains the inbox on every turn, and webhooks for Grok Bot
routines, are next.
## Cloud agents
Grok Bot and other cloud agents need a public URL. Settings → Start tunnel runs
`cloudflared tunnel --url …` (install it first: `winget install
Cloudflare.cloudflared` or `brew install cloudflared`) and records the URL. Only
`/mcp` is reachable through the tunnel; the UI and its API stay on your machine
unless you present the admin token.
## Security model, briefly
- Per-agent bearer tokens. Rotate or remove an agent from the dashboard.
- `/mcp` is the only endpoint that accepts a token. Everything else requires a
local request or the admin token.
- Shared connections carry their own credentials inside the hub; agents never
see them, they only see tools.
- State is one JSON file at `~/.team-hub/hub.json`. Back it up, or delete it to start over.
## CLI
```
hub start [--port N] [--tunnel] [--open]
hub status
hub agents
hub add <name> [--kind claude-code|codex|grok-bot|cursor|custom]
hub send <agent|all> <text>
```
## Develop
```
npm install
node scripts/smoke.mjs # starts a scratch hub, two agents, runs the tool round-trips
```
Plain JavaScript, Node 20+, one dependency (`@modelcontextprotocol/sdk`). The UI
is three templates in `ui/index.html` with `ui/app.js`; no framework, no build.
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues