# agent-mcp-hub [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/blackaxgit/agent-mcp-hub  
**GitHub Stars:** 0  
**npm Downloads (last month):** 328  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/agent-mcp-hub

## Description
One MCP server bridging the Codex, Cursor, OpenCode, and Claude CLI agents

## Tools
Capabilities this server exposes over MCP:

- **codex** — Delegate a prompt to `codex exec` (prompt piped via stdin)
- **cursor** — Delegate a prompt to `cursor-agent -p` (prompt piped via stdin)
- **opencode** — Delegate a prompt to `opencode run
- **claude** — Delegate a prompt to the Claude Code CLI (prompt piped via stdin)
- **agy** — Delegate a prompt to Google Antigravity (`agy --print=…`, prompt passed as a flag value)
- **run_all** — Same prompt to all agents in parallel, results side by side
- **list_agents** — Which agent CLIs are installed and on PATH
- **ping** — Health check

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "agent-mcp-hub": {
    "command": "npx",
    "args": ["-y","re-resolves"]
  }
}
```

## Documentation & README

# agent-mcp-hub

One MCP server that bridges multiple CLI coding agents — **Codex**, **Cursor**,
**OpenCode**, **Claude**, and **Antigravity** — into any MCP client.

> **stdio only — by design.** The hub ships no Docker image and no HTTP
> transport (both were removed during the 0.5.x line). A containerised or remote
> server cannot see the caller's repository path and cannot reuse the caller's
> CLI logins — it would break the product contract on both halves. The hub runs
> as a child process of your MCP client, on your machine, as you.

## Tools

| Tool | Description |
|---|---|
| `codex` | Delegate a prompt to `codex exec` (prompt piped via stdin) |
| `cursor` | Delegate a prompt to `cursor-agent -p` (prompt piped via stdin) |
| `opencode` | Delegate a prompt to `opencode run` |
| `claude` | Delegate a prompt to the Claude Code CLI (prompt piped via stdin) |
| `agy` | Delegate a prompt to Google Antigravity (`agy --print=…`, prompt passed as a flag value) |
| `run_all` | Same prompt to all agents in parallel, results side by side |
| `list_agents` | Which agent CLIs are installed and on PATH |
| `ping` | Health check |

