rf-mcp 0.34.0.dev1__tar.gz → 0.34.0.dev2__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 (263) hide show
  1. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/PKG-INFO +1 -1
  2. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/pyproject.toml +1 -1
  3. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/platynui_focus.py +2 -2
  4. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/suite_execution_service.py +69 -9
  5. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/library_checker.py +4 -1
  6. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.gitignore +0 -0
  7. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/@msgpackr-extract/msgpackr-extract-linux-x64/README.md +0 -0
  8. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/@standard-schema/spec/LICENSE +0 -0
  9. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/@standard-schema/spec/README.md +0 -0
  10. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/cross-spawn/LICENSE +0 -0
  11. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/cross-spawn/README.md +0 -0
  12. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/detect-libc/LICENSE +0 -0
  13. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/detect-libc/README.md +0 -0
  14. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/effect/LICENSE +0 -0
  15. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/effect/README.md +0 -0
  16. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/fast-check/LICENSE +0 -0
  17. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/fast-check/README.md +0 -0
  18. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/find-my-way-ts/LICENSE +0 -0
  19. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/find-my-way-ts/README.md +0 -0
  20. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/ini/LICENSE +0 -0
  21. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/ini/README.md +0 -0
  22. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/isexe/LICENSE +0 -0
  23. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/isexe/README.md +0 -0
  24. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/kubernetes-types/README.md +0 -0
  25. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/msgpackr/LICENSE +0 -0
  26. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/msgpackr/README.md +0 -0
  27. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/msgpackr-extract/LICENSE +0 -0
  28. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/msgpackr-extract/README.md +0 -0
  29. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/multipasta/LICENSE +0 -0
  30. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/multipasta/README.md +0 -0
  31. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/node-gyp-build-optional-packages/LICENSE +0 -0
  32. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/node-gyp-build-optional-packages/README.md +0 -0
  33. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/pure-rand/LICENSE +0 -0
  34. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/pure-rand/README.md +0 -0
  35. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/toml/LICENSE +0 -0
  36. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/toml/README.md +0 -0
  37. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/uuid/README.md +0 -0
  38. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/which/LICENSE +0 -0
  39. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/which/README.md +0 -0
  40. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/yaml/LICENSE +0 -0
  41. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/yaml/README.md +0 -0
  42. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/zod/LICENSE +0 -0
  43. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/.kilo/node_modules/zod/README.md +0 -0
  44. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/LICENSE +0 -0
  45. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/README.md +0 -0
  46. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/__init__.py +0 -0
  47. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/__init__.py +0 -0
  48. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/adapter_factory.py +0 -0
  49. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/browser_adapter.py +0 -0
  50. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/page_state_adapter.py +0 -0
  51. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/playwright_adapter.py +0 -0
  52. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/recovery_adapter.py +0 -0
  53. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/adapters/selenium_adapter.py +0 -0
  54. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/attach/__init__.py +0 -0
  55. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/attach/mcp_attach.py +0 -0
  56. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/compat/__init__.py +0 -0
  57. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/compat/fastmcp_compat.py +0 -0
  58. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/__init__.py +0 -0
  59. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/browser/__init__.py +0 -0
  60. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/browser/browser_library_manager.py +0 -0
  61. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/__init__.py +0 -0
  62. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/desktop_display_safety.py +0 -0
  63. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/desktop_execution_signals.py +0 -0
  64. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/desktop_guidance.py +0 -0
  65. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/desktop_launch_env.py +0 -0
  66. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/execution_coordinator.py +0 -0
  67. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/external_rf_client.py +0 -0
  68. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/keyword_executor.py +0 -0
  69. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/locator_arg_introspection.py +0 -0
  70. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/locator_converter.py +0 -0
  71. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/mobile_capability_service.py +0 -0
  72. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/page_source_service.py +0 -0
  73. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/rf_native_context_manager.py +0 -0
  74. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/session_manager.py +0 -0
  75. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/execution/ui_tree_service.py +0 -0
  76. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/keyword_matcher.py +0 -0
  77. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/library_recommender.py +0 -0
  78. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/nlp_processor.py +0 -0
  79. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/state_manager.py +0 -0
  80. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/test_builder.py +0 -0
  81. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/variables/__init__.py +0 -0
  82. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/components/variables/variable_resolver.py +0 -0
  83. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/config/__init__.py +0 -0
  84. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/config/library_registry.py +0 -0
  85. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/container.py +0 -0
  86. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/core/__init__.py +0 -0
  87. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/core/dynamic_keyword_orchestrator.py +0 -0
  88. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/core/event_bus.py +0 -0
  89. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/core/keyword_discovery.py +0 -0
  90. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/core/library_manager.py +0 -0
  91. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/core/session_manager.py +0 -0
  92. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/__init__.py +0 -0
  93. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/artifact_output/__init__.py +0 -0
  94. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/artifact_output/aggregates.py +0 -0
  95. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/artifact_output/entities.py +0 -0
  96. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/artifact_output/events.py +0 -0
  97. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/artifact_output/services.py +0 -0
  98. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/artifact_output/value_objects.py +0 -0
  99. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/batch_execution/__init__.py +0 -0
  100. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/batch_execution/aggregates.py +0 -0
  101. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/batch_execution/entities.py +0 -0
  102. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/batch_execution/events.py +0 -0
  103. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/batch_execution/services.py +0 -0
  104. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/batch_execution/value_objects.py +0 -0
  105. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/__init__.py +0 -0
  106. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/adapters/__init__.py +0 -0
  107. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/adapters/fastmcp_adapter.py +0 -0
  108. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/aggregates.py +0 -0
  109. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/entities.py +0 -0
  110. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/events.py +0 -0
  111. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/repository.py +0 -0
  112. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/security.py +0 -0
  113. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/services.py +0 -0
  114. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/instruction/value_objects.py +0 -0
  115. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/__init__.py +0 -0
  116. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/adapters/__init__.py +0 -0
  117. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/adapters/locator_normalizer_adapter.py +0 -0
  118. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/adapters/mcp_tool.py +0 -0
  119. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/adapters/session_lookup_adapter.py +0 -0
  120. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/aggregates.py +0 -0
  121. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/entities.py +0 -0
  122. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/events.py +0 -0
  123. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/services.py +0 -0
  124. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/intent/value_objects.py +0 -0
  125. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/keyword_resolution/__init__.py +0 -0
  126. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/keyword_resolution/aggregates.py +0 -0
  127. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/keyword_resolution/events.py +0 -0
  128. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/keyword_resolution/services.py +0 -0
  129. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/keyword_resolution/value_objects.py +0 -0
  130. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/__init__.py +0 -0
  131. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/adapters/__init__.py +0 -0
  132. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/adapters/fastmcp_adapter.py +0 -0
  133. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/adapters/sqlite_vec_adapter.py +0 -0
  134. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/aggregates.py +0 -0
  135. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/entities.py +0 -0
  136. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/events.py +0 -0
  137. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/repository.py +0 -0
  138. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/services.py +0 -0
  139. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/memory/value_objects.py +0 -0
  140. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/recovery/__init__.py +0 -0
  141. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/recovery/aggregates.py +0 -0
  142. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/recovery/entities.py +0 -0
  143. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/recovery/events.py +0 -0
  144. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/recovery/services.py +0 -0
  145. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/recovery/value_objects.py +0 -0
  146. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/response_optimization/__init__.py +0 -0
  147. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/response_optimization/aggregates.py +0 -0
  148. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/response_optimization/events.py +0 -0
  149. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/response_optimization/repository.py +0 -0
  150. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/response_optimization/services.py +0 -0
  151. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/response_optimization/value_objects.py +0 -0
  152. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/shared/__init__.py +0 -0
  153. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/shared/kernel.py +0 -0
  154. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/__init__.py +0 -0
  155. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/aggregates.py +0 -0
  156. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/delta_aggregates.py +0 -0
  157. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/delta_entities.py +0 -0
  158. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/delta_events.py +0 -0
  159. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/delta_service.py +0 -0
  160. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/delta_value_objects.py +0 -0
  161. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/diff_service.py +0 -0
  162. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/entities.py +0 -0
  163. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/events.py +0 -0
  164. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/list_folding.py +0 -0
  165. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/models.py +0 -0
  166. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/repository.py +0 -0
  167. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/services.py +0 -0
  168. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/snapshot/value_objects.py +0 -0
  169. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/__init__.py +0 -0
  170. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/aggregates.py +0 -0
  171. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/entities.py +0 -0
  172. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/events.py +0 -0
  173. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/keyword_classifier.py +0 -0
  174. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/services.py +0 -0
  175. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/timeout/value_objects.py +0 -0
  176. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/__init__.py +0 -0
  177. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/aggregates.py +0 -0
  178. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/entities.py +0 -0
  179. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/events.py +0 -0
  180. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/repository.py +0 -0
  181. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/services.py +0 -0
  182. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/token_accounting/value_objects.py +0 -0
  183. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/__init__.py +0 -0
  184. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/adapters/__init__.py +0 -0
  185. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/adapters/fastmcp_adapter.py +0 -0
  186. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/aggregates.py +0 -0
  187. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/entities.py +0 -0
  188. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/events.py +0 -0
  189. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/repository.py +0 -0
  190. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/services.py +0 -0
  191. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/domains/tool_profile/value_objects.py +0 -0
  192. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/entry.py +0 -0
  193. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/__init__.py +0 -0
  194. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/api.py +0 -0
  195. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/apps.py +0 -0
  196. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/asgi.py +0 -0
  197. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/bridge.py +0 -0
  198. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/config.py +0 -0
  199. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/controller.py +0 -0
  200. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/devserver.py +0 -0
  201. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/django_app.py +0 -0
  202. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/static/frontend/app.js +0 -0
  203. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/static/frontend/base.css +0 -0
  204. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/templates/frontend/index.html +0 -0
  205. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/templates/frontend/layout.html +0 -0
  206. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/urls.py +0 -0
  207. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/frontend/views.py +0 -0
  208. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/models/__init__.py +0 -0
  209. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/models/browser_models.py +0 -0
  210. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/models/config_models.py +0 -0
  211. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/models/execution_models.py +0 -0
  212. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/models/library_models.py +0 -0
  213. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/models/session_models.py +0 -0
  214. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/__init__.py +0 -0
  215. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/adapters.py +0 -0
  216. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/cli.py +0 -0
  217. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/codecs.py +0 -0
  218. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/diagnostics.py +0 -0
  219. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/installer.py +0 -0
  220. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/onboarding/manifest.py +0 -0
  221. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/__init__.py +0 -0
  222. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/collector.py +0 -0
  223. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/compression_learner.py +0 -0
  224. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/folding_learner.py +0 -0
  225. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/instruction_hooks.py +0 -0
  226. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/instruction_learner.py +0 -0
  227. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/page_analyzer.py +0 -0
  228. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/pattern_store.py +0 -0
  229. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/ref_learner.py +0 -0
  230. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/optimization/timeout_learner.py +0 -0
  231. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/__init__.py +0 -0
  232. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/base.py +0 -0
  233. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/builtin/__init__.py +0 -0
  234. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/builtin/browser_plugin.py +0 -0
  235. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/builtin/definitions.py +0 -0
  236. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/builtin/platynui_plugin.py +0 -0
  237. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/builtin/requests_plugin.py +0 -0
  238. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/builtin/selenium_plugin.py +0 -0
  239. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/contracts.py +0 -0
  240. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/discovery.py +0 -0
  241. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/plugins/manager.py +0 -0
  242. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/server.py +0 -0
  243. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/__init__.py +0 -0
  244. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/argument_processor.py +0 -0
  245. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/enhanced_response_serializer.py +0 -0
  246. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/enhanced_serialization_integration.py +0 -0
  247. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/hints.py +0 -0
  248. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/libdoc_argument_parser.py +0 -0
  249. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/library_detection.py +0 -0
  250. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/library_detector.py +0 -0
  251. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/library_loading_validator.py +0 -0
  252. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/logging_setup.py +0 -0
  253. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/requests_guidance.py +0 -0
  254. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/response_serializer.py +0 -0
  255. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/rf_libdoc_integration.py +0 -0
  256. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/rf_native_type_converter.py +0 -0
  257. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/rf_variables_compatibility.py +0 -0
  258. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/sampling.py +0 -0
  259. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/server_integration.py +0 -0
  260. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/session_resolution.py +0 -0
  261. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/token_efficient_output.py +0 -0
  262. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/validation.py +0 -0
  263. {rf_mcp-0.34.0.dev1 → rf_mcp-0.34.0.dev2}/src/robotmcp/utils/visual_guidance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rf-mcp
3
- Version: 0.34.0.dev1
3
+ Version: 0.34.0.dev2
4
4
  Summary: Robot Framework MCP Server - Natural Language Test Automation Bridge
5
5
  Project-URL: Homepage, https://github.com/manykarim/rf-mcp
6
6
  Project-URL: Repository, https://github.com/manykarim/rf-mcp
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "rf-mcp"
7
- version = "0.34.0.dev1"
7
+ version = "0.34.0.dev2"
8
8
  description = "Robot Framework MCP Server - Natural Language Test Automation Bridge"
9
9
  authors = [{ name = "Many Kasiriha" }]
10
10
  license = { text = "Apache-2.0" }
@@ -1052,7 +1052,7 @@ def x11_window_present(
1052
1052
  try:
1053
1053
  proc = subprocess.run(
1054
1054
  [sys.executable, "-c", _X11_WINDOW_PROBE_SRC, *names],
1055
- capture_output=True, text=True, timeout=5, env=env,
1055
+ capture_output=True, text=True, timeout=5, env=env, stdin=subprocess.DEVNULL,
1056
1056
  )
1057
1057
  out = (proc.stdout or "").strip()
1058
1058
  return out if out in ("present", "absent", "unknown") else "unknown"
@@ -1143,7 +1143,7 @@ def x11_display_pids() -> Optional[frozenset]:
1143
1143
  try:
1144
1144
  proc = subprocess.run(
1145
1145
  [sys.executable, "-c", _X11_PID_LIST_PROBE_SRC],
1146
- capture_output=True, text=True, timeout=5, env=dict(os.environ),
1146
+ capture_output=True, text=True, timeout=5, env=dict(os.environ), stdin=subprocess.DEVNULL,
1147
1147
  )
1148
1148
  out = (proc.stdout or "").strip()
1149
1149
  if not out or out == "unknown":
@@ -13,6 +13,7 @@ import json
13
13
  import io
14
14
  import subprocess
15
15
  import sys
16
+ import signal
16
17
  from contextlib import redirect_stdout, redirect_stderr
17
18
 
18
19
  try:
@@ -31,6 +32,37 @@ from robotmcp.models.config_models import ExecutionConfig
31
32
  logger = logging.getLogger(__name__)
32
33
 
33
34
 
35
+ def _kill_process_tree(proc: "subprocess.Popen") -> None:
36
+ """Best-effort terminate a child process AND all of its descendants.
37
+
38
+ change: fix-mcp-subprocess-stdin-deadlock. A plain ``proc.kill()`` reaps only the
39
+ direct child; a surviving grandchild (e.g. the uv-trampoline launcher's real
40
+ interpreter) keeps the captured stdout/stderr pipes open and hangs the post-kill
41
+ ``communicate()``. On Windows we ``taskkill /F /T`` the PID tree; on POSIX we
42
+ ``killpg`` (the child is spawned with ``start_new_session=True``). Never raises.
43
+ """
44
+ pid = getattr(proc, "pid", None)
45
+ if pid is not None:
46
+ try:
47
+ if os.name == "nt":
48
+ subprocess.run(
49
+ ["taskkill", "/F", "/T", "/PID", str(pid)],
50
+ stdin=subprocess.DEVNULL,
51
+ stdout=subprocess.DEVNULL,
52
+ stderr=subprocess.DEVNULL,
53
+ timeout=10,
54
+ )
55
+ else:
56
+ os.killpg(os.getpgid(pid), signal.SIGKILL)
57
+ except Exception:
58
+ pass # missing taskkill / already-dead / permission — fall through
59
+ # Ensure the direct child is gone regardless.
60
+ try:
61
+ proc.kill()
62
+ except Exception:
63
+ pass
64
+
65
+
34
66
  class SuiteExecutionService:
35
67
  """Service for executing Robot Framework test suites in dry run and normal modes."""
36
68
 
@@ -297,6 +329,12 @@ class SuiteExecutionService:
297
329
  start_time = datetime.now()
298
330
 
299
331
  # Prepare Robot Framework options
332
+ # NOTE: do NOT add --console none here. The dry-run captures RF's console output
333
+ # via a PIPE and the validation parser reads it (there is no output.xml —
334
+ # --output NONE), so suppressing the console would blank suite_info/test_count.
335
+ # The stdin=DEVNULL isolation below (change: fix-mcp-subprocess-stdin-deadlock)
336
+ # is what fixes the Windows deadlock; the captured stdout is a pipe, not an
337
+ # inherited handle, so there is nothing to defend against with --console none.
300
338
  rf_options = ["--dryrun", "--output", "NONE", "--report", "NONE", "--log", "NONE"]
301
339
 
302
340
  # Add validation level options (execution_options may override loglevel)
@@ -325,20 +363,42 @@ class SuiteExecutionService:
325
363
  # write to the underlying stdout fd and bypass contextlib.redirect_stdout).
326
364
  def run_robot_dry():
327
365
  cmd = [sys.executable, "-m", "robot", *rf_options]
366
+ # stdin=DEVNULL: the dry-run child MUST NOT inherit the MCP server's stdin
367
+ # (its JSON-RPC read channel). On Windows an inherited synchronous stdin
368
+ # pipe deadlocks the child's C-runtime stdio init behind the server's
369
+ # pending read → the dry-run hangs the full timeout (change:
370
+ # fix-mcp-subprocess-stdin-deadlock). Popen (not subprocess.run) so a
371
+ # timeout can reap the whole tree BEFORE draining the pipes.
372
+ popen_kwargs = dict(
373
+ stdin=subprocess.DEVNULL,
374
+ stdout=subprocess.PIPE,
375
+ stderr=subprocess.PIPE,
376
+ text=True,
377
+ encoding="utf-8",
378
+ errors="replace",
379
+ )
380
+ if os.name != "nt":
381
+ popen_kwargs["start_new_session"] = True # own group for killpg
328
382
  try:
329
- proc = subprocess.run(
330
- cmd,
331
- capture_output=True,
332
- text=True,
333
- encoding="utf-8",
334
- errors="replace",
335
- timeout=timeout_s,
336
- )
337
- return proc.returncode, proc.stdout or "", proc.stderr or ""
383
+ proc = subprocess.Popen(cmd, **popen_kwargs)
384
+ except Exception as e:
385
+ logger.error(f"Robot Framework dry run error: {e}")
386
+ return 252, "", str(e)
387
+ try:
388
+ stdout, stderr = proc.communicate(timeout=timeout_s)
389
+ return proc.returncode, stdout or "", stderr or ""
338
390
  except subprocess.TimeoutExpired:
391
+ # Reap the whole tree so an orphaned grandchild cannot keep the
392
+ # capture pipes open and hang the drain below.
393
+ _kill_process_tree(proc)
394
+ try:
395
+ proc.communicate(timeout=5)
396
+ except Exception:
397
+ pass
339
398
  raise
340
399
  except Exception as e:
341
400
  logger.error(f"Robot Framework dry run error: {e}")
401
+ _kill_process_tree(proc)
342
402
  return 252, "", str(e)
343
403
 
344
404
  loop = asyncio.get_event_loop()
@@ -97,9 +97,12 @@ class LibraryAvailabilityChecker:
97
97
  def check_pip_package_installed(self, package_name: str) -> bool:
98
98
  """Check if a pip package is installed using pip list."""
99
99
  try:
100
+ # stdin=DEVNULL: never inherit the MCP server's stdin — an inherited
101
+ # synchronous stdin pipe deadlocks this child on Windows behind the server's
102
+ # pending JSON-RPC read (change: fix-mcp-subprocess-stdin-deadlock).
100
103
  result = subprocess.run([
101
104
  sys.executable, '-m', 'pip', 'list', '--format=freeze'
102
- ], capture_output=True, text=True, timeout=10)
105
+ ], capture_output=True, text=True, timeout=10, stdin=subprocess.DEVNULL)
103
106
 
104
107
  if result.returncode == 0:
105
108
  installed_packages = result.stdout.lower()
File without changes
File without changes
File without changes