uiautomator2-mcp-server 0.1.0__py3-none-any.whl → 0.1.2__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.
u2mcp/tools/app.py CHANGED
@@ -1,231 +1,231 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- from typing import Any
5
-
6
- from ..mcp import mcp
7
- from .device import get_device
8
-
9
- __all__ = (
10
- "app_install",
11
- "app_uninstall",
12
- "app_uninstall_all",
13
- "app_start",
14
- "app_stop",
15
- "app_stop_all",
16
- "app_clear",
17
- "app_info",
18
- "app_current",
19
- "app_list",
20
- "app_list_running",
21
- "app_auto_grant_permissions",
22
- )
23
-
24
-
25
- @mcp.tool("app_install")
26
- async def app_install(serial: str, data: str):
27
- """Install app
28
-
29
- Args:
30
- serial (str): Android device serialno
31
- data (str): APK file path or url
32
- """
33
- async with get_device(serial) as device:
34
- await asyncio.to_thread(device.app_install, data)
35
-
36
-
37
- @mcp.tool("app_uninstall")
38
- async def app_uninstall(serial: str, package_name: str) -> bool:
39
- """Uninstall an app
40
-
41
- Args:
42
- serial (str): Android device serialno
43
- package_name (str): package name
44
-
45
- Returns:
46
- bool: success
47
- """
48
- async with get_device(serial) as device:
49
- return await asyncio.to_thread(device.app_uninstall, package_name)
50
-
51
-
52
- @mcp.tool("app_uninstall_all")
53
- async def app_uninstall_all(serial: str, excludes: list[str] | None = None) -> list[str]:
54
- """Uninstall all apps
55
-
56
- Args:
57
- serial (str): Android device serialno
58
- excludes (list[str] | None): packages that do not want to uninstall
59
-
60
- Returns:
61
- list[str]: list of uninstalled apps
62
- """
63
- async with get_device(serial) as device:
64
- return await asyncio.to_thread(device.app_uninstall_all, excludes or [])
65
-
66
-
67
- @mcp.tool("app_start")
68
- async def app_start(
69
- serial: str,
70
- package_name: str,
71
- activity: str | None = None,
72
- wait: bool = False,
73
- stop: bool = False,
74
- ):
75
- """Launch application
76
-
77
- Args:
78
- serial (str): Android device serialno
79
- package_name (str): package name
80
- activity (str): app activity
81
- stop (bool): Stop app before starting the activity. (require activity)
82
- wait (bool): wait until app started. default False
83
- """
84
- async with get_device(serial) as device:
85
- await asyncio.to_thread(device.app_start, package_name, activity, wait, stop)
86
-
87
-
88
- @mcp.tool("app_wait")
89
- async def app_wait(serial: str, package_name: str, timeout: float = 20.0, front=False):
90
- """Wait until app launched
91
-
92
- Args:
93
- serial (str): Android device serialno
94
- package_name (str): package name
95
- timeout (float): maximum wait time seconds
96
- front (bool): wait until app is current app
97
- """
98
- async with get_device(serial) as device:
99
- if not await asyncio.to_thread(device.app_wait, package_name, timeout, front):
100
- raise RuntimeError(f"Failed to wait App {package_name} to launch")
101
-
102
-
103
- @mcp.tool("app_stop")
104
- async def app_stop(serial: str, package_name: str):
105
- """Stop one application
106
-
107
- Args:
108
- serial (str): Android device serialno
109
- package_name (str): package name
110
- """
111
- async with get_device(serial) as device:
112
- await asyncio.to_thread(device.app_stop, package_name)
113
-
114
-
115
- @mcp.tool("app_stop_all")
116
- async def app_stop_all(serial: str, excludes: list[str] | None = None) -> list[str]:
117
- """Stop all third party applications
118
-
119
- Args:
120
- excludes (list): apps that do now want to kill
121
-
122
- Returns:
123
- list[str]: a list of killed apps
124
- """
125
- async with get_device(serial) as device:
126
- return await asyncio.to_thread(device.app_stop_all, excludes or [])
127
-
128
-
129
- @mcp.tool("app_clear")
130
- async def app_clear(serial: str, package_name: str):
131
- """Stop and clear app data: pm clear
132
-
133
- Args:
134
- serial (str): Android device serialno
135
- package_name (str): package name
136
-
137
- Returns:
138
- bool: success
139
- """
140
- async with get_device(serial) as device:
141
- await asyncio.to_thread(device.app_clear, package_name)
142
-
143
-
144
- @mcp.tool("app_info")
145
- async def app_info(serial: str, package_name: str) -> dict[str, Any]:
146
- """
147
- Get app info
148
-
149
- Args:
150
- serial (str): Android device serialno
151
- package_name (str): package name
152
-
153
- Returns:
154
- dict[str,Any]: app info
155
-
156
- Example:
157
- {"versionName": "1.1.7", "versionCode": 1001007}
158
- """
159
- async with get_device(serial) as device:
160
- return await asyncio.to_thread(device.app_info, package_name)
161
-
162
-
163
- @mcp.tool("app_current")
164
- async def app_current(serial: str) -> dict[str, Any]:
165
- """
166
- Get current app info
167
-
168
- Args:
169
- serial (str): Android device serialno
170
-
171
- Returns:
172
- dict[str,Any]: running app info
173
- """
174
- async with get_device(serial) as device:
175
- return await asyncio.to_thread(device.app_current)
176
-
177
-
178
- @mcp.tool("app_list")
179
- async def app_list(serial: str, filter: str = "") -> list[str]:
180
- """
181
- List installed app package names
182
-
183
- Args:
184
- serial (str): Android device serialno
185
- filter (str): [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]
186
-
187
- Returns:
188
- list[str]: list of apps by filter
189
- """
190
- async with get_device(serial) as device:
191
- return await asyncio.to_thread(device.app_list, filter.strip())
192
-
193
-
194
- @mcp.tool("app_list_running")
195
- async def app_list_running(serial: str) -> list[str]:
196
- """
197
- List running apps
198
-
199
- Args:
200
- serial (str): Android device serialno
201
-
202
- Returns:
203
- list[str]: list of running apps
204
- """
205
- async with get_device(serial) as device:
206
- return await asyncio.to_thread(device.app_list_running)
207
-
208
-
209
- @mcp.tool("app_auto_grant_permissions")
210
- async def app_auto_grant_permissions(serial: str, package_name: str):
211
- """auto grant permissions
212
-
213
- Args:
214
- serial (str): Android device serialno
215
- package_name (str): package name
216
-
217
- Help of "adb shell pm":
218
- grant [--user USER_ID] PACKAGE PERMISSION
219
- revoke [--user USER_ID] PACKAGE PERMISSION
220
- These commands either grant or revoke permissions to apps. The permissions
221
- must be declared as used in the app's manifest, be runtime permissions
222
- (protection level dangerous), and the app targeting SDK greater than Lollipop MR1 (API level 22).
223
-
224
- Help of "Android official pm" see <https://developer.android.com/tools/adb#pm>
225
- Grant a permission to an app. On devices running Android 6.0 (API level 23) and higher,
226
- the permission can be any permission declared in the app manifest.
227
- On devices running Android 5.1 (API level 22) and lower,
228
- must be an optional permission defined by the app.
229
- """
230
- async with get_device(serial) as device:
231
- await asyncio.to_thread(device.app_auto_grant_permissions, package_name)
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ from typing import Any
5
+
6
+ from ..mcp import mcp
7
+ from .device import get_device
8
+
9
+ __all__ = (
10
+ "app_install",
11
+ "app_uninstall",
12
+ "app_uninstall_all",
13
+ "app_start",
14
+ "app_stop",
15
+ "app_stop_all",
16
+ "app_clear",
17
+ "app_info",
18
+ "app_current",
19
+ "app_list",
20
+ "app_list_running",
21
+ "app_auto_grant_permissions",
22
+ )
23
+
24
+
25
+ @mcp.tool("app_install")
26
+ async def app_install(serial: str, data: str):
27
+ """Install app
28
+
29
+ Args:
30
+ serial (str): Android device serialno
31
+ data (str): APK file path or url
32
+ """
33
+ async with get_device(serial) as device:
34
+ await asyncio.to_thread(device.app_install, data)
35
+
36
+
37
+ @mcp.tool("app_uninstall")
38
+ async def app_uninstall(serial: str, package_name: str) -> bool:
39
+ """Uninstall an app
40
+
41
+ Args:
42
+ serial (str): Android device serialno
43
+ package_name (str): package name
44
+
45
+ Returns:
46
+ bool: success
47
+ """
48
+ async with get_device(serial) as device:
49
+ return await asyncio.to_thread(device.app_uninstall, package_name)
50
+
51
+
52
+ @mcp.tool("app_uninstall_all")
53
+ async def app_uninstall_all(serial: str, excludes: list[str] | None = None) -> list[str]:
54
+ """Uninstall all apps
55
+
56
+ Args:
57
+ serial (str): Android device serialno
58
+ excludes (list[str] | None): packages that do not want to uninstall
59
+
60
+ Returns:
61
+ list[str]: list of uninstalled apps
62
+ """
63
+ async with get_device(serial) as device:
64
+ return await asyncio.to_thread(device.app_uninstall_all, excludes or [])
65
+
66
+
67
+ @mcp.tool("app_start")
68
+ async def app_start(
69
+ serial: str,
70
+ package_name: str,
71
+ activity: str | None = None,
72
+ wait: bool = False,
73
+ stop: bool = False,
74
+ ):
75
+ """Launch application
76
+
77
+ Args:
78
+ serial (str): Android device serialno
79
+ package_name (str): package name
80
+ activity (str): app activity
81
+ stop (bool): Stop app before starting the activity. (require activity)
82
+ wait (bool): wait until app started. default False
83
+ """
84
+ async with get_device(serial) as device:
85
+ await asyncio.to_thread(device.app_start, package_name, activity, wait, stop)
86
+
87
+
88
+ @mcp.tool("app_wait")
89
+ async def app_wait(serial: str, package_name: str, timeout: float = 20.0, front=False):
90
+ """Wait until app launched
91
+
92
+ Args:
93
+ serial (str): Android device serialno
94
+ package_name (str): package name
95
+ timeout (float): maximum wait time seconds
96
+ front (bool): wait until app is current app
97
+ """
98
+ async with get_device(serial) as device:
99
+ if not await asyncio.to_thread(device.app_wait, package_name, timeout, front):
100
+ raise RuntimeError(f"Failed to wait App {package_name} to launch")
101
+
102
+
103
+ @mcp.tool("app_stop")
104
+ async def app_stop(serial: str, package_name: str):
105
+ """Stop one application
106
+
107
+ Args:
108
+ serial (str): Android device serialno
109
+ package_name (str): package name
110
+ """
111
+ async with get_device(serial) as device:
112
+ await asyncio.to_thread(device.app_stop, package_name)
113
+
114
+
115
+ @mcp.tool("app_stop_all")
116
+ async def app_stop_all(serial: str, excludes: list[str] | None = None) -> list[str]:
117
+ """Stop all third party applications
118
+
119
+ Args:
120
+ excludes (list): apps that do now want to kill
121
+
122
+ Returns:
123
+ list[str]: a list of killed apps
124
+ """
125
+ async with get_device(serial) as device:
126
+ return await asyncio.to_thread(device.app_stop_all, excludes or [])
127
+
128
+
129
+ @mcp.tool("app_clear")
130
+ async def app_clear(serial: str, package_name: str):
131
+ """Stop and clear app data: pm clear
132
+
133
+ Args:
134
+ serial (str): Android device serialno
135
+ package_name (str): package name
136
+
137
+ Returns:
138
+ bool: success
139
+ """
140
+ async with get_device(serial) as device:
141
+ await asyncio.to_thread(device.app_clear, package_name)
142
+
143
+
144
+ @mcp.tool("app_info")
145
+ async def app_info(serial: str, package_name: str) -> dict[str, Any]:
146
+ """
147
+ Get app info
148
+
149
+ Args:
150
+ serial (str): Android device serialno
151
+ package_name (str): package name
152
+
153
+ Returns:
154
+ dict[str,Any]: app info
155
+
156
+ Example:
157
+ {"versionName": "1.1.7", "versionCode": 1001007}
158
+ """
159
+ async with get_device(serial) as device:
160
+ return await asyncio.to_thread(device.app_info, package_name)
161
+
162
+
163
+ @mcp.tool("app_current")
164
+ async def app_current(serial: str) -> dict[str, Any]:
165
+ """
166
+ Get current app info
167
+
168
+ Args:
169
+ serial (str): Android device serialno
170
+
171
+ Returns:
172
+ dict[str,Any]: running app info
173
+ """
174
+ async with get_device(serial) as device:
175
+ return await asyncio.to_thread(device.app_current)
176
+
177
+
178
+ @mcp.tool("app_list")
179
+ async def app_list(serial: str, filter: str = "") -> list[str]:
180
+ """
181
+ List installed app package names
182
+
183
+ Args:
184
+ serial (str): Android device serialno
185
+ filter (str): [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]
186
+
187
+ Returns:
188
+ list[str]: list of apps by filter
189
+ """
190
+ async with get_device(serial) as device:
191
+ return await asyncio.to_thread(device.app_list, filter.strip())
192
+
193
+
194
+ @mcp.tool("app_list_running")
195
+ async def app_list_running(serial: str) -> list[str]:
196
+ """
197
+ List running apps
198
+
199
+ Args:
200
+ serial (str): Android device serialno
201
+
202
+ Returns:
203
+ list[str]: list of running apps
204
+ """
205
+ async with get_device(serial) as device:
206
+ return await asyncio.to_thread(device.app_list_running)
207
+
208
+
209
+ @mcp.tool("app_auto_grant_permissions")
210
+ async def app_auto_grant_permissions(serial: str, package_name: str):
211
+ """auto grant permissions
212
+
213
+ Args:
214
+ serial (str): Android device serialno
215
+ package_name (str): package name
216
+
217
+ Help of "adb shell pm":
218
+ grant [--user USER_ID] PACKAGE PERMISSION
219
+ revoke [--user USER_ID] PACKAGE PERMISSION
220
+ These commands either grant or revoke permissions to apps. The permissions
221
+ must be declared as used in the app's manifest, be runtime permissions
222
+ (protection level dangerous), and the app targeting SDK greater than Lollipop MR1 (API level 22).
223
+
224
+ Help of "Android official pm" see <https://developer.android.com/tools/adb#pm>
225
+ Grant a permission to an app. On devices running Android 6.0 (API level 23) and higher,
226
+ the permission can be any permission declared in the app manifest.
227
+ On devices running Android 5.1 (API level 22) and lower,
228
+ must be an optional permission defined by the app.
229
+ """
230
+ async with get_device(serial) as device:
231
+ await asyncio.to_thread(device.app_auto_grant_permissions, package_name)
u2mcp/tools/device.py CHANGED
@@ -3,14 +3,14 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  import sys
5
5
  from base64 import b64encode