Agent tools accept `prompt` (required), `model`, `cwd`, `timeoutMs` (total runtime
cap, default 1800000 = 30 min), and `idleTimeoutMs` (inactivity cap, default 300000
= 5 min). See [Long-running tasks & timeouts](#long-running-tasks--timeouts).

Known limitation: `opencode` prompts may not start with `-` (its CLI could parse
them as flags); the tool returns an actionable error instead of guessing.

### Choosing models per agent

**Model ids are agent-specific and do not overlap.** `o3` means nothing to
`agy`, `gemini-3.6-flash-low` means nothing to `codex`, and `opencode` namespaces
its own (`opencode/big-pickle`). So a single `model` value is valid for at most
one agent in a fan-out.

- `run_all` takes **`models`** — a per-agent map. Agents you don't list fall back
  to `model`, then to their own CLI default.
- `review_change` takes **`runnerModel`** and **`reviewerModel`**, so the agent
  writing the change and the agent judging it can use different engines *and*
  tiers. `model` remains a fallback for both.

```json
{
  "tool": "run_all",
  "arguments": {
    "prompt": "Explain the retry logic in src/exec.ts",
    "models": { "codex": "o3", "agy": "gemini-3.6-flash-low", "claude": "haiku" }
  }
}
```

An unknown agent name in `models` is rejected with the list of enabled agents —
a typo never silently falls back to the default model.

Where to find valid ids: `opencode models`, `cursor-agent models` and
`agy models` list them. `codex` and `claude` have no such command — codex reads
its default from `~/.codex/config.toml`, and claude accepts the documented
aliases (`opus`, `sonnet`, `haiku`, `fable`). Note `claude models` is **not** a
subcommand: it is treated as a prompt, so its "model list" is generated text,
not a source of truth.

### Error handling

When a wrapped CLI fails, the hub classifies the failure and returns a clean,
ANSI-free, actionable `isError` result — never a raw terminal dump — naming the
class and the exact fix:

| Class | Example remediation |
|---|---|
| `not_installed` | install the CLI (e.g. `npm i -g @openai/codex`) / fix PATH |
| `not_authenticated` | `codex login` · `cursor-agent login` · `opencode auth login` · `claude` → `/login` · `agy` → sign in on first run (or set the matching API key) |
| `not_configured` | set a model/provider in the CLI's config |
| `timed_out` | raise `timeoutMs`, or check the agent/model is responsive |
| `stream_stalled` | the agent reached the network but its stream keeps dropping (e.g. `cursor` behind a TLS-intercepting proxy) — treat that agent as unavailable; raising `timeoutMs` will not help |
| `server_busy` | retry shortly (upstream rate-limit, or the local agent-spawn queue is full) |
| `tool_failure` | generic non-zero exit — the message includes `(exit N)` and a trimmed output tail |

For example, an unauthenticated `cursor` no longer returns its ANSI "press any
key to sign in" banner — it returns `cursor is not authenticated … Fix: run
`cursor-agent login``.

### Review a change (`review_change`)

Runs a `runner` agent in a git `cwd` to make a change, captures the actual
`git diff` of what changed, then has a `reviewer` agent judge that diff. Returns
the runner's output, the diff (`--stat`), and a **PASS / WARN / FAIL** verdict
with findings.

**Inputs:** `runner`, `reviewer` (agent names), `prompt`, `cwd` (must be a git
worktree), optional `runnerModel`, `reviewerModel`, `model` (fallback for both),
`timeoutMs`.

**Key notes:**

- Cross-agent by design — e.g. `codex` writes, `claude` reviews.
- Returns the concrete diff that the plain agent tools don't expose.
- Newly-created (untracked) files are surfaced to the reviewer **with their
  contents** (bounded: 64 KiB per file, 50 files; excess is truncated and
  flagged). `git diff` alone would omit them entirely.
- If the worktree was already dirty, the diff may include pre-existing changes
  (noted in the output).
- Complements — does not replace — client-side stop-hooks or PR-time CI review.
- The confirm gate (`MCP_CONFIRM`) applies.
- **The reviewer runs least-privilege — but how much that guarantees depends on the
  agent.** The reviewer's prompt embeds an attacker-influenced diff, so it is run
  read-only rather than with the write grant the runner gets. Only two of the five
  are real restrictions:

  | Reviewer | Read-only mechanism | Enforced? |
  |---|---|---|
  | `codex` | `-s read-only` | **Yes — OS-level sandbox** |
  | `claude` | `--disallowedTools Write,Edit,…,Bash` | **Yes — harness-level deny** |
  | `cursor` | `--trust --mode plan` (no `--force`) | No — model-advisory only |
  | `agy` | permission grant withheld | Partly — headless auto-deny, not a sandbox |
  | `opencode` | *none available* | **No — unrestricted** |

  Pick `codex` or `claude` as the reviewer if you want the restriction to be real.
  This is defense-in-depth alongside the nonce-fenced diff and the throwaway temp
  cwd; none of it is a sandbox.

```json
{
  "tool": "review_change",
  "arguments": {
    "runner": "codex",
    "reviewer": "claude",
    "prompt": "Add retry with exponential backoff to the API client",
    "cwd": "/Users/you/projects/my-app"
  }
}
```

## Prerequisites

Install and authenticate the CLIs you want to use (any subset works):

- Codex: `npm i -g @openai/codex && codex login`
- Cursor: `curl https://cursor.com/install -fsS | bash && cursor-agent login`
- OpenCode: `npm i -g opencode-ai && opencode auth login`
- Claude Code: `npm i -g @anthropic-ai/claude-code && claude` (first run logs in)
- Antigravity: install the Antigravity CLI (e.g. `brew install --cask antigravity-cli`),
  then run `agy` once and sign in — it has no `login` subcommand and stores
  credentials in the OS keyring, so there is no API-key env var to set

## Install

**Recommended — global install (fast, reliable startup):** install the pinned
version once, then point your client at the `agent-mcp-hub` binary. Startup is
instant and the client connects reliably.

```bash
npm i -g agent-mcp-hub@0.5.0
```

### Claude Code

```bash
claude mcp add agent-hub -- agent-mcp-hub
```

### Cursor / generic mcp.json

```json
{
  "mcpServers": {
    "agent-hub": {
      "command": "agent-mcp-hub"
    }
  }
}
```

### Zero-install alternative (npx)

No global install, but npx re-resolves the package on every launch, so first
start is slower and can occasionally trip a client's connection-probe timeout
(the server itself is fine — just retry). Prefer the global install for a
persistent setup.

```bash
claude mcp add agent-hub -- npx -y agent-mcp-hub@0.5.0
# mcp.json:  "command": "npx", "args": ["-y", "agent-mcp-hub@0.5.0"]
```

> **Pre-release / fallback:** To test an unreleased commit, run directly from
> GitHub: `npx -y github:blackaxgit/agent-mcp-hub#<tag-or-sha>`. This builds
> from source on first fetch, so under npm v12+ you must allow the `prepare`
> script.

## Configuration

**`MCP_AGENTS`** — comma-separated allowlist of the agents to expose
(`codex,cursor,opencode,claude,agy`). Unset or empty exposes all agents. Disabled
agents get no tool and are absent from `list_agents`/`run_all`. An unknown name
fails at startup with an error listing the valid names, so typos never silently
disable an agent.

For stdio, set it in the client's `mcp.json`:

```json
{
  "mcpServers": {
    "agent-hub": {
      "command": "npx",
      "args": ["-y", "agent-mcp-hub@0.5.0"],
      "env": { "MCP_AGENTS": "codex,claude" }
    }
  }
}
```

### Confirm before running an agent — `MCP_CONFIRM`

Set `MCP_CONFIRM=1` (values `1`/`true`/`on`/`all`; default off) to require a
confirmation before any agent tool — and `run_all` — actually spawns a CLI. The
server sends a brief summary (agent · prompt · cwd · model) and waits: **accept**
runs the agent, **decline** runs nothing and returns a terminal cancellation.

This uses the standard MCP **elicitation** capability, so it is **client/IDE-agnostic** —
it works with any MCP client that supports form elicitation (Claude Code, Cursor,
VS Code, Zed, Windsurf, custom SDK clients, …); the gate keys on the protocol
capability, never a product name. Clients that don't support elicitation
transparently run without a prompt (no hang, no error).

```json
{
  "mcpServers": {
    "agent-hub": {
      "command": "npx",
      "args": ["-y", "agent-mcp-hub@0.5.0"],
      "env": { "MCP_CONFIRM": "1" }
    }
  }
}
```

### Long-running tasks & timeouts

A complex agent task can run for many minutes. The hub bounds each run with two
independent timers so a productive long run survives while a genuinely stuck one
fails fast:

- **Idle (inactivity) timeout** — `idleTimeoutMs` (per call) / `MCP_AGENT_IDLE_TIMEOUT_MS`
  (env), default **300000 (5 min)**. The timer resets on every chunk of output the
  CLI produces, so an agent that keeps working (streaming output) never trips it. An
  agent that goes silent — e.g. `opencode` stuck on an unreachable model backend —
  is killed after the idle window with an actionable "no output — the agent may be
  hung or its model/backend is unreachable" error, instead of burning the full cap.
- **Total runtime cap** — `timeoutMs` (per call) / `MCP_AGENT_TIMEOUT_MS` (env),
  default **1800000 (30 min)**. A hard upper bound regardless of activity.

Whichever fires first kills the agent's process group. **Tradeoff:** the idle reset
assumes the CLI streams intermediate output. `codex` and `opencode` do; `claude -p`,
`cursor-agent -p` and `agy --print` may emit only the final result, so a long
**silent** task on those can be idle-killed at 5 min — raise `idleTimeoutMs` /
`MCP_AGENT_IDLE_TIMEOUT_MS` for such tasks, or rely on the total cap.

`agy` is the strongest case here: it emits its entire answer in one flush at the
end (measured — every line of a 12-line reply arrived at the same instant), and
the hub raises its internal `--print-timeout` to 48h so that agy's own 5-minute
default can never truncate a run. The idle timer is therefore agy's only
protection against a genuine hang; budget `idleTimeoutMs` accordingly for long
autonomous agy tasks.

While an agent runs, the hub emits MCP **progress notifications** to clients that
request them (`_meta.progressToken`) — live feedback during long runs. Note: on
**Claude Code (stdio)** the per-server request `timeout` in `.mcp.json` (or the
`MCP_TOOL_TIMEOUT` env var it honors) is a hard wall-clock that progress does
**not** reset (default ~28h) — raise it if you lowered it below your longest run.

## Upgrading

**Global install:** install the new version — the pinned `agent-mcp-hub` command
in your MCP config picks it up on the next client start:

```bash
npm i -g agent-mcp-hub@0.6.0
```

**npx (pinned):** bump the pinned version in your MCP config — e.g. change
`agent-mcp-hub@0.5.0` to `agent-mcp-hub@0.6.0` everywhere.

**Always-latest (not recommended for shared configs):** use `agent-mcp-hub@latest`
instead of a pinned version. Note that `npx` caches by version — it may serve a
stale copy. Force a fresh fetch with `npx --prefer-online agent-mcp-hub` or
`npx clear-npx-cache`.

Pinning is reproducible and recommended for team-wide or checked-in
`mcp.json` files.

## Development

```bash
npm install
npm test           # vitest
npm run typecheck  # strict TS over src + tests
npm run dev        # run from source over stdio
npm run build      # emit dist/
```

## Architecture

Pure adapters (`src/adapters/*` — prompt → `{args, stdin?}`, no I/O) → one
subprocess boundary (`src/exec.ts`) → MCP stdio server (`src/server.ts`). Adding
an agent = one ~15-line adapter file + one line in `src/registry.ts`.

## License

[Mozilla Public License 2.0](https://github.com/blackaxgit/agent-mcp-hub/blob/HEAD/LICENSE) (MPL-2.0).

Versions **before 0.5.2 were released under the MIT license**; that grant stands
for those versions. MPL-2.0 applies from 0.5.2 onward.

