iflow-mcp_oddlyspaced-android-mcp-py 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
config.py ADDED
@@ -0,0 +1,5 @@
1
+ class AndroidMCPConfig:
2
+ adb_client_host = "127.0.0.1" # adb server host url
3
+ adb_client_port = 5037 # adb server host port
4
+ # serial number or ip of the connected device to use, if this is not present the first available device would be used
5
+ adb_device_serial = None # Auto-detect first available device
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iflow-mcp_oddlyspaced-android-mcp-py
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Ultimate Android MCP - A powerful MCP server for interacting with connected Android devices
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,18 @@
1
+ config.py,sha256=tQPJyGAK7OU8Q8EtToaPjXOSWsAb9IALMd_02jYRYR8,321
2
+ server.py,sha256=B1L8l9i0MyYYKrU2Urff6rxtQGoS8zfV25qP8OMfGZA,10122
3
+ iflow_mcp_oddlyspaced_android_mcp_py-0.1.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
4
+ src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ src/device_manager.py,sha256=4ZuXPoKvBXAp367KuPp-zBvhOrty0Csz6XaKlfNU5Nc,3047
6
+ src/handlers/cpu_info_handler.py,sha256=PxUGnsf9mxwNKa0rnPx_vx2b--fGPrc83fwEuTTb0ec,326
7
+ src/handlers/device_info_handler.py,sha256=QWH-0Xp9yDui22H_BDgCy-DsHXwhtVhFiqOHPP2LwQE,756
8
+ src/handlers/file_handler.py,sha256=eKUrv0Q73Umw6Oyc_jBPMqfESh4rkNA3pE-hhkIqbeM,288
9
+ src/handlers/input_handler.py,sha256=BRKZWQqBWjl59_NyeHU7DFfqPDQbQWwgH2QuHL_5aVE,1019
10
+ src/handlers/package_handler.py,sha256=1BOrISSnbws-WbBj7OmUeIEpcvegihjxirTuG9yfo9U,1261
11
+ src/handlers/process_info_handler.py,sha256=y3UKUKpopWQp_VuKPSh9U6q_czQjfy9q8OS2YDuMJP4,522
12
+ src/handlers/shell_handler.py,sha256=vdomnvE6KCJ8Dpu1QpxWl7AjvC0LGLpUsm9Aim67Hqw,196
13
+ src/handlers/ui_handler.py,sha256=Ykhk4SkJkXVsRZsXlKiM7pRPVAD4H1kFro6B6OxIdls,1692
14
+ iflow_mcp_oddlyspaced_android_mcp_py-0.1.1.dist-info/METADATA,sha256=S5ufeaEi0yHjSJdvKE9ghnuzA4ODnJvWxKam_xHHv4U,363
15
+ iflow_mcp_oddlyspaced_android_mcp_py-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
16
+ iflow_mcp_oddlyspaced_android_mcp_py-0.1.1.dist-info/entry_points.txt,sha256=n1QJZSFI2GpcCmmYqxw7NDQZn8Xz9_8-A2EJefGXZmE,81
17
+ iflow_mcp_oddlyspaced_android_mcp_py-0.1.1.dist-info/top_level.txt,sha256=FBTm-QWgq5cJyC42CsL7QXf_v6AfjWkl66AJAFaxsrc,18
18
+ iflow_mcp_oddlyspaced_android_mcp_py-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ android-mcp = iflow_mcp_oddlyspaced_android_mcp_py.server:main
@@ -0,0 +1,3 @@
1
+ config
2
+ server
3
+ src
server.py ADDED
@@ -0,0 +1,276 @@
1
+ from mcp.server.fastmcp import FastMCP
2
+ from src.device_manager import DeviceManager
3
+ from config import AndroidMCPConfig
4
+
5
+ config = AndroidMCPConfig()
6
+ handler = DeviceManager(config)
7
+
8
+ # Create an MCP server
9
+ mcp = FastMCP("Android MCP")
10
+
11
+
12
+ # Tool: Get list of all installed packages
13
+ @mcp.tool()
14
+ def all_packages() -> list[str]:
15
+ """Returns a list of all packages (both system and user-installed) currently installed on the connected Android device. No parameters are required."""
16
+ return handler.get_all_packages()
17
+
18
+
19
+ # Tool: Get list of all user installed packages
20
+ @mcp.tool()
21
+ def user_packages() -> list[str]:
22
+ """Returns a list of user-installed application package names on the connected Android device. No parameters are required."""
23
+ return handler.get_user_packages()
24
+
25
+
26
+ # Tool: Get list of all system installed packages
27
+ @mcp.tool()
28
+ def system_packages() -> list[str]:
29
+ """Returns a list of system application package names (pre-installed apps) on the connected Android device. No parameters are required."""
30
+ return handler.get_system_packages()
31
+
32
+
33
+ # Tool: Launch an app via its package name
34
+ @mcp.tool()
35
+ def launch_app(package_name: str) -> str:
36
+ """Launches the app with the specified package name on the connected Android device. Requires the `package_name` parameter, which is the package name of the app to be launched."""
37
+ try:
38
+ handler.launch_app(package_name)
39
+ return f"Successfully Launched {package_name}"
40
+ except:
41
+ return f"Error Launching {package_name}"
42
+
43
+
44
+ # Tool: Get all the visible text label nodes on the screen
45
+ @mcp.tool()
46
+ def get_current_ui_labels() -> list:
47
+ """Returns a list of UI nodes currently visible on the device screen, focusing on text labels and content descriptions. Each node contains properties like text, bounds, clickable, focusable, and others. No parameters are required."""
48
+ return handler.get_current_ui_labels()
49
+
50
+
51
+ # Tool: Get all the focused nodes
52
+ @mcp.tool()
53
+ def get_current_focused_nodes() -> list:
54
+ """Returns a list of UI nodes that are currently focused on the connected Android device screen. No parameters are required."""
55
+ return handler.get_current_focused_nodes()
56
+
57
+
58
+ # Tool: Input key event
59
+ @mcp.tool()
60
+ def input_keyevent(keycode: int):
61
+ """Simulates a key event with the specified keycode on the connected Android device. Requires the `keycode` parameter, which is the keycode of the key to simulate."""
62
+ return handler.input_keyevent(keycode)
63
+
64
+
65
+ # Tool: Back button
66
+ @mcp.tool()
67
+ def input_back():
68
+ """Simulates a back button event on the connected Android device. No parameters are required."""
69
+ return handler.input_back()
70
+
71
+
72
+ # Tool: Home button
73
+ @mcp.tool()
74
+ def input_home():
75
+ """Simulates a home button event on the connected Android device. No parameters are required."""
76
+ return handler.input_home()
77
+
78
+
79
+ # Tool: Input tap
80
+ @mcp.tool()
81
+ def input_tap(x: int, y: int):
82
+ """Simulates a tap gesture at the specified (x, y) coordinates on the connected Android device screen. Requires `x` and `y` parameters, which are the coordinates of the tap."""
83
+ return handler.input_tap(x, y)
84
+
85
+
86
+ # Tool: Input text
87
+ @mcp.tool()
88
+ def input_text(text: str):
89
+ """Simulates typing the given text input into the currently focused field on the connected Android device. Requires the `text` parameter, which is the string to be typed."""
90
+ return handler.input_text(text)
91
+
92
+
93
+ # Tool: Input press
94
+ @mcp.tool()
95
+ def input_press(keycode: int):
96
+ """Simulates a key press event with the specified keycode on the connected Android device. Requires the `keycode` parameter, which is the keycode of the key to press."""
97
+ return handler.input_press(keycode)
98
+
99
+
100
+ # Tool: Input roll
101
+ @mcp.tool()
102
+ def input_roll(dx: int, dy: int):
103
+ """Simulates a rolling gesture with the specified dx and dy values on the connected Android device. Requires `dx` and `dy` parameters, which are the rolling distances in the x and y directions respectively."""
104
+ return handler.input_roll(dx, dy)
105
+
106
+
107
+ # Tool: Input swipe
108
+ @mcp.tool()
109
+ def input_swipe(x1: int, y1: int, x2: int, y2: int, duration_ms: int = None):
110
+ """Simulates a swipe gesture from (x1, y1) to (x2, y2) with an optional duration on the connected Android device. Requires `x1`, `y1`, `x2`, `y2` parameters for the start and end coordinates, and an optional `duration_ms` parameter for the swipe duration in milliseconds."""
111
+ return handler.input_swipe(x1, y1, x2, y2, duration_ms)
112
+
113
+
114
+ # Tool: Check if keyboard is open
115
+ @mcp.tool()
116
+ def is_keyboard_open():
117
+ """Checks if the virtual keyboard is currently open on the connected Android device. No parameters are required."""
118
+ return handler.is_keyboard_open()
119
+
120
+
121
+ # Tool: Execute ADB shell command
122
+ @mcp.tool()
123
+ def execute_adb_shell(command: str):
124
+ """Executes a raw ADB shell command on the connected Android device and returns the output. Requires the `command` parameter, which is the shell command to execute."""
125
+ return handler.shell(command)
126
+
127
+
128
+ # Tool: Get CPU core count
129
+ @mcp.tool()
130
+ def cpu_count():
131
+ """Returns the number of CPU cores on the connected Android device. No parameters are required."""
132
+ return handler.cpu_count()
133
+
134
+
135
+ # Tool: Get CPU load percentage
136
+ @mcp.tool()
137
+ def cpu_percent():
138
+ """Returns the current CPU load percentage on the connected Android device. No parameters are required."""
139
+ return handler.cpu_percent()
140
+
141
+
142
+ # Tool: Get device serial number
143
+ @mcp.tool()
144
+ def get_serial_no():
145
+ """Returns the serial number of the connected Android device. No parameters are required."""
146
+ return handler.get_serial_no()
147
+
148
+
149
+ # Tool: Get device properties
150
+ @mcp.tool()
151
+ def get_properties():
152
+ """Returns the build.prop properties of the connected Android device. No parameters are required."""
153
+ return handler.get_properties()
154
+
155
+
156
+ # Tool: List device features
157
+ @mcp.tool()
158
+ def list_features():
159
+ """Returns the device overlay configuration properties of the connected Android device. No parameters are required."""
160
+ return handler.list_features()
161
+
162
+
163
+ # Tool: Get battery level
164
+ @mcp.tool()
165
+ def get_battery_level():
166
+ """Returns the battery level of the connected Android device. No parameters are required."""
167
+ return handler.get_battery_level()
168
+
169
+
170
+ # Tool: Get screen density
171
+ @mcp.tool()
172
+ def wm_density():
173
+ """Returns the screen density of the connected Android device. No parameters are required."""
174
+ return handler.wm_density()
175
+
176
+
177
+ # Tool: Get screen size
178
+ @mcp.tool()
179
+ def wm_size():
180
+ """Returns the screen size of the connected Android device. No parameters are required."""
181
+ return handler.wm_size()
182
+
183
+
184
+ # Tool: Pull file from device
185
+ @mcp.tool()
186
+ def pull_file(remote: str, local: str):
187
+ """Pulls a file from the connected Android device to the local machine. Requires `remote` and `local` parameters, which are the paths of the file on the device and the local machine respectively."""
188
+ return handler.pull(remote, local)
189
+
190
+
191
+ # Tool: Push file to device
192
+ @mcp.tool()
193
+ def push_file(local: str, remote: str):
194
+ """Pushes a file from the local machine to the connected Android device. Requires `local` and `remote` parameters, which are the paths of the file on the local machine and the device respectively."""
195
+ return handler.push(local, remote)
196
+
197
+
198
+ # Tool: Get process ID by package name
199
+ @mcp.tool()
200
+ def get_pid(package_name: str):
201
+ """Returns the process ID (PID) for the specified package name on the connected Android device. Requires the `package_name` parameter, which is the name of the package to query."""
202
+ return handler.get_pid(package_name)
203
+
204
+
205
+ # Tool: Get top activities
206
+ @mcp.tool()
207
+ def get_top_activities():
208
+ """Returns the activities currently on top on the connected Android device. No parameters are required."""
209
+ return handler.get_top_activities()
210
+
211
+
212
+ # Tool: Get top activity
213
+ @mcp.tool()
214
+ def get_top_activity():
215
+ """Returns the singular activity currently on top on the connected Android device. No parameters are required."""
216
+ return handler.get_top_activity()
217
+
218
+
219
+ # Tool: Install APK
220
+ @mcp.tool()
221
+ def install_apk(apk_path: str):
222
+ """Installs an APK on the connected Android device. Requires the `apk_path` parameter, which is the path to the APK file to be installed."""
223
+ return handler.install(apk_path)
224
+
225
+
226
+ # Tool: Uninstall package
227
+ @mcp.tool()
228
+ def uninstall_package(package_name: str):
229
+ """Uninstalls the specified package from the connected Android device. Requires the `package_name` parameter, which is the name of the package to uninstall."""
230
+ return handler.uninstall(package_name)
231
+
232
+
233
+ # Tool: Check if package is installed
234
+ @mcp.tool()
235
+ def is_installed(package_name: str):
236
+ """Checks if the specified package is installed on the connected Android device. Requires the `package_name` parameter, which is the name of the package to check."""
237
+ return handler.is_installed(package_name)
238
+
239
+
240
+ # Tool: Get all packages
241
+ @mcp.tool()
242
+ def get_all_packages(
243
+ user_installed_only: bool = False, system_installed_only: bool = False
244
+ ):
245
+ """Returns a list of all packages on the connected Android device, with optional filters for user-installed or system-installed packages. Accepts `user_installed_only` and `system_installed_only` as optional boolean parameters to filter the results."""
246
+ return handler.get_all_packages(user_installed_only, system_installed_only)
247
+
248
+
249
+ # Tool: Get system packages
250
+ @mcp.tool()
251
+ def get_system_packages():
252
+ """Returns a list of system-installed packages on the connected Android device. No parameters are required."""
253
+ return handler.get_system_packages()
254
+
255
+
256
+ # Tool: Get user packages
257
+ @mcp.tool()
258
+ def get_user_packages():
259
+ """Returns a list of user-installed packages on the connected Android device. No parameters are required."""
260
+ return handler.get_user_packages()
261
+
262
+
263
+ # Tool: Launch app
264
+ @mcp.tool()
265
+ def launch_app(package_name: str):
266
+ """Launches the specified app on the connected Android device. Requires the `package_name` parameter, which is the name of the app to launch."""
267
+ return handler.launch_app(package_name)
268
+
269
+
270
+ if __name__ == "__main__":
271
+ mcp.run(transport="stdio")
272
+
273
+
274
+ def main():
275
+ """Entry point for uvx and pip install."""
276
+ mcp.run(transport="stdio")
@@ -1,14 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- class CpuInfoHandler:
5
- def __init__(self, device: Device):
6
- self.device = device
7
-
8
- # returns count of cpu cores
9
- def cpu_count(self):
10
- return self.device.cpu_count()
11
-
12
- # retuns the current cpu load
13
- def cpu_percent(self):
14
- return self.device.cpu_percent()
@@ -1,29 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- # device specific information
5
- class DeviceInfoHandler:
6
- def __init__(self, device: Device):
7
- self.device = device
8
-
9
- # returns the serial number of the device
10
- def get_serial_no(self):
11
- return self.device.get_serial_no()
12
-
13
- # returns build.prop properties
14
- def get_properties(self):
15
- return self.device.get_properties()
16
-
17
- # returns device overlay config properties
18
- def list_features(self):
19
- return self.device.list_features()
20
-
21
- # returns the device battery level
22
- def get_battery_level(self):
23
- return self.device.get_battery_level()
24
-
25
- def wm_density(self):
26
- return self.device.wm_density()
27
-
28
- def wm_size(self):
29
- return self.device.wm_size()
handlers/file_handler.py DELETED
@@ -1,12 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- class FileHandler:
5
- def __init__(self, device: Device):
6
- self.device = device
7
-
8
- def pull(self, remote, local):
9
- return self.device.pull(remote, local)
10
-
11
- def push(self, local, remote):
12
- return self.device.push(local, remote)
handlers/input_handler.py DELETED
@@ -1,34 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- class InputHandler:
5
- def __init__(self, device: Device):
6
- self.device = device
7
-
8
- def input_keyevent(self, keycode):
9
- return self.device.input_keyevent(keycode)
10
-
11
- def input_back(self):
12
- return self.device.input_keyevent("KEYCODE_BACK")
13
-
14
- def input_home(self):
15
- return self.device.input_keyevent("KEYCODE_HOME")
16
-
17
- def input_tap(self, x, y):
18
- return self.device.input_tap(x, y)
19
-
20
- def input_text(self, text):
21
- return self.device.input_text(text)
22
-
23
- def input_press(self, keycode):
24
- return self.device.input_press(keycode)
25
-
26
- def input_roll(self, dx, dy):
27
- return self.device.input_roll(dx, dy)
28
-
29
- def input_swipe(self, x1, y1, x2, y2, duration_ms=None):
30
- return self.device.input_swipe(x1, y1, x2, y2, duration_ms)
31
-
32
- def is_keyboard_open(self) -> bool:
33
- # adb shell dumpsys input_method | grep mInputShown
34
- return "true" in self.device.shell("dumpsys input_method | grep mInputShown")
@@ -1,37 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- class PackageHandler:
5
- def __init__(self, device: Device):
6
- self.device = device
7
-
8
- def install(self, apk_path):
9
- return self.device.install(apk_path)
10
-
11
- def uninstall(self, package_name):
12
- return self.device.uninstall(package_name)
13
-
14
- def is_installed(self, package_name):
15
- return self.device.is_installed(package_name)
16
-
17
- def get_all_packages(
18
- self, user_installed_only: bool = False, system_installed_only: bool = False
19
- ) -> list[str]:
20
- command = "pm list packages"
21
- if user_installed_only == True:
22
- command += " -3"
23
- if system_installed_only == True:
24
- command += " -s"
25
- return [pkg.strip()[8:] for pkg in self.device.shell(command).splitlines()]
26
-
27
- def get_system_packages(self) -> list[str]:
28
- return self.get_all_packages(system_installed_only=True)
29
-
30
- def get_user_packages(self) -> list[str]:
31
- return self.get_all_packages(user_installed_only=True)
32
-
33
- def launch_app(self, package_name: str):
34
- # adb shell monkey -p com.example.app -c android.intent.category.LAUNCHER 1
35
- return self.device.shell(
36
- f"monkey -p {package_name} -c android.intent.category.LAUNCHER 1"
37
- )
@@ -1,18 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- class ProcessInfoHandler:
5
- def __init__(self, device: Device):
6
- self.device = device
7
-
8
- # returns the pid for a given package name
9
- def get_pid(self, package_name):
10
- return self.device.get_pid(package_name)
11
-
12
- # returns the activies currently on top
13
- def get_top_activities(self):
14
- return self.device.get_top_activities()
15
-
16
- # returns the singular activity currently on top
17
- def get_top_activity(self):
18
- return self.device.get_top_activity()
handlers/shell_handler.py DELETED
@@ -1,9 +0,0 @@
1
- from ppadb.device import Device
2
-
3
-
4
- class ShellHandler:
5
- def __init__(self, device: Device):
6
- self.device = device
7
-
8
- def shell(self, command):
9
- return self.device.shell(command)
handlers/ui_handler.py DELETED
@@ -1,59 +0,0 @@
1
- from ppadb.device import Device
2
- import xml.etree.ElementTree as ET
3
-
4
- from config import AndroidMCPConfig
5
-
6
-
7
- class UIHandler:
8
- def __init__(self, device: Device):
9
- self.device = device
10
-
11
- def get_current_ui_labels(self):
12
- self.device.shell("uiautomator dump")
13
- self.device.pull("/sdcard/window_dump.xml", "window_dump.xml")
14
- self.device.shell("rm /sdcard/window_dump.xml")
15
-
16
- tree = ET.parse("window_dump.xml")
17
- root = tree.getroot()
18
- results = []
19
-
20
- attributes_to_extract = [
21
- "text",
22
- "bounds",
23
- "content-desc",
24
- "checkable",
25
- "checked",
26
- "clickable",
27
- "enabled",
28
- "focusable",
29
- "focused",
30
- "long-clickable",
31
- "password",
32
- "selected",
33
- "hint",
34
- ]
35
-
36
- for node in root.iter("node"):
37
- text = node.attrib.get("text", "").strip()
38
- content_desc = node.attrib.get("content-desc", "").strip()
39
- if text or content_desc:
40
- element = {
41
- attr: node.attrib.get(attr, "") for attr in attributes_to_extract
42
- }
43
- results.append(element)
44
-
45
- return results
46
-
47
- def get_current_focused_nodes(self):
48
- self.device.shell("uiautomator dump")
49
- self.device.pull("/sdcard/window_dump.xml", "window_dump.xml")
50
- self.device.shell("rm /sdcard/window_dump.xml")
51
-
52
- tree = ET.parse("window_dump.xml")
53
- root = tree.getroot()
54
-
55
- for node in root.iter("node"):
56
- if node.attrib.get("focused") == "true":
57
- return node.attrib
58
-
59
- return None
@@ -1,24 +0,0 @@
1
- handlers/cpu_info_handler.py,sha256=PxUGnsf9mxwNKa0rnPx_vx2b--fGPrc83fwEuTTb0ec,326
2
- handlers/device_info_handler.py,sha256=QWH-0Xp9yDui22H_BDgCy-DsHXwhtVhFiqOHPP2LwQE,756
3
- handlers/file_handler.py,sha256=eKUrv0Q73Umw6Oyc_jBPMqfESh4rkNA3pE-hhkIqbeM,288
4
- handlers/input_handler.py,sha256=BRKZWQqBWjl59_NyeHU7DFfqPDQbQWwgH2QuHL_5aVE,1019
5
- handlers/package_handler.py,sha256=1BOrISSnbws-WbBj7OmUeIEpcvegihjxirTuG9yfo9U,1261
6
- handlers/process_info_handler.py,sha256=y3UKUKpopWQp_VuKPSh9U6q_czQjfy9q8OS2YDuMJP4,522
7
- handlers/shell_handler.py,sha256=vdomnvE6KCJ8Dpu1QpxWl7AjvC0LGLpUsm9Aim67Hqw,196
8
- handlers/ui_handler.py,sha256=Ykhk4SkJkXVsRZsXlKiM7pRPVAD4H1kFro6B6OxIdls,1692
9
- iflow_mcp_oddlyspaced_android_mcp_py-0.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
10
- src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- src/device_manager.py,sha256=4ZuXPoKvBXAp367KuPp-zBvhOrty0Csz6XaKlfNU5Nc,3047
12
- src/handlers/cpu_info_handler.py,sha256=PxUGnsf9mxwNKa0rnPx_vx2b--fGPrc83fwEuTTb0ec,326
13
- src/handlers/device_info_handler.py,sha256=QWH-0Xp9yDui22H_BDgCy-DsHXwhtVhFiqOHPP2LwQE,756
14
- src/handlers/file_handler.py,sha256=eKUrv0Q73Umw6Oyc_jBPMqfESh4rkNA3pE-hhkIqbeM,288
15
- src/handlers/input_handler.py,sha256=BRKZWQqBWjl59_NyeHU7DFfqPDQbQWwgH2QuHL_5aVE,1019
16
- src/handlers/package_handler.py,sha256=1BOrISSnbws-WbBj7OmUeIEpcvegihjxirTuG9yfo9U,1261
17
- src/handlers/process_info_handler.py,sha256=y3UKUKpopWQp_VuKPSh9U6q_czQjfy9q8OS2YDuMJP4,522
18
- src/handlers/shell_handler.py,sha256=vdomnvE6KCJ8Dpu1QpxWl7AjvC0LGLpUsm9Aim67Hqw,196
19
- src/handlers/ui_handler.py,sha256=Ykhk4SkJkXVsRZsXlKiM7pRPVAD4H1kFro6B6OxIdls,1692
20
- iflow_mcp_oddlyspaced_android_mcp_py-0.1.0.dist-info/METADATA,sha256=OIjgHBpNVirdnwp1Q8wfbFwOKh7jMPBOhofJghpILRo,363
21
- iflow_mcp_oddlyspaced_android_mcp_py-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
22
- iflow_mcp_oddlyspaced_android_mcp_py-0.1.0.dist-info/entry_points.txt,sha256=dOM-FQ2BRw1Th-w41F4mx4TyH75CoLAz3KdRckzzNIY,44
23
- iflow_mcp_oddlyspaced_android_mcp_py-0.1.0.dist-info/top_level.txt,sha256=frzRIBpXLRa70tNFoHcQEND9oSM-OZSuu0Q37S3fOAs,13
24
- iflow_mcp_oddlyspaced_android_mcp_py-0.1.0.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- android-mcp = server:main
@@ -1,2 +0,0 @@
1
- handlers
2
- src