> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcphub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> Manage a running mcphub instance and call MCP tools from the terminal

## Overview

The `mcphub` binary doubles as a CLI for the running hub. Invoke `mcphub` with no arguments to start the server (the original behavior); pass a subcommand to drive a remote (or local) hub over its HTTP API.

```bash theme={null}
mcphub --help                    # list every subcommand
mcphub <command> [options]       # run a CLI command
mcphub                            # legacy: start the server (unchanged)
```

The CLI ships with the same npm package as the server — there's nothing extra to install.

## Logging in

```bash theme={null}
mcphub login --url http://localhost:3000 --username admin --password ********
```

A JWT is cached in an XDG-compliant credentials file with `0600` permissions:

* macOS/Linux: `$XDG_DATA_HOME/mcphub/credentials.json` (default `~/.local/share/mcphub/credentials.json`)
* Legacy: `~/.mcphub/credentials.json` is still honored when it already exists

Multiple **profiles** are supported, so a single shell can target `staging`, `prod`, etc. side-by-side:

```bash theme={null}
mcphub login --profile staging --url https://staging.hub.example
mcphub config use prod
mcphub config list
```

You can also bypass the credentials file entirely:

| Override | Where it comes from |
| - | - |
| `--url`, `--token`, `--bearer` flags | per-command |
| `MCPHUB_URL`, `MCPHUB_TOKEN`, `MCPHUB_TOKEN_KIND` env | shell session / CI |
| Active profile in `credentials.json` | default |

Resolution order: flag → environment variable → active profile.

## Global options

| Option | Purpose |
| - | - |
| `--url <url>` | Override the active profile's base URL |
| `--token <token>` | Override the active profile's token |
| `--bearer` | Treat `--token` as a bearer key (default is JWT via `x-auth-token`) |
| `--profile <name>` | Pick a saved profile other than `current` |
| `--json` | Print JSON instead of human-friendly tables |
| `--debug` | Print stack traces on error |

## Commands

### `servers`

```bash theme={null}
mcphub servers list
mcphub servers get <name>

# Add from a JSON file:
mcphub servers add fetch --from-file ./fetch.json

# Or inline (--arg / --env can repeat):
mcphub servers add fetch \
  --type stdio --command uvx \
  --arg mcp-server-fetch \
  --env USER_AGENT=mcphub

mcphub servers remove fetch
mcphub servers toggle fetch --on
mcphub servers reload fetch
```

### `groups`

```bash theme={null}
mcphub groups list
mcphub groups add dev --description "developer tools"
mcphub groups add-server dev fetch
mcphub groups remove-server dev fetch
mcphub groups remove dev
```

`<group>` accepts either the UUID or the human-readable name; the CLI resolves the name to an id by listing groups first.

### `keys`

Manage bearer keys. Admins manage system-level and user-level keys; ordinary users manage their own
user-level keys.

```bash theme={null}
mcphub keys list
mcphub keys create --name ci --access-type all
mcphub keys create --name dev-only --access-type groups --groups dev,staging
mcphub keys delete <id>
```

The hub-generated token is printed once on `create` — copy it before navigating away.

### `tools` — discover what to call

`tools` is the agent-friendly index for `call`: it answers **what tools exist, what params each one takes, which server hosts it** without having to hand-parse `servers list` JSON.

```bash theme={null}
# Flat list of every tool across every connected server.
mcphub tools list
mcphub tools list --json                       # machine-readable, no schemas
mcphub tools list --schema --json              # include each tool's inputSchema
mcphub tools list --server fetch               # scope to one server
mcphub tools list --enabled-only

# Inspect one tool: description, parameter table, full input schema, sample command.
mcphub tools get fetch_url
mcphub tools get fetch_url --server fetch      # disambiguate when two servers expose the same name
mcphub tools schema fetch_url                  # alias for `get`
```

The `tools get` text view prints a parameter table marking which keys are `required`, followed by the full JSON schema and a ready-to-paste `mcphub call ...` example with the required params filled in.

### `call`

Call an MCP tool against the active profile's hub. By default `/mcp/$smart` is used so smart routing picks the right tool. The recommended agent workflow is **`tools list` → `tools get` → `call`**.

