Skip to content

Commit d5940e2

Browse files
RYABOV EvgenyRYABOV Evgeny
authored andcommitted
feat: add Qwen CLI client manager support
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Added QwenCliManager to handle Qwen CLI MCP server configurations Includes implementation and tests for Qwen CLI integration
1 parent bf2dc92 commit d5940e2

File tree

5 files changed

+127
-0
lines changed

5 files changed

+127
-0
lines changed

QWEN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Reference `CLAUDE.md` for project conventions.

src/mcpm/clients/client_registry.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from mcpm.clients.managers.fiveire import FiveireManager
2020
from mcpm.clients.managers.gemini_cli import GeminiCliManager
2121
from mcpm.clients.managers.goose import GooseClientManager
22+
from mcpm.clients.managers.qwen_cli import QwenCliManager
2223
from mcpm.clients.managers.trae import TraeManager
2324
from mcpm.clients.managers.vscode import VSCodeManager
2425
from mcpm.clients.managers.windsurf import WindsurfManager
@@ -50,6 +51,7 @@ class ClientRegistry:
5051
"vscode": VSCodeManager,
5152
"gemini-cli": GeminiCliManager,
5253
"codex-cli": CodexCliManager,
54+
"qwen-cli": QwenCliManager,
5355
}
5456

5557
@classmethod

src/mcpm/clients/managers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from mcpm.clients.managers.fiveire import FiveireManager
1414
from mcpm.clients.managers.gemini_cli import GeminiCliManager
1515
from mcpm.clients.managers.goose import GooseClientManager
16+
from mcpm.clients.managers.qwen_cli import QwenCliManager
1617
from mcpm.clients.managers.trae import TraeManager
1718
from mcpm.clients.managers.vscode import VSCodeManager
1819
from mcpm.clients.managers.windsurf import WindsurfManager
@@ -26,6 +27,7 @@
2627
"ContinueManager",
2728
"FiveireManager",
2829
"GooseClientManager",
30+
"QwenCliManager",
2931
"TraeManager",
3032
"VSCodeManager",
3133
"GeminiCliManager",
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""
2+
Qwen CLI integration utilities for MCP
3+
"""
4+
5+
import logging
6+
import os
7+
import shutil
8+
from typing import Any, Dict
9+
10+
from mcpm.clients.base import JSONClientManager
11+
12+
logger = logging.getLogger(__name__)
13+
14+
15+
class QwenCliManager(JSONClientManager):
16+
"""Manages Qwen CLI MCP server configurations"""
17+
18+
# Client information
19+
client_key = "qwen-cli"
20+
display_name = "Qwen CLI"
21+
download_url = "https://github.com/QwenLM/qwen-code"
22+
23+
def __init__(self, config_path_override: str | None = None):
24+
"""Initialize the Qwen CLI client manager
25+
26+
Args:
27+
config_path_override: Optional path to override the default config file location
28+
"""
29+
super().__init__(config_path_override=config_path_override)
30+
31+
if config_path_override:
32+
self.config_path = config_path_override
33+
else:
34+
# Qwen CLI stores its settings in ~/.qwen/settings.json
35+
self.config_path = os.path.expanduser("~/.qwen/settings.json")
36+
37+
def _get_empty_config(self) -> Dict[str, Any]:
38+
"""Get empty config structure for Qwen CLI"""
39+
return {
40+
"mcpServers": {},
41+
# Include other default settings that Qwen CLI expects
42+
"theme": "Qwen Dark",
43+
"selectedAuthType": "openai",
44+
}
45+
46+
def is_client_installed(self) -> bool:
47+
"""Check if Qwen CLI is installed
48+
Returns:
49+
bool: True if qwen command is available, False otherwise
50+
"""
51+
qwen_executable = "qwen.exe" if self._system == "Windows" else "qwen"
52+
return shutil.which(qwen_executable) is not None
53+
54+
def get_client_info(self) -> Dict[str, str]:
55+
"""Get information about this client
56+
57+
Returns:
58+
Dict: Information about the client including display name, download URL, and config path
59+
"""
60+
return {
61+
"name": self.display_name,
62+
"download_url": self.download_url,
63+
"config_file": self.config_path,
64+
"description": "Alibaba's Qwen CLI tool",
65+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""
2+
Test for Qwen CLI manager
3+
"""
4+
5+
import os
6+
import tempfile
7+
from unittest.mock import patch
8+
9+
from mcpm.clients.managers.qwen_cli import QwenCliManager
10+
11+
12+
def test_qwen_cli_manager_initialization():
13+
"""Test QwenCliManager initialization"""
14+
# Test with default config path
15+
manager = QwenCliManager()
16+
assert manager.client_key == "qwen-cli"
17+
assert manager.display_name == "Qwen CLI"
18+
assert manager.download_url == "https://github.com/QwenLM/qwen-code"
19+
assert manager.config_path == os.path.expanduser("~/.qwen/settings.json")
20+
21+
# Test with custom config path
22+
custom_path = "/tmp/custom_settings.json"
23+
manager = QwenCliManager(config_path_override=custom_path)
24+
assert manager.config_path == custom_path
25+
26+
27+
def test_qwen_cli_manager_get_empty_config():
28+
"""Test QwenCliManager _get_empty_config method"""
29+
manager = QwenCliManager()
30+
config = manager._get_empty_config()
31+
assert "mcpServers" in config
32+
assert "theme" in config
33+
assert "selectedAuthType" in config
34+
assert config["mcpServers"] == {}
35+
36+
37+
def test_qwen_cli_manager_is_client_installed():
38+
"""Test QwenCliManager is_client_installed method"""
39+
manager = QwenCliManager()
40+
41+
# Mock shutil.which to return a path (simulating installed client)
42+
with patch("shutil.which", return_value="/usr/local/bin/qwen"):
43+
assert manager.is_client_installed() is True
44+
45+
# Mock shutil.which to return None (simulating uninstalled client)
46+
with patch("shutil.which", return_value=None):
47+
assert manager.is_client_installed() is False
48+
49+
50+
def test_qwen_cli_manager_get_client_info():
51+
"""Test QwenCliManager get_client_info method"""
52+
manager = QwenCliManager()
53+
info = manager.get_client_info()
54+
assert info["name"] == "Qwen CLI"
55+
assert info["download_url"] == "https://github.com/QwenLM/qwen-code"
56+
assert info["config_file"] == os.path.expanduser("~/.qwen/settings.json")
57+
assert info["description"] == "Alibaba's Qwen CLI tool"

0 commit comments

Comments
 (0)