qwen-cli-mcp
Click on "Install 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., "@qwen-cli-mcpAsk Qwen to review the auth refactor in src/auth.ts and suggest fixes"
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.
qwen-cli-mcp
MCP server that delegates coding tasks to your locally installed Qwen Code CLI.
It wraps the real qwen binary instead of bundling its own copy of the agent, so every call
inherits your qwen auth, models, MCP servers and settings. Nothing about your model stack is
duplicated here, and the server does not drift when you upgrade qwen.
Sibling of pi-cli-mcp — same architecture, same principles, qwen behind the wheel. The authoritative design document is SPEC.md.
Use it when your primary agent (Claude Code, Cursor, pi itself, any MCP client) should hand work to qwen: a second opinion from a different model family, an investigation you want kept out of the main context window, or parallel work.
Install
npx -y qwen-cli-mcp # no install
npm install -g qwen-cli-mcp # or globalRequires Node ≥ 22 and a working qwen on PATH (npm i -g @qwen-code/qwen-code).
Claude Code
claude mcp add-json qwen -s user '{
"type": "stdio",
"command": "npx",
"args": ["-y", "qwen-cli-mcp"],
"timeout": 3600000
}'
claude mcp list | grep '^qwen:' # expect: ✔ ConnectedThe generous timeout matters: a real delegated task can run for minutes.
Any other MCP client
{
"mcpServers": {
"qwen": { "command": "npx", "args": ["-y", "qwen-cli-mcp"] }
}
}Keep the server name short (qwen): it becomes part of the tool names your model sees.
⚠️ Default approval mode is
yolo. Delegation is only useful when the delegate can act, so this server starts qwen with full tool approval by default — insidecwd, as your user. Narrow it withQWEN_MCP_APPROVAL_MODE, per-callapproval_mode, orallowed_tools. For analysis-only work passallowed_tools: "read,grep,ls"-style allowlists.
Tools
Tool | Purpose |
| Start a session. Returns |
| Continue a finished or interrupted session — including one killed by a timeout. |
| List models qwen can actually reach right now (live probe via the control plane). |
| Deliver into a turn executing right now ( |
| List turns executing right now that |
| List known sessions, newest first, with their working directory. |
qwen
Argument | Notes |
| Required. Must be self-contained — qwen cannot see your conversation. |
| Absolute path; defaults to this server's cwd. |
|
|
|
|
| Comma-separated tool allowlist passed as |
|
|
| Appended to qwen's system prompt for this run. |
|
|
| Wall clock for this run. A run killed at the deadline stays resumable via |
What comes back
Only qwen's final result plus aggregate stats — never the transcript, tool arguments or raw stdout:
[session: 0927adc5-a840-4b68-93ca-5ca344c9fafb]
Refactored retry() in src/http.rs; all 12 tests pass.
---
qwen: qwen3-coder-plus · 6 turns · 5 tool calls: bash×2, read×2, edit · 18k in / 310 out · 41sThe answer is the result envelope qwen emits at the end of a turn — there is no answer-selection
guesswork. An error envelope (error_max_turns, error_during_execution) fails the call while
keeping everything qwen managed to say, so the work stays resumable. A stream that ends without any
result envelope is reported as broken, never silently replaced by raw output.
Sessions
qwen returns a session id; qwen_reply resumes it with --resume. The conversation lives in
qwen's own session store, so follow-ups keep working across restarts of this server — the
session → directory map is persisted in ~/.local/state/qwen-mcp/sessions.json.
Concurrent replies to one session are serialized per server process: two qwen processes writing one session file would corrupt it. Cross-process caveat: if you run two MCP clients against two server processes and both reply to the same session id at the same time, nothing serializes them. In practice one client owns a session; for a hard guarantee, keep one server process.
Transports
|
| |
command |
|
|
process | stays up, speaks the control plane on stdin | one process per turn, exits when done |
mid-run delivery |
| impossible: qwen reads nothing while working |
deadline / cancel | qwen's own | SIGTERM, then SIGKILL |
stream is the default because it is a superset: the same message stream, plus a running turn
stays reachable and an interrupted one is ended in-protocol, keeping the tail of the stream.
Pick per call with transport, or set the default with QWEN_MCP_TRANSPORT=print.
This server never sends anything into qwen on its own. No automatic wrap-up before a deadline,
no injected instructions: qwen_send fires only when the caller calls it.
Environment
Variable | Default | Meaning |
|
| Path to the qwen binary. |
|
| Default approval mode for every call. See the warning above. |
| unset | Default model for every call. |
|
| Default transport: |
|
| Default wall clock; |
|
| Ceiling on what |
|
| Concurrent qwen processes. |
| unset | Cap on the answer. Unset means no truncation. |
|
| stderr tail included in the response. |
| unset |
|
|
| Read-buffer guard against a runaway stream. |
|
| Longest single message line from qwen before it is dropped. |
|
| Longest single JSON-RPC frame from the client. |
|
| Remembered sessions before the oldest is dropped. |
|
| SIGTERM → SIGKILL grace period. |
|
| How long |
|
| Initialize-handshake timeout (stream only). |
|
| Whole-run budget for the |
|
| Session → cwd map. |
| unset | Command prefix, e.g. a sandbox wrapper around qwen. |
Design
Process per call. Qwen's own session files are the source of truth, which is what makes follow-ups survive a restart of this server.
The wire contract is qwen's own stream-json protocol, spoken directly — newline-delimited messages on stdout, control requests and user turns on stdin. Its shapes are borrowed from
@qwen-code/sdkthroughimport type, so an upstream change breaks the build instead of the server. Zero runtime dependencies.Fail closed on anything from qwen. An unknown result subtype, a failed handshake, a line that does not parse — reported as such, never normalized into success.
No process outlives its request. Timeouts, cancellations and shutdown reap the whole qwen process tree; nothing is left behind on any path.
Development
TypeScript (native tsc), Biome, Vitest. Tests drive the real server binary over stdio against a
fixture that speaks qwen's protocol; live tests against the installed qwen are opt-in.
npm run hooks # once per clone: git hooks from .githooks/
npm run build # tsc -> dist/
npm test # unit + type tests, no API access, no tokens
npm run test:live # 4 live tests against the real qwen binary (spends tokens)
npm run check # format + types + tests
npm run fix # biome --writeLicense
MIT
This server cannot be installed
Maintenance
Related MCP Connectors
MCP server for generating rough-draft project plans from natural-language prompts.
MCP Server for Slima - AI Writing IDE for Novel Authors with AI Beta Reader.
MCP server for Clipkit — gives AI agents a video toolbox via the Clipkit schema.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/minmax/qwen-cli-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server