mobile-mcp-ai 2.3.3__tar.gz → 2.3.4__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.
Files changed (44) hide show
  1. {mobile_mcp_ai-2.3.3/mobile_mcp_ai.egg-info → mobile_mcp_ai-2.3.4}/PKG-INFO +1 -1
  2. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/basic_tools_lite.py +60 -102
  3. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/mobile_client.py +22 -27
  4. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mcp_tools/mcp_server.py +19 -40
  5. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4/mobile_mcp_ai.egg-info}/PKG-INFO +1 -1
  6. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/setup.py +1 -1
  7. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/LICENSE +0 -0
  8. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/MANIFEST.in +0 -0
  9. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/README.md +0 -0
  10. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/__init__.py +0 -0
  11. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/config.py +0 -0
  12. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/__init__.py +0 -0
  13. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/device_manager.py +0 -0
  14. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/dynamic_config.py +0 -0
  15. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/ios_client_wda.py +0 -0
  16. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/ios_device_manager_wda.py +0 -0
  17. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/utils/__init__.py +0 -0
  18. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/utils/logger.py +0 -0
  19. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/utils/operation_history_manager.py +0 -0
  20. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/core/utils/smart_wait.py +0 -0
  21. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/docs/iOS_SETUP_GUIDE.md +0 -0
  22. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mcp_tools/__init__.py +0 -0
  23. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mobile_mcp_ai.egg-info/SOURCES.txt +0 -0
  24. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mobile_mcp_ai.egg-info/dependency_links.txt +0 -0
  25. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mobile_mcp_ai.egg-info/entry_points.txt +0 -0
  26. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mobile_mcp_ai.egg-info/not-zip-safe +0 -0
  27. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mobile_mcp_ai.egg-info/requires.txt +0 -0
  28. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/mobile_mcp_ai.egg-info/top_level.txt +0 -0
  29. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/requirements.txt +0 -0
  30. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/setup.cfg +0 -0
  31. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_mind_cloud_my_space.py +0 -0
  32. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_mind_correct.py +0 -0
  33. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_mind_improved.py +0 -0
  34. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_mind_optimized.py +0 -0
  35. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_open_mind.py +0 -0
  36. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_priority_demo.py +0 -0
  37. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_simple.py +0 -0
  38. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_/344/270/276/346/212/245.py" +0 -0
  39. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_/345/210/207/346/215/242/350/257/255/350/250/200/345/210/260English.py" +0 -0
  40. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/tests/test_/346/265/213/350/257/225.py" +0 -0
  41. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/utils/__init__.py +0 -0
  42. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/utils/logger.py +0 -0
  43. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/utils/xml_formatter.py +0 -0
  44. {mobile_mcp_ai-2.3.3 → mobile_mcp_ai-2.3.4}/utils/xml_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mobile-mcp-ai
3
- Version: 2.3.3
3
+ Version: 2.3.4
4
4
  Summary: 移动端自动化 MCP Server - 支持 Android/iOS,AI 功能可选(基础工具不需要 AI)
5
5
  Home-page: https://github.com/test111ddff-hash/mobile-mcp-ai
6
6
  Author: douzi
@@ -109,6 +109,9 @@ class BasicMobileToolsLite:
109
109
  img = Image.open(temp_path)
110
110
 
111
111
  # 第3步:缩小尺寸(保持宽高比)
112
+ # 记录压缩后的图片尺寸(用于坐标转换)
113
+ image_width, image_height = img.width, img.height
114
+
112
115
  if img.width > max_width:
113
116
  ratio = max_width / img.width
114
117
  new_w = max_width
@@ -125,6 +128,8 @@ class BasicMobileToolsLite:
125
128
  # Pillow 旧版本
126
129
  resample = Image.ANTIALIAS
127
130
  img = img.resize((new_w, new_h), resample)
131
+ # 更新为压缩后的尺寸
132
+ image_width, image_height = new_w, new_h
128
133
 
