xcode-mcp-server 1.3.10__tar.gz → 1.3.11b2__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 (142) hide show
  1. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/PKG-INFO +1 -1
  2. xcode_mcp_server-1.3.11b2/__PUBLIC_REPO +0 -0
  3. xcode_mcp_server-1.3.11b2/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  4. {xcode_mcp_server-1.3.10/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj → xcode_mcp_server-1.3.11b2/test_projects/templates/BrokenApp/BrokenApp.xcodeproj}/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +1 -1
  5. xcode_mcp_server-1.3.11b2/tests/test_build_log_parser.py +140 -0
  6. xcode_mcp_server-1.3.11b2/tests/test_manifest_wait.py +229 -0
  7. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/__init__.py +1 -1
  8. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/cli.py +7 -3
  9. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/config_manager.py +50 -36
  10. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/security.py +76 -26
  11. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/build_project.py +115 -109
  12. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/clean_project.py +16 -28
  13. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/debug_list_notification_history.py +26 -10
  14. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_active_run_destination.py +91 -40
  15. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_build_errors.py +1 -1
  16. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_directory_listing.py +3 -19
  17. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_directory_tree.py +36 -23
  18. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_latest_test_results.py +3 -2
  19. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_project_schemes.py +11 -24
  20. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_xcode_projects.py +44 -11
  21. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/list_mac_app_windows.py +14 -15
  22. xcode_mcp_server-1.3.11b2/xcode_mcp_server/tools/list_project_tests.py +91 -0
  23. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/list_run_destinations.py +19 -13
  24. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/list_running_mac_apps.py +8 -8
  25. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/run_project_tests.py +101 -128
  26. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/run_project_unmonitored.py +9 -59
  27. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/run_project_until_terminated.py +15 -64
  28. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/run_project_with_user_interaction.py +100 -101
  29. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/set_run_destination.py +3 -16
  30. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/take_app_screenshot.py +2 -11
  31. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/take_simulator_screenshot.py +4 -15
  32. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/take_window_screenshot.py +2 -11
  33. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/take_xcode_screenshot.py +3 -12
  34. xcode_mcp_server-1.3.11b2/xcode_mcp_server/utils/applescript.py +322 -0
  35. xcode_mcp_server-1.3.11b2/xcode_mcp_server/utils/build_log_parser.py +589 -0
  36. xcode_mcp_server-1.3.11b2/xcode_mcp_server/utils/paths.py +14 -0
  37. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/utils/screenshot.py +45 -14
  38. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/utils/xcresult.py +150 -98
  39. xcode_mcp_server-1.3.10/fools-errand.md +0 -80
  40. xcode_mcp_server-1.3.10/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  41. xcode_mcp_server-1.3.10/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  42. xcode_mcp_server-1.3.10/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  43. xcode_mcp_server-1.3.10/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  44. xcode_mcp_server-1.3.10/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  45. xcode_mcp_server-1.3.10/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  46. xcode_mcp_server-1.3.10/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  47. xcode_mcp_server-1.3.10/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  48. xcode_mcp_server-1.3.10/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  49. xcode_mcp_server-1.3.10/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  50. xcode_mcp_server-1.3.10/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  51. xcode_mcp_server-1.3.10/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  52. xcode_mcp_server-1.3.10/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  53. xcode_mcp_server-1.3.10/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  54. xcode_mcp_server-1.3.10/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -19
  55. xcode_mcp_server-1.3.10/xcode_mcp_server/tools/list_project_tests.py +0 -84
  56. xcode_mcp_server-1.3.10/xcode_mcp_server/utils/applescript.py +0 -179
  57. xcode_mcp_server-1.3.10/xcode_mcp_server/utils/build_log_parser.py +0 -324
  58. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/.github/workflows/claude-code.yml +0 -0
  59. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/.github/workflows/claude-self-review.yml +0 -0
  60. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/.gitignore +0 -0
  61. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/CLAUDE.md +0 -0
  62. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/LICENSE +0 -0
  63. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/README.md +0 -0
  64. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/TODO.md +0 -0
  65. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/_venv-setup.sh +0 -0
  66. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/deploy-beta.sh +0 -0
  67. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/deploy.sh +0 -0
  68. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/dev.sh +0 -0
  69. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/info.sh +0 -0
  70. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/pyproject.toml +0 -0
  71. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/requirements.txt +0 -0
  72. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/run_local_for_claude.sh +0 -0
  73. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/cleanup_tests.sh +0 -0
  74. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/create_projects.py +0 -0
  75. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/create_real_projects.py +0 -0
  76. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/create_spm_projects.sh +0 -0
  77. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/create_xcode_projects.sh +0 -0
  78. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/run_all_tests.sh +0 -0
  79. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/setup_test_projects.sh +0 -0
  80. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/scripts/setup_tests.sh +0 -0
  81. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  82. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  83. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/Contents.json +0 -0
  84. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/ContentView.swift +0 -0
  85. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/iosEmptySwiftUIAppApp.swift +0 -0
  86. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.pbxproj +0 -0
  87. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  88. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp/main.swift +0 -0
  89. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.pbxproj +0 -0
  90. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  91. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  92. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  93. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/Contents.json +0 -0
  94. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/ContentView.swift +0 -0
  95. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/macosEmptySwiftUIAppApp.swift +0 -0
  96. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.pbxproj +0 -0
  97. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  98. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/BrokenApp/BrokenApp/main.swift +0 -0
  99. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.pbxproj +0 -0
  100. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  101. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/ConsoleApp/ConsoleApp/main.swift +0 -0
  102. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.pbxproj +0 -0
  103. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  104. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SimpleApp/SimpleApp/main.swift +0 -0
  105. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.pbxproj +0 -0
  106. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  107. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  108. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  109. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/Contents.json +0 -0
  110. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/ContentView.swift +0 -0
  111. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp/macosEmptySwiftUIAppApp.swift +0 -0
  112. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.pbxproj +0 -0
  113. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  114. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -0
  115. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  116. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/Contents.json +0 -0
  117. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp/ContentView.swift +0 -0
  118. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp/iosEmptySwiftUIAppApp.swift +0 -0
  119. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.pbxproj +0 -0
  120. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -0
  121. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/debug_build.py +0 -0
  122. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/debug_test.py +0 -0
  123. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/test_basic.py +0 -0
  124. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/test_build.py +0 -0
  125. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/test_fixed.py +0 -0
  126. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/test_minimal.py +0 -0
  127. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/tests/test_runner.py +0 -0
  128. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/__main__.py +0 -0
  129. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/config_ui.py +0 -0
  130. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/exceptions.py +0 -0
  131. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/server.py +0 -0
  132. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/__init__.py +0 -0
  133. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/create_project.py +0 -0
  134. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_build_results.py +0 -0
  135. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/get_runtime_output.py +0 -0
  136. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/list_booted_simulators.py +0 -0
  137. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/stop_project.py +0 -0
  138. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/tools/version.py +0 -0
  139. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/utils/__init__.py +0 -0
  140. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/utils/decode_active_destination.swift +0 -0
  141. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/utils/decode_xcode_recents.swift +0 -0
  142. {xcode_mcp_server-1.3.10 → xcode_mcp_server-1.3.11b2}/xcode_mcp_server/utils/project_templates.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xcode-mcp-server
