xcode-mcp-server 1.3.11b4__tar.gz → 1.3.13__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 (138) hide show
  1. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/PKG-INFO +2 -2
  2. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/pyproject.toml +1 -1
  3. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/__init__.py +1 -1
  4. xcode_mcp_server-1.3.13/xcode_mcp_server/server.py +80 -0
  5. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/build_project.py +17 -9
  6. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/clean_project.py +9 -5
  7. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/create_project.py +2 -2
  8. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/debug_list_notification_history.py +2 -2
  9. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_active_run_destination.py +2 -2
  10. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_build_errors.py +2 -2
  11. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_build_results.py +2 -2
  12. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_directory_listing.py +2 -2
  13. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_directory_tree.py +2 -2
  14. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_latest_test_results.py +2 -2
  15. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_project_schemes.py +2 -2
  16. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_runtime_output.py +2 -2
  17. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/get_xcode_projects.py +2 -2
  18. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/list_booted_simulators.py +2 -2
  19. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/list_mac_app_windows.py +2 -2
  20. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/list_project_tests.py +2 -2
  21. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/list_run_destinations.py +2 -2
  22. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/list_running_mac_apps.py +2 -2
  23. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/run_project_tests.py +21 -12
  24. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/run_project_unmonitored.py +2 -2
  25. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/run_project_until_terminated.py +19 -13
  26. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/run_project_with_user_interaction.py +2 -2
  27. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/set_run_destination.py +2 -2
  28. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/stop_project.py +2 -2
  29. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/take_app_screenshot.py +2 -2
  30. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/take_simulator_screenshot.py +2 -2
  31. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/take_window_screenshot.py +2 -2
  32. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/take_xcode_screenshot.py +2 -2
  33. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/version.py +2 -2
  34. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/applescript.py +48 -5
  35. xcode_mcp_server-1.3.11b4/xcode_mcp_server/server.py +0 -29
  36. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/.github/workflows/claude-code.yml +0 -0
  37. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/.github/workflows/claude-self-review.yml +0 -0
  38. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/.gitignore +0 -0
  39. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/CLAUDE.md +0 -0
  40. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/LICENSE +0 -0
  41. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/README.md +0 -0
  42. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/TODO.md +0 -0
  43. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/__PUBLIC_REPO +0 -0
  44. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/_venv-setup.sh +0 -0
  45. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/deploy-beta.sh +0 -0
  46. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/deploy.sh +0 -0
  47. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/dev.sh +0 -0
  48. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/info.sh +0 -0
  49. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/requirements.txt +0 -0
  50. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/run_local_for_claude.sh +0 -0
  51. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/cleanup_tests.sh +0 -0
  52. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/create_projects.py +0 -0
  53. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/create_real_projects.py +0 -0
  54. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/create_spm_projects.sh +0 -0
  55. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/create_xcode_projects.sh +0 -0
  56. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/run_all_tests.sh +0 -0
  57. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/setup_test_projects.sh +0 -0
  58. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/scripts/setup_tests.sh +0 -0
  59. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  60. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  61. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/Contents.json +0 -0
  62. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/ContentView.swift +0 -0
  63. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/iosEmptySwiftUIAppApp.swift +0 -0
  64. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.pbxproj +0 -0
  65. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  66. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  67. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  68. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp/main.swift +0 -0
  69. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.pbxproj +0 -0
  70. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  71. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  72. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  73. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  74. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  75. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/Contents.json +0 -0
  76. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/ContentView.swift +0 -0
  77. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/macosEmptySwiftUIAppApp.swift +0 -0
  78. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.pbxproj +0 -0
  79. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  80. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  81. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  82. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/BrokenApp/BrokenApp/main.swift +0 -0
  83. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.pbxproj +0 -0
  84. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  85. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  86. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  87. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/ConsoleApp/ConsoleApp/main.swift +0 -0
  88. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.pbxproj +0 -0
  89. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  90. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  91. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  92. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SimpleApp/SimpleApp/main.swift +0 -0
  93. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.pbxproj +0 -0
  94. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  95. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  96. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  97. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  98. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  99. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/Contents.json +0 -0
  100. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/ContentView.swift +0 -0
  101. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/macosEmptySwiftUIAppApp.swift +0 -0
  102. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.pbxproj +0 -0
  103. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  104. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  105. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  106. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  107. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  108. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/Contents.json +0 -0
  109. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp/ContentView.swift +0 -0
  110. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp/iosEmptySwiftUIAppApp.swift +0 -0
  111. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.pbxproj +0 -0
  112. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  113. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  114. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -0
  115. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/debug_build.py +0 -0
  116. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/debug_test.py +0 -0
  117. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_basic.py +0 -0
  118. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_build.py +0 -0
  119. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_build_log_parser.py +0 -0
  120. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_fixed.py +0 -0
  121. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_manifest_wait.py +0 -0
  122. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_minimal.py +0 -0
  123. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/tests/test_runner.py +0 -0
  124. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/__main__.py +0 -0
  125. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/cli.py +0 -0
  126. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/config_manager.py +0 -0
  127. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/config_ui.py +0 -0
  128. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/exceptions.py +0 -0
  129. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/security.py +0 -0
  130. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/tools/__init__.py +0 -0
  131. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/__init__.py +0 -0
  132. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/build_log_parser.py +0 -0
  133. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/decode_active_destination.swift +0 -0
  134. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/decode_xcode_recents.swift +0 -0
  135. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/paths.py +0 -0
  136. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/project_templates.py +0 -0
  137. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/screenshot.py +0 -0
  138. {xcode_mcp_server-1.3.11b4 → xcode_mcp_server-1.3.13}/xcode_mcp_server/utils/xcresult.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xcode-mcp-server
