{"id":35797508,"url":"https://github.com/apify/mcp-cli","last_synced_at":"2026-03-04T02:03:56.019Z","repository":{"id":331380790,"uuid":"1112733896","full_name":"apify/mcp-cli","owner":"apify","description":"mcpc is a CLI client for MCP. It supports persistent sessions, stdio/HTTP, OAuth 2.1, JSON output for code mode, proxy for AI sandboxes, and much more.","archived":false,"fork":false,"pushed_at":"2026-02-10T23:57:59.000Z","size":5306,"stargazers_count":309,"open_issues_count":6,"forks_count":10,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-02-11T02:10:16.172Z","etag":null,"topics":["ai-agents","bash","claude","cli","code-mode","command-line","mcp","mcp-client","model-context-protocol","shell"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@apify/mcpc","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apify.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-09T03:00:11.000Z","updated_at":"2026-02-10T23:58:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/apify/mcp-cli","commit_stats":null,"previous_names":["apify/mcpc"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/apify/mcp-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apify%2Fmcp-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apify%2Fmcp-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apify%2Fmcp-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apify%2Fmcp-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apify","download_url":"https://codeload.github.com/apify/mcp-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apify%2Fmcp-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29647768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T09:27:29.698Z","status":"ssl_error","status_checked_at":"2026-02-20T09:26:12.373Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","bash","claude","cli","code-mode","command-line","mcp","mcp-client","model-context-protocol","shell"],"created_at":"2026-01-07T10:00:54.767Z","updated_at":"2026-03-04T02:03:56.004Z","avatar_url":"https://github.com/apify.png","language":"TypeScript","readme":"# `mcpc`: Universal MCP command-line client\n\n`mcpc` is a CLI for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)\nthat maps MCP operations to intuitive commands for interactive shell use, scripts, and AI coding agents.\n\n`mcpc` is a Swiss Army knife for MCP. It is useful for inspecting servers, scripting,\nand enabling AI coding agents to use MCP [\"code mode\"](#ai-agents) in shell.\nAfter all, UNIX-compatible shell script is THE most universal coding language.\n\n![mcpc screenshot](https://raw.githubusercontent.com/apify/mcpc/main/docs/images/mcpc-demo.gif)\n\n**Key features:**\n- 🌎 **Compatible** - Works with any MCP server over Streamable HTTP or stdio.\n- 🔄 **Persistent sessions** - Keep multiple server connections alive simultaneously.\n- 🔧 **Strong MCP support** - Instructions, tools, resources, prompts, dynamic discovery.\n- 🔌 **Code mode** - JSON output enables integration with CLI tools like `jq` and scripting.\n- 🤖 **AI sandboxing** - MCP proxy server to securely access authenticated sessions from AI-generated code.\n- 🔒 **Secure** - Full OAuth 2.1 support, OS keychain for credentials storage.\n- 🪶 **Lightweight** - Minimal dependencies, works on Mac/Win/Linux, doesn't use LLMs on its own.\n\n\n## Table of contents\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Install](#install)\n- [Quickstart](#quickstart)\n- [Usage](#usage)\n- [Sessions](#sessions)\n- [Authentication](#authentication)\n- [MCP proxy](#mcp-proxy)\n- [AI agents](#ai-agents)\n- [MCP support](#mcp-support)\n- [Configuration](#configuration)\n- [Security](#security)\n- [Errors](#errors)\n- [Development](#development)\n- [Related work](#related-work)\n- [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Install\n\n```bash\nnpm install -g @apify/mcpc\n```\n\n**Linux users:** `mcpc` uses the OS keychain for secure credential storage via the\n[Secret Service API](https://specifications.freedesktop.org/secret-service/). Two things are required:\n\n1. **`libsecret`** — the shared library (client side):\n   ```bash\n   # Debian/Ubuntu\n   sudo apt-get install libsecret-1-0\n\n   # Fedora/RHEL/CentOS\n   sudo dnf install libsecret\n\n   # Arch Linux\n   sudo pacman -S libsecret\n   ```\n\n2. **A running secret service daemon** — on desktop systems (GNOME, KDE) this is already provided\n   by gnome-keyring or KWallet. On headless/server/CI environments you need to install and start one:\n   ```bash\n   # Debian/Ubuntu\n   sudo apt-get install gnome-keyring\n\n   # Then start it (e.g. in CI):\n   dbus-run-session -- bash -c \"echo -n 'password' | gnome-keyring-daemon --unlock \u0026\u0026 your-command\"\n   ```\n\n## Quickstart\n\n```bash\n# List all active sessions and saved authentication profiles\nmcpc\n\n# Login to remote MCP server and save OAuth credentials for future use\nmcpc mcp.apify.com login\n\n# Show information about a remote MCP server\nmcpc mcp.apify.com\n\n# Use JSON mode for scripting\nmcpc mcp.apify.com tools-list --json\n\n# Create and use persistent MCP session\nmcpc mcp.apify.com connect @test\nmcpc @test tools-call search-actors keywords:=\"website crawler\"\nmcpc @test shell\n\n# Interact with a local MCP server package (stdio) referenced from config file\nmcpc --config ~/.vscode/mcp.json filesystem tools-list\n```\n\n## Usage\n\n\u003c!-- AUTO-GENERATED: mcpc --help --\u003e\n\n```\nUsage: mcpc [options] \u003ctarget\u003e [command]\n\nUniversal command-line client for the Model Context Protocol (MCP).\n\nOptions:\n  -j, --json                    Output in JSON format for scripting\n  -c, --config \u003cfile\u003e           Path to MCP config JSON file (e.g. \".vscode/mcp.json\")\n  -H, --header \u003cheader\u003e         HTTP header for remote MCP server (can be repeated)\n  -v, --version                 Output the version number\n  --verbose                     Enable debug logging\n  --profile \u003cname\u003e              OAuth profile for the server (\"default\" if not provided)\n  --schema \u003cfile\u003e               Validate tool/prompt schema against expected schema\n  --schema-mode \u003cmode\u003e          Schema validation mode: strict, compatible (default), ignore\n  --timeout \u003cseconds\u003e           Request timeout in seconds (default: 300)\n  --proxy \u003c[host:]port\u003e         Start proxy MCP server for session (with \"connect\" command)\n  --proxy-bearer-token \u003ctoken\u003e  Require authentication for access to proxy server\n  --clean[=types]               Clean up mcpc data (types: sessions, logs, profiles, all)\n  -h, --help                    Display general help\n\nTargets:\n  @\u003csession\u003e                    Named persistent session (e.g. \"@apify\")\n  \u003cconfig-entry\u003e                Entry in MCP config file specified by --config (e.g. \"fs\")\n  \u003cserver-url\u003e                  Remote MCP server URL (e.g. \"mcp.apify.com\")\n\nManagement commands:\n  login                         Create OAuth profile with credentials for remote server\n  logout                        Remove OAuth profile for remote server\n  connect @\u003csession\u003e            Connect to server and create named persistent session\n  restart                       Kill and restart a session\n  close                         Close a session\n\nMCP server commands:\n  help                          Show server info (\"help\" can be omitted)\n  shell                         Open interactive shell\n  tools-list [--full]           Send \"tools/list\" MCP request...\n  tools-get \u003ctool-name\u003e\n  tools-call \u003ctool-name\u003e [arg1:=val1 arg2:=val2 ... | \u003cargs-json\u003e | \u003cstdin]\n  prompts-list\n  prompts-get \u003cprompt-name\u003e [arg1:=val1 arg2:=val2 ... | \u003cargs-json\u003e | \u003cstdin]\n  resources\n  resources-list\n  resources-read \u003curi\u003e\n  resources-subscribe \u003curi\u003e\n  resources-unsubscribe \u003curi\u003e\n  resources-templates-list\n  logging-set-level \u003clevel\u003e\n  ping\n  \nRun \"mcpc\" without \u003ctarget\u003e to show available sessions and profiles.\n```\n\n### General actions\n\nWhen `\u003ctarget\u003e` is omitted, `mcpc` provides general actions:\n\n```bash\n# List all sessions and OAuth profiles (also in JSON mode)\nmcpc\nmcpc --json\n\n# Show command help or version\nmcpc --help\nmcpc --version\n\n# Clean expired sessions and old log files (see below for details)\nmcpc --clean\n```\n\n### Targets\n\nTo connect and interact with an MCP server, you need to specify a `\u003ctarget\u003e`, which can be one of (in this order of precedence):\n\n- **Entry in a config file** (e.g. `--config .vscode/mcp.json filesystem`) - see [Config file](#mcp-server-config-file)\n- **Remote MCP server URL** (e.g. `https://mcp.apify.com`)\n- **Named session** (e.g. `@apify`) - see [Sessions](#sessions)\n\n`mcpc` automatically selects the transport protocol based on the server (stdio or Streamable HTTP),\nconnects, and enables you to interact with it.\n\n**URL handling:**\n- URLs without a scheme (e.g. `mcp.apify.com`) default to `https://`\n- `localhost` and `127.0.0.1` addresses without a scheme default to `http://` (for local dev/proxy servers)\n- To override the default, specify the scheme explicitly (e.g. `http://example.com`)\n\n### MCP commands\n\nWhen `\u003ctarget\u003e` is provided, `mcpc` sends MCP requests to the target server:\n\n```bash\n# Server from config file (stdio)\nmcpc --config .vscode/mcp.json fileSystem\nmcpc --config .vscode/mcp.json fileSystem tools-list\nmcpc --config .vscode/mcp.json fileSystem tools-call list_directory path:=/\n\n# Remote server (Streamable HTTP)\nmcpc mcp.apify.com\\?tools=docs\nmcpc mcp.apify.com\\?tools=docs tools-list\nmcpc mcp.apify.com\\?tools=docs tools-call search-apify-docs query:=\"What are Actors?\"\n\n# Session\nmcpc mcp.apify.com\\?tools=docs connect @apify\nmcpc @apify tools-list\nmcpc @apify tools-call search-apify-docs query:=\"What are Actors?\"\n```\n\nSee [MCP feature support](#mcp-feature-support) for details about all supported MCP features and commands.\n\n#### Command arguments\n\nThe `tools-call` and `prompts-get` commands accept arguments as positional parameters after the tool/prompt name:\n\n```bash\n# Key:=value pairs (auto-parsed: tries JSON, falls back to string)\nmcpc \u003ctarget\u003e tools-call \u003ctool-name\u003e greeting:=\"hello world\" count:=10 enabled:=true\nmcpc \u003ctarget\u003e tools-call \u003ctool-name\u003e config:='{\"key\":\"value\"}' items:='[1,2,3]'\n\n# Force string type with JSON quotes\nmcpc \u003ctarget\u003e tools-call \u003ctool-name\u003e id:='\"123\"' flag:='\"true\"'\n\n# Inline JSON object (if first arg starts with { or [)\nmcpc \u003ctarget\u003e tools-call \u003ctool-name\u003e '{\"greeting\":\"hello world\",\"count\":10}'\n\n# Read from stdin (automatic when no positional args and input is piped)\necho '{\"greeting\":\"hello\",\"count\":10}' | mcpc \u003ctarget\u003e tools-call \u003ctool-name\u003e\ncat args.json | mcpc \u003ctarget\u003e tools-call \u003ctool-name\u003e\n```\n\n**Rules:**\n- All arguments use `:=` syntax: `key:=value`\n- Values are auto-parsed: valid JSON becomes that type, otherwise treated as string\n  - `count:=10` → number `10`\n  - `enabled:=true` → boolean `true`\n  - `greeting:=hello` → string `\"hello\"` (not valid JSON, so string)\n  - `id:='\"123\"'` → string `\"123\"` (JSON string literal)\n- Inline JSON: If first argument starts with `{` or `[`, it's parsed as a JSON object/array\n- Stdin: When no positional args are provided and input is piped, reads JSON from stdin\n\n**Using shell variables:**\n\nWhen using shell variables that may contain spaces, use double quotes around the entire argument:\n\n```bash\n# Variable with spaces - use double quotes\nQUERY=\"hello world\"\nmcpc @server tools-call search \"query:=${QUERY}\"\n\n# Multiple variables\nCITY=\"New York\"\nTYPE=\"restaurants\"\nmcpc @server tools-call search \"query:=${CITY} ${TYPE}\"\n\n# For complex inputs, consider using JSON via stdin\necho \"{\\\"query\\\": \\\"${QUERY}\\\", \\\"limit\\\": 10}\" | mcpc @server tools-call search\n```\n\n**Common pitfall:** Don't put spaces around `:=` - it won't work:\n```bash\n# Wrong - spaces around :=\nmcpc @server tools-call search query := \"hello world\"\n\n# Correct - no spaces around :=\nmcpc @server tools-call search \"query:=hello world\"\n```\n\n### Interactive shell\n\n`mcpc` provides an interactive shell for discovery and testing of MCP servers.\n\n```bash\nmcpc mcp.apify.com shell    # Direct connection\nmcpc @apify shell           # Use existing session\n```\n\nShell commands: `help`, `exit`/`quit`/Ctrl+D, Ctrl+C to cancel.\nArrow keys navigate history (saved to `~/.mcpc/history`).\n\n### JSON mode\n\nBy default, `mcpc` prints output in Markdown-ish text format with colors, making it easy to read by both humans and AIs.\n\nWith `--json` option, `mcpc` always emits only a single JSON object (or array), to enable [scripting](#scripting).\n**For all MCP commands, the returned objects are always consistent with the\n[MCP specification](https://modelcontextprotocol.io/specification/latest).**\nOn success, the JSON object is printed to stdout, on error to stderr.\n\nNote that `--json` is not available for `shell`, `login`, and `mcpc --help` commands.\n\n## Sessions\n\nMCP is a [stateful protocol](https://modelcontextprotocol.io/specification/latest/basic/lifecycle):\nclients and servers negotiate protocol version and capabilities, and then communicate within a persistent session.\nTo support these sessions, `mcpc` can start a lightweight **bridge process** that maintains the connection and state.\nThis is more efficient than forcing every MCP command to reconnect and reinitialize,\nand enables long-term stateful sessions.\n\nThe sessions are given names prefixed with `@` (e.g. `@apify`),\nwhich then serve as unique reference in commands.\n\n```bash\n# Create a persistent session\nmcpc mcp.apify.com\\?tools=docs connect @apify\n\n# List all sessions and OAuth profiles\nmcpc\n\n# Run MCP commands in the session\nmcpc @apify tools-list\nmcpc @apify shell\n\n# Restart the session (kills and restarts the bridge process)\nmcpc @apify restart\n\n# Close the session, terminates bridge process\nmcpc @apify close\n\n# ...now session name \"@apify\" is forgotten and available for future use\n```\n\n### Session lifecycle\n\nThe sessions are persistent: metadata is saved in `~/.mcpc/sessions.json` file,\n[authentication tokens](#authentication) in OS keychain.\nThe `mcpc` bridge process keeps the session alive by sending periodic [ping messages](#ping) to the MCP server.\nStill, sessions can fail due to network disconnects, bridge process crash, or server dropping it.\n\n**Session states:**\n\n| State            | Meaning                                                                                       |\n|------------------|-----------------------------------------------------------------------------------------------|\n| 🟢 **`live`**    | Bridge process is running; server might or might not be operational                           |\n| 🟡 **`crashed`** | Bridge process crashed or was killed; will auto-restart on next use                           |\n| 🔴 **`expired`** | Server rejected the session (auth failed, session ID invalid); requires `close` and reconnect |\n\nHere's how `mcpc` handles various bridge process and server connection states:\n\n- While the **bridge process is running**:\n  - If **server positively responds** to pings, the session is marked 🟢 **`live`**, and everything is fine.\n  - If **server stops responding**, the bridge will keep trying to reconnect in the background.\n  - If **server negatively responds** to indicate `MCP-Session-Id` is no longer valid\n    or authentication permanently failed (HTTP 401 or 403),\n    the bridge process will flag the session as 🔴 **`expired`** and **terminate** to avoid wasting resources.\n    Any future attempt to use the session (`mcpc @my-session ...`) will fail.\n- If the **bridge process crashes**, `mcpc` will mark the session as 🟡 **`crashed`** on first use.\n  Next time you run `mcpc @my-session ...`, it will attempt to restart the bridge process.\n  - If bridge **restart succeeds**, everything starts again (see above).\n  - If bridge **restart fails**, `mcpc @my-session ...` returns error, and session remains marked 🟡 **`crashed`**.\n\nNote that `mcpc` never automatically removes sessions from the list.\nInstead, it keeps them flagged as 🟡 **`crashed`** or 🔴 **`expired`**,\nand any future attempts to use them will fail.\n\nTo **remove the session from the list**, you need to explicitly close it:\n\n```bash\nmcpc @apify close\n```\n\nYou can restart a session anytime, which kills the bridge process\nand opens new connection with new `MCP-Session-Id`, by running:\n\n```bash\nmcpc @apify restart\n```\n\n\n## Authentication\n\n`mcpc` supports all standard [MCP authorization methods](https://modelcontextprotocol.io/specification/latest/basic/authorization).\n\n### Anonymous access\n\nFor local servers (stdio) or remote servers (Streamable HTTP) which do not require credentials,\n`mcpc` can be used without authentication:\n\n```bash\n# One-shot command\nmcpc mcp.apify.com\\?tools=docs tools-list\n\n# Session command\nmcpc mcp.apify.com\\?tools=docs connect @test\nmcpc @test tools-list\n```\n\n### Bearer token authentication\n\nFor remote servers that require a Bearer token (but not OAuth), use the `--header` flag to pass the token.\nAll headers are stored securely in the OS keychain for the session, but they are **not** saved as reusable\n[OAuth profiles](#oauth-profiles). This means `--header` needs to be provided whenever\nrunning a one-shot command or connecting new session.\n\n```bash\n# One-time command with Bearer token\nmcpc --header \"Authorization: Bearer ${APIFY_TOKEN}\" https://mcp.apify.com tools-list\n\n# Create session with Bearer token (saved to keychain for this session only)\nmcpc --header \"Authorization: Bearer ${APIFY_TOKEN}\" https://mcp.apify.com connect @apify\n\n# Use the session (Bearer token is loaded from keychain automatically)\nmcpc @apify tools-list\n```\n\n### OAuth profiles\n\nFor OAuth-enabled remote MCP servers, `mcpc` implements the full OAuth 2.1 flow with PKCE, \nincluding `WWW-Authenticate` header discovery, server metadata discovery, client ID metadata documents, \ndynamic client registration, and automatic token refresh.\n\nThe OAuth authentication **always** needs to be initiated by the user calling the `login` command,\nwhich opens a web browser with login screen. `mcpc` never opens the web browser on its own.\n\nThe OAuth credentials to specific servers are securely stored as **authentication profiles** - reusable\ncredentials that allow you to:\n- Authenticate once, use credentials across multiple commands or sessions\n- Use different accounts (profiles) with the same server\n- Manage credentials independently from sessions\n\nKey concepts:\n- **Authentication profile**: Named set of OAuth credentials for a specific server (stored in `~/.mcpc/profiles.json` + OS keychain)\n- **Session**: Active connection to a server that may reference an authentication profile (stored in `~/.mcpc/sessions.json`)\n- **Default profile**: When `--profile` is not specified, `mcpc` uses the authentication profile named `default`\n\n**Example:**\n\n```bash\n# Login to server and save 'default' authentication profile for future use\nmcpc mcp.apify.com login\n\n# Use named authentication profile instead of 'default'\nmcpc mcp.apify.com login --profile work\n\n# Create two sessions using the two different credentials\nmcpc https://mcp.apify.com connect @apify-personal\nmcpc https://mcp.apify.com connect @apify-work --profile work\n\n# Both sessions now work independently\nmcpc @apify-personal tools-list  # Uses personal account\nmcpc @apify-work tools-list      # Uses work account\n\n# Re-authenticate existing profile (e.g., to refresh or change scopes)\nmcpc mcp.apify.com login --profile work\n\n# Delete \"default\" and \"work\" authentication profiles\nmcpc mcp.apify.com logout\nmcpc mcp.apify.com logout --profile work\n```\n\n### Authentication precedence\n\nWhen multiple authentication methods are available, `mcpc` uses this precedence order:\n\n1. **Command-line `--header` flag** (highest priority) - Always used if provided\n2. **Saved authentication profiles** - OAuth tokens from saved profile\n3. **Config file headers** - Headers from `--config` file for the server\n4. **No authentication** - Attempts unauthenticated connection\n\n\n`mcpc` automatically handles authentication based on whether you specify a profile:\n\n**When `--profile \u003cname\u003e` is specified:**\n\n1. **Profile exists for the server**: Use its stored credentials\n   - If authentication succeeds → Continue with command/session\n   - If authentication fails (expired/invalid) → Fail with an error\n2. **Profile doesn't exist**: Fail with an error\n\n**When no `--profile` is specified:**\n\n1. **`default` profile exists for the server**: Use its stored credentials\n   - If authentication succeeds → Continue with command/session\n   - If authentication fails (expired/invalid) → Fail with an error\n2. **`default` profile doesn't exist**: Attempt unauthenticated connection\n   - If server accepts (no auth required) → Continue without creating profile\n   - If server rejects with 401 + `WWW-Authenticate` → Fail with an error\n\nOn failure, the error message includes instructions on how to login and save the profile, so you know what to do.\n\nThis flow ensures:\n- You only authenticate when necessary\n- Credentials are never silently mixed up (personal → work) or downgraded (authenticated → unauthenticated)\n- You can mix authenticated sessions (with named profiles) and public access on the same server\n\n**Examples:**\n\n```bash\n# With specific profile - always authenticated:\n# - Uses 'work' if it exists\n# - Fails if it doesn't exist\nmcpc mcp.apify.com connect @apify-work --profile work\n\n# Without profile - opportunistic authentication:\n# - Uses 'default' if it exists\n# - Tries unauthenticated if 'default' doesn't exist\n# - Fails if the server requires authentication\nmcpc mcp.apify.com connect @apify-personal\n\n# Public server - no authentication needed:\nmcpc mcp.apify.com\\?tools=docs tools-list\n```\n\n\n## MCP proxy\n\nFor stronger isolation, `mcpc` can expose an MCP session under a new local proxy MCP server using the `--proxy` option.\nThe proxy forwards all MCP requests to the upstream server but **never exposes the original authentication tokens** to the client.\nThis is useful when you want to give someone or something MCP access without revealing your credentials.\nSee also [AI sandboxes](#ai-sandboxes).\n\n```bash\n# Human authenticates to a remote server\nmcpc mcp.apify.com login\n\n# Create authenticated session with proxy server on localhost:8080\nmcpc mcp.apify.com connect @open-relay --proxy 8080\n\n# Now any MCP client can connect to proxy like to a regular MCP server\n# The client has NO access to the original OAuth tokens or HTTP headers\n# Note: localhost/127.0.0.1 URLs default to http:// (no scheme needed)\nmcpc localhost:8080 tools-list\nmcpc 127.0.0.1:8080 tools-call search-actors keywords:=\"web scraper\"\n\n# Or create a new session from the proxy for convenience\nmcpc localhost:8080 connect @sandboxed\nmcpc @sandboxed tools-call search-actors keywords:=\"web scraper\"\n\n# Optionally protect proxy with bearer token for better security (stored in OS keychain)\nmcpc mcp.apify.com connect @secure-relay --proxy 8081 --proxy-bearer-token secret123\n# To use the proxy, caller needs to pass the bearer token in HTTP header\nmcpc localhost:8081 connect @sandboxed2 --header \"Authorization: Bearer secret123\"\n```\n\n**Proxy options for `connect` command:**\n\n| Option                         | Description                                                                    |\n|--------------------------------|--------------------------------------------------------------------------------|\n| `--proxy [host:]port`          | Start proxy MCP server. Default host: `127.0.0.1` (localhost only)             |\n| `--proxy-bearer-token \u003ctoken\u003e` | Requires `Authorization: Bearer \u003ctoken\u003e` header to access the proxy MCP server |\n\n**Security model:**\n\n- **Localhost by default**: `--proxy 8080` binds to `127.0.0.1` only, preventing network access\n- **Tokens hidden**: Original OAuth tokens and/or HTTP headers are never exposed to proxy clients\n- **Optional auth**: Use `--proxy-bearer-token` to add another layer of security\n- **Explicit opt-in**: Proxy only starts when `--proxy` flag is provided\n\n**Binding to network interfaces:**\n\n```bash\n# Localhost only (default, most secure)\nmcpc mcp.apify.com connect @relay --proxy 8080\n\n# Bind to all interfaces (allows network access - use with caution!)\nmcpc mcp.apify.com connect @relay --proxy 0.0.0.0:8080\n\n# Bind to specific interface\nmcpc mcp.apify.com connect @relay --proxy 192.168.1.100:8080\n```\n\nWhen listing sessions, proxy info is displayed prominently:\n\n```bash\nmcpc\n# @relay → https://mcp.apify.com (HTTP, OAuth: default) [proxy: 127.0.0.1:8080]\n```\n\n\n## AI agents\n\n`mcpc` is designed for CLI-enabled AI agents like Claude Code or Codex CLI, supporting both\ninteractive **tool calling** and **[code mode](https://www.anthropic.com/engineering/code-execution-with-mcp)**.\n\n**Tool calling mode** - Agents call `mcpc` commands to dynamically explore and interact with MCP servers,\nusing the default text output. This is similar to how MCP connectors in ChatGPT or Claude work,\nbut CLI gives you more flexibility and longer operation timeouts.\n\n```bash\n# Discover available tools\nmcpc @server tools-list\n\n# Get tool schema\nmcpc @server tools-get search\n\n# Call a tool\nmcpc @server tools-call search query:=\"hello world\"\n```\n\n**Code mode** - Once agents understand the server's capabilities, they can write shell scripts\nthat compose multiple `mcpc` commands with `--json` output. This can be\n[more accurate](https://www.anthropic.com/engineering/code-execution-with-mcp)\nand use fewer tokens than tool calling for complex workflows.\n\n```bash\n# AI-generated script using --json for structured data\nmcpc --json @apify tools-call search-actors keywords:=\"scraper\" \\\n  | jq '.content[0].text | fromjson | .items[0].id' \\\n  | xargs -I {} mcpc @apify tools-call get-actor actorId:=\"{}\"\n```\n\nWith [schema validation](#schema-validation), agents can ensure stability of integrations and faster failure recovery.\nAgents, make no harm!\n\nSee an [example](./docs/examples/company-lookup.sh) of an AI-generated shell script.\n\n### Scripting\n\nUse `--json` for machine-readable output (stdout on success, stderr on error).\nJSON output of all MCP commands follows the [MCP specification](https://modelcontextprotocol.io/specification/latest) strictly.\n\n```bash\n# Chain tools across sessions\nmcpc --json @apify tools-call search-actors keywords:=\"scraper\" \\\n  | jq '.content[0].text | fromjson | .items[0].id' \\\n  | xargs -I {} mcpc @apify tools-call get-actor actorId:=\"{}\"\n\n# Batch operations\nfor tool in $(mcpc --json @server tools-list | jq -r '.[].name'); do\n  mcpc --json @server tools-get \"$tool\" \u003e \"schemas/$tool.json\"\ndone\n```\n\nFor a complete example script, see [`docs/examples/company-lookup.sh`](./docs/examples/company-lookup.sh).\n\n### Schema validation\n\nValidate tool/prompt schemas using the `--schema` option to detect breaking changes early:\n\n```bash\n# Save expected schema\nmcpc --json @apify tools-get search-actors \u003e expected.json\n\n# Validate before calling (fails if schema changed incompatibly)\nmcpc @apify tools-call search-actors --schema expected.json keywords:=\"test\"\n```\n\nAvailable schema validation modes (`--schema-mode`):\n- `compatible` (default)\n  - Input schema: new optional fields OK, required fields must have the same type.\n  - Output schema: new fields OK, removed required fields cause error.\n- `strict` - Both input and output schemas must match exactly, including all fields, types, and descriptions\n- `ignore` - Skip validation completely (YOLO)\n\n### AI sandboxes\n\nTo ensure AI coding agents don't perform destructive actions or leak credentials,\nit's always a good idea to run them in a code sandbox with limited access to your resources.\n\nThe [proxy MCP server](#mcp-proxy) feature provides a security boundary for AI agents:\n\n1. **Human creates authentication profile**: `mcpc mcp.apify.com login --profile ai-access`\n2. **Human creates session**: `mcpc mcp.apify.com connect @ai-sandbox --profile ai-access --proxy 8080`\n3. **AI runs inside a sandbox**: If sandbox has access limited to `localhost:8080`,\n   it can only interact with the MCP server through the `@ai-sandbox` session,\n   without access to the original OAuth credentials, HTTP headers, or `mcpc` configuration.\n\nThis ensures AI agents operate only with pre-authorized credentials, preventing unauthorized access to MCP servers.\nThe human controls which servers the AI can access and with what permissions (OAuth scopes).\n\n**IMPORTANT:** Beware that MCP proxy will not make an insecure MCP server secure.\nLocal stdio servers will still have access to your local system, and HTTP servers to provided auth credentials,\nand both can easily perform destructive actions or leak credentials on their own, or let MCP clients do such actions.\n**Always use only trusted local and remote MCP servers and limit their access to the necessary minimum.**\n\n### Agent skills\n\nTo help Claude Code use `mcpc`, you can install this [Claude skill](./docs/claude-skill/README.md):\n\n\u003c!-- TODO: Add also AGENTS.md, GitHub skills etc. --\u003e\n\n## MCP support\n\n`mcpc` is built on the official [MCP SDK for TypeScript](https://github.com/modelcontextprotocol/typescript-sdk) and supports most [MCP protocol features](https://modelcontextprotocol.io/specification/latest).\n\n### Transport\n\n- **stdio**: Direct bidirectional JSON-RPC communication over\n  stdio server from the [config file](#mcp-server-config-file).\n- **Streamable HTTP**: Fully supported.\n- **HTTP with SSE** (deprecated): Legacy mode, not supported.\n\n### Authorization\n\n- [Anonymous access](#anonymous-access)\n- [HTTP header authorization](#bearer-token-authentication)\n- [OAuth 2.1](#oauth-profiles)\n\n### MCP session\n\nThe bridge process manages the full MCP session lifecycle:\n- Performs initialization handshake (`initialize` → `initialized`)\n- Negotiates protocol version and capabilities\n- Fetches server-provided `instructions`\n- Maintains persistent HTTP connections with bidirectional streaming, or stdio bidirectional pipe to subprocess\n- Handles `MCP-Protocol-Version` and `MCP-Session-Id` headers automatically\n- Handles multiple concurrent requests\n- Recovers transparently from network disconnections and bridge process crashes\n\n### MCP feature support\n\n| **Feature**                                        | **Status**                         |\n|:---------------------------------------------------|:-----------------------------------|\n| 📖 [**Instructions**](#server-instructions)        | ✅ Supported                        |\n| 🔧 [**Tools**](#tools)                             | ✅ Supported                        |\n| 💬 [**Prompts**](#prompts)                         | ✅ Supported                        |\n| 📦 [**Resources**](#resources)                     | ✅ Supported                        |\n| 📝 [**Logging**](#server-logs)                     | ✅ Supported                        |\n| 🔔 [**Notifications**](#list-change-notifications) | ✅ Supported                        |\n| 📄 [**Pagination**](#pagination)                   | ✅ Supported                        |\n| 🏓 [**Ping**](#ping)                               | ✅ Supported                        |\n| ⏳ **Async tasks**                                  | 🚧 Planned                         |\n| 📁 **Roots**                                       | 🚧 Planned                         |\n| ❓ **Elicitation**                                  | 🚧 Planned                         |\n| 🔤 **Completion**                                  | 🚧 Planned                         |\n| 🤖 **Sampling**                                    | ❌ Not applicable (no LLM access)   |\n\n#### Server instructions\n\nMCP servers can provide instructions describing their capabilities and usage. These are displayed when you connect to a server or run the `help` command:\n\n```bash\n# Show server info, capabilities, and instructions (both commands behave the same)\nmcpc @apify\nmcpc @apify help\n\n# JSON mode\nmcpc @apify --json\n```\n\nIn [JSON mode](#json-mode), the resulting object adheres\nto [`InitializeResult`](https://modelcontextprotocol.io/specification/latest/schema#initializeresult) object schema,\nand includes the `_mcpc` field with relevant server/session metadata.\n\n```json\n{\n  \"_mcpc\": {\n    \"sessionName\": \"@apify\",\n    \"profileName\": \"default\",\n    \"server\": {\n      \"url\": \"https://mcp.apify.com\"\n    },\n    \"notifications\": {\n      \"tools\": { \"listChangedAt\": \"2026-01-01T00:42:58.049Z\" }\n    }\n  },\n  \"protocolVersion\": \"2025-06-18\",\n  \"capabilities\": {\n    \"logging\": {},\n    \"prompts\": {},\n    \"resources\": {},\n    \"tools\": { \"listChanged\": true }\n  },\n  \"serverInfo\": {\n    \"name\": \"apify-mcp-server\",\n    \"version\": \"1.0.0\"\n  },\n  \"instructions\": \"Apify is the largest marketplace of tools for web scraping...\"\n}\n```\n\n#### Tools\n\nList, inspect, and call server-provided tools:\n\n```bash\n# List available tools (only names and attributes - useful for dynamic discovery)\nmcpc @apify tools-list\n\n# List available tools (full details including input/output args and description)\nmcpc @apify tools-list --full\n\n# Get tool schema with full details\nmcpc @apify tools-get search-actors\n\n# Call a tool with arguments\nmcpc @apify tools-call search-actors keywords:=\"web scraper\"\n\n# Pass complex JSON arguments\nmcpc @apify tools-call create-task '{\"name\": \"my-task\", \"options\": {\"memory\": 1024}}'\n\n# Load arguments from stdin\ncat data.json | mcpc @apify tools-call bulk-import\n```\n\n#### Prompts\n\nList and retrieve server-defined prompt templates:\n\n```bash\n# List available prompts\nmcpc @apify prompts-list\n\n# Get a prompt with arguments\nmcpc @apify prompts-get analyze-website url:=https://example.com\n```\n\n\u003c!-- TODO: Add example of prompt templates --\u003e\n\n#### Resources\n\nAccess server-provided data sources by URI:\n\n```bash\n# List available resources\nmcpc @apify resources-list\n\n# Read a resource\nmcpc @apify resources-read \"file:///config.json\"\n\n# Subscribe to resource changes (in shell mode)\nmcpc @apify resources-subscribe \"https://api.example.com/data\"\n\n# List resource templates\nmcpc @apify resources-templates-list\n```\n\n#### List change notifications\n\nWhen connected via a [session](#sessions), `mcpc` automatically handles `list_changed`\nnotifications for tools, resources, and prompts.\nThe bridge process tracks when each notification type was last received.\nIn [shell mode](#interactive-shell), notifications are displayed in real-time.\nThe timestamps are available in JSON output of `mcpc \u003ctarget\u003e --json` under the `_mcpc.notifications`\nfield - see [Server instructions](#server-instructions).\n\n#### Server logs\n\n`mcpc` supports server logging settings (`logging/setLevel`) and log messages (`notifications/message`).\nLog messages are printed to bridge log or stderr, subject to [verbosity level](#verbose-mode).\n\nYou can instruct MCP servers to adjust their [logging level](https://modelcontextprotocol.io/specification/latest/server/utilities/logging)\nusing the `logging-set-level` command:\n\n```bash\n# Set server log level to debug for detailed output\nmcpc @apify logging-set-level debug\n\n# Reduce server logging to only errors\nmcpc @apify logging-set-level error\n```\n\nNote that this sets the logging level on the **server side**.\nThe actual log output depends on the server's implementation.\n\n#### Pagination\n\nMCP servers may return paginated results for list operations\n(`tools-list`, `resources-list`, `prompts-list`, `resources-templates-list`).\n`mcpc` handles this automatically and always fetches all available pages using the `nextCursor`\ntoken - you always get the complete list without manual iteration. Keep it simple.\n\n#### Ping\n\nSessions automatically send periodic pings to keep the [connection alive](#session-lifecycle) and detect failures early.\nSend a ping to check if a server connection is alive:\n\n```bash\n# Ping a session and measure round-trip time\nmcpc @apify ping\nmcpc @apify ping --json\n```\n\n## Configuration\n\nYou can configure `mcpc` using a config file, environment variables, or command-line flags.\n\n**Precedence** (highest to lowest):\n1. Command-line flags (including `--config` option)\n2. Environment variables\n3. Built-in defaults\n\n### MCP server config file\n\n`mcpc` supports the [\"standard\"](https://gofastmcp.com/integrations/mcp-json-configuration)\nMCP server JSON config file, compatible with Claude Desktop, VS Code, and other MCP clients.\nYou can point to an existing config file with `--config`:\n\n```bash\n# One-shot command to an MCP server configured in Visual Studio Code\nmcpc --config .vscode/mcp.json apify tools-list\n\n# Open a session to a server specified in the custom config file\nmcpc --config .vscode/mcp.json apify connect @my-apify\n```\n\n**Example MCP config JSON file:**\n\n```json\n{\n  \"mcpServers\": {\n    \"apify\": {\n      \"url\": \"https://mcp.apify.com\",\n      \"headers\": {\n        \"Authorization\": \"Bearer ${APIFY_TOKEN}\"\n      }\n    },\n    \"filesystem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"],\n      \"env\": {\n        \"DEBUG\": \"mcp:*\"\n      }\n    },\n    \"local-package\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/server.js\"]\n    }\n  }\n}\n```\n\n**Server configuration properties:**\n\nFor **Streamable HTTP servers:**\n- `url` (required) - MCP server endpoint URL\n- `headers` (optional) - HTTP headers to include with requests\n- `timeout` (optional) - Request timeout in seconds\n\nFor **stdio servers:**\n- `command` (required) - Command to execute (e.g., `node`, `npx`, `python`)\n- `args` (optional) - Array of command arguments\n- `env` (optional) - Environment variables for the process\n\n**Using servers from config file:**\n\nWhen `--config` is provided, you can reference servers by name:\n\n```bash\n# With config file, use server names directly\nmcpc --config .vscode/mcp.json filesystem tools-list\n\n# Create a named session from server in config\nmcpc --config .vscode/mcp.json filesystem connect @fs\nmcpc @fs tools-call search\n```\n\n**Environment variable substitution:**\n\nConfig files support environment variable substitution using `${VAR_NAME}` syntax:\n\n```json\n{\n  \"mcpServers\": {\n    \"secure-server\": {\n      \"url\": \"https://mcp.apify.com\",\n      \"headers\": {\n        \"Authorization\": \"Bearer ${API_TOKEN}\",\n        \"X-User-ID\": \"${USER_ID}\"\n      }\n    }\n  }\n}\n```\n\n### Saved state\n\n`mcpc` saves its state to `~/.mcpc/` directory (unless overridden by `MCPC_HOME_DIR`), in the following files:\n\n- `~/.mcpc/sessions.json` - Active sessions with references to authentication profiles (file-locked for concurrent access)\n- `~/.mcpc/profiles.json` - Authentication profiles (OAuth metadata, scopes, expiry)\n- `~/.mcpc/bridges/` - Unix domain socket files for each bridge process\n- `~/.mcpc/logs/bridge-*.log` - Log files for each bridge process\n- OS keychain - Sensitive credentials (OAuth tokens, bearer tokens, client secrets)\n\n### Environment variables\n\n- `MCPC_HOME_DIR` - Directory for session and authentication profiles data (default is `~/.mcpc`)\n- `MCPC_VERBOSE` - Enable verbose logging (set to `1`, `true`, or `yes`, case-insensitive)\n- `MCPC_JSON` - Enable JSON output (set to `1`, `true`, or `yes`, case-insensitive)\n- `HTTPS_PROXY` / `https_proxy` / `HTTP_PROXY` / `http_proxy` - Proxy URL for outbound connections (e.g. `http://proxy.example.com:8080`); `HTTPS_PROXY` takes precedence\n- `NO_PROXY` / `no_proxy` - Comma-separated list of hostnames/IPs to bypass the proxy (e.g. `localhost,127.0.0.1`)\n\n### Cleanup\n\nYou can clean up the `mcpc` state and data using the `--clean` option:\n\n```bash\n# Safe non-destructive cleanup: remove expired sessions, delete old orphaned logs\nmcpc --clean\n\n# Clean specific resources (comma-separated)\nmcpc --clean=sessions      # Kill bridges, delete all sessions\nmcpc --clean=profiles      # Delete all authentication profiles\nmcpc --clean=logs          # Delete all log files\nmcpc --clean=sessions,logs # Clean multiple resource types\n\n# Nuclear option: remove everything\nmcpc --clean=all           # Delete all sessions, profiles, logs, and sockets\n```\n\n## Security\n\n`mcpc` follows [MCP security best practices](https://modelcontextprotocol.io/specification/latest/basic/security_best_practices).\nMCP enables arbitrary tool execution and data access - treat servers like you treat shells:\n\n- Use least-privilege tokens/headers\n- Only use trusted servers!\n- Audit tools before running them\n\n### Credential protection\n\n| What                   | How                                             |\n|------------------------|-------------------------------------------------|\n| **OAuth tokens**       | Stored in OS keychain, never on disk            |\n| **HTTP headers**       | Stored in OS keychain per-session               |\n| **Bridge credentials** | Passed via Unix socket IPC, kept in memory only |\n| **Process arguments**  | No secrets visible in `ps aux`                  |\n| **Config files**       | Contain only metadata, never tokens             |\n| **File permissions**   | `0600` (user-only) for all config files         |\n\n### Network security\n\n- HTTPS enforced for remote servers (auto-upgraded from HTTP)\n- OAuth callback binds to `127.0.0.1` only\n- Credentials never logged, even in verbose mode\n\n### AI security\n\nSee [AI sandboxes](#ai-sandboxes) for details.\n\n## Errors\n\n`mcpc` provides clear error messages for common issues:\n\n- **Connection failures**: Displays transport-level errors with retry suggestions\n- **Session timeouts**: Automatically attempts to reconnect or prompts for session recreation\n- **Invalid commands**: Shows available commands and correct syntax\n- **Tool execution errors**: Returns server error messages with context\n- **Bridge crashes**: Detects and cleans up orphaned processes, offers restart\n\n### Exit codes\n\n- `0` - Success\n- `1` - Client error (invalid arguments, command not found, etc.)\n- `2` - Server error (tool execution failed, resource not found, etc.)\n- `3` - Network error (connection failed, timeout, etc.)\n- `4` - Authentication error (invalid credentials, forbidden, etc.)\n\n### Verbose mode\n\nTo see what's happening, enable detailed logging with `--verbose`.\n\n```bash\nmcpc --verbose @apify tools-list\n```\n\nThis causes `mcpc` to print detailed debug messages to stderr.\n\n### Logs\n\nThe background bridge processes log to `~/.mcpc/logs/bridge-@\u003csession\u003e.log`.\nThe main `mcpc` process doesn't save log files, but supports [verbose mode](#verbose-mode).\n`mcpc` automatically rotates log files: keep last 10MB per session, max 5 files.\n\n### Troubleshooting\n\n**\"Cannot connect to bridge\"**\n- Bridge may have crashed. Try: `mcpc @\u003csession-name\u003e tools-list` to restart the bridge\n- Check bridge is running: `ps aux | grep -e 'mcpc-bridge' -e '[m]cpc/dist/bridge'`\n- Check socket exists: `ls ~/.mcpc/bridges/`\n\n**\"Session not found\"**\n- List existing sessions: `mcpc`\n- Create new session if expired: `mcpc @\u003csession-name\u003e close` and `mcpc \u003ctarget\u003e connect @\u003csession-name\u003e`\n\n**\"Authentication failed\"**\n- List saved OAuth profiles: `mcpc`\n- Re-authenticate: `mcpc \u003cserver\u003e login [--profile \u003cname\u003e]`\n- For bearer tokens: provide `--header \"Authorization: Bearer ${TOKEN}\"` again\n\n\n## Development\n\nThe initial version of `mcpc` was developed and [launched by Jan Curn](https://x.com/jancurn/status/2007144080959291756) of [Apify](https://apify.com)\nwith the help of Claude Code, during late nights over Christmas 2025 in North Beach, San Francisco.\n\nSee [CONTRIBUTING](./CONTRIBUTING.md) for development setup, architecture overview, and contribution guidelines.\n\n## Related work\n\n- MCP CLI clients\n  - https://github.com/chrishayuk/mcp-cli\n  - https://github.com/wong2/mcp-cli\n  - https://github.com/f/mcptools\n  - https://github.com/adhikasp/mcp-client-cli\n  - https://github.com/mattzcarey/cloudflare-mcp\n  - https://github.com/thellimist/clihub (see https://news.ycombinator.com/item?id=47157398)\n  - https://github.com/EstebanForge/mcp-cli-ent\n  - https://github.com/assimelha/cmcp\n- Code mode\n  - https://blog.cloudflare.com/code-mode/\n  - https://www.anthropic.com/engineering/code-execution-with-mcp\n  - https://github.com/steipete/mcporter\n- Dynamic tool discovery\n  - https://www.anthropic.com/engineering/advanced-tool-use\n    - https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool\n  - https://cursor.com/blog/dynamic-context-discovery\n  - https://github.com/philschmid/mcp-cli (https://www.philschmid.de/mcp-cli)\n- Other\n  - https://github.com/TeamSparkAI/mcpGraph\n\n\n## License\n\nApache-2.0 - see [LICENSE](./LICENSE) for details.\n\n","funding_links":[],"categories":["TypeScript","📚 Projects (2474 total)"],"sub_categories":["MCP Servers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapify%2Fmcp-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapify%2Fmcp-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapify%2Fmcp-cli/lists"}