Qwen Code says MCP is connected: why the tools are still missing
/mcp in Qwen Code can show a server connected, with names in View tools, while the model says it has no such tool. That is usually the deferred-tool bridge, not a broken connection.
The usual answer: Qwen withholds MCP (Model Context Protocol) tool schemas from the first request by default. If View tools lists the tool but the model says it has none, that is normal deferral; the model has to reach it through tool_search first.
MCP is the protocol an outside server uses to advertise tools to Qwen Code. Qwen reads its servers from mcpServers in user or workspace settings, a project .mcp.json, or --mcp-config, and connects at session start. That status is a transport handshake; registration, filtering and deferral happen later.
Run qwen --version first. This page was checked against v0.26.2 (tag 4029111) and main at 32f6713 on 27 October 2026; the MCP runtime, approval gate and deferred-tool bridge all changed in 2026, so an older build can fail where a current one does not.
Checked against Qwen Code's documentation on 27 October 2026.
Status, 27 October 2026: four open reports — an HTTP server connected with no tools (#13796), a /mcp status that disagrees with a working connection (#14032), ACP (Agent Client Protocol) tools registered but never announced (#14114), and an OAuth token pinned at connect time (#15649).
A tool passes seven gates: configured in a file the session reads; enabled, not switched off in /mcp or covered by mcp.excluded; approved if it comes from a project .mcp.json or repository settings; connected at the transport; discovered through its tool, prompt and resource listings; registered after the config filters; and declared or deferred into the model's function list.
Deferred by default, so the function list is empty#
Qwen defers every MCP tool by default, so its schema is not in the first request. The model gets a short list of names, reaches one through tool_search, then calls it through tool_call (resident context cost). A connected server whose tool never appears there is behaving as designed.
Two other commands mislead:
/toolsfilters out every MCP tool, working or not (tools command)./context detaillists only declared tools; deferred MCP tools are skipped, so absence proves nothing (context command).
/mcp and its View tools list are the right check for registration.
If the model says it cannot see a tool that /mcp lists, three levers, smallest first:
- Name the exact
mcp__server__toolshown in View tools. - Add that name to
tools.visible. Listed tools skip the bridge whenever the tool set is refreshed, including after MCP discovery (settings reference). - Set
tools.toolSearch.enabled: false(restart required). Both bridge tools are denied and ordinary deferred tools, MCP included, are force-declared, at the cost of every MCP schema in every request.
tools.toolSearch.threshold will not help on a fresh session: it defaults to 0, and the preload runs before MCP servers usually connect. MCP tools reach it from the next session start or after /clear, or immediately with QWEN_CODE_LEGACY_MCP_BLOCKING=1.
Two commands that answer for a different process#
qwen mcp list looks authoritative and is not. It opens its own short-lived connection to each configured server, gives the handshake ten seconds, prints Connected or Disconnected, and closes. It never asks for the tool list: connect plus version negotiation is the liveness proof (MCP list command). It lists the config, not the session: at that commit it ignores mcp.allowed, mcp.excluded, and the /mcp disable state, so a server you turned off can still print Connected. It does respect project approval and prints Pending approval or Rejected without connecting.
qwen mcp reconnect <name> connects, discovers tools, and checks that the status ends at connected (not the tool count). It runs in a separate process, and its own output says it "cannot refresh the MCP tools of an already-running Qwen Code session. Restart that session if its tools remain unavailable" (reconnect command). Use it to prove the config and transport, not to repair the current session.
What to check, outside and inside the session#
Outside the session:
qwen --version
qwen mcp listInside the terminal UI:
/mcp
/permissions/mcp is a management dialog, not a text dump. Select a server for its status, source (User Settings, .mcp.json, Workspace Settings, System Settings or Extension), command, tool count and View tools. Those names are the model's names. A failed discovery can flip the status back to disconnected, but it says nothing about filtering, registration or deferral.
Then read the deciding files:
jq '.mcpServers | keys' ~/.qwen/settings.json .qwen/settings.json .mcp.json
jq '.mcp, .tools.visible, .tools.disabled, .tools.toolSearch' ~/.qwen/settings.json .qwen/settings.json| What you see | What it usually means |
|---|---|
/mcp says connected, Tools: 0 | Nothing registered. The server may expose only resources or prompts, or a filter removed every tool. |
/mcp says needs approval or rejected | A project .mcp.json or repository settings server is gated; approve it in /mcp. |
/mcp says disabled (or the name is in mcp.excluded), qwen mcp list says Connected | The list command ignores the disabled state. Re-enable it in /mcp, or remove its name from mcp.excluded. |
/mcp says disconnected, Tools: 0 | The connection or discovery failed. Check the command or URL, the discovery timeout and folder trust. |
/mcp says disconnected, Tools: N | The status is stale; the tools are still registered. Try one before restarting. |
| View tools lists the name, the model says it has no such tool | Normal deferral, or a subagent with an explicit tool list; the tool is registered and has to be found. |
qwen mcp list says connected, /mcp shows nothing | The list command is a separate process and can connect to servers the session skips. |
When a filter removed it, or the name did not match#
The filters use two naming systems; mixing them hides tools that exist on the server.
Per server. includeTools and excludeTools compare the server's own names, such as create_issue, not the mcp__github__create_issue the model sees. excludeTools wins when a tool is on both. An allowlist that matches nothing leaves a connected server with zero tools.
{
"mcpServers": {
"github": {
"includeTools": ["create_issue", "list_issues"],
"excludeTools": ["delete_repository"]
}
}
}Globally. mcp.allowed and mcp.excluded compare server names, not tool names, and support * and ?. If a server is on both lists, mcp.excluded wins. mcp.allowed is ignored when --allowed-mcp-server-names is set.
Two other layers are easy to mistake for a missing tool:
permissions.denyblocks the call but leaves the tool in/mcp; it stays listed and findable.tools.disabledremoves a tool from the registry. It disappears from/mcpand cannot be searched or called.
Use the model-visible name in tools.visible, tools.disabled and permission rules. Qwen builds it as mcp__ + server name + __ + tool name, then replaces characters outside letters, digits, _ and - with underscores and truncates a name longer than 63 characters with a short hash suffix (name normalizer). With a dotted or long server name, the string in View tools is the only one that matches.
Which file won#
- Merge order. Qwen assembles the server map lowest priority first: user settings, project
.mcp.json, repository/workspace settings, then--mcp-config(server assembly). A same-named entry replaces the lower one whole; fields are not merged, so a.mcp.jsonentry that only addsincludeToolsto a user-scope server leaves it with no command or URL. - Where
qwen mcp addwrites.~/.qwen/settings.jsonby default, or the repository's.qwen/settings.jsonwith-s project, not.mcp.json(add command). That is why a server works on your machine and is missing in a teammate's checkout. - Approval and trust. A project
.mcp.jsonis the Claude Code convention; Qwen normalizes Claude'stype-based entries and treats them as untrusted until approved (project loader). The startup dialog asks once per exact config,Escrejects, and the approval is hashed on the entry's behavioural fields, so editing the command, URL, args or anenvvalue makes it pending again (approvals store). With folder trust on and the folder untrusted, Qwen skips MCP discovery entirely (MCP client manager);/permissionsshows the state, and folder trust is off by default (trusted folders).
It worked, then the tools vanished#
The token expired. Remote HTTP or SSE servers that use OAuth are affected; local stdio servers are not. Qwen pins the access token when it creates the transport. When it expires, the next call gets a 401, the pooled connection drops, and a reconnect refreshes the token; the tools are not re-registered, so later calls fail as "tool not found" (#15649, open; reported on 0.26.1 Desktop). A new session gets both.
The status went stale. A long-lived HTTP session can show disconnected in /mcp and 1 MCP offline while calls still succeed; in-dialog Reconnect can fail and leave it unchanged (#14032, open; reported on 0.25.1). If Tools is not zero, registration is still there.
The registration never happened. An HTTP server can connect at session start and register zero tools while a fresh qwen mcp list says Connected. /mcp offers Reconnect only when disconnected, so a connected server with zero tools has no in-session action; qwen mcp reconnect --all does not restore them either, and only a restart does (#13796, open; reported on 0.25.0).
The client is ACP. In qwen --acp (Agent Client Protocol, the editor integration used by Zed and JetBrains), servers passed in session/new are registered but never announced to the model. The same servers work with qwen -p --mcp-config and in the terminal (#14114, open; reproduced on 0.25.0 and 0.25.1).
For the token, stale-status and registration cases, a new session is the reliable reset. In ACP, test the server in the terminal first; qwen mcp reconnect runs in another process and cannot touch this session.
Startup timing and timeouts#
Qwen discovers MCP servers in the background after the terminal UI is interactive; the footer shows N/M MCP servers ready. A prompt sent in the first second sees only the servers that have finished; a later prompt sees more (MCP docs). Headless mode waits for discovery, so the same server can behave differently in qwen -p.
Each server has a discovery-only timeout: 30 seconds for stdio, 5 for remote HTTP or SSE. timeout is the per-tool-call timeout (default 10 minutes) and does not extend discovery. A remote server that takes more than five seconds to answer the listing can be marked disconnected; set discoveryTimeoutMs instead.
QWEN_CODE_LEGACY_MCP_BLOCKING=1 restores blocking startup. trust: true does not connect a server or make tools visible; it only skips tool-call confirmations in a trusted workspace.
If you came from Gemini CLI#
- Gemini CLI names an MCP tool
mcp_server_tool; Qwen names itmcp__server__tool. A rule or prompt written for one will not match the other (Gemini CLI MCP docs). - Qwen has no Gemini-style policy engine. Its layers are
includeToolsandexcludeToolson the server,mcp.allowedandmcp.excludedfor server names, and the permission rules in settings (why Qwen Code keeps asking for permission).
The Gemini CLI MCP page covers the same question for the other tool, including the checks that do not transfer.
Where to go next#
- Qwen Code guides — the rest of the set.
- Why Qwen Code keeps asking for permission — when the tool is found but the call is blocked or confirmed.
- Why your Qwen Code skill or subagent never activates — when the tool exists in the main session but not inside a subagent.
- Gemini CLI says MCP is connected — if you are comparing the two agents.