-
Notifications
You must be signed in to change notification settings - Fork 93
Expand file tree
/
Copy pathserver.py
More file actions
112 lines (92 loc) · 3.38 KB
/
Copy pathserver.py
File metadata and controls
112 lines (92 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import os
import sys
import yaml
from mcp.server.fastmcp import FastMCP, Image
from adbdevicemanager import AdbDeviceManager
CONFIG_FILE = "config.yaml"
CONFIG_FILE_EXAMPLE = "config.yaml.example"
# Load config (make config file optional)
config = {}
device_name = None
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE) as f:
config = yaml.safe_load(f.read()) or {}
device_config = config.get("device", {})
configured_device_name = device_config.get(
"name") if device_config else None
# Support multiple ways to specify auto-selection:
# 1. name: null (None in Python)
# 2. name: "" (empty string)
# 3. name field completely missing
if configured_device_name and configured_device_name.strip():
device_name = configured_device_name.strip()
print(f"Loaded config from {CONFIG_FILE}")
print(f"Configured device: {device_name}")
else:
print(f"Loaded config from {CONFIG_FILE}")
print(
"No device specified in config, will auto-select if only one device connected")
except Exception as e:
print(f"Error loading config file {CONFIG_FILE}: {e}", file=sys.stderr)
print(
f"Please check the format of your config file or recreate it from {CONFIG_FILE_EXAMPLE}", file=sys.stderr)
sys.exit(1)
else:
print(
f"Config file {CONFIG_FILE} not found, using auto-selection for device")
# Initialize MCP and device manager
# AdbDeviceManager will handle auto-selection if device_name is None
mcp = FastMCP("android")
deviceManager = AdbDeviceManager(device_name)
@mcp.tool()
def get_packages() -> str:
"""
Get all installed packages on the device
Returns:
str: A list of all installed packages on the device as a string
"""
result = deviceManager.get_packages()
return result
@mcp.tool()
def execute_adb_shell_command(command: str) -> str:
"""Executes an ADB command and returns the output or an error.
Args:
command (str): The ADB shell command to execute
Returns:
str: The output of the ADB command
"""
result = deviceManager.execute_adb_shell_command(command)
return result
@mcp.tool()
def get_uilayout() -> str:
"""
Retrieves information about clickable elements in the current UI.
Returns a formatted string containing details about each clickable element,
including its text, content description, bounds, and center coordinates.
Returns:
str: A formatted list of clickable elements with their properties
"""
result = deviceManager.get_uilayout()
return result
@mcp.tool()
def get_screenshot() -> Image:
"""Takes a screenshot of the device and returns it.
Returns:
Image: the screenshot
"""
deviceManager.take_screenshot()
return Image(path="compressed_screenshot.png")
@mcp.tool()
def get_package_action_intents(package_name: str) -> list[str]:
"""
Get all non-data actions from Activity Resolver Table for a package
Args:
package_name (str): The name of the package to get actions for
Returns:
list[str]: A list of all non-data actions from the Activity Resolver Table for the package
"""
result = deviceManager.get_package_action_intents(package_name)
return result
if __name__ == "__main__":
mcp.run(transport="stdio")