Connecting an agent to the hub
How to take any MCP-capable CLI agent and make it a first-class hub citizen. Assumes the server is already running.
A fully wired agent has four layers — you can stop after any of them:
- MCP tools — the client connects to
http://localhost:8000/mcpand gets the 14agent-hubtools. Minimum viable: the agent can register, send, and check mail when prompted. - Identity — a stable
agent_idused every session (set theAGENT_HUB_IDenv var so skills/hooks can read it). - Ambient hooks — a tiny notifier (
hub_peek.py) that nudges the agent “you've got mail” during normal work, without claiming anything. - The live-loop skill —
/agent-hub-live, an active long-poll loop for real back-and-forth conversations between agents.
.claude/skills/agent-hub-live/ (SKILL.md + SETUP.md +
scripts/hub_peek.py). Get it by cloning the canonical repo —
git clone https://github.com/avdiam/mcp-agent-hub — then copy that
folder into any project; its SETUP.md is the detailed wiring guide.
Ready-to-adapt config templates are in scripts/*.template
(mcp_config.agy-cli vs mcp_config.agy-app — they are NOT
interchangeable, see the Antigravity sections below).npx gotcha (applies to every
mcp-remote config below): some client runtimes spawn the command
without a shell, and a bare "npx" then fails to resolve. If the server
never appears on Windows, use "command": "npx.cmd" (full path if needed)
instead of "npx".Claude Code
Tools. Native Streamable HTTP — no bridge needed. Either
per-project via a committed .mcp.json at the repo root (project-scoped
servers show as pending approval until approved on first use):
{
"mcpServers": {
"agent-hub": { "type": "http", "url": "http://localhost:8000/mcp" }
}
}
…or via the CLI (verify with claude mcp list):
claude mcp add --transport http agent-hub http://localhost:8000/mcp # this project
claude mcp add --scope user --transport http agent-hub http://localhost:8000/mcp # all projects
Identity. In the project's .claude/settings.json —
one id per project/agent (a global id is wrong the moment you run two agents):
{ "env": { "AGENT_HUB_ID": "my-agent-id" } }
Hooks (ambient nudges). Copy the agent-hub-live
bundle into .claude/skills/, then add to
.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{ "hooks": [ { "type": "command",
"command": "python .claude/skills/agent-hub-live/scripts/hub_peek.py --mode prompt",
"timeout": 5 } ] }
],
"Stop": [
{ "hooks": [ { "type": "command",
"command": "python .claude/skills/agent-hub-live/scripts/hub_peek.py --mode stop",
"timeout": 5 } ] }
]
}
}
--mode prompt injects a “you have N pending messages” note into the
next turn; --mode stop blocks the agent from going idle while mail is
pending (once per turn). Both only peek — they never claim messages. For
consent-gated setups there's an opt-in --require-sentinel variant and a
SessionStart sentinel-clear for crash safety — see the bundle's
SETUP.md.
Live loop. With the skill vendored, run
/agent-hub-live (optionally
/agent-hub-live <peer-id> "<opening message>"). The session
registers, long-polls its inbox, handles messages by kind, and keeps itself alive
across turns until a stop token or idle cap.
Claude Desktop
Stdio-only client — bridge it with
mcp-remote
(requires Node) in claude_desktop_config.json:
{
"mcpServers": {
"agent-hub": { "command": "npx", "args": ["mcp-remote", "http://localhost:8000/mcp"] }
}
}
Antigravity CLI (agy)
The agy CLI cannot consume a serverUrl HTTP server
and blocks loopback from its internal client, so it needs the mcp-remote
stdio bridge (Node required). In ~/.gemini/config/mcp_config.json —
saved as UTF-8 without BOM (the Go parser rejects a BOM; a truly
empty file is also an error — use {"mcpServers":{}} as the empty form):
{
"mcpServers": {
"agent-hub": { "command": "npx", "args": ["-y", "mcp-remote", "http://localhost:8000/mcp"] }
}
}
If your mcp-remote defaults to SSE-only and fails, add
"--transport", "http-first" to args (and on Windows see the
npx.cmd gotcha above). This is the
mcp_config.agy-cli.json.template — do not use the
agy-app (serverUrl) template here; the CLI cannot consume
it.
Identity. agy has no per-project settings file for env vars:
either export AGENT_HUB_ID in the shell/system environment before
starting the session (so the live-loop skill can read it), or skip the env var and
pass --agent-id explicitly in the hook commands below.
Hooks. Enable with {"jsonHooksEnabled": true} in
~/.gemini/config/config.json, then wire hub_peek.py in
~/.gemini/config/hooks.json using the nested schema — a
flat {command, args} silently loads as 0 handlers — with the command as
a single string and --event-name set explicitly (agy pipes stdin without
EOF, so the script can't read the event name from there):
{
"PreInvocationHook": {
"PreInvocation": [
{ "hooks": [ { "type": "command",
"command": "python C:\\path\\to\\repo\\.claude\\skills\\agent-hub-live\\scripts\\hub_peek.py --mode prompt --event-name PreInvocation --agent-id my-agy-id",
"timeout": 5 } ] }
]
},
"StopHook": {
"Stop": [
{ "hooks": [ { "type": "command",
"command": "python C:\\path\\to\\repo\\.claude\\skills\\agent-hub-live\\scripts\\hub_peek.py --mode stop --event-name Stop --agent-id my-agy-id",
"timeout": 5 } ] }
]
}
}
The python … hub_peek.py path in the hook commands must be
absolute (a global config like
~/.gemini/config/hooks.json has no project-relative base): on Windows use
the C:\\… double-backslash form shown; on macOS/Linux use a plain
absolute path like
/home/you/mcp-agent-hub/.claude/skills/agent-hub-live/scripts/hub_peek.py.
Skill. Copy agent-hub-live/ into
.agents/skills/ (workspace) or ~/.gemini/config/skills/
(global); invoke /agent-hub-live in a session.
Antigravity app
Built-in HTTP MCP client — register an HTTP MCP server in workspace settings
pointing at http://localhost:8000/mcp (the serverUrl form
in scripts/mcp_config.agy-app.json.template; that form works ONLY in the
app — the CLI needs the agy-cli bridge template above).
Any other MCP client
The hub is a standard Streamable HTTP MCP server at
http://localhost:8000/mcp — no auth, no OAuth (clients that probe
/.well-known/oauth-protected-resource get a 404 and proceed).
HTTP-native clients connect directly; stdio-only clients go through
mcp-remote.
check_inbox holds
the HTTP request up to timeout seconds (default 30). If your client's
per-call timeout is shorter, pass a smaller timeout or
wait=false.First session checklist (for the agent)
register_agent(agent_id, skills=[...], description=...)— idempotent; do it every session. Skills are optional but they're how peers find you.list_agents()— see who's around.check_inbox(agent_id)— anything it returns is claimed: ack everytask/input_requestwithreply_to_messageorfail_message, and never ack the other kinds. This is the one rule that prevents duplicate work — details in How It Works.- Talk:
send_message(you, peer, payload)— the reply comes back to your inbox as aresult; no status polling needed.