mobile-mcp-ai 2.6.0__py3-none-any.whl → 2.6.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.
- mobile_mcp/core/basic_tools_lite.py +40 -3
- mobile_mcp/mcp_tools/mcp_server.py +22 -17
- {mobile_mcp_ai-2.6.0.dist-info → mobile_mcp_ai-2.6.1.dist-info}/METADATA +1 -1
- {mobile_mcp_ai-2.6.0.dist-info → mobile_mcp_ai-2.6.1.dist-info}/RECORD +8 -8
- {mobile_mcp_ai-2.6.0.dist-info → mobile_mcp_ai-2.6.1.dist-info}/WHEEL +0 -0
- {mobile_mcp_ai-2.6.0.dist-info → mobile_mcp_ai-2.6.1.dist-info}/entry_points.txt +0 -0
- {mobile_mcp_ai-2.6.0.dist-info → mobile_mcp_ai-2.6.1.dist-info}/licenses/LICENSE +0 -0
- {mobile_mcp_ai-2.6.0.dist-info → mobile_mcp_ai-2.6.1.dist-info}/top_level.txt +0 -0
|
@@ -2349,6 +2349,7 @@ class BasicMobileToolsLite:
|
|
|
2349
2349
|
for elem in root.iter():
|
|
2350
2350
|
text = elem.attrib.get('text', '')
|
|
2351
2351
|
content_desc = elem.attrib.get('content-desc', '')
|
|
2352
|
+
resource_id = elem.attrib.get('resource-id', '')
|
|
2352
2353
|
bounds_str = elem.attrib.get('bounds', '')
|
|
2353
2354
|
class_name = elem.attrib.get('class', '')
|
|
2354
2355
|
clickable = elem.attrib.get('clickable', 'false') == 'true'
|
|
@@ -2383,6 +2384,13 @@ class BasicMobileToolsLite:
|
|
|
2383
2384
|
score = 90
|
|
2384
2385
|
reason = f"描述='{content_desc}'"
|
|
2385
2386
|
|
|
2387
|
+
# 策略2.5:resource-id 包含关闭关键词(如 close_icon, ad_close 等)
|
|
2388
|
+
elif resource_id and any(kw in resource_id.lower() for kw in ['close', 'dismiss', 'skip', 'cancel']):
|
|
2389
|
+
score = 95
|
|
2390
|
+
# 提取简短的 id 名
|
|
2391
|
+
short_id = resource_id.split('/')[-1] if '/' in resource_id else resource_id
|
|
2392
|
+
reason = f"resource-id='{short_id}'"
|
|
2393
|
+
|
|
2386
2394
|
# 策略3:小尺寸的 clickable 元素(可能是 X 图标)
|
|
2387
2395
|
elif clickable:
|
|
2388
2396
|
min_size = max(20, int(screen_width * 0.03))
|
|
@@ -2417,7 +2425,9 @@ class BasicMobileToolsLite:
|
|
|
2417
2425
|
'center_y': center_y,
|
|
2418
2426
|
'x_percent': x_percent,
|
|
2419
2427
|
'y_percent': y_percent,
|
|
2420
|
-
'size': f"{width}x{height}"
|
|
2428
|
+
'size': f"{width}x{height}",
|
|
2429
|
+
'resource_id': resource_id,
|
|
2430
|
+
'text': text
|
|
2421
2431
|
})
|
|
2422
2432
|
|
|
2423
2433
|
if not candidates:
|
|
@@ -2443,7 +2453,16 @@ class BasicMobileToolsLite:
|
|
|
2443
2453
|
candidates.sort(key=lambda x: x['score'], reverse=True)
|
|
2444
2454
|
best = candidates[0]
|
|
2445
2455
|
|
|
2446
|
-
|
|
2456
|
+
# 生成推荐的点击命令(优先使用 resource-id)
|
|
2457
|
+
if best.get('resource_id'):
|
|
2458
|
+
short_id = best['resource_id'].split('/')[-1] if '/' in best['resource_id'] else best['resource_id']
|
|
2459
|
+
click_cmd = f"mobile_click_by_id('{best['resource_id']}')"
|
|
2460
|
+
elif best.get('text') and best['text'] in ['×', 'X', 'x', '关闭', '取消', '跳过', '知道了']:
|
|
2461
|
+
click_cmd = f"mobile_click_by_text('{best['text']}')"
|
|
2462
|
+
else:
|
|
2463
|
+
click_cmd = f"mobile_click_by_percent({best['x_percent']}, {best['y_percent']})"
|
|
2464
|
+
|
|
2465
|
+
result = {
|
|
2447
2466
|
"success": True,
|
|
2448
2467
|
"message": f"✅ 找到可能的关闭按钮",
|
|
2449
2468
|
"best_candidate": {
|
|
@@ -2454,7 +2473,7 @@ class BasicMobileToolsLite:
|
|
|
2454
2473
|
"size": best['size'],
|
|
2455
2474
|
"score": best['score']
|
|
2456
2475
|
},
|
|
2457
|
-
"click_command":
|
|
2476
|
+
"click_command": click_cmd,
|
|
2458
2477
|
"other_candidates": [
|
|
2459
2478
|
{"reason": c['reason'], "percent": f"({c['x_percent']}%, {c['y_percent']}%)", "score": c['score']}
|
|
2460
2479
|
for c in candidates[1:4]
|
|
@@ -2462,6 +2481,14 @@ class BasicMobileToolsLite:
|
|
|
2462
2481
|
"screen_size": {"width": screen_width, "height": screen_height}
|
|
2463
2482
|
}
|
|
2464
2483
|
|
|
2484
|
+
# 如果有 resource-id,额外提供
|
|
2485
|
+
if best.get('resource_id'):
|
|
2486
|
+
result["best_candidate"]["resource_id"] = best['resource_id']
|
|
2487
|
+
if best.get('text'):
|
|
2488
|
+
result["best_candidate"]["text"] = best['text']
|
|
2489
|
+
|
|
2490
|
+
return result
|
|
2491
|
+
|
|
2465
2492
|
except Exception as e:
|
|
2466
2493
|
return {"success": False, "message": f"❌ 查找关闭按钮失败: {e}"}
|
|
2467
2494
|
|
|
@@ -3442,6 +3469,16 @@ class BasicMobileToolsLite:
|
|
|
3442
3469
|
reason = f"文本含'{kw}'"
|
|
3443
3470
|
break
|
|
3444
3471
|
|
|
3472
|
+
# resource-id 匹配(如 close_icon, ad_close 等)
|
|
3473
|
+
if resource_id:
|
|
3474
|
+
res_id_lower = resource_id.lower()
|
|
3475
|
+
for kw in ['close', 'dismiss', 'skip', 'cancel']:
|
|
3476
|
+
if kw in res_id_lower:
|
|
3477
|
+
score += 9
|
|
3478
|
+
short_id = resource_id.split('/')[-1] if '/' in resource_id else resource_id
|
|
3479
|
+
reason = f"resource-id='{short_id}'"
|
|
3480
|
+
break
|
|
3481
|
+
|
|
3445
3482
|
# content-desc 匹配
|
|
3446
3483
|
for kw in close_content_desc:
|
|
3447
3484
|
if kw.lower() in content_desc.lower():
|
|
@@ -610,22 +610,25 @@ class MobileMCPServer:
|
|
|
610
610
|
name="mobile_find_close_button",
|
|
611
611
|
description="""🔍 智能查找关闭按钮(只找不点,返回位置)
|
|
612
612
|
|
|
613
|
-
|
|
613
|
+
⚡ 【推荐首选】遇到弹窗时优先调用此工具!无需先截图。
|
|
614
|
+
|
|
615
|
+
从元素树中找最可能的关闭按钮,返回坐标和推荐的点击命令。
|
|
614
616
|
|
|
615
617
|
🎯 识别策略(优先级):
|
|
616
|
-
1. 文本匹配:×、X、关闭、取消、跳过
|
|
617
|
-
2.
|
|
618
|
-
3.
|
|
618
|
+
1. 文本匹配:×、X、关闭、取消、跳过 等(得分100)
|
|
619
|
+
2. resource-id 匹配:包含 close/dismiss/skip(得分95)
|
|
620
|
+
3. content-desc 匹配:包含 close/关闭(得分90)
|
|
621
|
+
4. 小尺寸 clickable 元素(右上角优先,得分70+)
|
|
619
622
|
|
|
620
623
|
✅ 返回内容:
|
|
621
624
|
- 坐标 (x, y) 和百分比 (x%, y%)
|
|
622
|
-
-
|
|
623
|
-
-
|
|
625
|
+
- resource-id(如果有)
|
|
626
|
+
- 推荐的点击命令(优先 click_by_id,其次 click_by_text,最后 click_by_percent)
|
|
624
627
|
|
|
625
628
|
💡 使用流程:
|
|
626
|
-
1.
|
|
627
|
-
2.
|
|
628
|
-
3.
|
|
629
|
+
1. 直接调用此工具(无需先截图/列元素)
|
|
630
|
+
2. 根据返回的 click_command 执行点击
|
|
631
|
+
3. 如果返回 success=false,才需要截图分析""",
|
|
629
632
|
inputSchema={"type": "object", "properties": {}, "required": []}
|
|
630
633
|
))
|
|
631
634
|
|
|
@@ -711,24 +714,26 @@ class MobileMCPServer:
|
|
|
711
714
|
name="mobile_close_ad",
|
|
712
715
|
description="""🚫 【推荐】智能关闭广告弹窗
|
|
713
716
|
|
|
714
|
-
|
|
717
|
+
⚡ 直接调用即可,无需先截图!会自动按优先级尝试:
|
|
715
718
|
|
|
716
|
-
1️⃣
|
|
717
|
-
- 自动查找
|
|
719
|
+
1️⃣ **控件树查找**(最可靠,优先)
|
|
720
|
+
- 自动查找 resource-id 包含 close/dismiss
|
|
721
|
+
- 查找文本"关闭"、"跳过"、"×"等
|
|
718
722
|
- 找到直接点击,实时可靠
|
|
719
723
|
|
|
720
724
|
2️⃣ **模板匹配**(次优)
|
|
721
725
|
- 用 OpenCV 匹配已保存的 X 按钮模板
|
|
722
|
-
-
|
|
726
|
+
- 模板越多成功率越高
|
|
723
727
|
|
|
724
728
|
3️⃣ **返回截图供 AI 分析**(兜底)
|
|
725
|
-
-
|
|
729
|
+
- 前两步都失败才截图
|
|
726
730
|
- AI 分析后用 mobile_click_by_percent 点击
|
|
727
|
-
- 点击成功后用 mobile_template_add
|
|
731
|
+
- 点击成功后用 mobile_template_add 添加模板
|
|
728
732
|
|
|
729
|
-
💡
|
|
730
|
-
1. 遇到广告弹窗 →
|
|
733
|
+
💡 正确流程:
|
|
734
|
+
1. 遇到广告弹窗 → 直接调用此工具
|
|
731
735
|
2. 如果成功 → 完成
|
|
736
|
+
3. 只有失败时才需要截图分析
|
|
732
737
|
3. 如果失败 → 看截图找 X → 点击 → 添加模板""",
|
|
733
738
|
inputSchema={
|
|
734
739
|
"type": "object",
|
|
@@ -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=zBKruc_z-iYaa5PysC91AAB0eydt_qDFNTT7o5OuUqU,181240
|
|
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=T6H3jAEfxQzGeQgiTg9ROn2GpgonARrrlFWrzVfxmKU,50135
|
|
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.1.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
28
|
+
mobile_mcp_ai-2.6.1.dist-info/METADATA,sha256=oa_vxBNab-rKPX3yXVbetv6Joc-jjdh_XxgYA7vbEfY,10495
|
|
29
|
+
mobile_mcp_ai-2.6.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
30
|
+
mobile_mcp_ai-2.6.1.dist-info/entry_points.txt,sha256=KB_FglozgPHBprSM1vFbIzGyheFuHFmGanscRdMJ_8A,68
|
|
31
|
+
mobile_mcp_ai-2.6.1.dist-info/top_level.txt,sha256=lLm6YpbTv855Lbh8BIA0rPxhybIrvYUzMEk9OErHT94,11
|
|
32
|
+
mobile_mcp_ai-2.6.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|