mobile-mcp-ai 2.6.7__tar.gz → 2.6.8__tar.gz
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_ai-2.6.7/mobile_mcp_ai.egg-info → mobile_mcp_ai-2.6.8}/PKG-INFO +1 -1
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/basic_tools_lite.py +164 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mcp_tools/mcp_server.py +46 -1
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8/mobile_mcp_ai.egg-info}/PKG-INFO +1 -1
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/setup.py +1 -1
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/LICENSE +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/MANIFEST.in +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/README.md +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/__init__.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/config.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/__init__.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/device_manager.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/dynamic_config.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/ios_client_wda.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/ios_device_manager_wda.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/mobile_client.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/template_matcher.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_151217.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_152037.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_152840.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_153256.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_154847.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/gray_x_stock_ad.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/utils/__init__.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/utils/logger.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/utils/operation_history_manager.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/utils/smart_wait.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/docs/iOS_SETUP_GUIDE.md +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mcp_tools/__init__.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mobile_mcp_ai.egg-info/SOURCES.txt +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mobile_mcp_ai.egg-info/dependency_links.txt +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mobile_mcp_ai.egg-info/entry_points.txt +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mobile_mcp_ai.egg-info/not-zip-safe +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mobile_mcp_ai.egg-info/requires.txt +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/mobile_mcp_ai.egg-info/top_level.txt +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/requirements.txt +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/setup.cfg +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/templates/close_buttons/auto_x_0112_151217.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/templates/close_buttons/auto_x_0112_152037.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/templates/close_buttons/auto_x_0112_152840.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/templates/close_buttons/auto_x_0112_153256.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/templates/close_buttons/auto_x_0112_154847.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/templates/close_buttons/gray_x_stock_ad.png +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/utils/__init__.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/utils/logger.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/utils/xml_formatter.py +0 -0
- {mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/utils/xml_parser.py +0 -0
|
@@ -2271,6 +2271,170 @@ class BasicMobileToolsLite:
|
|
|
2271
2271
|
time.sleep(seconds)
|
|
2272
2272
|
return {"success": True, "message": f"✅ 已等待 {seconds} 秒"}
|
|
2273
2273
|
|
|
2274
|
+
async def drag_progress_bar(self, direction: str = "right", distance_percent: float = 30.0,
|
|
2275
|
+
y_percent: Optional[float] = None, y: Optional[int] = None) -> Dict:
|
|
2276
|
+
"""智能拖动进度条
|
|
2277
|
+
|
|
2278
|
+
自动检测进度条是否可见:
|
|
2279
|
+
- 如果进度条已显示,直接拖动(无需先点击播放区域)
|
|
2280
|
+
- 如果进度条未显示,先点击播放区域显示控制栏,再拖动
|
|
2281
|
+
|
|
2282
|
+
Args:
|
|
2283
|
+
direction: 拖动方向,'left'(倒退)或 'right'(前进),默认 'right'
|
|
2284
|
+
distance_percent: 拖动距离百分比 (0-100),默认 30%
|
|
2285
|
+
y_percent: 进度条的垂直位置百分比 (0-100),如果未指定则自动检测
|
|
2286
|
+
y: 进度条的垂直位置坐标(像素),如果未指定则自动检测
|
|
2287
|
+
"""
|
|
2288
|
+
try:
|
|
2289
|
+
import xml.etree.ElementTree as ET
|
|
2290
|
+
import re
|
|
2291
|
+
|
|
2292
|
+
if self._is_ios():
|
|
2293
|
+
return {"success": False, "message": "❌ iOS 暂不支持,请使用 mobile_swipe"}
|
|
2294
|
+
|
|
2295
|
+
if direction not in ['left', 'right']:
|
|
2296
|
+
return {"success": False, "message": f"❌ 拖动方向必须是 'left' 或 'right': {direction}"}
|
|
2297
|
+
|
|
2298
|
+
screen_width, screen_height = self.client.u2.window_size()
|
|
2299
|
+
|
|
2300
|
+
# 获取 XML 查找进度条
|
|
2301
|
+
xml_string = self.client.u2.dump_hierarchy(compressed=False)
|
|
2302
|
+
root = ET.fromstring(xml_string)
|
|
2303
|
+
|
|
2304
|
+
progress_bar_found = False
|
|
2305
|
+
progress_bar_y = None
|
|
2306
|
+
progress_bar_y_percent = None
|
|
2307
|
+
|
|
2308
|
+
# 查找进度条元素(SeekBar、ProgressBar)
|
|
2309
|
+
for elem in root.iter():
|
|
2310
|
+
class_name = elem.attrib.get('class', '')
|
|
2311
|
+
resource_id = elem.attrib.get('resource-id', '')
|
|
2312
|
+
bounds_str = elem.attrib.get('bounds', '')
|
|
2313
|
+
|
|
2314
|
+
# 检查是否是进度条
|
|
2315
|
+
is_progress_bar = (
|
|
2316
|
+
'SeekBar' in class_name or
|
|
2317
|
+
'ProgressBar' in class_name or
|
|
2318
|
+
'progress' in resource_id.lower() or
|
|
2319
|
+
'seek' in resource_id.lower()
|
|
2320
|
+
)
|
|
2321
|
+
|
|
2322
|
+
if is_progress_bar and bounds_str:
|
|
2323
|
+
# 解析 bounds 获取进度条位置
|
|
2324
|
+
match = re.match(r'\[(\d+),(\d+)\]\[(\d+),(\d+)\]', bounds_str)
|
|
2325
|
+
if match:
|
|
2326
|
+
x1, y1, x2, y2 = map(int, match.groups())
|
|
2327
|
+
center_y = (y1 + y2) // 2
|
|
2328
|
+
progress_bar_y = center_y
|
|
2329
|
+
progress_bar_y_percent = round(center_y / screen_height * 100, 1)
|
|
2330
|
+
progress_bar_found = True
|
|
2331
|
+
break
|
|
2332
|
+
|
|
2333
|
+
# 如果未找到进度条,尝试点击播放区域显示控制栏
|
|
2334
|
+
if not progress_bar_found:
|
|
2335
|
+
# 点击屏幕中心显示控制栏
|
|
2336
|
+
center_x, center_y = screen_width // 2, screen_height // 2
|
|
2337
|
+
self.client.u2.click(center_x, center_y)
|
|
2338
|
+
time.sleep(0.5)
|
|
2339
|
+
|
|
2340
|
+
# 再次查找进度条
|
|
2341
|
+
xml_string = self.client.u2.dump_hierarchy(compressed=False)
|
|
2342
|
+
root = ET.fromstring(xml_string)
|
|
2343
|
+
|
|
2344
|
+
for elem in root.iter():
|
|
2345
|
+
class_name = elem.attrib.get('class', '')
|
|
2346
|
+
resource_id = elem.attrib.get('resource-id', '')
|
|
2347
|
+
bounds_str = elem.attrib.get('bounds', '')
|
|
2348
|
+
|
|
2349
|
+
is_progress_bar = (
|
|
2350
|
+
'SeekBar' in class_name or
|
|
2351
|
+
'ProgressBar' in class_name or
|
|
2352
|
+
'progress' in resource_id.lower() or
|
|
2353
|
+
'seek' in resource_id.lower()
|
|
2354
|
+
)
|
|
2355
|
+
|
|
2356
|
+
if is_progress_bar and bounds_str:
|
|
2357
|
+
match = re.match(r'\[(\d+),(\d+)\]\[(\d+),(\d+)\]', bounds_str)
|
|
2358
|
+
if match:
|
|
2359
|
+
x1, y1, x2, y2 = map(int, match.groups())
|
|
2360
|
+
center_y = (y1 + y2) // 2
|
|
2361
|
+
progress_bar_y = center_y
|
|
2362
|
+
progress_bar_y_percent = round(center_y / screen_height * 100, 1)
|
|
2363
|
+
progress_bar_found = True
|
|
2364
|
+
break
|
|
2365
|
+
|
|
2366
|
+
# 确定使用的高度位置
|
|
2367
|
+
if y_percent is not None:
|
|
2368
|
+
swipe_y = int(screen_height * y_percent / 100)
|
|
2369
|
+
used_y_percent = y_percent
|
|
2370
|
+
elif y is not None:
|
|
2371
|
+
swipe_y = y
|
|
2372
|
+
used_y_percent = round(y / screen_height * 100, 1)
|
|
2373
|
+
elif progress_bar_found:
|
|
2374
|
+
swipe_y = progress_bar_y
|
|
2375
|
+
used_y_percent = progress_bar_y_percent
|
|
2376
|
+
else:
|
|
2377
|
+
# 默认使用屏幕底部附近(进度条常见位置)
|
|
2378
|
+
swipe_y = int(screen_height * 0.91)
|
|
2379
|
+
used_y_percent = 91.0
|
|
2380
|
+
|
|
2381
|
+
# 计算滑动距离
|
|
2382
|
+
swipe_distance = int(screen_width * distance_percent / 100)
|
|
2383
|
+
|
|
2384
|
+
# 计算起始和结束位置
|
|
2385
|
+
center_x = screen_width // 2
|
|
2386
|
+
if direction == 'left':
|
|
2387
|
+
start_x = min(center_x + swipe_distance // 2, screen_width - 10)
|
|
2388
|
+
end_x = start_x - swipe_distance
|
|
2389
|
+
if end_x < 10:
|
|
2390
|
+
end_x = 10
|
|
2391
|
+
start_x = min(end_x + swipe_distance, screen_width - 10)
|
|
2392
|
+
else: # right
|
|
2393
|
+
start_x = max(center_x - swipe_distance // 2, 10)
|
|
2394
|
+
end_x = start_x + swipe_distance
|
|
2395
|
+
if end_x > screen_width - 10:
|
|
2396
|
+
end_x = screen_width - 10
|
|
2397
|
+
start_x = max(end_x - swipe_distance, 10)
|
|
2398
|
+
|
|
2399
|
+
# 执行拖动
|
|
2400
|
+
self.client.u2.swipe(start_x, swipe_y, end_x, swipe_y, duration=0.5)
|
|
2401
|
+
time.sleep(0.3)
|
|
2402
|
+
|
|
2403
|
+
# 记录操作
|
|
2404
|
+
self._record_swipe(direction)
|
|
2405
|
+
|
|
2406
|
+
# 检查应用是否跳转
|
|
2407
|
+
app_check = self._check_app_switched()
|
|
2408
|
+
return_result = None
|
|
2409
|
+
if app_check['switched']:
|
|
2410
|
+
return_result = self._return_to_target_app()
|
|
2411
|
+
|
|
2412
|
+
# 构建返回消息
|
|
2413
|
+
msg = f"✅ 进度条拖动成功: {direction} (高度: {used_y_percent}%, 距离: {distance_percent}%)"
|
|
2414
|
+
if not progress_bar_found:
|
|
2415
|
+
msg += "\n💡 已自动点击播放区域显示控制栏"
|
|
2416
|
+
else:
|
|
2417
|
+
msg += "\n💡 进度条已显示,直接拖动"
|
|
2418
|
+
|
|
2419
|
+
if app_check['switched']:
|
|
2420
|
+
msg += f"\n{app_check['message']}"
|
|
2421
|
+
if return_result and return_result.get('success'):
|
|
2422
|
+
msg += f"\n{return_result['message']}"
|
|
2423
|
+
|
|
2424
|
+
return {
|
|
2425
|
+
"success": True,
|
|
2426
|
+
"message": msg,
|
|
2427
|
+
"progress_bar_found": progress_bar_found,
|
|
2428
|
+
"y_percent": used_y_percent,
|
|
2429
|
+
"distance_percent": distance_percent,
|
|
2430
|
+
"direction": direction,
|
|
2431
|
+
"app_check": app_check,
|
|
2432
|
+
"return_to_app": return_result
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
except Exception as e:
|
|
2436
|
+
return {"success": False, "message": f"❌ 拖动进度条失败: {e}"}
|
|
2437
|
+
|
|
2274
2438
|
# ==================== 应用管理 ====================
|
|
2275
2439
|
|
|
2276
2440
|
async def launch_app(self, package_name: str) -> Dict:
|
|
@@ -530,7 +530,8 @@ class MobileMCPServer:
|
|
|
530
530
|
"- 📌 拖动进度条时,distance_percent 控制拖动幅度\n\n"
|
|
531
531
|
"💡 拖动进度条示例:\n"
|
|
532
532
|
"- 倒退:direction='left', y_percent=91(进度条位置), distance_percent=30\n"
|
|
533
|
-
"- 前进:direction='right', y_percent=91, distance_percent=30"
|
|
533
|
+
"- 前进:direction='right', y_percent=91, distance_percent=30\n\n"
|
|
534
|
+
"⚠️ **推荐使用 mobile_drag_progress_bar 拖动进度条**(自动检测进度条位置,无需手动指定)",
|
|
534
535
|
inputSchema={
|
|
535
536
|
"type": "object",
|
|
536
537
|
"properties": {
|
|
@@ -560,6 +561,50 @@ class MobileMCPServer:
|
|
|
560
561
|
}
|
|
561
562
|
))
|
|
562
563
|
|
|
564
|
+
tools.append(Tool(
|
|
565
|
+
name="mobile_drag_progress_bar",
|
|
566
|
+
description="🎯 智能拖动进度条(⭐⭐ 推荐用于拖动视频/音频进度条)\n\n"
|
|
567
|
+
"✅ **自动检测进度条是否可见**:\n"
|
|
568
|
+
"- 如果进度条已显示,直接拖动(无需先点击播放区域)\n"
|
|
569
|
+
"- 如果进度条未显示,自动点击播放区域显示控制栏,再拖动\n\n"
|
|
570
|
+
"🎯 优势:\n"
|
|
571
|
+
"- 自动检测进度条位置,无需手动指定 y_percent\n"
|
|
572
|
+
"- 智能判断是否需要显示控制栏\n"
|
|
573
|
+
"- 使用 swipe 拖动,更稳定可靠\n\n"
|
|
574
|
+
"💡 参数说明:\n"
|
|
575
|
+
"- direction: 'left'(倒退)或 'right'(前进),默认 'right'\n"
|
|
576
|
+
"- distance_percent: 拖动距离百分比 (0-100),默认 30%\n"
|
|
577
|
+
"- y_percent: 进度条位置(可选,未指定则自动检测)\n"
|
|
578
|
+
"- y: 进度条位置坐标(可选,未指定则自动检测)\n\n"
|
|
579
|
+
"📋 使用示例:\n"
|
|
580
|
+
"- 前进30%:mobile_drag_progress_bar(direction='right', distance_percent=30)\n"
|
|
581
|
+
"- 倒退30%:mobile_drag_progress_bar(direction='left', distance_percent=30)\n"
|
|
582
|
+
"- 前进到指定位置:先点击进度条位置,或使用 mobile_swipe",
|
|
583
|
+
inputSchema={
|
|
584
|
+
"type": "object",
|
|
585
|
+
"properties": {
|
|
586
|
+
"direction": {
|
|
587
|
+
"type": "string",
|
|
588
|
+
"enum": ["left", "right"],
|
|
589
|
+
"description": "拖动方向:'left'(倒退)或 'right'(前进),默认 'right'"
|
|
590
|
+
},
|
|
591
|
+
"distance_percent": {
|
|
592
|
+
"type": "number",
|
|
593
|
+
"description": "拖动距离百分比 (0-100),默认 30%"
|
|
594
|
+
},
|
|
595
|
+
"y_percent": {
|
|
596
|
+
"type": "number",
|
|
597
|
+
"description": "进度条的垂直位置百分比 (0-100),可选,未指定则自动检测"
|
|
598
|
+
},
|
|
599
|
+
"y": {
|
|
600
|
+
"type": "integer",
|
|
601
|
+
"description": "进度条的垂直位置坐标(像素),可选,未指定则自动检测"
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
"required": []
|
|
605
|
+
}
|
|
606
|
+
))
|
|
607
|
+
|
|
563
608
|
tools.append(Tool(
|
|
564
609
|
name="mobile_press_key",
|
|
565
610
|
description="⌨️ 按键操作。支持:home, back, enter, search",
|
|
@@ -25,7 +25,7 @@ if requirements_file.exists():
|
|
|
25
25
|
|
|
26
26
|
setup(
|
|
27
27
|
name="mobile-mcp-ai",
|
|
28
|
-
version="2.6.
|
|
28
|
+
version="2.6.8", # 增强弹窗检测 - 添加浮动关闭按钮检测
|
|
29
29
|
author="douzi",
|
|
30
30
|
author_email="1492994674@qq.com",
|
|
31
31
|
description="移动端自动化 MCP Server - 支持 Android/iOS,AI 功能可选(基础工具不需要 AI)",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_151217.png
RENAMED
|
File without changes
|
{mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_152037.png
RENAMED
|
File without changes
|
{mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_152840.png
RENAMED
|
File without changes
|
{mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_153256.png
RENAMED
|
File without changes
|
{mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/auto_x_0112_154847.png
RENAMED
|
File without changes
|
{mobile_mcp_ai-2.6.7 → mobile_mcp_ai-2.6.8}/core/templates/close_buttons/gray_x_stock_ad.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|