3
- Version: 1.3.10
3
+ Version: 1.3.11b2
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
File without changes
@@ -4,7 +4,7 @@
4
4
  <dict>
5
5
  <key>SchemeUserState</key>
6
6
  <dict>
7
- <key>iosEmptySwiftUIApp.xcscheme_^#shared#^_</key>
7
+ <key>BrokenApp.xcscheme_^#shared#^_</key>
8
8
  <dict>
9
9
  <key>orderHint</key>
10
10
  <integer>0</integer>
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Regression tests for xcactivitylog parsing.
4
+
5
+ Two coverage gaps caused persistent stale warnings in build_project output:
6
+
7
+ 1. The path regex required [a-zA-Z0-9_/.-] only, silently dropping any project
8
+ path containing a space (very common: "/Users/x/My Project/..."). Files
9
+ missing from compiled_files can never be cleared from the stale-warning set,
10
+ so old warnings linger across incremental builds until the user does a clean.
11
+
12
+ 2. Only SwiftCompile lines and .swift warnings/errors were matched. Mixed-language
13
+ projects (ObjC/C/C++/Metal) were invisible to the parser, so their warnings
14
+ never appeared in aggregation and recompiles never cleared anything.
15
+ """
16
+
17
+ import gzip
18
+ import os
19
+ import sys
20
+ import tempfile
21
+ import unittest
22
+ from pathlib import Path
23
+
24
+ sys.path.insert(0, str(Path(__file__).parent.parent))
25
+
26
+ from xcode_mcp_server.utils.build_log_parser import parse_xcactivitylog
27
+
28
+
29
+ def _write_gzipped_log(path: str, text: str) -> None:
30
+ """xcactivitylog files are gzipped — write a fake one."""
31
+ with gzip.open(path, 'wb') as f:
32
+ f.write(text.encode('utf-8'))
33
+
34
+
35
+ class PathsWithSpacesTests(unittest.TestCase):
36
+ def test_swift_file_with_space_in_path_is_tracked_as_compiled(self):
37
+ """A path with a space must be recognized in SwiftCompile lines."""
38
+ log_text = (
39
+ "Some preamble\r"
40
+ "SwiftCompile normal arm64 /Users/test/My Project/Sources/Foo.swift "
41
+ "(in target 'App' from project 'App')\r"
42
+ "more output\r"
43
+ )
44
+ with tempfile.NamedTemporaryFile(suffix='.xcactivitylog', delete=False) as tmp:
45
+ tmp_path = tmp.name
46
+ try:
47
+ _write_gzipped_log(tmp_path, log_text)
48
+ warnings, compiled = parse_xcactivitylog(tmp_path)
49
+ self.assertIn('/Users/test/My Project/Sources/Foo.swift', compiled,
50
+ f"compiled files were: {compiled}")
51
+ finally:
52
+ os.unlink(tmp_path)
53
+
54
+ def test_warning_on_path_with_space_is_extracted(self):
55
+ log_text = (
56
+ "/Users/test/My Project/Sources/Foo.swift:42:5: warning: "
57
+ "variable 'x' was never used\r"
58
+ )
59
+ with tempfile.NamedTemporaryFile(suffix='.xcactivitylog', delete=False) as tmp:
60
+ tmp_path = tmp.name
61
+ try:
62
+ _write_gzipped_log(tmp_path, log_text)
63
+ warnings, _ = parse_xcactivitylog(tmp_path)
64
+ files = [w['file'] for w in warnings]
65
+ self.assertIn('/Users/test/My Project/Sources/Foo.swift', files,
66
+ f"warnings were: {warnings}")
67
+ finally:
68
+ os.unlink(tmp_path)
69
+
70
+
71
+ class MixedLanguageTests(unittest.TestCase):
72
+ def test_objc_compilec_line_tracks_source_file(self):
73
+ """CompileC <obj> <source> — we want the source path tracked."""
74
+ log_text = (
75
+ "CompileC /tmp/Build/Foo.o /Users/test/MyProj/Foo.m "
76
+ "normal arm64 objective-c\r"
77
+ )
78
+ with tempfile.NamedTemporaryFile(suffix='.xcactivitylog', delete=False) as tmp:
79
+ tmp_path = tmp.name
80
+ try:
81
+ _write_gzipped_log(tmp_path, log_text)
82
+ _, compiled = parse_xcactivitylog(tmp_path)
83
+ self.assertIn('/Users/test/MyProj/Foo.m', compiled,
84
+ f"compiled files were: {compiled}")
85
+ finally:
86
+ os.unlink(tmp_path)
87
+
88
+ def test_objc_warning_is_extracted(self):
89
+ log_text = (
90
+ "/Users/test/MyProj/Foo.m:10:3: warning: "
91
+ "'someAPI' is deprecated\r"
92
+ )
93
+ with tempfile.NamedTemporaryFile(suffix='.xcactivitylog', delete=False) as tmp:
94
+ tmp_path = tmp.name
95
+ try:
96
+ _write_gzipped_log(tmp_path, log_text)
97
+ warnings, _ = parse_xcactivitylog(tmp_path)
98
+ self.assertTrue(
99
+ any(w['file'] == '/Users/test/MyProj/Foo.m' for w in warnings),
100
+ f"warnings were: {warnings}"
101
+ )
102
+ finally:
103
+ os.unlink(tmp_path)
104
+
105
+
106
+ class ExistingBehaviorPreservedTests(unittest.TestCase):
107
+ def test_plain_swift_path_still_works(self):
108
+ log_text = (
109
+ "SwiftCompile normal arm64 /Users/test/Proj/Sources/Foo.swift "
110
+ "(in target 'App' from project 'App')\r"
111
+ "/Users/test/Proj/Sources/Foo.swift:99:1: warning: shadows\r"
112
+ )
113
+ with tempfile.NamedTemporaryFile(suffix='.xcactivitylog', delete=False) as tmp:
114
+ tmp_path = tmp.name
115
+ try:
116
+ _write_gzipped_log(tmp_path, log_text)
117
+ warnings, compiled = parse_xcactivitylog(tmp_path)
118
+ self.assertIn('/Users/test/Proj/Sources/Foo.swift', compiled)
119
+ self.assertEqual(len(warnings), 1)
120
+ self.assertEqual(warnings[0]['line'], 99)
121
+ self.assertEqual(warnings[0]['column'], 1)
122
+ self.assertEqual(warnings[0]['type'], 'warning')
123
+ finally:
124
+ os.unlink(tmp_path)
125
+
126
+ def test_error_extracted_with_type_error(self):
127
+ log_text = "/Users/test/Proj/Sources/Foo.swift:5:1: error: bad thing\r"
128
+ with tempfile.NamedTemporaryFile(suffix='.xcactivitylog', delete=False) as tmp:
129
+ tmp_path = tmp.name
130
+ try:
131
+ _write_gzipped_log(tmp_path, log_text)
132
+ warnings, _ = parse_xcactivitylog(tmp_path)
133
+ self.assertEqual(len(warnings), 1)
134
+ self.assertEqual(warnings[0]['type'], 'error')
135
+ finally:
136
+ os.unlink(tmp_path)
137
+
138
+
139
+ if __name__ == '__main__':
140
+ unittest.main(verbosity=2)
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Regression tests for the LogStoreManifest UUID-diff wait used to fix stale
4
+ build warnings.
5
+
6
+ Before this fix, build_project read the manifest immediately after AppleScript
7
+ returned, before Xcode had necessarily written the current build's xcactivitylog
8
+ entry. Aggregation then operated on stale data and surfaced warnings the user
9
+ had already fixed.
10
+
11
+ These tests exercise the deterministic alternative: snapshot the manifest's
12
+ build UUIDs before kicking off the build, then poll until a new build UUID
13
+ appears whose timeStartedRecording is at or after our start time.
14
+ """
15
+
16
+ import os
17
+ import sys
18
+ import time
19
+ import plistlib
20
+ import tempfile
21
+ import threading
22
+ import unittest
23
+ import uuid
24
+ from pathlib import Path
25
+
26
+ sys.path.insert(0, str(Path(__file__).parent.parent))
27
+
28
+ from xcode_mcp_server.utils.build_log_parser import (
29
+ CF_EPOCH_OFFSET,
30
+ snapshot_build_uuids,
31
+ wait_for_new_build_uuid,
32
+ )
33
+
34
+
35
+ def _make_entry(title: str, time_started_cf: float, file_uuid: str = None) -> dict:
36
+ """Build a single LogStoreManifest-style log entry."""
37
+ if file_uuid is None:
38
+ file_uuid = str(uuid.uuid4()).upper()
39
+ return {
40
+ 'className': 'IDEActivityLogSection',
41
+ 'documentTypeString': '<nil>',
42
+ 'domainType': 'Xcode.IDEActivityLogDomainType.BuildLog',
43
+ 'fileName': f'{file_uuid}.xcactivitylog',
44
+ 'hasPrimaryLog': True,
45
+ 'primaryObservable': {
46
+ 'highLevelStatus': 'S',
47
+ 'totalNumberOfAnalyzerIssues': 0,
48
+ 'totalNumberOfErrors': 0,
49
+ 'totalNumberOfTestFailures': 0,
50
+ 'totalNumberOfWarnings': 0,
51
+ },
52
+ 'schemeIdentifier-containerName': 'Test project',
53
+ 'schemeIdentifier-schemeName': 'TestScheme',
54
+ 'schemeIdentifier-sharedScheme': 1,
55
+ 'signature': title,
56
+ 'timeStartedRecording': time_started_cf,
57
+ 'timeStoppedRecording': time_started_cf + 1.0,
58
+ 'title': title,
59
+ 'uniqueIdentifier': file_uuid,
60
+ }
61
+
62
+
63
+ def _write_manifest(path: str, entries: list) -> None:
64
+ plist = {
65
+ 'logFormatVersion': 11,
66
+ 'logs': {e['uniqueIdentifier']: e for e in entries},
67
+ }
68
+ with open(path, 'wb') as f:
69
+ plistlib.dump(plist, f)
70
+
71
+
72
+ def _now_cf() -> float:
73
+ """Current time as CFAbsoluteTime (seconds since 2001-01-01 UTC)."""
74
+ return time.time() - CF_EPOCH_OFFSET
75
+
76
+
77
+ class SnapshotTests(unittest.TestCase):
78
+ def test_snapshot_returns_all_uuids_regardless_of_title(self):
79
+ """The snapshot is just the existing UUIDs — title filtering happens later."""
80
+ with tempfile.TemporaryDirectory() as tmp:
81
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
82
+ build_uuid = str(uuid.uuid4()).upper()
83
+ clean_uuid = str(uuid.uuid4()).upper()
84
+ _write_manifest(manifest, [
85
+ _make_entry('Build TestScheme', _now_cf() - 60, build_uuid),
86
+ _make_entry('Clean TestScheme', _now_cf() - 30, clean_uuid),
87
+ ])
88
+
89
+ snap = snapshot_build_uuids(manifest)
90
+
91
+ self.assertIn(build_uuid, snap)
92
+ self.assertIn(clean_uuid, snap)
93
+
94
+ def test_snapshot_missing_manifest_returns_empty_set(self):
95
+ """First-ever build has no manifest yet — must not crash."""
96
+ with tempfile.TemporaryDirectory() as tmp:
97
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
98
+ snap = snapshot_build_uuids(manifest)
99
+ self.assertEqual(snap, set())
100
+
101
+
102
+ class WaitForNewBuildUUIDTests(unittest.TestCase):
103
+ def test_returns_immediately_when_new_build_already_present(self):
104
+ with tempfile.TemporaryDirectory() as tmp:
105
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
106
+ existing_uuid = str(uuid.uuid4()).upper()
107
+ _write_manifest(manifest, [
108
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
109
+ ])
110
+ before = snapshot_build_uuids(manifest)
111
+
112
+ start_unix = time.time()
113
+ new_uuid = str(uuid.uuid4()).upper()
114
+ _write_manifest(manifest, [
115
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
116
+ _make_entry('Build TestScheme', _now_cf() + 0.1, new_uuid),
117
+ ])
118
+
119
+ found = wait_for_new_build_uuid(manifest, before, start_unix, timeout_seconds=2.0)
120
+ self.assertEqual(found, new_uuid)
121
+
122
+ def test_returns_new_uuid_added_mid_poll(self):
123
+ with tempfile.TemporaryDirectory() as tmp:
124
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
125
+ existing_uuid = str(uuid.uuid4()).upper()
126
+ _write_manifest(manifest, [
127
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
128
+ ])
129
+ before = snapshot_build_uuids(manifest)
130
+ start_unix = time.time()
131
+ new_uuid = str(uuid.uuid4()).upper()
132
+
133
+ def append_after_delay():
134
+ time.sleep(0.6)
135
+ _write_manifest(manifest, [
136
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
137
+ _make_entry('Build TestScheme', _now_cf(), new_uuid),
138
+ ])
139
+
140
+ t = threading.Thread(target=append_after_delay, daemon=True)
141
+ t.start()
142
+
143
+ found = wait_for_new_build_uuid(manifest, before, start_unix, timeout_seconds=5.0)
144
+ t.join(timeout=2.0)
145
+ self.assertEqual(found, new_uuid)
146
+
147
+ def test_timeout_returns_none(self):
148
+ with tempfile.TemporaryDirectory() as tmp:
149
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
150
+ existing_uuid = str(uuid.uuid4()).upper()
151
+ _write_manifest(manifest, [
152
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
153
+ ])
154
+ before = snapshot_build_uuids(manifest)
155
+ start_unix = time.time()
156
+
157
+ found = wait_for_new_build_uuid(manifest, before, start_unix, timeout_seconds=1.0)
158
+ self.assertIsNone(found)
159
+
160
+ def test_clean_entries_are_ignored(self):
161
+ """A Clean operation creates a manifest entry too; it must not be mistaken for our build."""
162
+ with tempfile.TemporaryDirectory() as tmp:
163
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
164
+ existing_uuid = str(uuid.uuid4()).upper()
165
+ _write_manifest(manifest, [
166
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
167
+ ])
168
+ before = snapshot_build_uuids(manifest)
169
+ start_unix = time.time()
170
+ clean_uuid = str(uuid.uuid4()).upper()
171
+ _write_manifest(manifest, [
172
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
173
+ _make_entry('Clean TestScheme', _now_cf(), clean_uuid),
174
+ ])
175
+
176
+ found = wait_for_new_build_uuid(manifest, before, start_unix, timeout_seconds=1.0)
177
+ self.assertIsNone(found, "Clean entry must not be returned as 'our' build")
178
+
179
+ def test_pre_existing_build_with_old_timestamp_is_rejected(self):
180
+ """
181
+ If a user-triggered build finished before our snapshot (but somehow wasn't
182
+ in the snapshot — e.g. they hit Cmd-B between our snapshot and our wait),
183
+ its older timestamp must exclude it from being treated as ours.
184
+ """
185
+ with tempfile.TemporaryDirectory() as tmp:
186
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
187
+ old_present_uuid = str(uuid.uuid4()).upper()
188
+ _write_manifest(manifest, [
189
+ _make_entry('Build TestScheme', _now_cf() - 60, old_present_uuid),
190
+ ])
191
+ before = snapshot_build_uuids(manifest)
192
+
193
+ start_unix = time.time()
194
+ # A build entry that started well before our start time, but isn't
195
+ # in `before` — this represents an entry we missed.
196
+ stray_uuid = str(uuid.uuid4()).upper()
197
+ _write_manifest(manifest, [
198
+ _make_entry('Build TestScheme', _now_cf() - 60, old_present_uuid),
199
+ _make_entry('Build TestScheme', _now_cf() - 30, stray_uuid),
200
+ ])
201
+
202
+ found = wait_for_new_build_uuid(manifest, before, start_unix, timeout_seconds=1.0)
203
+ self.assertIsNone(found)
204
+
205
+ def test_accepts_only_build_with_timestamp_at_or_after_start(self):
206
+ """Stale stray entry (older) ignored; our entry (newer) accepted."""
207
+ with tempfile.TemporaryDirectory() as tmp:
208
+ manifest = os.path.join(tmp, 'LogStoreManifest.plist')
209
+ existing_uuid = str(uuid.uuid4()).upper()
210
+ _write_manifest(manifest, [
211
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
212
+ ])
213
+ before = snapshot_build_uuids(manifest)
214
+ start_unix = time.time()
215
+
216
+ stray_uuid = str(uuid.uuid4()).upper()
217
+ our_uuid = str(uuid.uuid4()).upper()
218
+ _write_manifest(manifest, [
219
+ _make_entry('Build TestScheme', _now_cf() - 60, existing_uuid),
220
+ _make_entry('Build TestScheme', _now_cf() - 30, stray_uuid),
221
+ _make_entry('Build TestScheme', _now_cf() + 0.1, our_uuid),
222
+ ])
223
+
224
+ found = wait_for_new_build_uuid(manifest, before, start_unix, timeout_seconds=2.0)
225
+ self.assertEqual(found, our_uuid)
226
+
227
+
228
+ if __name__ == '__main__':
229
+ unittest.main(verbosity=2)
@@ -1,6 +1,6 @@
1
1
  """Xcode MCP Server - Model Context Protocol server for Xcode integration"""
