Skip to content

Commit ec471c5

Browse files
authored
add minimal tests (#6)
1 parent 310aee7 commit ec471c5

3 files changed

Lines changed: 163 additions & 0 deletions

File tree

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ Add to your `mcp.json`:
3838
- `search_conan_packages(query="zlib", remote="conancenter")` - Search for zlib
3939
in conancenter remote
4040

41+
**`get_conan_profile`**: Get Conan profile configuration
42+
- `profile` (optional): If provided, show that specific profile; otherwise, default
43+
44+
**Examples:**
45+
- `get_conan_profile()`
46+
- `get_conan_profile(profile="linux-debug")`
47+
48+
**`list_conan_profiles`**: List available Conan profiles
49+
- No parameters
50+
51+
**Examples:**
52+
- `list_conan_profiles()`
53+
4154
## Local Development
4255

4356
### Clone and run

main.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,58 @@ async def run_command(cmd: list[str], timeout: float = 30.0) -> str:
4949
raise RuntimeError(f"Error running command: {str(e)}")
5050

5151

52+
@mcp.tool(
53+
description="Get Conan profile configuration for the user's platform and build environment"
54+
)
55+
async def get_conan_profile(
56+
profile: str = Field(default=None, description="Specific profile name to retrieve. If not provided, uses the default profile.")
57+
) -> str:
58+
"""Get Conan profile configuration.
59+
60+
This tool should be called when the user mentions:
61+
- Their platform (Windows, macOS, Linux)
62+
- Their compiler (gcc, clang, msvc, etc.)
63+
- Their architecture (x86_64, arm64, etc.)
64+
- Build configurations
65+
- When they want to list packages for their specific platform
66+
- When they need context about their Conan environment
67+
- When they want to check a specific profile configuration
68+
69+
This is typically a prerequisite step before listing packages or making
70+
platform-specific recommendations, as it provides essential context about
71+
the user's build environment.
72+
73+
Args:
74+
profile: Optional profile name to retrieve. If not specified, retrieves the default profile.
75+
76+
Returns:
77+
JSON string containing both host and build profile configurations.
78+
The JSON structure includes:
79+
- "host": Host profile settings (compiler, arch, build_type, etc.)
80+
- "build": Build profile settings (compiler, arch, build_type, etc.)
81+
- Additional configuration like package_settings, options, tool_requires, etc.
82+
"""
83+
cmd = ["conan", "profile", "show", "--format=json"]
84+
if profile:
85+
cmd.extend(["--profile", profile])
86+
return await run_command(cmd)
87+
88+
89+
@mcp.tool(
90+
description="List available Conan profiles."
91+
)
92+
async def list_conan_profiles() -> str:
93+
"""List Conan profiles available.
94+
95+
Use this tool to see which profiles are available to select or inspect.
96+
97+
Returns:
98+
JSON string with a list of profile names.
99+
"""
100+
cmd = ["conan", "profile", "list", "--format=json"]
101+
return await run_command(cmd)
102+
103+
52104
@mcp.tool(
53105
description="Search for Conan packages and check available versions across remotes."
54106
)

test/test_conan_mcp.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,102 @@ async def test_search_conan_packages_empty_query(mock_run_command, client_sessio
166166
mock_run_command.assert_called_once()
167167
call_args = mock_run_command.call_args[0][0]
168168
assert "" in call_args # Empty string in command args
169+
170+
171+
@pytest.mark.anyio
172+
@patch('main.run_command')
173+
async def test_get_conan_profile_default(mock_run_command, client_session: ClientSession):
174+
"""Test get_conan_profile with default profile."""
175+
# Minimal conan profile response
176+
mock_profile = {
177+
"host": {"settings": {}},
178+
"build": {"settings": {}}
179+
}
180+
mock_run_command.return_value = str(mock_profile).replace("'", '"')
181+
182+
# Test calling the tool without profile parameter
183+
result = await client_session.call_tool("get_conan_profile", {})
169184

185+
# Check that we get a valid response structure
186+
assert isinstance(result, CallToolResult)
187+
assert len(result.content) > 0
188+
assert isinstance(result.content[0], TextContent)
189+
assert result.content[0].type == "text"
190+
191+
# Basic sanity check: got some text back
192+
response_text = result.content[0].text
193+
assert isinstance(response_text, str)
194+
195+
# Verify the command was called correctly (no --profile flag)
196+
mock_run_command.assert_called_once()
197+
call_args = mock_run_command.call_args[0][0]
198+
assert "conan" in call_args
199+
assert "profile" in call_args
200+
assert "show" in call_args
201+
assert "--format=json" in call_args
202+
assert "--profile" not in call_args
203+
204+
205+
@pytest.mark.anyio
206+
@patch('main.run_command')
207+
async def test_get_conan_profile_specific(mock_run_command, client_session: ClientSession):
208+
"""Test get_conan_profile with specific profile."""
209+
# Minimal conan profile response
210+
mock_profile = {
211+
"host": {"settings": {}},
212+
"build": {"settings": {}}
213+
}
214+
mock_run_command.return_value = str(mock_profile).replace("'", '"')
215+
216+
# Test calling the tool with specific profile
217+
result = await client_session.call_tool("get_conan_profile", {"profile": "linux-debug"})
218+
219+
# Check that we get a valid response structure
220+
assert isinstance(result, CallToolResult)
221+
assert len(result.content) > 0
222+
assert isinstance(result.content[0], TextContent)
223+
assert result.content[0].type == "text"
224+
225+
# Basic sanity check: got some text back
226+
response_text = result.content[0].text
227+
assert isinstance(response_text, str)
228+
229+
# Verify the command was called correctly (with --profile flag)
230+
mock_run_command.assert_called_once()
231+
call_args = mock_run_command.call_args[0][0]
232+
assert "conan" in call_args
233+
assert "profile" in call_args
234+
assert "show" in call_args
235+
assert "--format=json" in call_args
236+
assert "--profile" in call_args
237+
assert "linux-debug" in call_args
238+
239+
240+
@pytest.mark.anyio
241+
@patch('main.run_command')
242+
async def test_list_conan_profiles(mock_run_command, client_session: ClientSession):
243+
"""Test listing conan profiles successfully."""
244+
mock_response = {
245+
"local": [
246+
"default",
247+
"linux-debug",
248+
"macos-release"
249+
]
250+
}
251+
mock_run_command.return_value = str(mock_response).replace("'", '"')
252+
253+
result = await client_session.call_tool("list_conan_profiles", {})
254+
255+
assert isinstance(result, CallToolResult)
256+
assert len(result.content) > 0
257+
assert isinstance(result.content[0], TextContent)
258+
259+
response_text = result.content[0].text
260+
assert isinstance(response_text, str)
261+
262+
mock_run_command.assert_called_once()
263+
call_args = mock_run_command.call_args[0][0]
264+
assert "conan" in call_args
265+
assert "profile" in call_args
266+
assert "list" in call_args
267+
assert "--format=json" in call_args

0 commit comments

Comments
 (0)