mobile-mcp-ai 2.2.6__py3-none-any.whl → 2.5.3__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.
Files changed (52) hide show
  1. mobile_mcp/config.py +3 -2
  2. mobile_mcp/core/basic_tools_lite.py +3193 -0
  3. mobile_mcp/core/ios_client_wda.py +569 -0
  4. mobile_mcp/core/ios_device_manager_wda.py +306 -0
  5. mobile_mcp/core/mobile_client.py +246 -20
  6. mobile_mcp/core/template_matcher.py +429 -0
  7. mobile_mcp/core/templates/close_buttons/auto_x_0112_151217.png +0 -0
  8. mobile_mcp/core/templates/close_buttons/auto_x_0112_152037.png +0 -0
  9. mobile_mcp/core/templates/close_buttons/auto_x_0112_152840.png +0 -0
  10. mobile_mcp/core/templates/close_buttons/auto_x_0112_153256.png +0 -0
  11. mobile_mcp/core/templates/close_buttons/auto_x_0112_154847.png +0 -0
  12. mobile_mcp/core/templates/close_buttons/gray_x_stock_ad.png +0 -0
  13. mobile_mcp/mcp_tools/__init__.py +10 -0
  14. mobile_mcp/mcp_tools/mcp_server.py +992 -0
  15. mobile_mcp_ai-2.5.3.dist-info/METADATA +456 -0
  16. mobile_mcp_ai-2.5.3.dist-info/RECORD +32 -0
  17. mobile_mcp_ai-2.5.3.dist-info/entry_points.txt +2 -0
  18. mobile_mcp/core/ai/__init__.py +0 -11
  19. mobile_mcp/core/ai/ai_analyzer.py +0 -197
  20. mobile_mcp/core/ai/ai_config.py +0 -116
  21. mobile_mcp/core/ai/ai_platform_adapter.py +0 -399
  22. mobile_mcp/core/ai/smart_test_executor.py +0 -520
  23. mobile_mcp/core/ai/test_generator.py +0 -365
  24. mobile_mcp/core/ai/test_generator_from_history.py +0 -391
  25. mobile_mcp/core/ai/test_generator_standalone.py +0 -293
  26. mobile_mcp/core/assertion/__init__.py +0 -9
  27. mobile_mcp/core/assertion/smart_assertion.py +0 -341
  28. mobile_mcp/core/basic_tools.py +0 -945
  29. mobile_mcp/core/h5/__init__.py +0 -10
  30. mobile_mcp/core/h5/h5_handler.py +0 -548
  31. mobile_mcp/core/ios_client.py +0 -219
  32. mobile_mcp/core/ios_device_manager.py +0 -252
  33. mobile_mcp/core/locator/__init__.py +0 -10
  34. mobile_mcp/core/locator/cursor_ai_auto_analyzer.py +0 -119
  35. mobile_mcp/core/locator/cursor_vision_helper.py +0 -414
  36. mobile_mcp/core/locator/mobile_smart_locator.py +0 -1747
  37. mobile_mcp/core/locator/position_analyzer.py +0 -813
  38. mobile_mcp/core/locator/script_updater.py +0 -157
  39. mobile_mcp/core/nl_test_runner.py +0 -585
  40. mobile_mcp/core/smart_app_launcher.py +0 -421
  41. mobile_mcp/core/smart_tools.py +0 -311
  42. mobile_mcp/mcp/__init__.py +0 -13
  43. mobile_mcp/mcp/mcp_server.py +0 -1126
  44. mobile_mcp/mcp/mcp_server_simple.py +0 -23
  45. mobile_mcp/vision/__init__.py +0 -10
  46. mobile_mcp/vision/vision_locator.py +0 -405
  47. mobile_mcp_ai-2.2.6.dist-info/METADATA +0 -503
  48. mobile_mcp_ai-2.2.6.dist-info/RECORD +0 -49
  49. mobile_mcp_ai-2.2.6.dist-info/entry_points.txt +0 -2
  50. {mobile_mcp_ai-2.2.6.dist-info → mobile_mcp_ai-2.5.3.dist-info}/WHEEL +0 -0
  51. {mobile_mcp_ai-2.2.6.dist-info → mobile_mcp_ai-2.5.3.dist-info}/licenses/LICENSE +0 -0
  52. {mobile_mcp_ai-2.2.6.dist-info → mobile_mcp_ai-2.5.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,456 @@
1
+ Metadata-Version: 2.4
2
+ Name: mobile-mcp-ai
3
+ Version: 2.5.3
4
+ Summary: 移动端自动化 MCP Server - 支持 Android/iOS,AI 功能可选(基础工具不需要 AI)
5
+ Home-page: https://github.com/test111ddff-hash/mobile-mcp-ai
6
+ Author: douzi
7
+ Author-email: 1492994674@qq.com
8
+ Project-URL: Documentation, https://github.com/test111ddff-hash/mobile-mcp-ai
9
+ Project-URL: Source, https://github.com/test111ddff-hash/mobile-mcp-ai
10
+ Project-URL: Tracker, https://github.com/test111ddff-hash/mobile-mcp-ai/issues
11
+ Keywords: mobile,automation,testing,android,ios,mcp,ai,pytest,cursor
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: uiautomator2>=2.16.0
26
+ Requires-Dist: adbutils>=1.2.0
27
+ Requires-Dist: Pillow>=10.0.0
28
+ Requires-Dist: mcp>=0.9.0
29
+ Requires-Dist: python-dotenv>=1.0.0
30
+ Provides-Extra: ai
31
+ Requires-Dist: dashscope>=1.10.0; extra == "ai"
32
+ Requires-Dist: openai>=1.0.0; extra == "ai"
33
+ Requires-Dist: anthropic>=0.3.0; extra == "ai"
34
+ Provides-Extra: test
35
+ Requires-Dist: pytest>=8.0.0; extra == "test"
36
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
37
+ Requires-Dist: allure-pytest>=2.13.0; extra == "test"
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
40
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
41
+ Requires-Dist: twine>=4.0.0; extra == "dev"
42
+ Requires-Dist: build>=0.10.0; extra == "dev"
43
+ Provides-Extra: ios
44
+ Requires-Dist: tidevice>=0.11.0; extra == "ios"
45
+ Requires-Dist: facebook-wda>=1.4.0; extra == "ios"
46
+ Provides-Extra: h5
47
+ Requires-Dist: Appium-Python-Client>=3.0.0; extra == "h5"
48
+ Requires-Dist: selenium>=4.0.0; extra == "h5"
49
+ Provides-Extra: all
50
+ Requires-Dist: dashscope>=1.10.0; extra == "all"
51
+ Requires-Dist: openai>=1.0.0; extra == "all"
52
+ Requires-Dist: anthropic>=0.3.0; extra == "all"
53
+ Requires-Dist: Appium-Python-Client>=3.0.0; extra == "all"
54
+ Requires-Dist: selenium>=4.0.0; extra == "all"
55
+ Requires-Dist: pytest>=8.0.0; extra == "all"
56
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "all"
57
+ Requires-Dist: allure-pytest>=2.13.0; extra == "all"
58
+ Dynamic: author
59
+ Dynamic: author-email
60
+ Dynamic: classifier
61
+ Dynamic: description
62
+ Dynamic: description-content-type
63
+ Dynamic: home-page
64
+ Dynamic: keywords
65
+ Dynamic: license-file
66
+ Dynamic: project-url
67
+ Dynamic: provides-extra
68
+ Dynamic: requires-dist
69
+ Dynamic: requires-python
70
+ Dynamic: summary
71
+
72
+ # 📱 Mobile MCP AI
73
+
74
+ > 让 Cursor 直接控制手机的 MCP 工具
75
+
76
+ <div align="center">
77
+
78
+ [![PyPI](https://img.shields.io/pypi/v/mobile-mcp-ai.svg?style=flat-square&color=blue)](https://pypi.org/project/mobile-mcp-ai/)
79
+ [![Python](https://img.shields.io/badge/python-3.8+-green.svg?style=flat-square)](https://www.python.org/)
80
+ [![License](https://img.shields.io/badge/license-Apache%202.0-orange.svg?style=flat-square)](LICENSE)
81
+ [![Android](https://img.shields.io/badge/Android-支持-brightgreen.svg?style=flat-square&logo=android)](https://developer.android.com/)
82
+ [![iOS](https://img.shields.io/badge/iOS-支持-black.svg?style=flat-square&logo=apple)](docs/iOS_SETUP_GUIDE.md)
83
+
84
+ **⭐ 觉得有用?给个 Star 支持一下!**
85
+
86
+ **📱 支持 Android 和 iOS 双平台**
87
+
88
+ </div>
89
+
90
+ ---
91
+
92
+ ## 🎬 演示
93
+
94
+ <div align="center">
95
+
96
+ ![演示动图](docs/videos/demo.gif)
97
+
98
+ *[查看高清视频 →](docs/videos/demo.mp4)*
99
+
100
+ </div>
101
+
102
+ ---
103
+
104
+ ## ✨ 核心特性
105
+
106
+ <table>
107
+ <tr>
108
+ <td width="50%">
109
+
110
+ ### 🧠 AI 原生驱动
111
+
112
+ 基于 MCP 协议与 Cursor AI 深度集成,自然语言直接操控手机,告别繁琐的脚本编写
113
+
114
+ </td>
115
+ <td width="50%">
116
+
117
+ ### 👁️ 视觉智能识别
118
+
119
+ Cursor AI 自动分析截图,精准定位 UI 元素,游戏、原生应用通吃
120
+
121
+ </td>
122
+ </tr>
123
+ <tr>
124
+ <td width="50%">
125
+
126
+ ### ⚡ 零配置启动
127
+
128
+ `pip install` 一行命令,开箱即用,无需额外 AI 密钥
129
+
130
+ </td>
131
+ <td width="50%">
132
+
133
+ ### 🔄 一键生成脚本
134
+
135
+ 操作即录制,自动生成可复用的 pytest 测试脚本
136
+
137
+ </td>
138
+ </tr>
139
+ <tr>
140
+ <td width="50%">
141
+
142
+ ### 🎯 双模式定位
143
+
144
+ 元素树 + 视觉坐标双引擎,普通 App 秒定位,游戏场景不迷路
145
+
146
+ </td>
147
+ <td width="50%">
148
+
149
+ ### 🛡️ 智能验证机制
150
+
151
+ 按键操作自动验证生效,告别"假成功"
152
+
153
+ </td>
154
+ </tr>
155
+ </table>
156
+
157
+ ---
158
+
159
+ ## 📱 平台支持
160
+
161
+ | 平台 | 支持状态 | 系统要求 | 配置指南 |
162
+ |:---:|:---:|:---:|:---:|
163
+ | **Android** | ✅ 完整支持 | Windows / macOS / Linux | 开箱即用 |
164
+ | **iOS** | ✅ 完整支持 | macOS(必须) | [iOS 配置指南 →](docs/iOS_SETUP_GUIDE.md) |
165
+
166
+ ---
167
+
168
+ ## 📦 安装
169
+
170
+ ```bash
171
+ pip install mobile-mcp-ai
172
+ ```
173
+
174
+ **升级到最新版**
175
+
176
+ ```bash
177
+ pip install --upgrade mobile-mcp-ai
178
+ ```
179
+
180
+ **查看当前版本**
181
+
182
+ ```bash
183
+ pip show mobile-mcp-ai
184
+ ```
185
+
186
+ ---
187
+
188
+ ## 📱 连接设备
189
+
190
+ ### Android 设备
191
+
192
+ 确保手机已开启 USB 调试,然后:
193
+
194
+ ```bash
195
+ adb devices
196
+ ```
197
+
198
+ 看到设备列表即表示连接成功。
199
+
200
+ ### iOS 设备(macOS)
201
+
202
+ iOS 自动化需要额外配置 WebDriverAgent,请参考:
203
+
204
+ 📖 **[iOS 配置指南 →](docs/iOS_SETUP_GUIDE.md)**
205
+
206
+ 快速检查连接:
207
+ ```bash
208
+ tidevice list
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 🎯 新用户快速入门
214
+
215
+ ### 第一步:安装
216
+
217
+ ```bash
218
+ pip install mobile-mcp-ai
219
+ ```
220
+
221
+ ### 第二步:连接设备
222
+
223
+ **Android 用户:**
224
+ ```bash
225
+ # 开启手机 USB 调试,连接电脑
226
+ adb devices
227
+ ```
228
+
229
+ **iOS 用户:**
230
+ ```bash
231
+ # 安装依赖
232
+ pip install tidevice facebook-wda
233
+ brew install libimobiledevice
234
+
235
+ # 检查连接
236
+ tidevice list
237
+ ```
238
+
239
+ > 📖 iOS 需要额外配置 WebDriverAgent,详见 **[iOS 配置指南](docs/iOS_SETUP_GUIDE.md)**
240
+
241
+ ### 第三步:配置 Cursor
242
+
243
+ 编辑 `~/.cursor/mcp.json`:
244
+
245
+ ```json
246
+ {
247
+ "mcpServers": {
248
+ "mobile-automation": {
249
+ "command": "mobile-mcp"
250
+ }
251
+ }
252
+ }
253
+ ```
254
+
255
+ > 💡 提示:会自动检测 Android/iOS 设备,无需额外配置
256
+
257
+ ### 第四步:重启 Cursor
258
+
259
+ 保存配置后,**重启 Cursor** 使配置生效。
260
+
261
+ ### 第五步:开始使用
262
+
263
+ 在 Cursor 中输入:
264
+
265
+ ```
266
+ @MCP 检查设备连接
267
+ ```
268
+
269
+ ```
270
+ @MCP 截图看看当前页面
271
+ ```
272
+
273
+ ```
274
+ @MCP 点击"登录"按钮
275
+ ```
276
+
277
+ ---
278
+
279
+ ## ⚙️ 高级配置
280
+
281
+ ### 方式一:pip 安装后配置(推荐)
282
+
283
+ 先安装:`pip install mobile-mcp-ai`
284
+
285
+ ```json
286
+ {
287
+ "mcpServers": {
288
+ "mobile-automation": {
289
+ "command": "mobile-mcp"
290
+ }
291
+ }
292
+ }
293
+ ```
294
+
295
+ ### 方式二:源码方式配置
296
+
297
+ 如果你是从源码运行:
298
+
299
+ **Android 配置:**
300
+
301
+ ```json
302
+ {
303
+ "mcpServers": {
304
+ "mobile-automation": {
305
+ "command": "/path/to/your/venv/bin/python",
306
+ "args": ["-m", "mobile_mcp.mcp_tools.mcp_server"],
307
+ "cwd": "/path/to/mobile_mcp",
308
+ "env": {
309
+ "MOBILE_PLATFORM": "android"
310
+ }
311
+ }
312
+ }
313
+ }
314
+ ```
315
+
316
+ **iOS 配置:**
317
+
318
+ ```json
319
+ {
320
+ "mcpServers": {
321
+ "mobile-automation": {
322
+ "command": "/path/to/your/venv/bin/python",
323
+ "args": ["-m", "mobile_mcp.mcp_tools.mcp_server"],
324
+ "cwd": "/path/to/mobile_mcp",
325
+ "env": {
326
+ "MOBILE_PLATFORM": "ios"
327
+ }
328
+ }
329
+ }
330
+ }
331
+ ```
332
+
333
+ > ⚠️ 请将 `/path/to/` 替换为你的实际路径
334
+ >
335
+ > 📖 iOS 需要先配置 WebDriverAgent,详见 **[iOS 配置指南](docs/iOS_SETUP_GUIDE.md)**
336
+
337
+ 保存后**重启 Cursor**。
338
+
339
+ ---
340
+
341
+ ## 🚀 使用示例
342
+
343
+ 在 Cursor 中直接对话:
344
+
345
+ **基础操作**
346
+
347
+ ```
348
+ @MCP 列出当前页面所有元素
349
+ ```
350
+
351
+ ```
352
+ @MCP 点击"登录"按钮
353
+ ```
354
+
355
+ ```
356
+ @MCP 在用户名输入框输入 test123
357
+ ```
358
+
359
+ **应用控制**
360
+
361
+ ```
362
+ @MCP 启动微信
363
+ ```
364
+
365
+ ```
366
+ @MCP 打开抖音,向上滑动 3 次
367
+ ```
368
+
369
+ ```
370
+ @MCP 列出手机上所有已安装的应用
371
+ ```
372
+
373
+ **截图分析**
374
+
375
+ ```
376
+ @MCP 截图看看当前页面
377
+ ```
378
+
379
+ ```
380
+ @MCP 截图,然后点击页面上的搜索图标
381
+ ```
382
+
383
+ **测试脚本生成**
384
+
385
+ ```
386
+ @MCP 帮我测试登录流程:输入用户名密码,点击登录
387
+ ```
388
+
389
+ ```
390
+ @MCP 把刚才的操作生成 pytest 测试脚本
391
+ ```
392
+
393
+ **组合操作**
394
+
395
+ ```
396
+ @MCP 打开设置,找到 WLAN,点进去截图
397
+ ```
398
+
399
+ ```
400
+ @MCP 打开微信,点击发现,再点击朋友圈
401
+ ```
402
+
403
+ ---
404
+
405
+ ## 🛠️ 工具列表
406
+
407
+ | 类别 | 工具 | 说明 |
408
+ |:---:|------|------|
409
+ | 📋 | `mobile_list_elements` | 列出页面元素 |
410
+ | 📸 | `mobile_take_screenshot` | 截图 |
411
+ | 📐 | `mobile_get_screen_size` | 屏幕尺寸 |
412
+ | 👆 | `mobile_click_by_text` | 文本点击 |
413
+ | 👆 | `mobile_click_by_id` | ID 点击 |
414
+ | 👆 | `mobile_click_at_coords` | 坐标点击 |
415
+ | ⌨️ | `mobile_input_text_by_id` | ID 输入 |
416
+ | ⌨️ | `mobile_input_at_coords` | 坐标输入 |
417
+ | 👆 | `mobile_swipe` | 滑动 |
418
+ | ⌨️ | `mobile_press_key` | 按键 |
419
+ | ⏱️ | `mobile_wait` | 等待 |
420
+ | 📦 | `mobile_launch_app` | 启动应用 |
421
+ | 📦 | `mobile_terminate_app` | 终止应用 |
422
+ | 📦 | `mobile_list_apps` | 列出应用 |
423
+ | 📱 | `mobile_list_devices` | 列出设备 |
424
+ | 🔌 | `mobile_check_connection` | 检查连接 |
425
+ | ✅ | `mobile_assert_text` | 断言文本 |
426
+ | 📜 | `mobile_get_operation_history` | 操作历史 |
427
+ | 🗑️ | `mobile_clear_operation_history` | 清空历史 |
428
+ | 📝 | `mobile_generate_test_script` | 生成测试脚本 |
429
+
430
+ ---
431
+
432
+ ## 📞 联系作者
433
+
434
+ <div align="center">
435
+
436
+ <img src="docs/images/wechat-qr.jpg" alt="微信" width="250"/>
437
+
438
+ *添加微信交流(备注:mobile-mcp)*
439
+
440
+ </div>
441
+
442
+ ---
443
+
444
+ ## 📄 License
445
+
446
+ Apache 2.0
447
+
448
+ ---
449
+
450
+ <div align="center">
451
+
452
+ [Gitee](https://gitee.com/chang-xinping/mobile-automation-mcp-service) · [GitHub](https://github.com/test111ddff-hash/mobile-mcp-ai) · [PyPI](https://pypi.org/project/mobile-mcp-ai/)
453
+
454
+ **🚀 让移动端测试更简单**
455
+
456
+ </div>
@@ -0,0 +1,32 @@
1
+ mobile_mcp/__init__.py,sha256=sQJZTL_sxQFzmcS7jOtS2AHCfUySz40vhX96N6u1qy4,816
2
+ mobile_mcp/config.py,sha256=yaFLAV4bc2wX0GQPtZDo7OYF9E88tXV-av41fQsJwK4,4480
3
+ mobile_mcp/core/__init__.py,sha256=ndMy-cLAIsQDG5op7gM_AIplycqZSZPWEkec1pEhvEY,170
4
+ mobile_mcp/core/basic_tools_lite.py,sha256=BzPT180GPQjhTNHaAKl46m1jvCM5KoQIPgySGdNSD30,149836
5
+ mobile_mcp/core/device_manager.py,sha256=PX3-B5bJFnKNt6C8fT7FSY8JwD-ngZ3toF88bcOV9qA,8766
6
+ mobile_mcp/core/dynamic_config.py,sha256=Ja1n1pfb0HspGByqk2_A472mYVniKmGtNEWyjUjmgK8,9811
7
+ mobile_mcp/core/ios_client_wda.py,sha256=Nq9WxevhTWpVpolM-Ymp-b0nUQV3tXLFszmJHbDC4wA,18770
8
+ mobile_mcp/core/ios_device_manager_wda.py,sha256=A44glqI-24un7qST-E3w6BQD8mV92YVUbxy4rLlTScY,11264
9
+ mobile_mcp/core/mobile_client.py,sha256=bno3HvU-QSAC3G4TnoFngTxqXeu-ZP5rGlEWdWh8jOo,62570
10
+ mobile_mcp/core/template_matcher.py,sha256=tv8RU6zdeDobqphaP4Y8sicb1esg3gcQlZae1tNyitM,14559
11
+ mobile_mcp/core/templates/close_buttons/auto_x_0112_151217.png,sha256=s7tBVaYLBApNSEXjwi5kX8GXwUqgbNyNVEhXYjN9nd4,27373
12
+ mobile_mcp/core/templates/close_buttons/auto_x_0112_152037.png,sha256=s7tBVaYLBApNSEXjwi5kX8GXwUqgbNyNVEhXYjN9nd4,27373
13
+ mobile_mcp/core/templates/close_buttons/auto_x_0112_152840.png,sha256=s7tBVaYLBApNSEXjwi5kX8GXwUqgbNyNVEhXYjN9nd4,27373
14
+ mobile_mcp/core/templates/close_buttons/auto_x_0112_153256.png,sha256=s7tBVaYLBApNSEXjwi5kX8GXwUqgbNyNVEhXYjN9nd4,27373
15
+ mobile_mcp/core/templates/close_buttons/auto_x_0112_154847.png,sha256=apPPFft1LLP_4KppbRGd2zOl3nfSGYFqzYeyzncaduk,27679
16
+ mobile_mcp/core/templates/close_buttons/gray_x_stock_ad.png,sha256=5D3pOa74Zj21v7I-zpYo2Pe4ZC8PB-N3_yo_LFNnlLw,4504
17
+ mobile_mcp/core/utils/__init__.py,sha256=RhMMsPszmEn8Q8GoNufypVSHJxyM9lio9U6jjpnuoPI,378
18
+ mobile_mcp/core/utils/logger.py,sha256=XXQAHUwT1jc70pq_tYFmL6f_nKrFlYm3hcgl-5RYRg0,3402
19
+ mobile_mcp/core/utils/operation_history_manager.py,sha256=gi8S8HJAMqvkUrY7_-kVbko3Xt7c4GAUziEujRd-N-Y,4792
20
+ mobile_mcp/core/utils/smart_wait.py,sha256=PvKXImfN9Irru3bQJUjf4FLGn8LjY2VLzUNEl-i7xLE,8601
21
+ mobile_mcp/mcp_tools/__init__.py,sha256=xkro8Rwqv_55YlVyhh-3DgRFSsLE3h1r31VIb3bpM6E,143
22
+ mobile_mcp/mcp_tools/mcp_server.py,sha256=jN4ooXb4yzrRhC_4POdLtxppWCAfBjVUVoov8RMLfyw,46054
23
+ mobile_mcp/utils/__init__.py,sha256=8EH0i7UGtx1y_j_GEgdN-cZdWn2sRtZSEOLlNF9HRnY,158
24
+ mobile_mcp/utils/logger.py,sha256=Sqq2Nr0Y4p03erqcrbYKVPCGiFaNGHMcE_JwCkeOfU4,3626
25
+ mobile_mcp/utils/xml_formatter.py,sha256=uwTRb3vLbqhT8O-udzWT7s7LsV-DyDUz2DkofD3hXOE,4556
26
+ mobile_mcp/utils/xml_parser.py,sha256=QhL8CWbdmNDzmBLjtx6mEnjHgMFZzJeHpCL15qfXSpI,3926
27
+ mobile_mcp_ai-2.5.3.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
28
+ mobile_mcp_ai-2.5.3.dist-info/METADATA,sha256=3SFUMmLse8MPlU8ihd1JcvTGNShkp1JgCbtAs8nS_eM,9745
29
+ mobile_mcp_ai-2.5.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ mobile_mcp_ai-2.5.3.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
31
+ mobile_mcp_ai-2.5.3.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
32
+ mobile_mcp_ai-2.5.3.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mobile-mcp = mobile_mcp.mcp_tools.mcp_server:main
@@ -1,11 +0,0 @@
1
- """
2
- 移动端AI工具模块
3
- """
4
-
5
- from .test_generator import MobileTestGenerator, MobileTestStep
6
-
7
- __all__ = [
8
- 'MobileTestGenerator',
9
- 'MobileTestStep',
10
- ]
11
-
@@ -1,197 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- AI分析器 - 智能兜底,分析候选元素
5
- """
6
- import sys
7
- import json
8
- from typing import Dict, List, Optional
9
- from .ai_config import ai_config
10
-
11
-
12
- class AIAnalyzer:
13
- """AI分析器 - 用于智能兜底"""
14
-
15
- def __init__(self):
16
- """初始化AI分析器"""
17
- self.config = ai_config
18
-
19
- async def analyze_candidates(self, query: str, candidates: List[Dict], context: str = "") -> Optional[Dict]:
20
- """
21
- 分析候选元素,选择最佳匹配
22
-
23
- Args:
24
- query: 用户查询
25
- candidates: 候选元素列表
26
- context: 上下文信息(可选)
27
-
28
- Returns:
29
- 最佳匹配的元素信息
30
- """
31
- if not self.config.is_configured():
32
- print(" ⚠️ AI未配置,跳过AI分析", file=sys.stderr)
33
- return None
34
-
35
- if not candidates:
36
- print(" ⚠️ 没有候选元素,跳过AI分析", file=sys.stderr)
37
- return None
38
-
39
- try:
40
- import httpx
41
-
42
- # 构建提示词
43
- prompt = self._build_prompt(query, candidates, context)
44
-
45
- print(f" 🤖 调用AI分析(模型: {self.config.model})...", file=sys.stderr)
46
-
47
- # 调用通义千问API
48
- async with httpx.AsyncClient(timeout=self.config.timeout) as client:
49
- response = await client.post(
50
- f"{self.config.api_base}/chat/completions",
51
- headers={
52
- "Authorization": f"Bearer {self.config.api_key}",
53
- "Content-Type": "application/json"
54
- },
55
- json={
56
- "model": self.config.model,
57
- "messages": [
58
- {
59
- "role": "system",
60
- "content": "你是一个专业的移动端UI元素分析助手。请根据用户查询和候选元素,选择最匹配的元素,并返回JSON格式的结果。"
61
- },
62
- {
63
- "role": "user",
64
- "content": prompt
65
- }
66
- ],
67
- "temperature": 0.1, # 低温度,更确定性
68
- "response_format": {"type": "json_object"} # 强制返回JSON
69
- }
70
- )
71
-
72
- if response.status_code != 200:
73
- print(f" ❌ AI调用失败: HTTP {response.status_code}", file=sys.stderr)
74
- print(f" {response.text}", file=sys.stderr)
75
- return None
76
-
77
- result = response.json()
78
- ai_response = result['choices'][0]['message']['content']
79
-
80
- # 解析AI返回的JSON
81
- ai_result = json.loads(ai_response)
82
-
83
- if not ai_result.get('selected_index'):
84
- print(f" ⚠️ AI未能选择元素", file=sys.stderr)
85
- return None
86
-
87
- selected_index = ai_result['selected_index'] - 1 # 转换为0-based索引
88
-
89
- if selected_index < 0 or selected_index >= len(candidates):
90
- print(f" ⚠️ AI返回的索引无效: {selected_index + 1}", file=sys.stderr)
91
- return None
92
-
93
- selected = candidates[selected_index]
94
- confidence = ai_result.get('confidence', 85)
95
- reason = ai_result.get('reason', '未提供原因')
96
-
97
- print(f" ✅ AI选择: 候选{selected_index + 1}/{len(candidates)}", file=sys.stderr)
98
- print(f" 元素: {selected.get('text') or selected.get('content_desc') or selected.get('class_name')}", file=sys.stderr)
99
- print(f" 置信度: {confidence}%", file=sys.stderr)
100
- print(f" 理由: {reason}", file=sys.stderr)
101
-
102
- return {
103
- 'element': selected.get('text') or selected.get('content_desc') or query,
104
- 'ref': self._get_ref(selected),
105
- 'confidence': confidence,
106
- 'method': 'ai_analysis',
107
- 'reason': reason
108
- }
109
-
110
- except Exception as e:
111
- print(f" ❌ AI分析异常: {e}", file=sys.stderr)
112
- import traceback
113
- traceback.print_exc()
114
- return None
115
-
116
- def _build_prompt(self, query: str, candidates: List[Dict], context: str) -> str:
117
- """构建AI提示词"""
118
- # 格式化候选元素
119
- candidates_text = []
120
- for i, elem in enumerate(candidates, 1):
121
- text = elem.get('text', '')
122
- desc = elem.get('content_desc', '')
123
- resource_id = elem.get('resource_id', '')
124
- class_name = elem.get('class_name', '')
125
- bounds = elem.get('bounds', '')
126
- clickable = elem.get('clickable', False)
127
- focusable = elem.get('focusable', False)
128
-
129
- # 计算位置
130
- position = "未知"
131
- if bounds:
132
- try:
133
- # bounds格式: "[x1,y1][x2,y2]"
134
- coords = bounds.replace('[', '').replace(']', ',').split(',')
135
- y1 = int(coords[1])
136
- if y1 < 400:
137
- position = "顶部"
138
- elif y1 < 800:
139
- position = "中部"
140
- else:
141
- position = "底部"
142
- except:
143
- pass
144
-
145
- parts = [f"候选{i}:"]
146
- if text:
147
- parts.append(f"文本=\"{text[:50]}\"")
148
- if desc:
149
- parts.append(f"描述=\"{desc[:50]}\"")
150
- if resource_id:
151
- parts.append(f"ID={resource_id}")
152
- parts.append(f"类型={class_name}")
153
- parts.append(f"位置={position}")
154
- if clickable:
155
- parts.append("可点击")
156
- if focusable:
157
- parts.append("可聚焦")
158
-
159
- candidates_text.append(" | ".join(parts))
160
-
161
- prompt = f"""
162
- 用户查询: "{query}"
163
-
164
- 页面上有以下候选元素:
165
- {chr(10).join(candidates_text)}
166
-
167
- {f"上下文信息: {context}" if context else ""}
168
-
169
- 请分析哪个元素最匹配用户查询,并返回JSON格式:
170
- {{
171
- "selected_index": <1到{len(candidates)}的数字>,
172
- "confidence": <置信度0-100>,
173
- "reason": "<选择理由>"
174
- }}
175
-
176
- 分析要点:
177
- 1. 优先匹配文本/描述的语义
178
- 2. 考虑元素类型是否合理(如输入框应该是EditText)
179
- 3. 考虑元素位置(如"顶部按钮"、"底部输入框")
180
- 4. 考虑用户意图(如"点击"需要可点击元素)
181
- """
182
- return prompt
183
-
184
- def _get_ref(self, element: Dict) -> str:
185
- """获取元素引用"""
186
- # 优先级: resource_id > content_desc > text > bounds
187
- return (
188
- element.get('resource_id') or
189
- element.get('content_desc') or
190
- element.get('text') or
191
- element.get('bounds', '')
192
- )
193
-
194
-
195
- # 全局实例
196
- ai_analyzer = AIAnalyzer()
197
-