mcp-cli
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-clilist the available CLI commands"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@qodalis/mcp-cli
A resilient Model Context Protocol server that gives Claude Code a Qodalis CLI server: its CLI commands, files, data explorer, jobs and plugin tools.
Every Qodalis CLI server (.NET, Node or Python) can expose an MCP endpoint at
<server>/api/qcli/mcp. mcp-cli runs on your machine as a stdio MCP server
and proxies to that endpoint: Claude Code sees exactly the server's tools, with
the permissions of the account you configure. It handles sign-in, reconnects
after network drops and lets you narrow what the assistant may use.
Highlights
No tool-specific code. Tools come from the server's
tools/listand are passed through unchanged (names, schemas, annotations); calls are forwarded. New commands on the server show up without updating the proxy.Token or password. Use an API token (
QCLI_TOKEN), or sign in withQCLI_USER/QCLI_PASSWORD; an expired session is renewed automatically on the next call.Read-only mode (
QCLI_READ_ONLY=true) exposes only the tools the server marks read-only, and refuses calls to anything else.Client-side allow and deny lists (
QCLI_TOOLS,QCLI_EXCLUDE, trailing*allowed) on top of the server's own permissions.Self-healing connection. It connects on first use, never caches a failed connect, retries once when the connection drops, and fails fast (8 s) when the server is unreachable, with a message that says what to check.
Clear errors: a rejected token, MCP not enabled on the server, a missing permission or an unreachable host each come back as one actionable sentence.
Related MCP server: Claude Code Manager WAN
Quick start
npx -y @qodalis/mcp-cli --helpThe server must have MCP enabled (mcp option; see
MCP endpoint).
Default ports: .NET 8046, Node 8047, Python 8048.
Claude Code
claude mcp add qcli -- npx -y @qodalis/mcp-clithen set the environment in ~/.claude.json:
{
"mcpServers": {
"qcli": {
"command": "npx",
"args": ["-y", "@qodalis/mcp-cli"],
"env": {
"QCLI_URL": "http://localhost:8047",
"QCLI_TOKEN": "qcli_pat_..."
}
}
}
}or sign in with a user name and password instead of a token:
"env": {
"QCLI_URL": "http://localhost:8047",
"QCLI_USER": "ops",
"QCLI_PASSWORD": "********"
}The same in one command, with -e flags:
claude mcp add qcli -e QCLI_URL=http://localhost:8047 -e QCLI_TOKEN=qcli_pat_... -- npx -y @qodalis/mcp-cliAdd --scope user to make it available in every project. With
--scope project the entry goes into the project's .mcp.json, which is
usually committed: keep the secret out of it with
"QCLI_TOKEN": "${QCLI_TOKEN}" and set the variable in your shell. A .env
file works too:
{ "command": "npx", "args": ["-y", "@qodalis/mcp-cli", "--env-file", "/path/to/.env"] }Pin a version in shared configs (@qodalis/mcp-cli@0.1.0) so an upgrade is a
deliberate change.
Getting a token
In the web CLI connected to the server (users plugin), signed in as the account the assistant should act as:
token create claude --expires=90
# token create claude --permissions=commands:execute,files:read (narrower scope)The token (qcli_pat_…) is shown once. Without the web CLI, sign in and create
one with curl:
SESSION=$(curl -s http://localhost:8047/api/v1/qcli/sessions \
-H 'Content-Type: application/json' -d '{"username":"ops","password":"..."}' | jq -r .token)
curl -s http://localhost:8047/api/v1/qcli/tokens -H "Authorization: Bearer $SESSION" \
-H 'Content-Type: application/json' -d '{"name":"claude","expiresInDays":90}' | jq -r .token
curl -s -X DELETE http://localhost:8047/api/v1/qcli/sessions/current -H "Authorization: Bearer $SESSION"A server without the users plugin protects its endpoint with a static token
(its mcp.token option): put that value in QCLI_TOKEN. If it sets none, the
endpoint is open and no auth variable is needed.
Configuration
Every setting is an environment variable. QODALIS_CLI_* names are accepted as
aliases for every key.
Variable | Default | Description |
| required | Server base URL, e.g. |
| none | API token ( |
| none | Sign in with this user name instead of a token (needs |
| none | Password for |
|
| Expose and allow only tools annotated |
| all | Comma-separated allow-list of tool names; a trailing |
| none | Comma-separated deny-list, same syntax, applied after |
|
| Milliseconds to wait for the TCP/TLS connection before reporting the server unreachable. |
|
| Milliseconds a single request ( |
|
| Accept a self-signed TLS certificate. |
| none | Path to a |
Set either QCLI_TOKEN or QCLI_USER + QCLI_PASSWORD, not both.
Tools
The tools are whatever the server exposes to your account. A typical server offers:
Tools | Available when |
| always: version, enabled features |
one tool per CLI command ( | always |
| the server's filesystem API is enabled |
| the data explorer is enabled |
| the jobs plugin is installed |
plugin tools | a server plugin contributes them |
Each one is limited by the account's permissions on the server (for example
commands:execute, files:read / files:write, data:query, jobs:manage),
and by the token's scope when it was created with --permissions.
Read-only mode
With QCLI_READ_ONLY=true the proxy lists only the tools the server annotates
readOnlyHint: true (such as server_info, fs_list, fs_read,
data_schema, jobs_list) and refuses calls to any other tool before they
reach the server. Command tools carry no read-only annotation, so they are
hidden in this mode; add the ones you want with a separate, non-read-only entry
and QCLI_TOOLS.
The filter is defence in depth. The real boundary is the account: give the assistant a user (or a token scope) with only the permissions it should have.
Several servers
Add one entry per server (and per access level) with a distinct name:
{
"mcpServers": {
"qcli-dev": {
"command": "npx",
"args": ["-y", "@qodalis/mcp-cli"],
"env": { "QCLI_URL": "http://localhost:8047", "QCLI_TOKEN": "qcli_pat_dev..." }
},
"qcli-prod": {
"command": "npx",
"args": ["-y", "@qodalis/mcp-cli"],
"env": {
"QCLI_URL": "https://cli.example.com",
"QCLI_TOKEN": "qcli_pat_prod...",
"QCLI_READ_ONLY": "true"
}
},
"qcli-prod-jobs": {
"command": "npx",
"args": ["-y", "@qodalis/mcp-cli"],
"env": {
"QCLI_URL": "https://cli.example.com",
"QCLI_TOKEN": "qcli_pat_prod...",
"QCLI_TOOLS": "jobs_*,server_info",
"QCLI_EXCLUDE": "jobs_cancel"
}
}
}
}Troubleshooting
claude mcp list shows whether each server connects; inside a session /mcp
shows its status and tools and lets you reconnect. The proxy logs to stderr
(claude --debug shows it).
Message | What to do |
| Create a new token ( |
| Check the credentials; the account may be disabled or locked out after failed sign-ins. |
| The account lacks |
| Turn on the server's |
| The server is down, the URL or port is wrong, or the VPN is disconnected. Retry the call once it is back: the proxy reconnects by itself. |
| A slow command; raise |
A tool is missing | The account (or token scope) lacks its permission, the feature is not enabled on the server, or |
| The |
How reconnection works
The proxy connects to the endpoint on the first
tools/listortools/call, not at startup, so Claude Code starts even when the server is down.A failed connect is not cached: the next call tries again.
A connection-level error (refused, reset, socket closed, DNS failure) drops the connection and retries the request once on a fresh one. A connect timeout is not retried, so an unreachable host fails within
QCLI_CONNECTION_TIMEOUT.With
QCLI_USER/QCLI_PASSWORD, a 401 signs in again and retries once.The tool list is cached for 60 s; a call to a tool the proxy does not know yet refreshes it first, so new server commands work without a restart.
Security notes
Tokens and passwords are read from the environment, sent only to
QCLI_URL, and never written to logs or tool results.Prefer an API token with a narrow
--permissionsscope and an expiry over a password; revoke it withtoken revoke <id>when it is no longer needed.Use
https://for anything butlocalhost.QCLI_TRUST_CERT=truedisables certificate verification for this process; use it only for self-signed certificates you control.Nothing is written to stdout except the MCP protocol stream.
See SECURITY.md for reporting vulnerabilities.
Library use
The pieces are exported for embedding:
import { createProxyServer, loadConfig, RemoteServer } from '@qodalis/mcp-cli';
const config = loadConfig(process.env);
const remote = new RemoteServer(config, { clientInfo: { name: 'my-app', version: '1.0.0' } });
const server = createProxyServer(remote, config); // a low-level MCP Server: connect any transportDevelopment
npm install
npm run build
npm test # unit tests and stdio end-to-end tests against a fake server (build first)
npm run typecheck
npm run check-format
npm run dev -- --env-file .env # run from sourceSee CONTRIBUTING.md.
License
MIT © Qodalis Solutions SRL
This server cannot be deployed
Related MCP Connectors
Work on your own computers from Claude or ChatGPT: run commands, edit and search files.
Use your Mac, Windows or Linux computer from ChatGPT, Claude or Codex: files, commands, documents.
Termalin's hosted MCP server. Claude, ChatGPT or any MCP client runs commands, moves files over SFTP, queries databases and reads server metrics and monitoring alerts on your servers, keylessly through Termalin Connectors: no SSH key is handed over and no inbound port is opened. Per-host command policy and an audit log. Needs a termal.in Pro or Team account (new accounts start with a 14-day Pro trial).
Source-checked CLI guides and model-aware planning for Claude Code, Codex, and Grok Build.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to interact programmatically with Claude Code CLI, managing sessions, streaming outputs, and handling permission requests.77 npm1MIT
- FlicenseNot gradedqualityCmaintenanceEnables ISLI agents and MCP clients to dispatch natural-language coding and terminal tasks to a locally-installed Claude Code CLI, supporting both one-shot execution and persistent sessions with workspace and security controls.-
- AlicenseNot gradedqualityAmaintenanceLets Codex delegate coding and repository work to an installed Claude Code CLI with permission-aware inspect/write access, model and effort selection, resumable and cloud-attached sessions, and durable synchronous or asynchronous jobs.MIT
- AlicenseAqualityBmaintenanceBridges MCP clients such as Claude Code and Cursor to independent Codex app-server sessions, letting them start, poll, steer, review, compact, cancel, and answer prompts for asynchronous Codex tasks over local stdio or a remote authenticated WebSocket. Runs read-only by default, with workspace-write sandboxing only when a user explicitly enables it, and reports job status, model listing, and progress back to the client.101MIT