3
- Version: 1.3.11b4
3
+ Version: 1.3.13
4
4
  Summary: Drew's MCP server for Xcode integration
5
5
  Project-URL: Homepage, https://github.com/drewster99/xcode-mcp-server
6
6
  Project-URL: Repository, https://github.com/drewster99/xcode-mcp-server
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.10
20
- Requires-Dist: mcp[cli]>=1.2.0
20
+ Requires-Dist: mcp[cli]>=1.7.0
21
21
  Requires-Dist: questionary>=2.0.0
22
22
  Requires-Dist: rich>=13.0.0
23
23
  Description-Content-Type: text/markdown
@@ -23,7 +23,7 @@ classifiers = [
23
23
  "Programming Language :: Python :: 3.12",
24
24
  ]
25
25
  dependencies = [
26
- "mcp[cli]>=1.2.0",
26
+ "mcp[cli]>=1.7.0",
27
27
  "questionary>=2.0.0",
28
28
  "rich>=13.0.0",
29
29
  ]
@@ -1,6 +1,6 @@
1
1
  """Xcode MCP Server - Model Context Protocol server for Xcode integration"""
2
2
 
3
- __version__ = "1.3.11b4"
3
+ __version__ = "1.3.13"
4
4
 
5
5
 
6
6
  def main():
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env python3
2
+ """FastMCP server instance for Xcode MCP Server"""
3
+
4
+ from mcp.server.fastmcp import FastMCP
5
+ from mcp.types import ToolAnnotations
6
+
7
+ # Initialize the MCP server
8
+ mcp = FastMCP("Xcode MCP Server",
9
+ instructions="""
10
+ This server provides access to the Xcode IDE. For any project intended
11
+ for Apple platforms, such as iOS or macOS, this MCP server is the best
12
+ way to build or run .xcodeproj or .xcworkspace Xcode projects, and should
13
+ ALWAYS be preferred over using `xcodebuild`, `swift build`, or
14
+ `swift package build`. Building with this tool ensures the build happens
15
+ exactly the same way as when the user builds with Xcode, with all the same
16
+ settings, so you will get the same results the user sees. The user can also
17
+ see any results immediately and a subsequent build and run by the user will
18
+ happen almost instantly for the user.
19
+
20
+ Call `get_xcode_projects` to find Xcode project (.xcodeproj) and
21
+ Xcode workspace (.xcworkspace) folders under a given root folder.
22
+
23
+ Call `get_project_schemes` to get the build scheme names for a given
24
+ .xcodeproj or .xcworkspace.
25
+
26
+ Call `build_project` to build the project and get back the first 25 lines of
27
+ error (and/or potentially warning) output. `build_project` will default to the
28
+ active scheme if none is provided.
29
+ """
30
+ )
31
+
32
+ # Tool behavior annotations (advisory hints for MCP clients).
33
+ #
34
+ # These describe how a tool affects its environment so clients can gate
35
+ # auto-approval and label tools appropriately. The build/run/test tools are
36
+ # marked destructive AND open-world: a build executes arbitrary third-party
37
+ # code (Run Script phases, SPM plugins/macros) and resolves packages from
38
+ # arbitrary remote hosts, so we cannot honestly claim it is additive-only,
39
+ # idempotent, or hermetic.
40
+
41
+ # Pure observers: reading state, listing, screenshots. No mutation, no network.
42
+ TOOL_READONLY = ToolAnnotations(
43
+ readOnlyHint=True,
44
+ idempotentHint=True,
45
+ destructiveHint=False,
46
+ openWorldHint=False,
47
+ )
48
+
49
+ # Builds and runs: execute arbitrary build/install scripts and fetch packages.
50
+ TOOL_BUILD = ToolAnnotations(
51
+ readOnlyHint=False,
52
+ idempotentHint=False,
53
+ destructiveHint=True,
54
+ openWorldHint=True,
55
+ )
56
+
57
+ # Clean: deletes build artifacts. Destructive but locally bounded and idempotent.
58
+ TOOL_CLEAN = ToolAnnotations(
59
+ readOnlyHint=False,
60
+ idempotentHint=True,
61
+ destructiveHint=True,
62
+ openWorldHint=False,
63
+ )
64
+
65
+ # Create: writes a fresh template and refuses to overwrite. Additive, local.
66
+ TOOL_CREATE = ToolAnnotations(
67
+ readOnlyHint=False,
68
+ idempotentHint=False,
69
+ destructiveHint=False,
70
+ openWorldHint=False,
71
+ )
72
+
73
+ # Settles a piece of local state (run destination, stopping a run). Re-applying
74
+ # the same call lands on the same state, and nothing is destroyed.
75
+ TOOL_MUTATING_IDEMPOTENT = ToolAnnotations(
76
+ readOnlyHint=False,
77
+ idempotentHint=True,
78
+ destructiveHint=False,
79
+ openWorldHint=False,
80
+ )
@@ -8,14 +8,14 @@ import sys
8
8
  import time
