We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/stonehill-2345/mcp-autogui-multinode'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
import pytest
from core.config import settings
from core.logger import logger
from fastmcp import Client
from mcp import types
from mcp import StdioServerParameters
from pathlib import Path
import sys
PROJECT_ROOT = Path(__file__).parent.parent
MCP_LOCAL_SCRIPT = PROJECT_ROOT / "mcp_local.py"
MCP_BASE_URL = f"http://localhost:{settings.mcp_port}/mcp"
# must start the mcp server before running the tests
# example:
# First start the mcp server:
# uv run python mcp_local.py http
# Then run the tests:
# uv run pytest tests/test_local_mcp_client.py
@pytest.mark.asyncio
async def test_move_mouse_with_client():
"""Test moving the mouse via client"""
logger.info("Testing move_mouse with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("move_mouse", {"x": 100, "y": 200})
logger.info("MCP move_mouse response: {}", response)
assert response is not None
# Response should be a dict with output/error
if isinstance(response, dict):
assert "output" in response or "error" in response
elif hasattr(response, 'content'):
# Handle FastMCP response format
assert response.content is not None
@pytest.mark.asyncio
@pytest.mark.parametrize("button_type,description", [
("left", "Left click"),
("right", "Right click"),
("middle", "Middle click"),
("double_left", "Double click"),
])
async def test_click_mouse_types_with_client(button_type, description):
"""Test different mouse click types: left, right, and double click"""
logger.info("Testing click_mouse ({}) with client, {}", description, MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("click_mouse", {
"x": 100,
"y": 200,
"button": button_type
})
logger.info("MCP click_mouse ({}) response: {}", description, response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
elif hasattr(response, 'content'):
assert response.content is not None
@pytest.mark.asyncio
async def test_get_cursor_position_with_client():
"""Test getting cursor position via client"""
logger.info("Testing get_cursor_position with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("get_cursor_position", {})
logger.info("MCP get_cursor_position response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
# Cursor position should have PositionX and PositionY
if response.get("output"):
output = response["output"]
assert isinstance(output, dict)
assert "PositionX" in output or "PositionY" in output
@pytest.mark.asyncio
async def test_take_screenshot_with_client():
"""Test taking screenshot via client"""
logger.info("Testing take_screenshot with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("take_screenshot", {})
logger.info("MCP take_screenshot response: {}", response)
assert response is not None
if isinstance(response, list):
# Screenshot should return base64 encoded image
if len(response) > 0:
for item in response:
if item.type == "image":
image = item.data
assert image is not None
elif item.type == "text":
text = item.text
assert text is not None
else:
assert False
@pytest.mark.asyncio
async def test_press_mouse_with_client():
"""Test pressing mouse button via client"""
logger.info("Testing press_mouse with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("press_mouse", {"x": 100, "y": 190, "button": "left"})
logger.info("MCP press_mouse response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
@pytest.mark.asyncio
async def test_release_mouse_with_client():
"""Test releasing mouse button via client"""
logger.info("Testing release_mouse with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("release_mouse", {"x": 100, "y": 200, "button": "left"})
logger.info("MCP release_mouse response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
@pytest.mark.asyncio
async def test_drag_mouse_with_client():
"""Test dragging mouse via client"""
logger.info("Testing drag_mouse with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("drag_mouse", {
"source_x": 100,
"source_y": 200,
"target_x": 300,
"target_y": 400
})
logger.info("MCP drag_mouse response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
@pytest.mark.asyncio
async def test_scroll_with_client():
"""Test scrolling via client"""
logger.info("Testing scroll with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
# 移动到屏幕中央的安全区域,避免在系统UI区域滚动
await client.call_tool("move_mouse", {"x": 500, "y": 500})
await client.call_tool("wait", {"duration": 100})
# 在安全位置进行滚动,使用屏幕中央坐标
response = await client.call_tool("scroll", {
"scroll_direction": "up",
"scroll_amount": 3,
"x": 500, # 使用屏幕中央位置,远离系统UI区域
"y": 500 # 避免在顶部菜单栏或底部Dock区域
})
logger.info("MCP scroll response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
elif hasattr(response, 'content'):
assert response.content is not None
@pytest.mark.asyncio
async def test_scroll_down_with_client():
"""Test scrolling down via client"""
logger.info("Testing scroll down with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
# 先移动到屏幕中央的安全区域(避免在系统UI区域滚动)
# 使用较大的 y 坐标,避免在顶部菜单栏区域
await client.call_tool("move_mouse", {"x": 500, "y": 500})
# 添加短暂延迟,确保鼠标位置稳定
await client.call_tool("wait", {"duration": 100})
# 在安全位置进行滚动,明确指定坐标,使用较小的滚动量
response = await client.call_tool("scroll", {
"scroll_direction": "down",
"scroll_amount": 1,
"x": 500, # 明确指定坐标,避免使用当前鼠标位置
"y": 500 # 使用屏幕中央位置,远离系统UI区域
})
logger.info("MCP scroll down response: {}", response)
assert response is not None
if isinstance(response, types.Content):
assert response.text is not None
@pytest.mark.asyncio
async def test_press_key_with_client():
"""Test pressing key via client"""
logger.info("Testing press_key with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("press_key", {"key": "enter"})
logger.info("MCP press_key response: {}", response)
assert response is not None
if isinstance(response, types.Content):
assert response.text is not None
@pytest.mark.asyncio
async def test_press_key_combination_with_client():
"""Test pressing key combination via client"""
logger.info("Testing press_key combination with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("press_key", {"key": "ctrl space"})
logger.info("MCP press_key combination response: {}", response)
assert response is not None
if isinstance(response, types.Content):
assert response.text is not None
@pytest.mark.asyncio
async def test_type_text_with_client():
"""Test typing text via client"""
logger.info("Testing type_text with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("type_text", {"text": "Hello, World!"})
logger.info("MCP type_text response: {}", response)
assert response is not None
if isinstance(response, types.Content):
assert response.text is not None
@pytest.mark.asyncio
async def test_wait_with_client():
"""Test waiting via client"""
logger.info("Testing wait with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("wait", {"duration": 100})
logger.info("MCP wait response: {}", response)
assert response is not None
if isinstance(response, types.Content):
assert response.text is not None
@pytest.mark.asyncio
async def test_click_mouse_right_button_with_client():
"""Test right clicking mouse via client"""
logger.info("Testing click_mouse right button with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("click_mouse", {"x": 100, "y": 200, "button": "right"})
logger.info("MCP click_mouse right button response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
elif hasattr(response, 'content'):
assert response.content is not None
@pytest.mark.asyncio
async def test_click_mouse_double_click_with_client():
"""Test double clicking mouse via client"""
logger.info("Testing click_mouse double click with client, {}", MCP_BASE_URL)
client = Client(MCP_BASE_URL)
async with client:
response = await client.call_tool("click_mouse", {"x": 100, "y": 200, "button": "double_left"})
logger.info("MCP click_mouse double click response: {}", response)
assert response is not None
if isinstance(response, dict):
assert "output" in response or "error" in response
elif hasattr(response, 'content'):
assert response.content is not None