6
+ from collections.abc import AsyncGenerator
6
7
  from contextlib import asynccontextmanager
7
8
  from io import BytesIO
8
9
  from typing import Any, Literal
9
10
 
10
11
  import uiautomator2 as u2
11
12
  from adbutils import adb
12
- from fastmcp.dependencies import CurrentContext
13
- from fastmcp.server.context import Context
13
+ from fastmcp.server.dependencies import get_context
14
14
  from fastmcp.utilities.logging import get_logger
15
15
  from PIL.Image import Image
16
16
 
@@ -36,7 +36,7 @@ _device_connect_lock = asyncio.Lock()
36
36
 
37
37
 
38
38
  @asynccontextmanager
39
- async def get_device(serial: str):
39
+ async def get_device(serial: str) -> AsyncGenerator[u2.Device]:
40
40
  async with _device_connect_lock:
41
41
  try:
42
42
  semaphore, device = _devices[serial]
@@ -61,7 +61,7 @@ async def device_list() -> list[dict[str, Any]]:
61
61
 
62
62
 
63
63
  @mcp.tool("init")
64
- async def init(serial: str = "", ctx: Context = CurrentContext()):
64
+ async def init(serial: str = ""):
65
65
  """Install essential resources to device.
66
66
 
67
67
  Important:
@@ -110,6 +110,8 @@ async def init(serial: str = "", ctx: Context = CurrentContext()):
110
110
 
111
111
  logger.info("read uiautomator2 init command stdio")
112
112
 
113
+ ctx = get_context()
114
+
113
115
  while True:
114
116
  tag, line = await output_queue.get()
115
117
 
@@ -156,10 +158,10 @@ async def connect(serial: str = ""):
156
158
 
157
159
  if serial := serial.strip():
158
160
  try:
159
- async with get_device(serial) as device:
161
+ async with get_device(serial) as device_1:
160
162
  # Found, then check if it's still connected
161
163
  try:
162
- return await asyncio.to_thread(lambda: device.device_info | device.info)
164
+ return await asyncio.to_thread(lambda: device_1.device_info | device_1.info)
163
165
  except u2.ConnectError as e:
164
166
  # Found, but not connected, delete it
165
167
  logger.warning("Device %s is no longer connected, delete it!", serial)
@@ -172,6 +174,8 @@ async def connect(serial: str = ""):
172
174
  # make new connection here!
173
175
  async with _device_connect_lock:
174
176
  device = await asyncio.to_thread(u2.connect, serial)
177
+ if device is None:
178
+ raise RuntimeError("Cannot connect to device")
175
179
  logger.info("Connected to device %s", device.serial)
176
180
  result = await asyncio.to_thread(lambda: device.device_info | device.info)
177
181
  _devices[device.serial] = asyncio.Semaphore(), device
@@ -287,4 +291,3 @@ async def info(serial: str) -> dict[str, Any]:
287
291
 
288
292
  async with get_device(serial) as device:
289
293
  return await asyncio.to_thread(lambda: device.info)
290
-
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.4
2
+ Name: uiautomator2-mcp-server
3
+ Version: 0.1.2
4
+ Summary: uiautomator2 mcp server
5
+ Author-email: tanbro <tanbro@163.com>
6
+ License-Expression: GPL-3.0-or-later
7
+ Project-URL: homepage, https://github.com/tanbro/uiautomator2-mcp-server
8
+ Project-URL: documentation, https://github.com/tanbro/uiautomator2-mcp-server/blob/main/README.md
9
+ Project-URL: repository, https://github.com/tanbro/uiautomator2-mcp-server.git
10
+ Project-URL: issues, https://github.com/tanbro/uiautomator2-mcp-server/issues
11
+ Project-URL: changelog, https://github.com/tanbro/uiautomator2-mcp-server/blob/main/CHANGELOG.md
12
+ Keywords: uiautomator2,mcp,fastmcp,adb,android,adbutils
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: fastmcp<3.0,>=2.11.0
23
+ Requires-Dist: uiautomator2<4.0,>=3.5
24
+ Dynamic: license-file
25
+
26
+ # uiautomator2-mcp-server
27
+
28
+ [![GitHub Tag](https://img.shields.io/github/v/tag/tanbro/uiautomator2-mcp-server)](https://github.com/tanbro/uiautomator2-mcp-server)
29
+ [![PyPI - Version](https://img.shields.io/pypi/v/uiautomator2-mcp-server)](https://pypi.org/project/uiautomator2-mcp-server/)
30
+
31
+ A MCP (Model Context Protocol) server that provides tools for controlling and interacting with Android devices using uiautomator2. This server allows you to perform various operations on Android devices such as connecting to devices, taking screenshots, getting device information, accessing UI hierarchy, tap on screens, and more.
32
+
33
+ ## Features
34
+
35
+ - **Device Management**: List connected devices, initialize devices, connect/disconnect from devices
36
+ - **Screen Operations**: Take screenshots, get device window size, dump UI hierarchy
37
+ - **Touch Actions**: Click, long click, double click at specific coordinates
38
+ - **Gesture Controls**: Swipe, swipe through multiple points, drag operations
39
+ - **System Controls**: Screen on/off, key presses
40
+ - **App Management**: Install, uninstall, start, stop, clear, and manage Android applications
41
+ - **Text Operations**: Send text input, clear text fields
42
+
43
+ ## Requirements
44
+
45
+ - Python >= 3.11
46
+ - adb executable in your PATH
47
+ - Android device connected in debug mode
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ # Install the package
53
+ pip install uiautomator2-mcp-server
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ ### Running the Server
59
+
60
+ The server can be run in different transport modes:
61
+
62
+ ```bash
63
+ # Run in streamable HTTP mode
64
+ u2mcp --host 0.0.0.0 --port 8000 --no-token http
65
+
66
+ # Run in stdio mode
67
+ u2mcp stdio
68
+ ```
69
+
70
+ ### Using the Tools
71
+
72
+ Connect it to any tool that supports MCP protocol.
73
+
74
+ ## Available Tools
75
+
76
+ ### Device Management
77
+ - `device_list`: Get list of connected devices
78
+ - `init`: Install essential resources to device
79
+ - `connect`, `disconnect`, `disconnect_all`: Manage device connections
80
+ - `info`: Get device information
81
+ - `window_size`: Get device window size
82
+ - `screenshot`: Take device screenshot
83
+ - `dump_hierarchy`: Get UI hierarchy of device
84
+
85
+ ### Action Tools
86
+ - `click`: Click at specific coordinates
87
+ - `long_click`: Long click at specific coordinates
88
+ - `double_click`: Double click at specific coordinates
89
+ - `swipe`: Swipe from one point to another
90
+ - `swipe_points`: Swipe through multiple points
91
+ - `drag`: Drag from one point to another
92
+ - `press_key`: Press device key
93
+ - `send_text`: Send text to device
94
+ - `clear_text`: Clear text input
95
+ - `screen_on`/`screen_off`: Control screen state
96
+
97
+ ### App Management
98
+ - `app_install`: Install an app
99
+ - `app_uninstall`: Uninstall an app
100
+ - `app_uninstall_all`: Uninstall all apps
101
+ - `app_start`: Start an app
102
+ - `app_stop`: Stop an app
103
+ - `app_stop_all`: Stop all apps
104
+ - `app_clear`: Clear app data
105
+ - `app_info`: Get app information
106
+ - `app_current`: Get current app
107
+ - `app_list`: List installed apps
108
+ - `app_list_running`: List running apps
109
+ - `app_auto_grant_permissions`: Auto grant permissions
110
+
111
+ ## License
112
+
113
+ This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
@@ -0,0 +1,16 @@
1
+ u2mcp/.gitignore,sha256=mr9Izcwvjgv215xjRKhWEZ7vsyrKWhMqvWjSLHRYDjk,13
2
+ u2mcp/__init__.py,sha256=xsioVkbaN9sg-us_kNMeH-DojD8xM-h6Nlhde6uRHCQ,104
3
+ u2mcp/__main__.py,sha256=CBZpaNarWiWkg-g-BCfwFxaMdP4EqG5ckHtc-ZMMwcE,2813
4
+ u2mcp/_version.py,sha256=UPabfftDNarXNRt7p9IXx9_aYhCVscDiY35GxOcfT8s,738
5
+ u2mcp/mcp.py,sha256=jP87QaNePDt3LGzdZnlI5W8r8P-I0NrH3Tyj336ZQO8,2017
6
+ u2mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ u2mcp/tools/__init__.py,sha256=tKfsoF6tYQSapfGC1ybEcU4S77cipyfO5tYR6u0eAlI,66
8
+ u2mcp/tools/action.py,sha256=A9dCED1NiKOJpw9lBewOQ9YQvfGOkK8bEL1L9FLjCQg,5088
9
+ u2mcp/tools/app.py,sha256=b-cOdDtjSKC8KeUK5TTJCPRXtzvwSH74P02Cm3mS-ck,6809
10
+ u2mcp/tools/device.py,sha256=herrj5IQ1jEav2W6K4i7UidJ7eQsg-WJCiHJD1qYKVA,9196
11
+ uiautomator2_mcp_server-0.1.2.dist-info/licenses/LICENSE,sha256=ea2KuPdrBJ0Dhw1ncbc7siZDKG4cz2z-_8cSQiu4n1g,33122
12
+ uiautomator2_mcp_server-0.1.2.dist-info/METADATA,sha256=9BxLeh6VjVBCtTx4S6w4YMcl2Nu7aFv8lfUJZpbk44s,4251
13
+ uiautomator2_mcp_server-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ uiautomator2_mcp_server-0.1.2.dist-info/entry_points.txt,sha256=y7lg94G2U5_VgrDtyY8-Ne4ZClFtHo6eAs3RnShuDSI,92
15
+ uiautomator2_mcp_server-0.1.2.dist-info/top_level.txt,sha256=elTNF05b2GS8jjS4Haa3ESnG6xbfRjpyoSRsivT0Uks,6
16
+ uiautomator2_mcp_server-0.1.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -1,3 +1,3 @@
1
1
  [console_scripts]
2
2
  u2mcp = u2mcp.__main__:main
3
-
3
+ uiautomator2-mcp-server = u2mcp.__main__:main