129
134
  # 第4步:生成最终文件名(JPEG 格式)
130
135
  if description:
@@ -160,14 +165,18 @@ class BasicMobileToolsLite:
160
165
  "screenshot_path": str(final_path),
161
166
  "screen_width": screen_width,
162
167
  "screen_height": screen_height,
168
+ "image_width": image_width,
169
+ "image_height": image_height,
163
170
  "original_size": f"{original_size/1024:.1f}KB",
164
171
  "compressed_size": f"{compressed_size/1024:.1f}KB",
165
172
  "saved_percent": f"{saved_percent:.0f}%",
166
173
  "message": f"📸 截图已保存: {final_path}\n"
167
174
  f"📐 屏幕尺寸: {screen_width}x{screen_height}\n"
175
+ f"🖼️ 图片尺寸: {image_width}x{image_height}(AI 分析用)\n"
168
176
  f"📦 已压缩: {original_size/1024:.0f}KB → {compressed_size/1024:.0f}KB (省 {saved_percent:.0f}%)\n"
169
- f"💡 Cursor 分析图片后,返回的坐标可直接用于 mobile_click_at_coords\n"
170
- f"💡 或使用 mobile_click_by_percent 进行跨设备兼容点击"
177
+ f"⚠️ 【重要】AI 返回的坐标需要转换!\n"
178
+ f" 请使用 mobile_click_at_coords 并传入 image_width={image_width}, image_height={image_height}\n"
179
+ f" 工具会自动将图片坐标转换为屏幕坐标"
171
180
  }
172
181
  else:
173
182
  # 不压缩,直接重命名临时文件
@@ -180,11 +189,14 @@ class BasicMobileToolsLite:
180
189
  final_path = self.screenshot_dir / filename
181
190
  temp_path.rename(final_path)
182
191
 
192
+ # 不压缩时,图片尺寸 = 屏幕尺寸
183
193
  return {
184
194
  "success": True,
185
195
  "screenshot_path": str(final_path),
186
196
  "screen_width": screen_width,
187
197
  "screen_height": screen_height,
198
+ "image_width": screen_width,
199
+ "image_height": screen_height,
188
200
  "file_size": f"{original_size/1024:.1f}KB",
189
201
  "message": f"📸 截图已保存: {final_path}\n"
190
202
  f"📐 屏幕尺寸: {screen_width}x{screen_height}\n"
@@ -226,11 +238,14 @@ class BasicMobileToolsLite:
226
238
  width = info.get('displayWidth', 0)
227
239
  height = info.get('displayHeight', 0)
228
240
 
241
+ # 不压缩时,图片尺寸 = 屏幕尺寸
229
242
  return {
230
243
  "success": True,
231
244
  "screenshot_path": str(screenshot_path),
232
245
  "screen_width": width,
233
246
  "screen_height": height,
247
+ "image_width": width,
248
+ "image_height": height,
234
249
  "message": f"📸 截图已保存: {screenshot_path}\n"
235
250
  f"📐 屏幕尺寸: {width}x{height}\n"
236
251
  f"⚠️ 未压缩(PIL 未安装),建议安装: pip install Pillow"
@@ -266,25 +281,51 @@ class BasicMobileToolsLite:
266
281
 
267
282
  # ==================== 点击操作 ====================
268
283
 
269
- def click_at_coords(self, x: int, y: int) -> Dict:
270
- """点击坐标(核心功能)"""
284
+ def click_at_coords(self, x: int, y: int, image_width: int = 0, image_height: int = 0) -> Dict:
285
+ """点击坐标(核心功能,支持自动坐标转换)
286
+
287
+ Args:
288
+ x: X 坐标(来自截图分析或屏幕坐标)
289
+ y: Y 坐标(来自截图分析或屏幕坐标)
290
+ image_width: 截图的宽度(可选,传入后自动转换坐标)
291
+ image_height: 截图的高度(可选,传入后自动转换坐标)
292
+
293
+ 坐标转换说明:
294
+ 如果截图被压缩过(如 1080→720),AI 返回的坐标是基于压缩图的。
295
+ 传入 image_width/image_height 后,工具会自动将坐标转换为屏幕坐标。
296
+ """
271
297
  try:
272
- # 获取屏幕尺寸(用于后续转换百分比)
298
+ # 获取屏幕尺寸
273
299
  screen_width, screen_height = 0, 0
274
300
  if self._is_ios():
275
301
  ios_client = self._get_ios_client()
276
302
  if ios_client and hasattr(ios_client, 'wda'):
277
- ios_client.wda.click(x, y)
278
303
  size = ios_client.wda.window_size()
279
304
  screen_width, screen_height = size[0], size[1]
280
305
  else:
281
306
  return {"success": False, "message": "❌ iOS 客户端未初始化"}
282
307
  else:
283
- self.client.u2.click(x, y)
284
308
  info = self.client.u2.info
285
309
  screen_width = info.get('displayWidth', 0)
286
310
  screen_height = info.get('displayHeight', 0)
287
311
 
312
+ # 🎯 坐标转换:如果传入了图片尺寸,将图片坐标转换为屏幕坐标
313
+ original_x, original_y = x, y
314
+ converted = False
315
+ if image_width > 0 and image_height > 0 and screen_width > 0 and screen_height > 0:
316
+ if image_width != screen_width or image_height != screen_height:
317
+ # 按比例转换坐标
318
+ x = int(x * screen_width / image_width)
319
+ y = int(y * screen_height / image_height)
320
+ converted = True
321
+
322
+ # 执行点击
323
+ if self._is_ios():
324
+ ios_client = self._get_ios_client()
325
+ ios_client.wda.click(x, y)
326
+ else:
327
+ self.client.u2.click(x, y)
328
+
288
329
  time.sleep(0.3)
289
330
 
290
331
  # 计算百分比坐标(用于跨设备兼容)
@@ -303,10 +344,18 @@ class BasicMobileToolsLite:
303
344
  ref=f"coords_{x}_{y}"
304
345
  )
305
346
 
306
- return {
307
- "success": True,
308
- "message": f"✅ 点击成功: ({x}, {y}) [相对位置: {x_percent}%, {y_percent}%]"
309
- }
347
+ if converted:
348
+ return {
349
+ "success": True,
350
+ "message": f"✅ 点击成功: ({x}, {y})\n"
351
+ f" 📐 坐标已转换: ({original_x},{original_y}) → ({x},{y})\n"
352
+ f" 🖼️ 图片尺寸: {image_width}x{image_height} → 屏幕: {screen_width}x{screen_height}"
353
+ }
354
+ else:
355
+ return {
356
+ "success": True,
357
+ "message": f"✅ 点击成功: ({x}, {y}) [相对位置: {x_percent}%, {y_percent}%]"
358
+ }
310
359
  except Exception as e:
311
360
  return {"success": False, "message": f"❌ 点击失败: {e}"}
312
361
 
@@ -813,97 +862,6 @@ class BasicMobileToolsLite:
813
862
  except Exception as e:
814
863
  return {"success": False, "message": f"❌ 断言失败: {e}"}
815
864
 
816
- def close_ad(self, keywords: Optional[List[str]] = None, max_attempts: int = 3) -> Dict:
817
- """关闭广告弹窗
818
-
819
- 自动检测并点击广告关闭按钮,支持多种关闭方式:
820
- 1. 文本匹配:关闭、跳过、Skip、Close 等
821
- 2. 特殊符号:×、X、✕ 等
822
- 3. content-desc 匹配
823
-
824
- Args:
825
- keywords: 自定义关键词列表,默认使用内置关键词
826
- max_attempts: 最大尝试次数,默认3次(处理多层弹窗)
827
-
828
- Returns:
829
- 关闭结果,包含关闭的广告数量
830
- """
831
- # 默认关键词(按优先级排序)
832
- default_keywords = [
833
- '关闭', '跳过', 'Skip', 'Close', 'close',
834
- '×', 'X', '✕', '╳',
835
- '我知道了', '稍后再说', '不再提示', '取消',
836
- '知道了', '好的', '确定',
837
- 'Later', 'No thanks', 'Not now', 'Dismiss'
838
- ]
839
-
840
- search_keywords = keywords if keywords else default_keywords
841
- closed_count = 0
842
- closed_items = []
843
-
844
- try:
845
- for attempt in range(max_attempts):
846
- found_in_this_round = False
847
-
848
- for keyword in search_keywords:
849
- try:
850
- if self._is_ios():
851
- ios_client = self._get_ios_client()
852
- if ios_client and hasattr(ios_client, 'wda'):
853
- # iOS: 尝试 name 和 label
854
- elem = ios_client.wda(name=keyword)
855
- if not elem.exists:
856
- elem = ios_client.wda(label=keyword)
857
- if not elem.exists:
858
- elem = ios_client.wda(nameContains=keyword)
859
-
860
- if elem.exists:
861
- elem.click()
862
- time.sleep(0.5)
863
- closed_count += 1
864
- closed_items.append(keyword)
865
- found_in_this_round = True
866
- break
867
- else:
868
- # Android: 尝试 text 和 content-desc
869
- elem = self.client.u2(text=keyword)
870
- if not elem.exists(timeout=0.2):
871
- elem = self.client.u2(textContains=keyword)
872
- if not elem.exists(timeout=0.2):
873
- elem = self.client.u2(description=keyword)
874
- if not elem.exists(timeout=0.2):
875
- elem = self.client.u2(descriptionContains=keyword)
876
-
877
- if elem.exists(timeout=0.2):
878
- elem.click()
879
- time.sleep(0.5)
880
- closed_count += 1
881
- closed_items.append(keyword)
882
- found_in_this_round = True
883
- break
884
- except Exception:
885
- continue
886
-
887
- if not found_in_this_round:
888
- # 这一轮没找到广告,退出
889
- break
890
-
891
- if closed_count > 0:
892
- return {
893
- "success": True,
894
- "closed_count": closed_count,
895
- "closed_items": closed_items,
896
- "message": f"✅ 已关闭 {closed_count} 个广告弹窗: {', '.join(closed_items)}"
897
- }
898
- else:
899
- return {
900
- "success": True,
901
- "closed_count": 0,
902
- "message": "✅ 未发现广告弹窗(或已全部关闭)"
903
- }
904
- except Exception as e:
905
- return {"success": False, "message": f"❌ 关闭广告失败: {e}"}
906
-
907
865
  # ==================== 脚本生成 ====================
908
866
 
909
867
  def get_operation_history(self, limit: Optional[int] = None) -> Dict:
@@ -825,34 +825,29 @@ class MobileClient:
825
825
  return {"success": False, "reason": str(e)}
826
826
 
827
827
  # Android平台
828
- # 🎯 尝试使用智能启动(如果模块存在)
828
+ # 🎯 优先使用智能启动(推荐)
829
829
  if smart_wait:
830
- try:
831
- from .smart_app_launcher import SmartAppLauncher
832
- launcher = SmartAppLauncher(self)
833
- # 优化:快速模式,最多3
834
- smart_wait_time = min(wait_time, 3)
835
-
836
- # 🎯 从环境变量读取是否自动关闭广告(默认True)
837
- import os
838
- auto_close_ads = os.environ.get('AUTO_CLOSE_ADS', 'true').lower() in ['true', '1', 'yes']
839
-
840
- result = await launcher.launch_with_smart_wait(
841
- package_name,
842
- max_wait=smart_wait_time,
843
- auto_close_ads=auto_close_ads
844
- )
845
-
846
- # 打印截图路径(供Cursor AI查看验证)
847
- if result.get('screenshot_path'):
848
- print(f"\n📸 启动截图已保存: {result['screenshot_path']}", file=sys.stderr)
849
- print(f"💡 提示: 请查看截图确认App是否已正确进入主页", file=sys.stderr)
850
-
851
- return result
852
- except ImportError:
853
- # SmartAppLauncher 模块不存在,使用传统方式
854
- print(f" 💡 智能启动模块未安装,使用传统启动方式", file=sys.stderr)
855
- # 继续执行下面的传统方式
830
+ from .smart_app_launcher import SmartAppLauncher
831
+ launcher = SmartAppLauncher(self)
832
+ # 优化:快速模式,最多3秒
833
+ smart_wait_time = min(wait_time, 3)
834
+
835
+ # 🎯 从环境变量读取是否自动关闭广告(默认True)
836
+ import os
837
+ auto_close_ads = os.environ.get('AUTO_CLOSE_ADS', 'true').lower() in ['true', '1', 'yes']
838
+
839
+ result = await launcher.launch_with_smart_wait(
840
+ package_name,
841
+ max_wait=smart_wait_time,
842
+ auto_close_ads=auto_close_ads
843
+ )
844
+
845
+ # 打印截图路径(供Cursor AI查看验证)
846
+ if result.get('screenshot_path'):
847
+ print(f"\n📸 启动截图已保存: {result['screenshot_path']}", file=sys.stderr)
848
+ print(f"💡 提示: 请查看截图确认App是否已正确进入主页", file=sys.stderr)
849
+
850
+ return result
856
851
 
857
852
  # 传统方式(快速启动,不等待加载)
858
853
  print(f" 📱 启动App: {package_name}", file=sys.stderr)
@@ -156,12 +156,15 @@ class MobileMCPServer:
156
156
  # ==================== 截图(视觉兜底)====================
157
157
  tools.append(Tool(
158
158
  name="mobile_take_screenshot",
159
- description="📸 截图(视觉定位用)。返回截图路径和屏幕尺寸。\n\n"
159
+ description="📸 截图(视觉定位用)。返回截图路径、屏幕尺寸和图片尺寸。\n\n"
160
160
  "🎯 使用场景:\n"
161
161
  "- 游戏(Unity/Cocos)无法获取元素时\n"
162
162
  "- mobile_list_elements 返回空时\n"
163
163
  "- 需要确认页面状态时\n\n"
164
- "⚠️ 截图分辨率 = 屏幕分辨率,坐标可直接使用",
164
+ "⚠️ 【重要】截图会被压缩!\n"
165
+ " - screen_width/screen_height = 原始屏幕尺寸\n"
166
+ " - image_width/image_height = 压缩后图片尺寸(AI 看到的)\n"
167
+ " - 点击时必须传入 image_width/image_height 让工具自动转换坐标!",
165
168
  inputSchema={
166
169
  "type": "object",
167
170
  "properties": {
@@ -215,13 +218,17 @@ class MobileMCPServer:
215
218
  "- 游戏(Unity/Cocos)无法获取元素\n"
216
219
  "- mobile_list_elements 返回空\n"
217
220
  "- 元素没有 id 和 text\n\n"
218
- " 自动记录百分比坐标,生成脚本时会转换为跨分辨率兼容的百分比定位\n"
219
- "💡 录制测试脚本时,请先调用 mobile_list_elements 尝试获取元素!",
221
+ "⚠️ 【重要】如果坐标来自压缩截图,必须传入 image_width 和 image_height!\n"
222
+ " 截图返回的 image_width/image_height 字段就是需要传入的值。\n"
223
+ " 工具会自动将图片坐标转换为屏幕坐标。\n\n"
224
+ "✅ 自动记录百分比坐标,生成脚本时会转换为跨分辨率兼容的百分比定位",
220
225
  inputSchema={
221
226
  "type": "object",
222
227
  "properties": {
223
- "x": {"type": "number", "description": "X 坐标(像素)"},
224
- "y": {"type": "number", "description": "Y 坐标(像素)"}
228
+ "x": {"type": "number", "description": "X 坐标(像素,来自截图分析或屏幕坐标)"},
229
+ "y": {"type": "number", "description": "Y 坐标(像素,来自截图分析或屏幕坐标)"},
230
+ "image_width": {"type": "number", "description": "截图的宽度(可选,传入后自动转换坐标)"},
231
+ "image_height": {"type": "number", "description": "截图的高度(可选,传入后自动转换坐标)"}
225
232
  },
226
233
  "required": ["x", "y"]
227
234
  }
@@ -379,32 +386,6 @@ class MobileMCPServer:
379
386
  }
380
387
  ))
381
388
 
382
- tools.append(Tool(
383
- name="mobile_close_ad",
384
- description="📢 关闭广告弹窗(自动检测并点击关闭按钮)\n\n"
385
- "🎯 自动检测以下关闭方式:\n"
386
- "- 文本:关闭、跳过、Skip、Close、我知道了、稍后再说\n"
387
- "- 符号:×、X、✕ 等\n"
388
- "- 无障碍描述(content-desc)\n\n"
389
- "💡 支持多层弹窗,最多尝试3次\n"
390
- "✅ 比视觉识别更准确,推荐使用!",
391
- inputSchema={
392
- "type": "object",
393
- "properties": {
394
- "keywords": {
395
- "type": "array",
396
- "items": {"type": "string"},
397
- "description": "自定义关键词列表(可选,默认使用内置关键词)"
398
- },
399
- "max_attempts": {
400
- "type": "number",
401
- "description": "最大尝试次数(可选,默认3次,用于处理多层弹窗)"
402
- }
403
- },
404
- "required": []
405
- }
406
- ))
407
-
408
389
  # ==================== pytest 脚本生成 ====================
409
390
  tools.append(Tool(
410
391
  name="mobile_get_operation_history",
@@ -472,7 +453,12 @@ class MobileMCPServer:
472
453
 
473
454
  # 点击
474
455
  elif name == "mobile_click_at_coords":
475
- result = self.tools.click_at_coords(arguments["x"], arguments["y"])
456
+ result = self.tools.click_at_coords(
457
+ arguments["x"],
458
+ arguments["y"],
459
+ arguments.get("image_width", 0),
460
+ arguments.get("image_height", 0)
461
+ )
476
462
  return [TextContent(type="text", text=self.format_response(result))]
477
463
 
478
464
  elif name == "mobile_click_by_text":
@@ -540,13 +526,6 @@ class MobileMCPServer:
540
526
  result = self.tools.assert_text(arguments["text"])
541
527
  return [TextContent(type="text", text=self.format_response(result))]
542
528
 
543
- elif name == "mobile_close_ad":
544
- result = self.tools.close_ad(
545
- arguments.get("keywords"),
546
- arguments.get("max_attempts", 3)
547
- )
548
- return [TextContent(type="text", text=self.format_response(result))]
549
-
550
529
  # 脚本生成
551
530
  elif name == "mobile_get_operation_history":
552
531
  result = self.tools.get_operation_history(arguments.get("limit"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mobile-mcp-ai
3
- Version: 2.3.3
3
+ Version: 2.3.4
4
4
  Summary: 移动端自动化 MCP Server - 支持 Android/iOS,AI 功能可选(基础工具不需要 AI)
5
5
  Home-page: https://github.com/test111ddff-hash/mobile-mcp-ai
6
6
  Author: douzi
@@ -25,7 +25,7 @@ if requirements_file.exists():
25
25
 
26
26
  setup(
27
27
  name="mobile-mcp-ai",
28
- version="2.3.3", # 新增 mobile_close_ad 广告关闭工具 + 修复 SmartAppLauncher 异常
28
+ version="2.3.4", # 修复截图坐标偏移问题:支持图片坐标自动转换为屏幕坐标
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