9
9
  from typing import Optional
10
10
 
11
- from xcode_mcp_server.server import mcp
11
+ from xcode_mcp_server.server import mcp, TOOL_BUILD
12
12
  from xcode_mcp_server.config_manager import apply_config
13
13
  from xcode_mcp_server.security import validate_and_normalize_project_path
14
14
  from xcode_mcp_server.exceptions import InvalidParameterError, XCodeMCPError
15
15
  from xcode_mcp_server.utils.applescript import (
16
- BUILD_TIMEOUT_SECONDS,
17
16
  build_open_and_wait_applescript,
18
17
  build_wait_for_completion_applescript,
18
+ resolve_build_timeout,
19
19
  escape_applescript_string,
20
20
  run_applescript,
21
21
  show_notification,
@@ -283,18 +283,20 @@ def _supplement_with_xcactivitylog_warnings(
283
283
  return errors_json
284
284
 
285
285
 
286
- @mcp.tool()
286
+ @mcp.tool(annotations=TOOL_BUILD)
287
287
  @apply_config
288
288
  def build_project(project_path: str,
289
289
  scheme: Optional[str] = None,
290
290
  include_warnings: Optional[bool] = None,
291
291
  regex_filter: Optional[str] = None,
292
- max_lines: int = 25) -> str:
292
+ max_lines: int = 25,
293
+ timeout: Optional[int] = None) -> str:
293
294
  """
294
295
  Build the specified Xcode project or workspace.
295
296
 
296
- Builds will run for up to 10 minutes before timing out. This timeout is hardcoded
297
- to prevent issues with builds hanging indefinitely.
297
+ Builds run for up to `timeout` seconds (default 600, i.e. 10 minutes) before
298
+ timing out, which guards against a build that hangs indefinitely. Raise it
299
+ for large projects whose cold build exceeds the default.
298
300
 
299
301
  Args:
300
302
  project_path: Path to an Xcode project or workspace directory.
@@ -302,6 +304,8 @@ def build_project(project_path: str,
302
304
  include_warnings: Include warnings in build output. If not provided, uses global setting.
303
305
  regex_filter: Optional regex to filter error/warning lines
304
306
  max_lines: Maximum number of error/warning lines to show (default 25)
307
+ timeout: Maximum seconds to wait for the build to complete. If not
308
+ provided, defaults to 600. Must be a positive integer.
305
309
 
306
310
  Returns:
307
311
  Always returns JSON with format:
@@ -317,6 +321,10 @@ def build_project(project_path: str,
317
321
  if include_warnings is not None and not isinstance(include_warnings, bool):
318
322
  raise InvalidParameterError("include_warnings must be a boolean value")
319
323
 
324
+ # Resolve the build timeout up front so an invalid value errors immediately,
325
+ # before any AppleScript runs.
326
+ effective_timeout = resolve_build_timeout(timeout)
327
+
320
328
  # Validate regex_filter up front so a bad pattern produces a clear error
321
329
  # immediately, before any AppleScript runs. The supplement helper assumes
322
330
  # the pattern compiles.
@@ -340,7 +348,7 @@ def build_project(project_path: str,
340
348
  script = (
341
349
  build_open_and_wait_applescript(escaped_path, escaped_scheme)
342
350
  + ' set actionResult to build workspaceDoc\n'
343
- + build_wait_for_completion_applescript("actionResult", BUILD_TIMEOUT_SECONDS)
351
+ + build_wait_for_completion_applescript("actionResult", effective_timeout)
344
352
  + ' set buildStatus to "unknown"\n'
345
353
  + ' try\n'
346
354
  + ' set buildStatus to status of actionResult as string\n'
@@ -359,10 +367,10 @@ def build_project(project_path: str,
359
367
  manifest_path = os.path.join(derived_data_path, "Logs", "Build", "LogStoreManifest.plist")
360
368
  pre_build_uuids = snapshot_build_uuids(manifest_path)
361
369
 
362
- # The script polls inside AppleScript for up to BUILD_TIMEOUT_SECONDS; the
370
+ # The script polls inside AppleScript for up to effective_timeout; the
363
371
  # subprocess timeout must exceed that, with a small buffer for workspace
364
372
  # load and IPC overhead.
365
- success, output = run_applescript(script, timeout=BUILD_TIMEOUT_SECONDS + 60)
373
+ success, output = run_applescript(script, timeout=effective_timeout + 60)
366
374
 
367
375
  if success:
368
376
  # Parse the BUILD_STATUS: prefix from the AppleScript output
@@ -2,14 +2,15 @@
2
2
  """clean_project tool - Clean an Xcode project"""
3
3
 
4
4
  import os
5
+ from typing import Optional
5
6
 
6
- from xcode_mcp_server.server import mcp
7
+ from xcode_mcp_server.server import mcp, TOOL_CLEAN
7
8
  from xcode_mcp_server.config_manager import apply_config
8
9
  from xcode_mcp_server.security import validate_and_normalize_project_path
9
10
  from xcode_mcp_server.exceptions import XCodeMCPError
10
11
  from xcode_mcp_server.utils.applescript import (
11
- BUILD_TIMEOUT_SECONDS,
12
12
  build_open_and_wait_applescript,
13
+ resolve_build_timeout,
13
14
  escape_applescript_string,
14
15
  run_applescript,
15
16
  show_result_notification,
@@ -17,14 +18,16 @@ from xcode_mcp_server.utils.applescript import (
17
18
  )
18
19
 
19
20
 
20
- @mcp.tool()
21
+ @mcp.tool(annotations=TOOL_CLEAN)
21
22
  @apply_config
22
- def clean_project(project_path: str) -> str:
23
+ def clean_project(project_path: str, timeout: Optional[int] = None) -> str:
23
24
  """
24
25
  Clean the specified Xcode project or workspace.
25
26
 
26
27
  Args:
27
28
  project_path: Path to an Xcode project/workspace directory.
29
+ timeout: Maximum seconds to wait for the clean to complete. If not
30
+ provided, defaults to 600. Must be a positive integer.
28
31
 
29
32
  Returns:
30
33
  Output message
@@ -32,6 +35,7 @@ def clean_project(project_path: str) -> str:
32
35
  # Validate and normalize path
33
36
  normalized_path = validate_and_normalize_project_path(project_path, "Cleaning")
34
37
  escaped_path = escape_applescript_string(normalized_path)
38
+ effective_timeout = resolve_build_timeout(timeout)
35
39
 
36
40
  script = build_open_and_wait_applescript(escaped_path) + (
37
41
  ' clean workspaceDoc\n'
@@ -41,7 +45,7 @@ def clean_project(project_path: str) -> str:
41
45
 
42
46
  # Clean is synchronous in AppleScript and can take minutes on large projects;
43
47
  # use the same budget as build/test rather than the short default.
44
- success, output = run_applescript(script, timeout=BUILD_TIMEOUT_SECONDS + 60)
48
+ success, output = run_applescript(script, timeout=effective_timeout + 60)
45
49
 
46
50
  project_name = os.path.basename(normalized_path)
47
51
 
@@ -5,7 +5,7 @@ import json
5
5
  import os
6
6
  from typing import Optional
7
7
 
8
- from xcode_mcp_server.server import mcp
8
+ from xcode_mcp_server.server import mcp, TOOL_CREATE
9
9
  from xcode_mcp_server.config_manager import apply_config
10
10
  from xcode_mcp_server.security import validate_parent_for_new_project
11
11
  from xcode_mcp_server.exceptions import InvalidParameterError
@@ -23,7 +23,7 @@ from xcode_mcp_server.tools.get_xcode_projects import register_created_project
23
23
  SUPPORTED_PLATFORMS = {"ios", "macos"}
24
24
 
25
25
 
26
- @mcp.tool()
26
+ @mcp.tool(annotations=TOOL_CREATE)
27
27
  @apply_config
28
28
  def create_project(
29
29
  parent_directory: str,
@@ -5,7 +5,7 @@ import os
5
5
  import subprocess
6
6
  import sys
7
7
 
8
- from xcode_mcp_server.server import mcp
8
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
9
9
  from xcode_mcp_server.config_manager import apply_config
10
10
  from xcode_mcp_server.utils.applescript import get_notification_history
11
11
  from xcode_mcp_server.utils.paths import DEBUG_DIR
@@ -16,7 +16,7 @@ from xcode_mcp_server.utils.paths import DEBUG_DIR
16
16
  NOTIFICATION_HISTORY_FILE = os.path.join(DEBUG_DIR, "notification-history.txt")
17
17
 
18
18
 
19
- @mcp.tool()
19
+ @mcp.tool(annotations=TOOL_READONLY)
20
20
  @apply_config
21
21
  def debug_list_notification_history() -> str:
22
22
  """
@@ -7,7 +7,7 @@ import os
7
7
  import subprocess
8
8
  import sys
9
9
 
10
- from xcode_mcp_server.server import mcp
10
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
11
11
  from xcode_mcp_server.config_manager import apply_config
12
12
  from xcode_mcp_server.security import validate_and_normalize_project_path
13
13
  from xcode_mcp_server.exceptions import XCodeMCPError
@@ -162,7 +162,7 @@ def _lookup_simulator_info(udid: str) -> tuple:
162
162
  return ("", "")
163
163
 
164
164
 
165
- @mcp.tool()
165
+ @mcp.tool(annotations=TOOL_READONLY)
166
166
  @apply_config
167
167
  def get_active_run_destination(
168
168
  project_path: str,
@@ -3,7 +3,7 @@
3
3
 
4
4
  from typing import Optional
5
5
 
6
- from xcode_mcp_server.server import mcp
6
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
7
7
  from xcode_mcp_server.config_manager import apply_config
8
8
  from xcode_mcp_server.security import validate_and_normalize_project_path
9
9
  from xcode_mcp_server.exceptions import InvalidParameterError, XCodeMCPError
@@ -11,7 +11,7 @@ from xcode_mcp_server.utils.applescript import escape_applescript_string, run_ap
11
11
  from xcode_mcp_server.utils.xcresult import extract_build_errors_and_warnings
12
12
 
13
13
 
14
- @mcp.tool()
14
+ @mcp.tool(annotations=TOOL_READONLY)
15
15
  @apply_config
16
16
  def get_build_errors(project_path: str,
17
17
  include_warnings: Optional[bool] = None,
@@ -5,7 +5,7 @@ import os
5
5
  import json
6
6
  from typing import Optional
7
7
 
8
- from xcode_mcp_server.server import mcp
8
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
9
9
  from xcode_mcp_server.config_manager import apply_config
10
10
  from xcode_mcp_server.security import validate_and_normalize_project_path
11
11
  from xcode_mcp_server.exceptions import XCodeMCPError
@@ -15,7 +15,7 @@ from xcode_mcp_server.utils.build_log_parser import (
15
15
  )
16
16
 
17
17
 
18
- @mcp.tool()
18
+ @mcp.tool(annotations=TOOL_READONLY)
19
19
  @apply_config
20
20
  def get_build_results(project_path: str,
21
21
  max_warnings: int = 50) -> str:
@@ -6,14 +6,14 @@ import re
6
6
  import datetime
7
7
  from typing import Optional
8
8
 
9
- from xcode_mcp_server.server import mcp
9
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
10
10
  from xcode_mcp_server.config_manager import apply_config
11
11
  from xcode_mcp_server.security import validate_and_normalize_directory_path
12
12
  from xcode_mcp_server.exceptions import AccessDeniedError, InvalidParameterError, XCodeMCPError
13
13
  from xcode_mcp_server.utils.applescript import show_error_notification
14
14
 
15
15
 
16
- @mcp.tool()
16
+ @mcp.tool(annotations=TOOL_READONLY)
17
17
  @apply_config
18
18
  def get_directory_listing(directory_path: str,
19
19
  regex_filter: Optional[str] = None,
@@ -4,7 +4,7 @@
4
4
  import os
5
5
  from typing import List
6
6
 
7
- from xcode_mcp_server.server import mcp
7
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
8
8
  from xcode_mcp_server.config_manager import apply_config
9
9
  from xcode_mcp_server.security import validate_and_normalize_directory_path
10
10
  from xcode_mcp_server.exceptions import InvalidParameterError, XCodeMCPError
@@ -32,7 +32,7 @@ SKIP_DIR_NAMES = frozenset([
32
32
  MAX_TREE_LINES = 5000
33
33
 
34
34
 
35
- @mcp.tool()
35
+ @mcp.tool(annotations=TOOL_READONLY)
36
36
  @apply_config
37
37
  def get_directory_tree(directory_path: str, max_depth: int = 4) -> str:
38
38
  """
@@ -5,7 +5,7 @@ import os
5
5
  import json
6
6
  import sys
7
7
 
8
- from xcode_mcp_server.server import mcp
8
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
9
9
  from xcode_mcp_server.config_manager import apply_config
10
10
  from xcode_mcp_server.security import validate_and_normalize_project_path
11
11
  from xcode_mcp_server.utils.applescript import (
@@ -18,7 +18,7 @@ from xcode_mcp_server.utils.applescript import (
18
18
  from xcode_mcp_server.utils.xcresult import find_xcresult_bundle, extract_test_results_from_xcresult
19
19
 
20
20
 
21
- @mcp.tool()
21
+ @mcp.tool(annotations=TOOL_READONLY)
22
22
  @apply_config
23
23
  def get_latest_test_results(project_path: str) -> str:
24
24
  """
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """get_project_schemes tool - Get available build schemes"""
3
3
 
4
- from xcode_mcp_server.server import mcp
4
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
5
5
  from xcode_mcp_server.config_manager import apply_config
6
6
  from xcode_mcp_server.security import validate_and_normalize_project_path
7
7
  from xcode_mcp_server.exceptions import XCodeMCPError
@@ -14,7 +14,7 @@ from xcode_mcp_server.utils.applescript import (
14
14
  )
15
15
 
16
16
 
17
- @mcp.tool()
17
+ @mcp.tool(annotations=TOOL_READONLY)
18
18
  @apply_config
19
19
  def get_project_schemes(project_path: str) -> str:
20
20
  """
@@ -5,7 +5,7 @@ import sys
5
5
  import json
6
6
  from typing import Optional
7
7
 
8
- from xcode_mcp_server.server import mcp
8
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
9
9
  from xcode_mcp_server.config_manager import apply_config
10
10
  from xcode_mcp_server.security import validate_and_normalize_project_path
11
11
  from xcode_mcp_server.exceptions import InvalidParameterError, XCodeMCPError
@@ -13,7 +13,7 @@ from xcode_mcp_server.utils.xcresult import find_xcresult_for_project, extract_c
13
13
  from xcode_mcp_server.utils.applescript import show_error_notification, show_warning_notification, show_result_notification
14
14
 
15
15
 
16
- @mcp.tool()
16
+ @mcp.tool(annotations=TOOL_READONLY)
17
17
  @apply_config
18
18
  def get_runtime_output(project_path: str,
19
19
  regex_filter: Optional[str] = None,
@@ -6,7 +6,7 @@ import sys
6
6
  import subprocess
7
7
  import re
8
8
 
9
- from xcode_mcp_server.server import mcp
9
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
10
10
  from xcode_mcp_server.config_manager import apply_config
11
11
  from xcode_mcp_server.security import ALLOWED_FOLDERS, is_path_allowed
12
12
  from xcode_mcp_server.exceptions import AccessDeniedError, InvalidParameterError
@@ -179,7 +179,7 @@ def _filter_project_results(paths: list[str], search_paths: list[str] = None, ma
179
179
  return final_results
180
180
 
181
181
 
182
- @mcp.tool()
182
+ @mcp.tool(annotations=TOOL_READONLY)
183
183
  @apply_config
184
184
  def get_xcode_projects(
185
185
  search_path: str = "",
@@ -3,14 +3,14 @@
3
3
 
4
4
  import subprocess
5
5
 
6
- from xcode_mcp_server.server import mcp
6
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
7
7
  from xcode_mcp_server.config_manager import apply_config
8
8
  from xcode_mcp_server.exceptions import XCodeMCPError
9
9
  from xcode_mcp_server.utils.applescript import show_result_notification, show_error_notification
10
10
  from xcode_mcp_server.utils.screenshot import _get_booted_simulators
11
11
 
12
12
 
13
- @mcp.tool()
13
+ @mcp.tool(annotations=TOOL_READONLY)
14
14
  @apply_config
15
15
  def list_booted_simulators() -> str:
16
16
  """
@@ -5,13 +5,13 @@ import os
5
5
  import tempfile
6
6
  import subprocess
7
7
 
8
- from xcode_mcp_server.server import mcp
8
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
9
9
  from xcode_mcp_server.config_manager import apply_config
10
10
  from xcode_mcp_server.exceptions import XCodeMCPError
11
11
  from xcode_mcp_server.utils.applescript import show_result_notification, show_error_notification
12
12
 
13
13
 
14
- @mcp.tool()
14
+ @mcp.tool(annotations=TOOL_READONLY)
15
15
  @apply_config
16
16
  def list_mac_app_windows() -> str:
17
17
  """
@@ -6,14 +6,14 @@ import re
6
6
  import subprocess
7
7
  import sys
8
8
 
9
- from xcode_mcp_server.server import mcp
9
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
10
10
  from xcode_mcp_server.config_manager import apply_config
11
11
  from xcode_mcp_server.exceptions import XCodeMCPError
12
12
  from xcode_mcp_server.security import validate_and_normalize_project_path
13
13
  from xcode_mcp_server.utils.applescript import show_result_notification, show_error_notification
14
14
 
15
15
 
16
- @mcp.tool()
16
+ @mcp.tool(annotations=TOOL_READONLY)
17
17
  @apply_config
18
18
  def list_project_tests(project_path: str) -> str:
19
19
  """
@@ -8,7 +8,7 @@ import subprocess
8
8
  import sys
9
9
  from typing import Optional
10
10
 
11
- from xcode_mcp_server.server import mcp
11
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
12
12
  from xcode_mcp_server.config_manager import apply_config
13
13
  from xcode_mcp_server.security import validate_and_normalize_project_path
14
14
  from xcode_mcp_server.exceptions import XCodeMCPError
@@ -73,7 +73,7 @@ def _parse_destination_line(line: str) -> Optional[dict]:
73
73
  return result
74
74
 
75
75
 
76
- @mcp.tool()
76
+ @mcp.tool(annotations=TOOL_READONLY)
77
77
  @apply_config
78
78
  def list_run_destinations(
79
79
  project_path: str,
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env python3
2
2
  """list_running_mac_apps tool - List running macOS applications"""
3
3
 
4
- from xcode_mcp_server.server import mcp
4
+ from xcode_mcp_server.server import mcp, TOOL_READONLY
5
5
  from xcode_mcp_server.config_manager import apply_config
6
6
  from xcode_mcp_server.exceptions import XCodeMCPError
7
7
  from xcode_mcp_server.utils.applescript import show_notification, run_applescript, show_result_notification, show_error_notification
8
8
 
9
9
 
10
- @mcp.tool()
10
+ @mcp.tool(annotations=TOOL_READONLY)
11
11
  @apply_config
12
12
  def list_running_mac_apps() -> str:
13
13
  """
@@ -7,14 +7,15 @@ import time
7
7
  import json
8
8
  from typing import Optional, List
9
9
 
10
- from xcode_mcp_server.server import mcp
10
+ from xcode_mcp_server.server import mcp, TOOL_BUILD
11
11
  from xcode_mcp_server.config_manager import apply_config
12
12
  from xcode_mcp_server.security import validate_and_normalize_project_path
13
13
  from xcode_mcp_server.exceptions import InvalidParameterError
14
14
  from xcode_mcp_server.utils.applescript import (
15
- BUILD_TIMEOUT_SECONDS,
16
15
  build_open_and_wait_applescript,
17
16
  build_wait_for_completion_applescript,
17
+ resolve_build_timeout,
18
+ format_timeout_duration,
18
19
  escape_applescript_string,
19
20
  run_applescript,
20
21
  show_notification,
@@ -149,19 +150,23 @@ from xcode_mcp_server.utils.xcresult import find_xcresult_bundle, extract_test_r
149
150
  # return f"⏳ Tests did not complete within {max_wait_seconds} seconds"
150
151
 
151
152
 
152
- @mcp.tool()
153
+ @mcp.tool(annotations=TOOL_BUILD)
153
154
  @apply_config
154
155
  def run_project_tests(project_path: str,
155
- scheme: Optional[str] = None) -> str:
156
+ scheme: Optional[str] = None,
157
+ timeout: Optional[int] = None) -> str:
156
158
  """
157
159
  Run tests for the specified Xcode project or workspace.
158
160
 
159
- Tests will run for up to 10 minutes before timing out. This timeout is hardcoded
160
- to prevent issues with test runs hanging indefinitely.
161
+ Tests run for up to `timeout` seconds (default 600, i.e. 10 minutes) before
162
+ timing out, which guards against a test run hanging indefinitely. Raise it
163
+ for large projects whose build-for-testing alone exceeds the default.
161
164
 
162
165
  Args:
163
166
  project_path: Path to Xcode project/workspace directory
164
167
  scheme: Optional scheme to test (uses active scheme if not specified)
168
+ timeout: Maximum seconds to wait for the build-for-testing plus test run
169
+ to complete. If not provided, defaults to 600. Must be a positive integer.
165
170
 
166
171
  Returns:
167
172
  JSON with test results if tests complete, otherwise plain text status message.
@@ -176,6 +181,10 @@ def run_project_tests(project_path: str,
176
181
  # Validate and normalize the project path
177
182
  project_path = validate_and_normalize_project_path(project_path, "run_project_tests")
178
183
 
184
+ # Resolve the test timeout up front so an invalid value errors immediately,
185
+ # before any AppleScript runs or notifications post.
186
+ effective_timeout = resolve_build_timeout(timeout)
187
+
179
188
  # Show notification
180
189
  show_notification("Drew's Xcode MCP", subtitle=os.path.basename(project_path), message="Running tests")
181
190
 
@@ -275,14 +284,14 @@ def run_project_tests(project_path: str,
275
284
  script = (
276
285
  build_open_and_wait_applescript(escaped_path, escaped_scheme)
277
286
  + ' set testResult to test workspaceDoc\n'
278
- + build_wait_for_completion_applescript("testResult", BUILD_TIMEOUT_SECONDS)
287
+ + build_wait_for_completion_applescript("testResult", effective_timeout)
279
288
  + failure_extraction_tail
280
289
  + 'end tell\n'
281
290
  )
282
291
 
283
- # The script polls inside AppleScript for up to BUILD_TIMEOUT_SECONDS; the
292
+ # The script polls inside AppleScript for up to effective_timeout; the
284
293
  # subprocess timeout must exceed that, plus buffer for workspace load.
285
- success, output = run_applescript(script, timeout=BUILD_TIMEOUT_SECONDS + 60)
294
+ success, output = run_applescript(script, timeout=effective_timeout + 60)
286
295
 
287
296
  if not success:
288
297
  show_error_notification("Failed to run tests", os.path.basename(project_path))
@@ -307,10 +316,10 @@ def run_project_tests(project_path: str,
307
316
  output_lines = []
308
317
 
309
318
  if not completed:
310
- minutes = BUILD_TIMEOUT_SECONDS // 60
311
- output_lines.append(f"⏳ Tests did not complete within {minutes} minutes")
319
+ duration = format_timeout_duration(effective_timeout)
320
+ output_lines.append(f"⏳ Tests did not complete within {duration}")
312
321
  output_lines.append(f"Status: {status}")
313
- show_warning_notification(f"Tests timeout ({minutes} min)")
322
+ show_warning_notification(f"Tests timeout ({duration})")
314
323
  return '\n'.join(output_lines)
315
324
 
316
325
  # If tests completed, get detailed results from xcresult
@@ -4,7 +4,7 @@
4
4
  import os
5
5
  from typing import Optional
6
6
 
7
- from xcode_mcp_server.server import mcp
7
+ from xcode_mcp_server.server import mcp, TOOL_BUILD
8
8
  from xcode_mcp_server.config_manager import apply_config
9
9
  from xcode_mcp_server.security import validate_and_normalize_project_path
10
10
  from xcode_mcp_server.exceptions import XCodeMCPError
@@ -17,7 +17,7 @@ from xcode_mcp_server.utils.applescript import (
17
17
  )
18
18
 
19
19
 
20
- @mcp.tool()
20
+ @mcp.tool(annotations=TOOL_BUILD)
21
21
  @apply_config
22
22
  def run_project_unmonitored(project_path: str,
23
23
  scheme: Optional[str] = None) -> str: