qwen-code/docs/users/features/mcp.md
Dragon e324104ce8
docs: refresh settings, MCP glob, auth alias, and autonomous loop docs (#6090)
Audit docs/ against the current codebase and correct user-facing drift:

- Document glob-pattern support (* and ?) for mcp.allowed / mcp.excluded
  in settings.md and the MCP feature page (feat #6012).
- Add missing user-facing settings rows: general.terminalBell,
  general.preventSystemSleep, general.chatRecording; ui.showStatusInTitle,
  ui.disableWorkflowKeywordTrigger, ui.enableUserFeedback, ui.compactInline,
  ui.useTerminalBuffer, ui.hideBuiltinWorktreeIndicator;
  memory.enableTeamMemory, memory.enableTeamMemorySync; tools.toolSearch.enabled.
- Note the QWEN_MODEL alias for OPENAI_MODEL in the auth protocol table.
- Document the autonomous (bare /loop) mode in scheduled-tasks (feat #5991).

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-01 06:43:29 +00:00

24 KiB
Raw Permalink Blame History

Connect Qwen Code to tools via MCP

Qwen Code can connect to external tools and data sources through the Model Context Protocol (MCP). MCP servers give Qwen Code access to your tools, databases, and APIs.

What you can do with MCP

With MCP servers connected, you can ask Qwen Code to:

  • Work with files and repos (read/search/write, depending on the tools you enable)
  • Query databases (schema inspection, queries, reporting)
  • Integrate internal services (wrap your APIs as MCP tools)
  • Automate workflows (repeatable tasks exposed as tools/prompts)

Tip

If youre looking for the “one command to get started”, jump to Quick start.

Quick start

Qwen Code loads MCP servers from mcpServers in your settings.json. You can configure servers either:

  • By editing settings.json directly
  • By using qwen mcp commands (see CLI reference)

Add your first server

  1. Add a server (example: remote HTTP MCP server):
qwen mcp add --transport http my-server http://localhost:3000/mcp
  1. Start Qwen Code and open the MCP management dialog to view and manage servers:
qwen

Then enter:

/mcp
  1. If Qwen Code was already running before you added the server, restart it in the same project. Then ask the model to use tools from that server.

Where configuration is stored (scopes)

Most users only need these two scopes:

  • User scope (default): ~/.qwen/settings.json across all projects on your machine
  • Project scope: .qwen/settings.json in your project root

Write to user scope:

qwen mcp add --scope user --transport http my-server http://localhost:3000/mcp

Tip

For advanced configuration layers (system defaults/system settings and precedence rules), see Settings.

Configure servers

Choose a transport

Transport When to use JSON field(s)
http Recommended for remote services; works well for cloud MCP servers httpUrl (+ optional headers)
sse Legacy/deprecated servers that only support Server-Sent Events url (+ optional headers)
stdio Local process (scripts, CLIs, Docker) on your machine command, args (+ optional cwd, env)

Note

If a server supports both, prefer HTTP over SSE.

Configure via settings.json vs qwen mcp add

Both approaches produce the same mcpServers entries in your settings.json—use whichever you prefer.

Stdio server (local process)

JSON (.qwen/settings.json):

{
  "mcpServers": {
    "pythonTools": {
      "command": "python",
      "args": ["-m", "my_mcp_server", "--port", "8080"],
      "cwd": "./mcp-servers/python",
      "env": {
        "DATABASE_URL": "$DB_CONNECTION_STRING",
        "API_KEY": "${EXTERNAL_API_KEY}"
      },
      "timeout": 15000
    }
  }
}

CLI (writes to user scope by default):

qwen mcp add pythonTools -e DATABASE_URL=$DB_CONNECTION_STRING -e API_KEY=$EXTERNAL_API_KEY \
  --timeout 15000 python -m my_mcp_server --port 8080

HTTP server (remote streamable HTTP)

JSON:

{
  "mcpServers": {
    "httpServerWithAuth": {
      "httpUrl": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer your-api-token"
      },
      "timeout": 5000
    }
  }
}

CLI:

qwen mcp add --transport http httpServerWithAuth http://localhost:3000/mcp \
  --header "Authorization: Bearer your-api-token" --timeout 5000

SSE server (remote Server-Sent Events)

JSON:

{
  "mcpServers": {
    "sseServer": {
      "url": "http://localhost:8080/sse",
      "timeout": 30000
    }
  }
}

CLI:

qwen mcp add --transport sse sseServer http://localhost:8080/sse --timeout 30000

Using MCP prompts and resources

Besides tools, Qwen Code discovers and surfaces two other MCP primitives.

Prompts (slash commands)

Any prompt a server advertises via prompts/list becomes an executable slash command. After discovery, type / and you'll see the prompt listed (labeled MCP: <server>); run it like any other command:

/my_prompt --arg1="value" --arg2="value"
# positional form also works:
/my_prompt "value" "value"
# show the prompt's arguments:
/my_prompt help

The prompt's messages are sent to the model, which then acts on them.

Discovery is lenient about the declared prompts capability: some servers implement prompts/list but omit prompts from their initialize capabilities. Qwen Code attempts prompts/list anyway, so those prompts still appear. A server that genuinely has no prompts simply answers Method not found, which is ignored.

Resources

Resources a server advertises via resources/list are discovered per server. Open the management dialog with /mcp and select a server to see its Resources count alongside its tools and prompts. Choose View resources to browse the server's resource URIs; selecting one shows its description and MIME type along with the exact @server:uri reference to paste into a message. As with prompts, the resources capability is not required to be declared.

Inject a resource's contents into your message with the @server:uri syntax — type @, then the server name, a colon, and the resource URI:

summarize @myserver:file:///docs/spec.md and list the open questions

Typing @myserver: shows an autocomplete list of that server's resources; keep typing to filter, matching (case-insensitively) either the resource URI or its friendly name/title. You don't have to know a URI by heart — before you reach the colon, typing part of a server name also suggests matching servers that expose resources, so you can pick one and drill straight into its resource list. On submit, the referenced resource is read and its contents are appended to your message (text inline, binary blobs as attachments); the @server:uri reference is preserved in the prompt so the model knows what it is looking at. The server prefix must match a configured MCP server — otherwise the token is treated as a normal file path, so existing @path/to/file references are unaffected. Resource reads are disabled in untrusted folders.

Progressive availability and discovery timeouts

Qwen Code discovers MCP servers in the background after the UI is already interactive. You see the cli's first prompt within a few hundred milliseconds even when one of your MCP servers takes several seconds (or never responds), and the model's tool list updates within roughly one frame (~16 ms) of each server completing its discover handshake.

  • Interactive mode: the UI appears immediately; an MCP status pill in the bottom-right shows N/M MCP servers ready while discovery is in flight. Sending a prompt before MCP finishes simply means the model sees the tools that are ready at that moment; subsequent prompts see more tools as servers come online.
  • Non-interactive mode (--prompt, stream-json, ACP): the cli still waits for MCP discovery to settle before sending the first prompt, so scripted / piped invocations see the same complete tool set the legacy synchronous behavior produced.

Per-server discoveryTimeoutMs

Each MCP server gets a discovery-only timeout that caps how long the initial handshake (connect + tools/list + prompts/list + resources/list) is allowed to take. Defaults:

  • stdio servers: 30 s
  • remote HTTP / SSE servers: 5 s (network risk is higher)

Override per server when needed:

{
  "mcpServers": {
    "slow-stdio": {
      "command": "node",
      "args": ["./slow-server.js"],
      "discoveryTimeoutMs": 60000,
    },
    "flaky-remote": {
      "httpUrl": "https://example.com/mcp",
      "discoveryTimeoutMs": 10000,
    },
  },
}

The existing timeout field is tool-call timeout (used for each tools/call request, default 10 minutes) and is unaffected by discoveryTimeoutMs — a long-running tool invocation is not a startup pathology.

Rolling back progressive MCP

If you need the old synchronous behavior (cli waits for every MCP server before showing any UI), set QWEN_CODE_LEGACY_MCP_BLOCKING=1 in your environment. This is kept as an escape hatch for at least one release.

Safety and control

Trust (skip confirmations)

  • Server trust (trust: true): bypasses confirmation prompts for that server (use sparingly).

OAuth authentication

Qwen Code supports OAuth 2.0 authentication for MCP servers. This is useful when accessing remote servers that require authentication.

Basic usage

When you add an MCP server with OAuth credentials, Qwen Code will automatically handle the authentication flow:

qwen mcp add --transport sse oauth-server https://api.example.com/sse/ \
  --oauth-client-id your-client-id \
  --oauth-redirect-uri https://your-server.com/oauth/callback \
  --oauth-authorization-url https://provider.example.com/authorize \
  --oauth-token-url https://provider.example.com/token

Important: Redirect URI configuration

The OAuth flow requires a redirect URI where the authorization provider sends the authentication code.

  • Local development: By default, Qwen Code uses http://localhost:7777/oauth/callback. This works when running Qwen Code on your local machine with a local browser.

  • Remote/cloud deployments: When running Qwen Code on remote servers, cloud IDEs, or web terminals, the default localhost redirect will NOT work. You MUST configure --oauth-redirect-uri to point to a publicly accessible URL that can receive the OAuth callback.

Example for remote servers:

qwen mcp add --transport sse remote-server https://api.example.com/sse/ \
  --oauth-redirect-uri https://your-remote-server.example.com/oauth/callback

Manual configuration via settings.json

You can also configure OAuth by editing settings.json directly:

{
  "mcpServers": {
    "oauthServer": {
      "url": "https://api.example.com/sse/",
      "oauth": {
        "enabled": true,
        "clientId": "your-client-id",
        "clientSecret": "your-client-secret",
        "authorizationUrl": "https://provider.example.com/authorize",
        "tokenUrl": "https://provider.example.com/token",
        "redirectUri": "https://your-server.com/oauth/callback",
        "scopes": ["read", "write"]
      }
    }
  }
}

OAuth configuration properties:

Property Description
enabled Enable OAuth for this server (boolean)
clientId OAuth client identifier (string, optional with dynamic registration)
clientSecret OAuth client secret (string, optional for public clients)
authorizationUrl OAuth authorization endpoint (string, auto-discovered if omitted)
tokenUrl OAuth token endpoint (string, auto-discovered if omitted)
scopes Required OAuth scopes (array of strings)
redirectUri Custom redirect URI (string). Critical for remote deployments. Defaults to http://localhost:7777/oauth/callback
tokenParamName Query parameter name for tokens in SSE URLs (string)
audiences Audiences the token is valid for (array of strings)

Token management

OAuth tokens are automatically:

  • Stored in ~/.qwen/mcp-oauth-tokens.json (plaintext, mode 0600) by default. If QWEN_CODE_FORCE_ENCRYPTED_FILE_STORAGE=true is set, Qwen Code uses keychain-backed storage where available, or ~/.qwen/mcp-oauth-tokens-v2.json with AES-256-GCM encryption.
  • Refreshed when expired (if refresh tokens are available)
  • Validated before each connection attempt

Warning

By default, OAuth tokens are stored unencrypted on disk. On shared or multi-user machines, set QWEN_CODE_FORCE_ENCRYPTED_FILE_STORAGE=true to protect credentials.

Use the /mcp dialog within Qwen Code to inspect MCP servers and manage authentication interactively.

Tool filtering (allow/deny tools per server)

Use includeTools / excludeTools to restrict tools exposed by a server (from Qwen Codes perspective).

Example: include only a few tools:

{
  "mcpServers": {
    "filteredServer": {
      "command": "python",
      "args": ["-m", "my_mcp_server"],
      "includeTools": ["safe_tool", "file_reader", "data_processor"],
      "timeout": 30000
    }
  }
}

Global allow/deny lists

The mcp object in your settings.json defines global rules for all MCP servers:

  • mcp.allowed: allow-list of MCP server names (keys in mcpServers)
  • mcp.excluded: deny-list of MCP server names

Both lists support glob patterns: * matches any sequence of characters and ? matches a single character (for example, "*puppeteer*" matches every server whose name contains puppeteer). Entries without glob characters are matched exactly. When a server matches both lists, mcp.excluded takes precedence.

Example:

{
  "mcp": {
    "allowed": ["my-trusted-server", "*-internal"],
    "excluded": ["experimental-server"]
  }
}

Troubleshooting

  • Server shows “Disconnected” in qwen mcp list: verify the URL/command is correct, then increase timeout.
  • Stdio server fails to start: use an absolute command path, and double-check cwd/env.
  • Environment variables in JSON dont resolve: ensure they exist in the environment where Qwen Code runs (shell vs GUI app environments can differ).

Reference

settings.json structure

Server-specific configuration (mcpServers)

Add an mcpServers object to your settings.json file:

// ... file contains other config objects
{
  "mcpServers": {
    "serverName": {
      "command": "path/to/server",
      "args": ["--arg1", "value1"],
      "env": {
        "API_KEY": "$MY_API_TOKEN"
      },
      "cwd": "./server-directory",
      "timeout": 30000,
      "trust": false
    }
  }
}

Configuration properties:

Required (one of the following):

Property Description
command Path to the executable for Stdio transport
url SSE endpoint URL (e.g., "http://localhost:8080/sse")
httpUrl HTTP streaming endpoint URL

Optional:

Property Type/Default Description
args array Command-line arguments for Stdio transport
headers object Custom HTTP headers when using url or httpUrl
env object Environment variables for the server process. Values can reference environment variables using $VAR_NAME or ${VAR_NAME} syntax
cwd string Working directory for Stdio transport
timeout number
(default: 600,000)
Request timeout in milliseconds (default: 600,000ms = 10 minutes)
trust boolean
(default: false)
When true, bypasses all tool call confirmations for this server (default: false)
includeTools array List of tool names to include from this MCP server. When specified, only the tools listed here will be available from this server (allowlist behavior). If not specified, all tools from the server are enabled by default.
excludeTools array List of tool names to exclude from this MCP server. Tools listed here will not be available to the model, even if they are exposed by the server.
Note: excludeTools takes precedence over includeTools - if a tool is in both lists, it will be excluded.
targetAudience string The OAuth Client ID allowlisted on the IAP-protected application you are trying to access. Used with authProviderType: 'service_account_impersonation'.
targetServiceAccount string The email address of the Google Cloud Service Account to impersonate. Used with authProviderType: 'service_account_impersonation'.

Manage MCP servers with qwen mcp

You can always configure MCP servers by manually editing settings.json, but the CLI is usually faster.

Adding a server (qwen mcp add)

qwen mcp add [options] <name> <commandOrUrl> [args...]
Argument/Option Description Default Example
<name> A unique name for the server. example-server
<commandOrUrl> The command to execute (for stdio) or the URL (for http/sse). /usr/bin/python or http://localhost:8
[args...] Optional arguments for a stdio command. --port 5000
-s, --scope Configuration scope (user or project). user -s user
-t, --transport Transport type (stdio, sse, http). stdio -t sse
-e, --env Set environment variables. -e KEY=value
-H, --header Set HTTP headers for SSE and HTTP transports. -H "X-Api-Key: abc123"
--timeout Set connection timeout in milliseconds. --timeout 30000
--trust Trust the server (bypass all tool call confirmation prompts). — (false) --trust
--description Set the description for the server. --description "Local tools"
--include-tools A comma-separated list of tools to include. all tools included --include-tools mytool,othertool
--exclude-tools A comma-separated list of tools to exclude. none --exclude-tools mytool
--oauth-client-id OAuth client ID for MCP server authentication. --oauth-client-id your-client-id
--oauth-client-secret OAuth client secret for MCP server authentication. --oauth-client-secret your-client-secret
--oauth-redirect-uri OAuth redirect URI for authentication callback. http://localhost:7777/oauth/callback --oauth-redirect-uri https://your-server.com/oauth/callback
--oauth-authorization-url OAuth authorization URL. --oauth-authorization-url https://provider.example.com/authorize
--oauth-token-url OAuth token URL. --oauth-token-url https://provider.example.com/token
--oauth-scopes OAuth scopes (comma-separated). --oauth-scopes scope1,scope2

--oauth-* flags apply only to --transport sse and --transport http. Combining them with --transport stdio is rejected.

Removing a server (qwen mcp remove)

qwen mcp remove <name>