A CLI client for Model Context Protocol (MCP) servers that supports two OAuth 2.0 client authentication strategies:
- CIMD (Client ID Metadata Document) — the client's HTTPS metadata URL is used directly as
client_id. The authorization server fetches your public key from that URL; no prior registration is required. - DCR (Dynamic Client Registration, RFC 7591) — the client registers itself with the server's registration endpoint at runtime and receives a
client_id(and optionally aclient_secret).
Tokens and registration data are cached locally (~/.config/mcp-console/) so subsequent connections are instant.
- Node.js ≥ 20
- npm ≥ 9
# From source
git clone <repo-url>
cd mcp-console
npm install
npm run build
npm link # makes mcp-console available globally-
Register — generate an RSA key pair and a CIMD metadata document:
mcp-console register \ --client-id-url https://example.com/my-mcp-client.json \ --client-name "My MCP Client"This writes
cimd-client-metadata.jsonto the current directory and saves your keys to~/.config/mcp-console/keys.json. -
Host the metadata file — make the generated JSON reachable at the URL you provided. It must be served over HTTPS and be publicly accessible.
-
Connect — open an interactive session with an MCP server:
mcp-console connect https://api.example.com/mcp
The first time you connect, a browser window opens for OAuth authorization. Tokens are cached automatically.
No registration step required. Just connect and the client registers itself on the fly:
mcp-console --auth dcr connect https://api.example.com/mcpThe --auth flag is a global option — place it before the subcommand:
mcp-console --auth <mode> <command> [args]| Mode | Behaviour |
|---|---|
auto |
(default) Checks per-server history. If a clientIdUrl is configured, tries CIMD first; falls back to DCR automatically on invalid_client. |
cimd |
Always use CIMD. Requires register to have been run first. |
dcr |
Always use Dynamic Client Registration. Ignores any configured clientIdUrl. |
Once a mode is resolved automatically, it is saved per-server in ~/.config/mcp-console/servers/. Subsequent connects reuse the saved mode without re-probing.
Generate an RSA key pair (RS256, 2048-bit) and a CIMD client metadata document.
mcp-console register --client-id-url <url> [options]| Option | Default | Description |
|---|---|---|
--client-id-url <url> |
(required) | HTTPS URL where the metadata document will be hosted. Used as the OAuth client_id. |
--client-name <name> |
mcp-console |
Human-readable name included in the metadata. |
--redirect-uri <uri> |
http://localhost:3000/callback |
OAuth redirect URI. |
--out <path> |
cimd-client-metadata.json |
Output file path for the metadata document. |
--regenerate-keys |
— | Force regeneration of the RSA key pair even if one already exists. |
After running, host the generated file at the URL you specified. The authorization server will fetch it when verifying your identity.
Connect to an MCP server and open an interactive REPL.
mcp-console [--auth <mode>] connect <server-url> [--port <number>]| Option | Default | Description |
|---|---|---|
--port <number> |
3000 |
Local port for the OAuth callback server. |
Inside the REPL you can list and call tools, list and read resources, and list and get prompts — all through an arrow-key menu.
Delete all stored configuration for an MCP server — tokens, client registration, and resolved auth mode.
mcp-console forget <server-url>After running, the next connect to that server will go through the full OAuth authorization flow again, as if connecting for the first time.
Example:
mcp-console forget https://api.example.com/mcpmcp-console [--auth <mode>] tools list <server-url> [--port <number>]Prints all tools exposed by the server, including their names, descriptions, and argument names.
mcp-console [--auth <mode>] tools call <server-url> <tool-name> [--args <json>] [--port <number>]| Option | Default | Description |
|---|---|---|
--args <json> |
{} |
Tool arguments as a JSON object. |
Example:
mcp-console tools call https://api.example.com/mcp get_weather \
--args '{"location":"Madrid"}'mcp-console [--auth <mode>] resources list <server-url> [--port <number>]mcp-console [--auth <mode>] resources read <server-url> <uri> [--port <number>]Text resources are printed to stdout. Binary resources (blobs) are written as raw bytes — suitable for piping:
mcp-console resources read https://api.example.com/mcp file://image.png > image.pngmcp-console [--auth <mode>] prompts list <server-url> [--port <number>]mcp-console [--auth <mode>] prompts get <server-url> <prompt-name> [--args <json>] [--port <number>]| Option | Default | Description |
|---|---|---|
--args <json> |
{} |
Prompt arguments as a JSON object. |
~/.config/mcp-console/
├── config.json # Global config (clientIdUrl, clientName, …)
├── keys.json # RSA private + public key (JWK format)
├── clients/
│ └── <hash>.json # DCR-registered client_id / client_secret per server
├── tokens/
│ └── <hash>.json # Cached access + refresh tokens per server
└── servers/
└── <hash>.json # Resolved auth mode per server (avoids re-probing)
<hash> is the first 16 characters of the SHA-256 hash of the server URL.
Each MCP server you connect to gets its own set of files under ~/.config/mcp-console/, keyed by a 16-character SHA-256 hash of the server URL.
Stores the resolved authentication mode so subsequent connects skip re-probing.
{
"authMode": "cimd"
}| Field | Values | Description |
|---|---|---|
authMode |
cimd | dcr |
Written after the first successful OAuth flow or auto-detection. |
Stores the OAuth client identity obtained during registration.
{
"client_id": "https://example.com/my-mcp-client.json",
"client_secret": "optional-secret-for-dcr-clients"
}| Field | Description |
|---|---|
client_id |
For CIMD: your clientIdUrl. For DCR: the server-assigned ID. |
client_secret |
Only present for DCR when the server issues one. |
Caches the OAuth access and refresh tokens so reconnects are instant.
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600,
"expires_at": 1748000000,
"refresh_token": "eyJ...",
"scope": "mcp"
}| Field | Description |
|---|---|
access_token |
Bearer token sent with every MCP request. |
expires_at |
Unix timestamp (seconds). The client uses a 60-second buffer before expiry to trigger a refresh. |
refresh_token |
Used to obtain a new access token without re-authorising in the browser. |
To force re-authentication with a specific server, delete or empty its tokens/<hash>.json file.
npm install # install dependencies
npm run dev -- <args> # run from source with tsx (e.g. npm run dev -- --help)
npm run typecheck # type-check without building
npm run build # compile to dist/npm test # run all tests once
npm run test:watch # re-run tests on file changes
npm run test:coverage # run tests and generate a coverage reportTests are co-located with their source files (src/**/*.test.ts) and run with Vitest.