npm package: @mcp-s/mcp-cli
Description: A lightweight CLI for interacting with MCP (Model Context Protocol) servers
Author: Idan Chetrit
Latest version: 0.0.8

# mcp-cli

A lightweight CLI for connecting AI agents to the [Webrix](https://webrix.ai) MCP Gateway — Webrix's enterprise-grade identity and access layer for AI agents.

## Overview

Webrix's MCP Gateway is the secure connection layer between AI agents and your enterprise systems (GitHub, Slack, Jira, internal APIs, etc.). This CLI lets you interact with a single Webrix MCP server from your terminal or from inside AI coding agents (Claude, Cursor, Gemini CLI, etc.).

Each CLI invocation connects to **one MCP server at a time**, identified by the server name configured in your local config file.

## Features

- **Lightweight** — Minimal dependencies, fast startup
- **Shell-friendly** — JSON output for `call`, pipes with `jq`, chaining support
- **Agent-optimized** — Designed for AI coding agents (Claude Code, Cursor, Gemini CLI, etc.)
- **Secure** — Supports OAuth login and Bearer token auth to the Webrix Gateway
- **Connection pooling** — Lazy-spawn daemon keeps connections warm (configurable idle timeout)
- **Tool filtering** — Allow/disable specific tools per server via config
- **Actionable errors** — Structured error messages with recovery suggestions

---

## Quick Start

### 1. Install

Requires [Node.js](https://nodejs.org/) >= 18.

```bash
npm install -g @mcp-s/mcp-cli
```

Or run without installing:

```bash
npx @mcp-s/mcp-cli
```

### 2. Initialize config with your Webrix Gateway URL

```bash
# Interactive setup (recommended)
mcp-cli init

# Or non-interactive: HTTP server with a Bearer token
mcp-cli init Webrix --url https://<your-org>.webrix.ai/mcp --token <your-token>

# Or: OAuth-based (run login after init)
mcp-cli init Webrix --url https://<your-org>.webrix.ai/mcp
mcp-cli login
```

### 3. Discover available tools

```bash
# List all tools on all configured servers
mcp-cli

# With descriptions
mcp-cli -d
```

### 4. Call a tool

```bash
# View tool schema first
mcp-cli info Webrix <tool_name>

# Call the tool
mcp-cli call Webrix <tool_name> '{"param": "value"}'
```

---

## Usage

```
mcp-cli [options]                             List all configured servers and their tools
mcp-cli [options] info <server>               Show all tools on a server
mcp-cli [options] info <server> <tool>        Show schema for a specific tool
mcp-cli [options] grep <pattern>              Search tools by glob pattern
mcp-cli [options] call <server> <tool>        Call a tool (reads JSON args from stdin)
mcp-cli [options] call <server> <tool> <json> Call a tool with inline JSON arguments
mcp-cli init [name] [--org <org>] [--base-url <url>] [...]  Initialize global config with a server
mcp-cli whoami                                Show config location, servers, and auth state
mcp-cli login                                 Log in to the configured server via OAuth
mcp-cli logout                                Remove stored OAuth tokens
mcp-cli clear                                 Remove all MCP servers from config
mcp-cli clear-auth                            Remove all stored auth data
```

**Both formats work:** `info <server> <tool>` or `info <server>/<tool>`

> **Tip:** Add `-d` to any command to include tool descriptions.

### Options

| Option                    | Description                            |
| ------------------------- | -------------------------------------- |
| `-h, --help`              | Show help message                      |
| `-v, --version`           | Show version number                    |
| `-d, --with-descriptions` | Include tool descriptions in output    |
| `-c, --config <path>`     | Path to a custom `mcp-cli.json` config |

### Output streams

| Stream     | Content                                |
| ---------- | -------------------------------------- |
| **stdout** | Tool results and human-readable output |
| **stderr** | Errors and diagnostics                 |

---

## Commands

### List Servers and Tools

```bash
# Basic listing
$ mcp-cli
Webrix
  • search_issues
  • create_ticket
  • list_channels

# With descriptions
$ mcp-cli -d
Webrix
  • search_issues - Search Jira issues by query
  • create_ticket - Create a new Jira ticket
  • list_channels - List Slack channels
```

### Search Tools

```bash
# Find tools matching a glob pattern
$ mcp-cli grep "*ticket*"
Webrix/create_ticket
Webrix/update_ticket

# With descriptions
$ mcp-cli grep "*search*" -d
Webrix/search_issues - Search Jira issues by query
```

### View Server Details

```bash
$ mcp-cli info Webrix
Server: Webrix
Transport: http
URL: https://<your-org>.webrix.ai/mcp

Tools (12):
  search_issues
    Search Jira issues by query
    Parameters:
      • query (string, required) - JQL or natural language query
      • limit (number, optional) - Max results
  ...
```

### View Tool Schema

```bash
# Both formats work:
$ mcp-cli info Webrix search_issues
$ mcp-cli info Webrix/search_issues

Tool: search_issues
Server: Webrix

Description:
  Search Jira issues by query

Input Schema:
  {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "JQL or natural language query" },
      "limit": { "type": "number" }
    },
    "required": ["query"]
  }
```

### Call a Tool

Each `call` invocation connects to **one server only** — the one you specify.

```bash
# With inline JSON
$ mcp-cli call Webrix search_issues '{"query": "bug in authentication", "limit": 5}'

# Pipe the JSON output
$ mcp-cli call Webrix search_issues '{"query": "open bugs"}' | jq '.content[0].text'

# Read JSON args from stdin (no '-' needed)
$ echo '{"query": "urgent"}' | mcp-cli call Webrix search_issues

# Heredoc for complex JSON
$ mcp-cli call Webrix create_ticket <<EOF
{"title": "Fix login bug", "description": "Users can't log in with SSO"}
EOF
```

### Initialize Global Config

Set up `~/.config/mcp-cli/mcp-cli.json` with your Webrix MCP Gateway:

```bash
# Interactive (prompts for name, connection type, credentials)
mcp-cli init

# HTTP mode — derive URL from org name
mcp-cli init Webrix --org <your-org>

# HTTP mode — provide a custom base URL
mcp-cli init Webrix --base-url https://<your-org>.mcp-s.com/mcp

# HTTP mode with optional mcp/toolkit headers
mcp-cli init Webrix --org <your-org> --mcp slack --toolkit my-tk

# stdio mode — add a user access key (runs via npx @mcp-s/mcp)
mcp-cli init Webrix --org <your-org> --mcp slack --toolkit my-tk --user-access-key <key>
mcp-cli init Webrix --base-url example.com --mcp slack --user-access-key <key>
```

| Option                    | Description                                                    |
| ------------------------- | -------------------------------------------------------------- |
| `--org <org>`             | Org name — derives URL as `https://<org>.mcp-s.com/mcp`        |
| `--base-url <url>`        | Custom server URL                                              |
| `--mcp <id>`              | MCP identifier (sent as `x-mcp` header or `MCP` env var)       |
| `--toolkit <name>`        | Toolkit name (sent as `x-toolkit` header or `TOOLKIT` env var) |
| `--user-access-key <key>` | User access key — triggers stdio mode                          |

**Mode selection:**

- `--user-access-key` absent → **HTTP mode**: produces a `url` + optional `headers` config
- `--user-access-key` present → **stdio mode**: produces a `type: stdio` config running `npx -y @mcp-s/mcp` with env vars

Either `--org` or `--base-url` is required; they are mutually exclusive.

> **Note:** `init` overwrites the global config file. It is intended as a quick-start helper.

### Authentication

```bash
# Log in via OAuth (opens browser)
mcp-cli login

# Log out (removes stored tokens from auth.json)
mcp-cli logout

# Show current auth state and config location
mcp-cli whoami
```

### Maintenance

```bash
# Remove all MCP servers from config (sets mcpServers to {})
mcp-cli clear

# Remove all stored OAuth tokens (sets auth.json to {})
mcp-cli clear-auth
```

---

## Working with Complex JSON Arguments

For arguments containing single quotes, special characters, or multi-line content, use stdin to avoid shell escaping issues:

```bash
# Heredoc (clean, no escaping needed)
mcp-cli call Webrix create_ticket <<EOF
{"title": "It's broken", "description": "User said \"it doesn't work\""}
EOF

# From a file
cat args.json | mcp-cli call Webrix some_tool

# Using jq to build the payload
jq -n '{query: "open bugs", assignee: "me"}' | mcp-cli call Webrix search_issues
```

---

## Chaining and Scripting

Chain MCP calls using shell pipes and `jq`:

```bash
# Find issues and extract URLs
mcp-cli call Webrix search_issues '{"query": "priority: high"}' \
  | jq -r '.content[0].text | fromjson | .issues[].url'

# Conditional: check something exists before acting on it
mcp-cli call Webrix list_channels '{}' \
  | jq -e '.content[0].text | contains("engineering")' \
  && mcp-cli call Webrix post_message '{"channel": "engineering", "text": "Deploy complete"}'

# Error handling in scripts
if result=$(mcp-cli call Webrix get_config '{}' 2>/dev/null); then
  echo "$result" | jq '.content[0].text | fromjson'
else
  echo "Failed to fetch config"
fi
```

**Tips:**

- Use `jq -r` for raw string output (no surrounding quotes)
- Use `jq -e` for conditional checks (exits 1 if false/null)
- Use `2>/dev/null` to suppress errors when testing existence
- Use `jq -s '.'` to merge multiple JSON outputs into an array

---

## Configuration

### Environment Variables

| Variable             | Description                                       | Default |
| -------------------- | ------------------------------------------------- | ------- |
| `MCP_DEBUG`          | Enable debug output                               | `false` |
| `MCP_TIMEOUT`        | Request timeout (seconds)                         | `1800`  |
| `MCP_CONCURRENCY`    | Servers to query in parallel for list/grep        | `5`     |
| `MCP_MAX_RETRIES`    | Retry attempts for transient errors (0 = disable) | `3`     |
| `MCP_RETRY_DELAY`    | Base retry delay (milliseconds)                   | `1000`  |
| `MCP_STRICT_ENV`     | Error on missing `${VAR}` in config               | `true`  |
| `MCP_DAEMON`         | Enable connection caching (daemon mode)           | `true`  |
| `MCP_DAEMON_TIMEOUT` | Idle timeout for cached connections (seconds)     | `300`   |

---

## Using with AI Agents

`mcp-cli` is designed to give AI coding agents direct access to the Webrix MCP Gateway via the shell. Rather than loading full tool schemas into the agent's context window (which consumes thousands of tokens), the CLI lets agents discover and call tools on demand.

### System Prompt Integration

Add this to your AI agent's system prompt:

```xml
## MCP Tools (via Webrix Gateway)

You have access to enterprise tools through the Webrix MCP Gateway via the `mcp-cli` CLI.

Commands:
  mcp-cli                              # List all servers and tools
  mcp-cli info <server>                # List tools on a server
  mcp-cli info <server> <tool>         # Get tool schema
  mcp-cli grep "<pattern>"             # Search tools by name
  mcp-cli call <server> <tool>         # Call tool (stdin for JSON args)
  mcp-cli call <server> <tool> '{}'    # Call tool with inline JSON

Both formats work: `info Webrix tool_name` or `info Webrix/tool_name`

Workflow:
1. Discover: `mcp-cli` to see available tools
2. Inspect:  `mcp-cli info Webrix <tool>` to get the schema
3. Execute:  `mcp-cli call Webrix <tool> '<json>'` with the required args

Examples:
  mcp-cli call Webrix search_issues '{"query": "open bugs"}'
  echo '{"query": "urgent"}' | mcp-cli call Webrix search_issues
  mcp-cli call Webrix create_ticket <<EOF
  {"title": "Bug", "description": "Details here"}
  EOF
```

### Agents Skill

For AI agents that support Skill files (Cursor, Gemini CLI, Claude Code, etc.), use the included `SKILL.md` in your skills directory for a ready-made integration.

### Common Errors

| Wrong command             | Error code           | Fix                           |
| ------------------------- | -------------------- | ----------------------------- |
| `mcp-cli Webrix tool`     | `AMBIGUOUS_COMMAND`  | Use `call Webrix tool`        |
| `mcp-cli run Webrix tool` | `UNKNOWN_SUBCOMMAND` | Use `call`                    |
| `mcp-cli list`            | `UNKNOWN_SUBCOMMAND` | Use `mcp-cli` (no subcommand) |

---

## Architecture

### Connection Model

Each `call` command connects to exactly **one server**. List and grep commands connect to all configured servers in parallel.

| Command                             | Servers connected         |
| ----------------------------------- | ------------------------- |
| `mcp-cli` (list all)                | All servers in parallel   |
| `mcp-cli grep "<pattern>"`          | All servers in parallel   |
| `mcp-cli info <server>`             | Only the specified server |
| `mcp-cli info <server> <tool>`      | Only the specified server |
| `mcp-cli call <server> <tool> '{}'` | Only the specified server |

### Connection Pooling (Daemon)

Daemon mode is enabled by default. The daemon keeps the MCP server connection open for `MCP_DAEMON_TIMEOUT` seconds (default: 300s) after the last request, avoiding repeated startup latency on subsequent calls.

```bash
mcp-cli call Webrix some_tool '{}'    # Uses cached connection (default)
MCP_DAEMON=0 mcp-cli info Webrix     # Disable daemon, use a fresh connection
MCP_DEBUG=1 mcp-cli info Webrix      # See connection debug output
```

With daemon disabled, each CLI call opens a fresh connection and closes it when done.

### Error Handling and Retry

The CLI automatically retries transient failures with exponential backoff.

**Retried automatically:** network errors (`ECONNREFUSED`, `ETIMEDOUT`, `ECONNRESET`), HTTP `429`, `502`, `503`, `504`

**Fail immediately:** config errors, auth errors (`401`, `403`), tool not found, invalid JSON

---

## Error Messages

All errors include actionable recovery suggestions, optimized for humans and AI agents alike:

```
Error [AMBIGUOUS_COMMAND]: Ambiguous command: did you mean to call a tool or view info?
  Details: Received: mcp-cli Webrix search_issues
  Suggestion: Use 'mcp-cli call Webrix search_issues' to execute, or 'mcp-cli info Webrix search_issues' to view schema

Error [SERVER_NOT_FOUND]: Server "github" not found in config
  Details: Available servers: Webrix
  Suggestion: Use one of: mcp-cli info Webrix

Error [TOOL_NOT_FOUND]: Tool "search" not found in server "Webrix"
  Details: Available tools: search_issues, create_ticket, list_channels (+5 more)
  Suggestion: Run 'mcp-cli info Webrix' to see all available tools

Error [INVALID_JSON_ARGUMENTS]: Invalid JSON in tool arguments
  Details: Parse error: Unexpected identifier "test"
  Suggestion: Arguments must be valid JSON. Use single quotes: '{"key": "value"}'
```

---

## Development

### Setup

```bash
git clone https://github.com/webrix-ai/mcp-cli
cd mcp-cli
npm install
```

### Commands

```bash
# Run in development mode
npm run dev

# Type checking
npm run typecheck

# Linting
npm run lint
npm run lint:fix

# Run all tests
npm test

# Run integration tests (requires a running MCP server, ~35s)
npm run test:integration

# Build
npm run build
```

### Local Testing

```bash
# Link globally for local testing
npm link
mcp-cli --help
mcp-cli call Webrix some_tool '{}'

# Run directly without linking
npm run dev -- --help
npm run dev -- info Webrix

# Unlink when done
npm unlink
```

### Releasing

```bash
./scripts/release.sh 0.2.0
```

---

## License

MIT License — see [LICENSE](LICENSE) for details.