mobile-mcp-ai 2.6.7__py3-none-any.whl → 2.6.10__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.
- mobile_mcp/core/basic_tools_lite.py +1501 -669
- mobile_mcp/mcp_tools/mcp_server.py +153 -45
- {mobile_mcp_ai-2.6.7.dist-info → mobile_mcp_ai-2.6.10.dist-info}/METADATA +1 -1
- {mobile_mcp_ai-2.6.7.dist-info → mobile_mcp_ai-2.6.10.dist-info}/RECORD +8 -8
- {mobile_mcp_ai-2.6.7.dist-info → mobile_mcp_ai-2.6.10.dist-info}/WHEEL +0 -0
- {mobile_mcp_ai-2.6.7.dist-info → mobile_mcp_ai-2.6.10.dist-info}/entry_points.txt +0 -0
- {mobile_mcp_ai-2.6.7.dist-info → mobile_mcp_ai-2.6.10.dist-info}/licenses/LICENSE +0 -0
- {mobile_mcp_ai-2.6.7.dist-info → mobile_mcp_ai-2.6.10.dist-info}/top_level.txt +0 -0
|
@@ -248,18 +248,30 @@ class MobileMCPServer:
|
|
|
248
248
|
tools.append(Tool(
|
|
249
249
|
name="mobile_screenshot_with_som",
|
|
250
250
|
description="📸🏷️ Set-of-Mark 截图(⭐⭐ 强烈推荐!默认截图方式)\n\n"
|
|
251
|
-
"
|
|
251
|
+
"【智能标注】给每个可点击元素画框+编号。\n"
|
|
252
252
|
"AI 看图直接说'点击 3 号',调用 mobile_click_by_som(3) 即可!\n\n"
|
|
253
253
|
"🎯 优势:\n"
|
|
254
254
|
"- 元素有编号,精准点击不会误触\n"
|
|
255
|
-
"- 自动检测弹窗,标注可能的关闭按钮位置\n"
|
|
256
255
|
"- 适用于所有页面和所有操作\n\n"
|
|
257
256
|
"⚡ 推荐流程:\n"
|
|
258
257
|
"1. 找不到目标元素时,优先调用此工具\n"
|
|
259
258
|
"2. 看标注图,找到目标元素编号\n"
|
|
260
259
|
"3. 调用 mobile_click_by_som(编号) 精准点击\n"
|
|
261
|
-
"4.
|
|
262
|
-
|
|
260
|
+
"4. 🔴【必须】点击后再次截图确认操作是否成功!\n\n"
|
|
261
|
+
"💡 弹窗检测:\n"
|
|
262
|
+
"- check_popup=True: 明确弹窗场景时使用(如调用 mobile_close_popup 前)\n"
|
|
263
|
+
"- check_popup=False: 普通截图,不检测弹窗(默认)",
|
|
264
|
+
inputSchema={
|
|
265
|
+
"type": "object",
|
|
266
|
+
"properties": {
|
|
267
|
+
"check_popup": {
|
|
268
|
+
"type": "boolean",
|
|
269
|
+
"description": "是否检测弹窗,默认 False。仅在明确弹窗场景时设置为 True",
|
|
270
|
+
"default": False
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"required": []
|
|
274
|
+
}
|
|
263
275
|
))
|
|
264
276
|
|
|
265
277
|
tools.append(Tool(
|
|
@@ -530,7 +542,8 @@ class MobileMCPServer:
|
|
|
530
542
|
"- 📌 拖动进度条时,distance_percent 控制拖动幅度\n\n"
|
|
531
543
|
"💡 拖动进度条示例:\n"
|
|
532
544
|
"- 倒退:direction='left', y_percent=91(进度条位置), distance_percent=30\n"
|
|
533
|
-
"- 前进:direction='right', y_percent=91, distance_percent=30"
|
|
545
|
+
"- 前进:direction='right', y_percent=91, distance_percent=30\n\n"
|
|
546
|
+
"⚠️ **推荐使用 mobile_drag_progress_bar 拖动进度条**(自动检测进度条位置,无需手动指定)",
|
|
534
547
|
inputSchema={
|
|
535
548
|
"type": "object",
|
|
536
549
|
"properties": {
|
|
@@ -560,6 +573,50 @@ class MobileMCPServer:
|
|
|
560
573
|
}
|
|
561
574
|
))
|
|
562
575
|
|
|
576
|
+
tools.append(Tool(
|
|
577
|
+
name="mobile_drag_progress_bar",
|
|
578
|
+
description="🎯 智能拖动进度条(⭐⭐ 推荐用于拖动视频/音频进度条)\n\n"
|
|
579
|
+
"✅ **自动检测进度条是否可见**:\n"
|
|
580
|
+
"- 如果进度条已显示,直接拖动(无需先点击播放区域)\n"
|
|
581
|
+
"- 如果进度条未显示,自动点击播放区域显示控制栏,再拖动\n\n"
|
|
582
|
+
"🎯 优势:\n"
|
|
583
|
+
"- 自动检测进度条位置,无需手动指定 y_percent\n"
|
|
584
|
+
"- 智能判断是否需要显示控制栏\n"
|
|
585
|
+
"- 使用 swipe 拖动,更稳定可靠\n\n"
|
|
586
|
+
"💡 参数说明:\n"
|
|
587
|
+
"- direction: 'left'(倒退)或 'right'(前进),默认 'right'\n"
|
|
588
|
+
"- distance_percent: 拖动距离百分比 (0-100),默认 30%\n"
|
|
589
|
+
"- y_percent: 进度条位置(可选,未指定则自动检测)\n"
|
|
590
|
+
"- y: 进度条位置坐标(可选,未指定则自动检测)\n\n"
|
|
591
|
+
"📋 使用示例:\n"
|
|
592
|
+
"- 前进30%:mobile_drag_progress_bar(direction='right', distance_percent=30)\n"
|
|
593
|
+
"- 倒退30%:mobile_drag_progress_bar(direction='left', distance_percent=30)\n"
|
|
594
|
+
"- 前进到指定位置:先点击进度条位置,或使用 mobile_swipe",
|
|
595
|
+
inputSchema={
|
|
596
|
+
"type": "object",
|
|
597
|
+
"properties": {
|
|
598
|
+
"direction": {
|
|
599
|
+
"type": "string",
|
|
600
|
+
"enum": ["left", "right"],
|
|
601
|
+
"description": "拖动方向:'left'(倒退)或 'right'(前进),默认 'right'"
|
|
602
|
+
},
|
|
603
|
+
"distance_percent": {
|
|
604
|
+
"type": "number",
|
|
605
|
+
"description": "拖动距离百分比 (0-100),默认 30%"
|
|
606
|
+
},
|
|
607
|
+
"y_percent": {
|
|
608
|
+
"type": "number",
|
|
609
|
+
"description": "进度条的垂直位置百分比 (0-100),可选,未指定则自动检测"
|
|
610
|
+
},
|
|
611
|
+
"y": {
|
|
612
|
+
"type": "integer",
|
|
613
|
+
"description": "进度条的垂直位置坐标(像素),可选,未指定则自动检测"
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
"required": []
|
|
617
|
+
}
|
|
618
|
+
))
|
|
619
|
+
|
|
563
620
|
tools.append(Tool(
|
|
564
621
|
name="mobile_press_key",
|
|
565
622
|
description="⌨️ 按键操作。支持:home, back, enter, search",
|
|
@@ -587,7 +644,12 @@ class MobileMCPServer:
|
|
|
587
644
|
# ==================== 应用管理 ====================
|
|
588
645
|
tools.append(Tool(
|
|
589
646
|
name="mobile_launch_app",
|
|
590
|
-
description="🚀
|
|
647
|
+
description="""🚀 启动应用
|
|
648
|
+
|
|
649
|
+
🎯 弹窗检测场景:启动应用后会自动检测弹窗(启动应用场景)
|
|
650
|
+
|
|
651
|
+
启动后建议等待 2-3 秒让页面加载。
|
|
652
|
+
如果检测到弹窗,返回结果中会包含 popup_detected=true,建议调用 mobile_close_popup() 关闭弹窗。""",
|
|
591
653
|
inputSchema={
|
|
592
654
|
"type": "object",
|
|
593
655
|
"properties": {
|
|
@@ -644,10 +706,13 @@ class MobileMCPServer:
|
|
|
644
706
|
从元素树中找最可能的关闭按钮,返回坐标和推荐的点击命令。
|
|
645
707
|
|
|
646
708
|
🎯 识别策略(优先级):
|
|
647
|
-
1.
|
|
648
|
-
2. resource-id
|
|
649
|
-
3.
|
|
650
|
-
4.
|
|
709
|
+
1. 确认性按钮文本:同意、确认、允许、好的、OK等(得分120)
|
|
710
|
+
2. 确认性 resource-id:包含 confirm/accept/agree/allow(得分115)
|
|
711
|
+
3. 关闭/取消按钮文本:×、X、关闭、取消、跳过等(得分100)
|
|
712
|
+
4. 关闭类 resource-id:包含 close/dismiss/cancel(得分95)
|
|
713
|
+
5. 小尺寸 clickable 元素(右上角优先,得分70+)
|
|
714
|
+
|
|
715
|
+
⭐ 优先点击确认性按钮(同意、确认等),而不是取消/拒绝按钮
|
|
651
716
|
|
|
652
717
|
✅ 返回内容:
|
|
653
718
|
- 坐标 (x, y) 和百分比 (x%, y%)
|
|
@@ -663,21 +728,42 @@ class MobileMCPServer:
|
|
|
663
728
|
|
|
664
729
|
tools.append(Tool(
|
|
665
730
|
name="mobile_close_popup",
|
|
666
|
-
description="""🚫
|
|
731
|
+
description="""🚫 智能关闭弹窗(优化版)
|
|
667
732
|
|
|
668
|
-
|
|
733
|
+
🎯 弹窗检测场景:
|
|
734
|
+
- 启动应用后:mobile_launch_app 会自动检测弹窗
|
|
735
|
+
- 异常情况:操作失败时会检测弹窗
|
|
736
|
+
- 明确弹窗场景:调用此工具时(明确弹窗场景)
|
|
669
737
|
|
|
670
|
-
|
|
671
|
-
|
|
738
|
+
⭐ 按钮点击优先级(确认按钮优先):
|
|
739
|
+
1️⃣ **确认性按钮**(最高优先级):同意、确认、允许、好的、知道了、OK等
|
|
740
|
+
2️⃣ **关闭/取消按钮**(次优先级):关闭、取消、跳过、×、X等
|
|
741
|
+
3️⃣ **小尺寸可点击元素**(最低优先级):右上角X图标等
|
|
672
742
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
743
|
+
优化后的降级策略:
|
|
744
|
+
1️⃣ **控件树优先**(最快、最可靠):list_elements() → 查找确认/关闭按钮 → 点击
|
|
745
|
+
2️⃣ **截图AI分析**(中等速度、高准确率):如果控件树失败 → 截图 → 返回候选建议 → AI分析 → 点击
|
|
746
|
+
3️⃣ **模板匹配**(最慢、最精确):如果AI分析失败 → 模板匹配 → 点击
|
|
677
747
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
748
|
+
✅ 优先点击「同意」「确认」等确认性按钮,而不是「取消」「不同意」
|
|
749
|
+
✅ 每个阶段都会使用页面指纹对比验证弹窗是否真的关闭
|
|
750
|
+
✅ 复用元素列表和XML,减少重复调用开销
|
|
751
|
+
✅ 支持 Android 和 iOS 双平台
|
|
752
|
+
✅ 支持自动学习模板(可选)""",
|
|
753
|
+
inputSchema={
|
|
754
|
+
"type": "object",
|
|
755
|
+
"properties": {
|
|
756
|
+
"auto_learn": {
|
|
757
|
+
"type": "boolean",
|
|
758
|
+
"description": "是否自动学习新模板(模板匹配成功时),默认 false"
|
|
759
|
+
},
|
|
760
|
+
"confidence_threshold": {
|
|
761
|
+
"type": "number",
|
|
762
|
+
"description": "弹窗检测置信度阈值(0-1),默认 0.6。值越高越严格,减少误检但可能漏检"
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
"required": []
|
|
766
|
+
}
|
|
681
767
|
))
|
|
682
768
|
|
|
683
769
|
tools.append(Tool(
|
|
@@ -807,29 +893,16 @@ Toast 是 Android 系统级的短暂提示消息,常用于显示操作结果
|
|
|
807
893
|
# ==================== 广告弹窗关闭工具 ====================
|
|
808
894
|
tools.append(Tool(
|
|
809
895
|
name="mobile_close_ad",
|
|
810
|
-
description="""🚫
|
|
896
|
+
description="""🚫 【推荐】智能关闭广告弹窗(已合并到 mobile_close_popup)
|
|
811
897
|
|
|
812
|
-
⚡
|
|
898
|
+
⚡ 此工具现在调用 mobile_close_popup,功能完全相同。
|
|
813
899
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
900
|
+
内部使用统一的降级策略:
|
|
901
|
+
1️⃣ **控件树优先**(最快、最可靠)
|
|
902
|
+
2️⃣ **截图AI分析**(中等速度、高准确率)
|
|
903
|
+
3️⃣ **模板匹配**(最精确的兜底方案,支持自动学习)
|
|
818
904
|
|
|
819
|
-
|
|
820
|
-
- 用 OpenCV 匹配已保存的 X 按钮模板
|
|
821
|
-
- 模板越多成功率越高
|
|
822
|
-
|
|
823
|
-
3️⃣ **返回截图供 AI 分析**(兜底)
|
|
824
|
-
- 前两步都失败才截图
|
|
825
|
-
- AI 分析后用 mobile_click_by_percent 点击
|
|
826
|
-
- 点击成功后用 mobile_template_add 添加模板
|
|
827
|
-
|
|
828
|
-
💡 正确流程:
|
|
829
|
-
1. 遇到广告弹窗 → 直接调用此工具
|
|
830
|
-
2. 如果成功 → 完成
|
|
831
|
-
3. 只有失败时才需要截图分析
|
|
832
|
-
3. 如果失败 → 看截图找 X → 点击 → 添加模板""",
|
|
905
|
+
💡 推荐使用 mobile_close_popup 代替(功能相同)""",
|
|
833
906
|
inputSchema={
|
|
834
907
|
"type": "object",
|
|
835
908
|
"properties": {},
|
|
@@ -936,7 +1009,37 @@ Toast 是 Android 系统级的短暂提示消息,常用于显示操作结果
|
|
|
936
1009
|
return [TextContent(type="text", text=self.format_response(result))]
|
|
937
1010
|
|
|
938
1011
|
elif name == "mobile_screenshot_with_som":
|
|
939
|
-
|
|
1012
|
+
check_popup = arguments.get("check_popup", False)
|
|
1013
|
+
result = self.tools.take_screenshot_with_som(check_popup=check_popup)
|
|
1014
|
+
|
|
1015
|
+
# 如果结果包含截图路径,尝试返回图片内容供 AI 分析
|
|
1016
|
+
screenshot_path = result.get("screenshot_path")
|
|
1017
|
+
if screenshot_path:
|
|
1018
|
+
try:
|
|
1019
|
+
from pathlib import Path
|
|
1020
|
+
import base64
|
|
1021
|
+
|
|
1022
|
+
img_path = Path(screenshot_path)
|
|
1023
|
+
if img_path.exists():
|
|
1024
|
+
# 读取图片并转换为 base64
|
|
1025
|
+
with open(img_path, 'rb') as f:
|
|
1026
|
+
image_data = f.read()
|
|
1027
|
+
image_base64 = base64.b64encode(image_data).decode('utf-8')
|
|
1028
|
+
|
|
1029
|
+
# 检查是否有 AI 分析请求
|
|
1030
|
+
ai_analysis = result.get("ai_analysis")
|
|
1031
|
+
if ai_analysis and ai_analysis.get("needs_ai_analysis"):
|
|
1032
|
+
# 返回文本结果和图片内容
|
|
1033
|
+
# 注意:MCP 协议可能不支持 ImageContent,这里先返回文本
|
|
1034
|
+
# Cursor AI 会自动看到截图文件并分析
|
|
1035
|
+
return [
|
|
1036
|
+
TextContent(type="text", text=self.format_response(result)),
|
|
1037
|
+
# 如果 MCP 支持 ImageContent,可以添加:
|
|
1038
|
+
# ImageContent(type="image", data=image_base64, mimeType="image/jpeg")
|
|
1039
|
+
]
|
|
1040
|
+
except Exception:
|
|
1041
|
+
pass # 图片处理失败,只返回文本
|
|
1042
|
+
|
|
940
1043
|
return [TextContent(type="text", text=self.format_response(result))]
|
|
941
1044
|
|
|
942
1045
|
elif name == "mobile_click_by_som":
|
|
@@ -1072,7 +1175,12 @@ Toast 是 Android 系统级的短暂提示消息,常用于显示操作结果
|
|
|
1072
1175
|
return [TextContent(type="text", text=self.format_response(result))]
|
|
1073
1176
|
|
|
1074
1177
|
elif name == "mobile_close_popup":
|
|
1075
|
-
|
|
1178
|
+
auto_learn = arguments.get("auto_learn", False)
|
|
1179
|
+
confidence_threshold = arguments.get("confidence_threshold", None)
|
|
1180
|
+
result = self.tools.close_popup(
|
|
1181
|
+
auto_learn=auto_learn,
|
|
1182
|
+
confidence_threshold=confidence_threshold
|
|
1183
|
+
)
|
|
1076
1184
|
return [TextContent(type="text", text=self.format_response(result))]
|
|
1077
1185
|
|
|
1078
1186
|
elif name == "mobile_assert_text":
|
|
@@ -1115,9 +1223,9 @@ Toast 是 Android 系统级的短暂提示消息,常用于显示操作结果
|
|
|
1115
1223
|
)
|
|
1116
1224
|
return [TextContent(type="text", text=self.format_response(result))]
|
|
1117
1225
|
|
|
1118
|
-
#
|
|
1226
|
+
# 智能关闭广告弹窗(已合并到 mobile_close_popup)
|
|
1119
1227
|
elif name == "mobile_close_ad":
|
|
1120
|
-
result = self.tools.
|
|
1228
|
+
result = self.tools.close_popup(auto_learn=False)
|
|
1121
1229
|
return [TextContent(type="text", text=self.format_response(result))]
|
|
1122
1230
|
|
|
1123
1231
|
# 模板匹配(精简版)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
mobile_mcp/__init__.py,sha256=sQJZTL_sxQFzmcS7jOtS2AHCfUySz40vhX96N6u1qy4,816
|
|
2
2
|
mobile_mcp/config.py,sha256=yaFLAV4bc2wX0GQPtZDo7OYF9E88tXV-av41fQsJwK4,4480
|
|
3
3
|
mobile_mcp/core/__init__.py,sha256=ndMy-cLAIsQDG5op7gM_AIplycqZSZPWEkec1pEhvEY,170
|
|
4
|
-
mobile_mcp/core/basic_tools_lite.py,sha256=
|
|
4
|
+
mobile_mcp/core/basic_tools_lite.py,sha256=oWzxM38aci6ab8CypqNkYN7Ur62OqBgdVi0FMu3SVQQ,239283
|
|
5
5
|
mobile_mcp/core/device_manager.py,sha256=xG5DoeNFs45pl-FTEhEWblqVwxtFK-FmVEGlNL6EqRI,8798
|
|
6
6
|
mobile_mcp/core/dynamic_config.py,sha256=Ja1n1pfb0HspGByqk2_A472mYVniKmGtNEWyjUjmgK8,9811
|
|
7
7
|
mobile_mcp/core/ios_client_wda.py,sha256=Nq9WxevhTWpVpolM-Ymp-b0nUQV3tXLFszmJHbDC4wA,18770
|
|
@@ -19,14 +19,14 @@ mobile_mcp/core/utils/logger.py,sha256=XXQAHUwT1jc70pq_tYFmL6f_nKrFlYm3hcgl-5RYR
|
|
|
19
19
|
mobile_mcp/core/utils/operation_history_manager.py,sha256=gi8S8HJAMqvkUrY7_-kVbko3Xt7c4GAUziEujRd-N-Y,4792
|
|
20
20
|
mobile_mcp/core/utils/smart_wait.py,sha256=N5wKTUYrNWPruBILqrAjpvtso8Z3GRWCfMIR_aZxPLg,8649
|
|
21
21
|
mobile_mcp/mcp_tools/__init__.py,sha256=xkro8Rwqv_55YlVyhh-3DgRFSsLE3h1r31VIb3bpM6E,143
|
|
22
|
-
mobile_mcp/mcp_tools/mcp_server.py,sha256=
|
|
22
|
+
mobile_mcp/mcp_tools/mcp_server.py,sha256=HCqlmWOPmO-ndq0U42mc-zkKPd25jiZIZZqGAPKXokU,62916
|
|
23
23
|
mobile_mcp/utils/__init__.py,sha256=8EH0i7UGtx1y_j_GEgdN-cZdWn2sRtZSEOLlNF9HRnY,158
|
|
24
24
|
mobile_mcp/utils/logger.py,sha256=Sqq2Nr0Y4p03erqcrbYKVPCGiFaNGHMcE_JwCkeOfU4,3626
|
|
25
25
|
mobile_mcp/utils/xml_formatter.py,sha256=uwTRb3vLbqhT8O-udzWT7s7LsV-DyDUz2DkofD3hXOE,4556
|
|
26
26
|
mobile_mcp/utils/xml_parser.py,sha256=QhL8CWbdmNDzmBLjtx6mEnjHgMFZzJeHpCL15qfXSpI,3926
|
|
27
|
-
mobile_mcp_ai-2.6.
|
|
28
|
-
mobile_mcp_ai-2.6.
|
|
29
|
-
mobile_mcp_ai-2.6.
|
|
30
|
-
mobile_mcp_ai-2.6.
|
|
31
|
-
mobile_mcp_ai-2.6.
|
|
32
|
-
mobile_mcp_ai-2.6.
|
|
27
|
+
mobile_mcp_ai-2.6.10.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
28
|
+
mobile_mcp_ai-2.6.10.dist-info/METADATA,sha256=VHon2Gd5-xseda14dgKTeMLu2mhX-IK75tjfp4uXjQI,10496
|
|
29
|
+
mobile_mcp_ai-2.6.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
30
|
+
mobile_mcp_ai-2.6.10.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
|
|
31
|
+
mobile_mcp_ai-2.6.10.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
|
|
32
|
+
mobile_mcp_ai-2.6.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|