2
2
 
3
- __version__ = "1.3.10"
3
+ __version__ = "1.3.11b2"
4
4
 
5
5
 
6
6
  def main():
@@ -10,7 +10,7 @@ from xcode_mcp_server import __version__
10
10
  from xcode_mcp_server.server import mcp
11
11
  from xcode_mcp_server.security import get_allowed_folders, set_allowed_folders
12
12
  from xcode_mcp_server.utils.applescript import set_notifications_enabled
13
- from xcode_mcp_server.utils.xcresult import set_build_warnings_enabled
13
+ from xcode_mcp_server.utils.xcresult import set_build_warnings_enabled, freeze_build_warnings_settings
14
14
 
15
15
 
16
16
  def initialize_server():
@@ -95,8 +95,8 @@ All specified folders must:
95
95
  subprocess.run(['osascript', '-e',
96
96
  'display alert "Drew\'s Xcode MCP Server Error" message "No valid allowed folders found. Check your configuration."'],
97
97
  capture_output=True)
98
- except:
99
- pass # Ignore notification errors
98
+ except Exception:
99
+ pass
100
100
 
101
101
  sys.exit(1)
102
102
 
@@ -127,5 +127,9 @@ All specified folders must:
127
127
  subtitle="✅ Server started"
128
128
  )
129
129
 
130
+ # Lock startup-only globals so any later mutation surfaces as a
131
+ # RuntimeError instead of silently racing concurrent tool readers.
132
+ freeze_build_warnings_settings()
133
+
130
134
  # Run the server
131
135
  mcp.run()
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env python3
2
2
  import os
3
- import sys
4
3
  import json
5
4
  import hashlib
6
5
  import inspect
6
+ import tempfile
7
+ import threading
7
8
  from pathlib import Path
8
9
  from dataclasses import dataclass
9
10
  from typing import Optional, Any, Dict, List, Set
@@ -36,20 +37,32 @@ class ConfigManager:
36
37
  """
37
38
 
38
39
  _instance = None
40
+ _instance_lock = threading.Lock()
39
41
  _config_dir = Path.home() / ".xcode-mcp-server"
40
42
 
41
43
  def __new__(cls):
44
+ # Double-checked locking: cheap fast path once the singleton exists,
45
+ # serialized construction-and-init otherwise. FastMCP dispatches sync
46
+ # tools onto a threadpool, so two threads can race on first
47
+ # construction. All one-time setup — including `_tool_registry` — is
48
+ # done here under the lock so a second concurrent constructor call
49
+ # can't run __init__ a second time and clobber the first thread's
50
+ # registrations.
42
51
  if cls._instance is None:
43
- cls._instance = super().__new__(cls)
44
- cls._instance._initialized = False
52
+ with cls._instance_lock:
53
+ if cls._instance is None:
54
+ instance = super().__new__(cls)
55
+ instance._tool_registry = {}
56
+ instance._ensure_config_dir_exists()
57
+ instance._initialized = True
58
+ cls._instance = instance
45
59
  return cls._instance
46
60
 
47
61
  def __init__(self):
48
- if self._initialized:
49
- return
50
- self._ensure_config_dir_exists()
51
- self._tool_registry = {} # Will be populated by decorator
52
- self._initialized = True
62
+ # All one-time setup happens in __new__ under the singleton lock; a
63
+ # no-op __init__ keeps construction atomic against repeated
64
+ # `ConfigManager()` calls from concurrent threadpool tools.
65
+ return
53
66
 
54
67
  # === INTERNAL ===
55
68
 
@@ -79,10 +92,35 @@ class ConfigManager:
79
92
  return None
80
93
 
81
94
  def _save_config_file(self, file_path: Path, data: dict):
82
- """Write config JSON file"""
95
+ """Write config JSON file atomically.
96
+
97
+ Writes to a sibling temp file then `os.replace`s into place so a crash
98
+ or concurrent write can't leave the destination truncated or partially
99
+ written. `os.replace` is atomic on POSIX when source and destination
100
+ are on the same filesystem, which is guaranteed here because the temp
101
+ file is created in `file_path.parent`.
102
+ """
83
103
  self._ensure_config_dir_exists()
84
- with open(file_path, 'w') as f:
85
- json.dump(data, f, indent=2)
104
+ file_path = Path(file_path)
105
+ tmp = tempfile.NamedTemporaryFile(
106
+ mode='w',
107
+ dir=file_path.parent,
108
+ prefix=file_path.name + '.',
109
+ suffix='.tmp',
110
+ delete=False,
111
+ )
112
+ try:
113
+ json.dump(data, tmp, indent=2)
114
+ tmp.flush()
115
+ os.fsync(tmp.fileno())
116
+ tmp.close()
117
+ os.replace(tmp.name, file_path)
118
+ except Exception:
119
+ try:
120
+ os.unlink(tmp.name)
121
+ except OSError:
122
+ pass
123
+ raise
86
124
 
87
125
  def _create_empty_config(self, level_type: str, name: str, path: str) -> dict:
88
126
  """Create an empty config structure"""
@@ -419,39 +457,15 @@ def apply_config(func):
419
457
  from xcode_mcp_server.exceptions import XCodeMCPError
420
458
  raise XCodeMCPError(f"{func.__name__} is disabled in configuration")
421
459
 
422
- # Apply parameter overrides (track which ones for debugging)
423
- overridden_params = []
460
+ # Apply parameter overrides
424
461
  for param_name in sig.parameters:
425
462
  override = config.get_parameter_override(func.__name__, param_name, project_path)
426
463
  if override is not None:
427
- overridden_params.append(f"{param_name}={override}")
428
464
  bound.arguments[param_name] = override
429
465
 
430
466
  # Check if notification should be shown
431
467
  should_notify = config.should_show_notification(func.__name__, project_path)
432
468
 
433
- # DEBUG: Show configuration info in alert
434
- import subprocess
435
- debug_lines = [
436
- "[apply_config DEBUG]",
437
- f"Function: {func.__name__}",
438
- f"Project: {project_path or 'None'}",
439
- f"Show notification: {should_notify}",
440
- f"Overridden params: {', '.join(overridden_params) if overridden_params else 'None'}"
441
- ]
442
- debug_msg = "\\n".join(debug_lines)
443
-
444
- # Print to stderr
445
- print(debug_msg.replace("\\n", "\n"), file=sys.stderr)
446
-
447
- # Show in AppleScript alert (temporary debugging)
448
- # try:
449
- # alert_script = f'display alert "apply_config Debug" message "{debug_msg}"'
450
- # # No timeout - let the user dismiss it when ready
451
- # subprocess.run(['osascript', '-e', alert_script], capture_output=True)
452
- # except:
453
- # pass # Ignore alert errors
454
-
455
469
  # Set tool context for this execution
456
470
  context = {
457
471
  'tool_name': func.__name__,