```bash theme={null}
# 1. Find a tool
mcphub tools list --json | jq '.[] | select(.name | contains("fetch"))'

# 2. Check its schema
mcphub tools get fetch_url --json | jq '.inputSchema'

# 3. Call it
mcphub call fetch_url url=https://example.com timeout=30
mcphub call fetch_url url=https://example.com --server fetch        # pin to a specific server
mcphub call my_tool --group dev nested='{"a":1}'
mcphub call my_tool --params-json '{"deep":{"v":1}}'
```

Routing precedence inside `call`: `--smart` > `--server <name>` > `--group <name>` > default (`$smart`). All three resolve to the same `/mcp/<slug>` endpoint; `--server` is the natural pair for `tools list`/`tools get` output.

`key=value` argument coercion:

| Form | Result |
| - | - |
| `n=42`, `f=1.5` | number |
| `b=true`, `b=false` | boolean |
| `x=null` | `null` |
| `obj={"a":1}`, `arr=[1,2]` | parsed JSON |
| `payload=@./body.json` | JSON loaded from file |
| `phone=0123` | preserved as the string `"0123"` (leading-zero protection) |
| anything else | string |

Pass `--no-coerce` to treat every value as a string.

### `export`

Download `mcp_settings.json` from the running hub.

```bash theme={null}
mcphub export --out backup.json
mcphub export > backup.json
```

### `discover` / `install` (marketplace)

When the hub has `systemConfig.discovery.enabled = true`, the CLI can browse the public marketplace and install servers into your own hub or directly into a client-side config file.

```bash theme={null}
# Browse the active profile's hub
mcphub discover --search github --limit 10
mcphub discover info amap-maps
mcphub discover categories
mcphub discover tags

# Install into the active hub (POST /api/servers)
mcphub install amap-maps --env AMAP_MAPS_API_KEY=...

# Install from a different hub into the active one
mcphub install some-server --remote https://hub.example.com --yes

# Dry-run: just print the mcpServers snippet
mcphub install amap-maps --dry-run

# Install into a Claude Desktop / OpenClaw-style config file
mcphub install amap-maps --to file --out ~/Library/Application\ Support/Claude/claude_desktop_config.json
```

Notes:

* `--type` picks the installation method (`npm`, `docker`, `uvx`, `pip`, `binary`). If omitted, the hub picks the first available; if the requested type doesn't exist, the CLI lists the alternatives.
* `--env KEY=VAL` (repeatable) injects environment values — both predeclared and additional keys are merged into the resulting `env` block.
* `--to file` writes atomically (temp file + rename), so a crashed write can't corrupt your client config.

`mcphub call` initializes an MCP session before invoking the tool, accepts JSON or SSE responses, and closes the session after the call. This supports both older sessionful hubs and current hubs through their compatible Streamable HTTP endpoint.

## Exit codes

| Code | Meaning |
| - | - |
| `0` | Success |
| `1` | Usage error (bad flag, missing argument, unauthorized state) |
| `2` | API error (non-2xx response from the hub) |

## Autonomous-agent recipe

Every command supports `--json` and reads `MCPHUB_URL` / `MCPHUB_TOKEN`, so an agent can drive the entire discover → call loop from JSON:

```bash theme={null}
export MCPHUB_URL=http://localhost:3000
export MCPHUB_TOKEN=$JWT

# 1. enumerate tools
mcphub tools list --json > tools.json

# 2. pick one and read its schema
mcphub tools get fetch_url --json > schema.json

# 3. build a payload from the schema and invoke
mcphub call fetch_url --params-json "$(jq -n '{url:"https://example.com"}')" --json
```

The `tools list --json` response is intentionally flat (`{server, serverStatus, name, description, enabled}`) so an agent can filter in one pass without traversing nested `servers[*].tools[*]`.

## Scripting and CI

The CLI is JSON-friendly: `--json` is honored by every command, and `MCPHUB_URL` / `MCPHUB_TOKEN` make it easy to skip the credentials file in CI.

```bash theme={null}
export MCPHUB_URL=https://hub.example.com
export MCPHUB_TOKEN=$CI_HUB_TOKEN

mcphub servers list --json | jq '.[] | select(.status != "connected") | .name'
```

For bearer-key auth in CI, add `MCPHUB_TOKEN_KIND=bearer` (or `--bearer`). Note that only system-level bearer keys with `accessType=all` authorize the `/api/*` management surface. Scoped system keys and user-level keys are for MCP transports only.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.