@hybridlabor-api/aos 4.4.0 → 4.4.2-beta.0

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 (306) hide show
  1. package/.agents/skills/firecrawl/SKILL.md +149 -0
  2. package/.agents/skills/firecrawl/rules/install.md +82 -0
  3. package/.agents/skills/firecrawl/rules/security.md +26 -0
  4. package/.agents/skills/firecrawl-agent/SKILL.md +58 -0
  5. package/.agents/skills/firecrawl-build/SKILL.md +39 -0
  6. package/.agents/skills/firecrawl-build-interact/SKILL.md +68 -0
  7. package/.agents/skills/firecrawl-build-onboarding/SKILL.md +103 -0
  8. package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
  9. package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
  10. package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
  11. package/.agents/skills/firecrawl-build-scrape/SKILL.md +69 -0
  12. package/.agents/skills/firecrawl-build-search/SKILL.md +69 -0
  13. package/.agents/skills/firecrawl-crawl/SKILL.md +59 -0
  14. package/.agents/skills/firecrawl-download/SKILL.md +70 -0
  15. package/.agents/skills/firecrawl-interact/SKILL.md +84 -0
  16. package/.agents/skills/firecrawl-map/SKILL.md +51 -0
  17. package/.agents/skills/firecrawl-scrape/SKILL.md +69 -0
  18. package/.agents/skills/firecrawl-search/SKILL.md +60 -0
  19. package/.claude/hooks/memb-inject.mjs +6 -0
  20. package/CLAUDE.md +573 -0
  21. package/README.de.md +0 -8
  22. package/README.md +0 -8
  23. package/README.pt.md +0 -8
  24. package/assets/brand/ao-ant-mark.svg +91 -0
  25. package/assets/brand/bdb-core-mark.svg +34 -0
  26. package/assets/brand/heimdall-guardian-mark.svg +16 -0
  27. package/assets/brand/memb-crystal-mark.svg +18 -0
  28. package/bin/aos-config.mjs +89 -0
  29. package/bin/aos-dashboard.mjs +608 -0
  30. package/bin/aos-uninstall.mjs +227 -0
  31. package/docs/sessions/audit-2026-09-14-silent-failures.md +114 -0
  32. package/docs/skills_table.md +0 -3
  33. package/installer.js +428 -237
  34. package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +10 -0
  35. package/mcps/after-effects-mcp/build/index.js +840 -0
  36. package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +153 -0
  37. package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +218 -0
  38. package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +71 -0
  39. package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +147 -0
  40. package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +114 -0
  41. package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +115 -0
  42. package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +192 -0
  43. package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +90 -0
  44. package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +50 -0
  45. package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +1773 -0
  46. package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +160 -0
  47. package/mcps/computer-use-mcp/dist/client.d.ts +150 -0
  48. package/mcps/computer-use-mcp/dist/client.js +136 -0
  49. package/mcps/computer-use-mcp/dist/entrypoint.d.ts +16 -0
  50. package/mcps/computer-use-mcp/dist/entrypoint.js +26 -0
  51. package/mcps/computer-use-mcp/dist/native.d.ts +212 -0
  52. package/mcps/computer-use-mcp/dist/native.js +50 -0
  53. package/mcps/computer-use-mcp/dist/server.d.ts +32 -0
  54. package/mcps/computer-use-mcp/dist/server.js +342 -0
  55. package/mcps/computer-use-mcp/dist/session.d.ts +101 -0
  56. package/mcps/computer-use-mcp/dist/session.js +2372 -0
  57. package/package.json +13 -4
  58. package/skills/global_config/aos-project-init/SKILL.md +97 -130
  59. package/skills/global_config/aos-project-init/assets/openwikiignore.template +62 -0
  60. package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +38 -1
  61. package/skills/global_config/aos-setup/SKILL.md +110 -11
  62. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +48 -4
  63. package/skills/global_config/ask-tim/SKILL.md +2 -7
  64. package/skills/global_config/openwiki-skill/scripts/openwiki_daemon.py +65 -12
  65. package/bin/setup-saas.mjs +0 -792
  66. package/mcps/blender-mcp-server/.dockerignore +0 -19
  67. package/mcps/blender-mcp-server/.github/workflows/ci.yml +0 -67
  68. package/mcps/blender-mcp-server/.github/workflows/publish-pypi.yml +0 -54
  69. package/mcps/blender-mcp-server/CHANGELOG.md +0 -64
  70. package/mcps/blender-mcp-server/CONTRIBUTING.md +0 -107
  71. package/mcps/blender-mcp-server/Dockerfile +0 -19
  72. package/mcps/blender-mcp-server/LICENSE +0 -21
  73. package/mcps/blender-mcp-server/README.md +0 -409
  74. package/mcps/blender-mcp-server/addon/__init__.py +0 -1440
  75. package/mcps/blender-mcp-server/addon/models.py +0 -223
  76. package/mcps/blender-mcp-server/pyproject.toml +0 -120
  77. package/mcps/blender-mcp-server/scripts/blender_bridge_request.py +0 -71
  78. package/mcps/blender-mcp-server/scripts/blender_create_test_cube.py +0 -49
  79. package/mcps/blender-mcp-server/scripts/blender_scene_info.py +0 -38
  80. package/mcps/blender-mcp-server/scripts/build_addon_zip.sh +0 -29
  81. package/mcps/blender-mcp-server/scripts/demos/README.md +0 -186
  82. package/mcps/blender-mcp-server/scripts/demos/dam_break_scene.py +0 -276
  83. package/mcps/blender-mcp-server/scripts/demos/open_dam_break_gui.py +0 -33
  84. package/mcps/blender-mcp-server/scripts/demos/pipe_movement_study.py +0 -518
  85. package/mcps/blender-mcp-server/scripts/demos/pipe_pressure_failure_scene.py +0 -806
  86. package/mcps/blender-mcp-server/scripts/demos/procedural_dam_break_scene.py +0 -600
  87. package/mcps/blender-mcp-server/scripts/demos/run_dam_break.py +0 -510
  88. package/mcps/blender-mcp-server/scripts/launch_blender_gui.py +0 -41
  89. package/mcps/blender-mcp-server/scripts/library/README.md +0 -64
  90. package/mcps/blender-mcp-server/scripts/library/apply_transforms.py +0 -46
  91. package/mcps/blender-mcp-server/scripts/library/camera.py +0 -51
  92. package/mcps/blender-mcp-server/scripts/library/collections.py +0 -65
  93. package/mcps/blender-mcp-server/scripts/library/create_mesh.py +0 -41
  94. package/mcps/blender-mcp-server/scripts/library/effector.py +0 -48
  95. package/mcps/blender-mcp-server/scripts/library/fluid_domain.py +0 -80
  96. package/mcps/blender-mcp-server/scripts/library/fluid_inflow.py +0 -98
  97. package/mcps/blender-mcp-server/scripts/library/frame_range.py +0 -35
  98. package/mcps/blender-mcp-server/scripts/library/keyframes.py +0 -59
  99. package/mcps/blender-mcp-server/scripts/library/rigid_body.py +0 -52
  100. package/mcps/blender-mcp-server/scripts/library/save_blend.py +0 -40
  101. package/mcps/blender-mcp-server/scripts/server_start.sh +0 -26
  102. package/mcps/blender-mcp-server/src/blender_mcp_server/__init__.py +0 -3
  103. package/mcps/blender-mcp-server/src/blender_mcp_server/headless.py +0 -330
  104. package/mcps/blender-mcp-server/src/blender_mcp_server/server.py +0 -606
  105. package/mcps/davinci-mcp-professional/.bandit +0 -35
  106. package/mcps/davinci-mcp-professional/.claude/commands/security-review.md +0 -191
  107. package/mcps/davinci-mcp-professional/.claude/settings.json +0 -1
  108. package/mcps/davinci-mcp-professional/.editorconfig +0 -27
  109. package/mcps/davinci-mcp-professional/.gitattributes +0 -207
  110. package/mcps/davinci-mcp-professional/.github/CODEOWNERS +0 -2
  111. package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
  112. package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  113. package/mcps/davinci-mcp-professional/.github/PULL_REQUEST_TEMPLATE.md +0 -20
  114. package/mcps/davinci-mcp-professional/.github/SECURITY.md +0 -97
  115. package/mcps/davinci-mcp-professional/.github/dependabot.yml +0 -27
  116. package/mcps/davinci-mcp-professional/.github/workflows/ci.yml +0 -39
  117. package/mcps/davinci-mcp-professional/ATTRIBUTION.md +0 -4
  118. package/mcps/davinci-mcp-professional/AUTHORS.md +0 -9
  119. package/mcps/davinci-mcp-professional/BUGS.md +0 -55
  120. package/mcps/davinci-mcp-professional/CLAUDE.md +0 -229
  121. package/mcps/davinci-mcp-professional/CONTRIBUTING.md +0 -51
  122. package/mcps/davinci-mcp-professional/COPYING.md +0 -228
  123. package/mcps/davinci-mcp-professional/Doxyfile +0 -379
  124. package/mcps/davinci-mcp-professional/README.md +0 -143
  125. package/mcps/davinci-mcp-professional/SECURITY.md +0 -40
  126. package/mcps/davinci-mcp-professional/USING.md +0 -301
  127. package/mcps/davinci-mcp-professional/VERSION.md +0 -13
  128. package/mcps/davinci-mcp-professional/build.py +0 -169
  129. package/mcps/davinci-mcp-professional/claude_desktop_config_template.json +0 -11
  130. package/mcps/davinci-mcp-professional/hooks/ci-check.sh +0 -29
  131. package/mcps/davinci-mcp-professional/hooks/pre-push +0 -46
  132. package/mcps/davinci-mcp-professional/main.py +0 -40
  133. package/mcps/davinci-mcp-professional/mcp_server.py +0 -30
  134. package/mcps/davinci-mcp-professional/pyproject.toml +0 -115
  135. package/mcps/davinci-mcp-professional/security_audit.py +0 -379
  136. package/mcps/davinci-mcp-professional/src/davinci_mcp/__init__.py +0 -19
  137. package/mcps/davinci-mcp-professional/src/davinci_mcp/cli.py +0 -138
  138. package/mcps/davinci-mcp-professional/src/davinci_mcp/resolve_client.py +0 -342
  139. package/mcps/davinci-mcp-professional/src/davinci_mcp/resources/__init__.py +0 -60
  140. package/mcps/davinci-mcp-professional/src/davinci_mcp/server.py +0 -185
  141. package/mcps/davinci-mcp-professional/src/davinci_mcp/tools/__init__.py +0 -146
  142. package/mcps/davinci-mcp-professional/src/davinci_mcp/types.py +0 -125
  143. package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/__init__.py +0 -19
  144. package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/platform.py +0 -239
  145. package/mcps/davinci-mcp-professional/test.py +0 -186
  146. package/mcps/davinci-mcp-professional/uv.lock +0 -2073
  147. package/mcps/davinci-resolve-mcp/.claude/skills/media-analysis.md +0 -44
  148. package/mcps/davinci-resolve-mcp/.clinerules +0 -17
  149. package/mcps/davinci-resolve-mcp/.cursorrules +0 -17
  150. package/mcps/davinci-resolve-mcp/.github/copilot-instructions.md +0 -17
  151. package/mcps/davinci-resolve-mcp/.github/workflows/npm-publish.yml +0 -109
  152. package/mcps/davinci-resolve-mcp/.windsurfrules +0 -17
  153. package/mcps/davinci-resolve-mcp/AGENTS.md +0 -114
  154. package/mcps/davinci-resolve-mcp/CHANGELOG.md +0 -2648
  155. package/mcps/davinci-resolve-mcp/CLAUDE.md +0 -15
  156. package/mcps/davinci-resolve-mcp/LICENSE +0 -21
  157. package/mcps/davinci-resolve-mcp/README.md +0 -173
  158. package/mcps/davinci-resolve-mcp/SECURITY.md +0 -53
  159. package/mcps/davinci-resolve-mcp/bin/davinci-resolve-mcp.mjs +0 -450
  160. package/mcps/davinci-resolve-mcp/examples/README.md +0 -53
  161. package/mcps/davinci-resolve-mcp/examples/markers/README.md +0 -81
  162. package/mcps/davinci-resolve-mcp/examples/media/README.md +0 -94
  163. package/mcps/davinci-resolve-mcp/examples/timeline/README.md +0 -98
  164. package/mcps/davinci-resolve-mcp/install.py +0 -1687
  165. package/mcps/davinci-resolve-mcp/package.json +0 -52
  166. package/mcps/davinci-resolve-mcp/release-notes/v2.22.0.md +0 -51
  167. package/mcps/davinci-resolve-mcp/release-notes/v2.23.0.md +0 -51
  168. package/mcps/davinci-resolve-mcp/release-notes/v2.23.1.md +0 -35
  169. package/mcps/davinci-resolve-mcp/release-notes/v2.24.1.md +0 -32
  170. package/mcps/davinci-resolve-mcp/scripts/audit_api_parity.py +0 -275
  171. package/mcps/davinci-resolve-mcp/scripts/audit_readwrite_symmetry.py +0 -80
  172. package/mcps/davinci-resolve-mcp/scripts/doctor.py +0 -227
  173. package/mcps/davinci-resolve-mcp/scripts/gen_api_limitations.py +0 -144
  174. package/mcps/davinci-resolve-mcp/scripts/live_media_analysis_polish_probe.py +0 -65
  175. package/mcps/davinci-resolve-mcp/scripts/measure_bridge_cost.py +0 -65
  176. package/mcps/davinci-resolve-mcp/scripts/regen_panel_screenshots.py +0 -76
  177. package/mcps/davinci-resolve-mcp/src/__init__.py +0 -3
  178. package/mcps/davinci-resolve-mcp/src/analysis_dashboard.py +0 -15505
  179. package/mcps/davinci-resolve-mcp/src/batch_cli.py +0 -540
  180. package/mcps/davinci-resolve-mcp/src/control_panel.py +0 -13
  181. package/mcps/davinci-resolve-mcp/src/granular/__init__.py +0 -17
  182. package/mcps/davinci-resolve-mcp/src/granular/common.py +0 -741
  183. package/mcps/davinci-resolve-mcp/src/granular/folder.py +0 -420
  184. package/mcps/davinci-resolve-mcp/src/granular/gallery.py +0 -306
  185. package/mcps/davinci-resolve-mcp/src/granular/graph.py +0 -309
  186. package/mcps/davinci-resolve-mcp/src/granular/media_pool.py +0 -679
  187. package/mcps/davinci-resolve-mcp/src/granular/media_pool_item.py +0 -1020
  188. package/mcps/davinci-resolve-mcp/src/granular/media_storage.py +0 -179
  189. package/mcps/davinci-resolve-mcp/src/granular/project.py +0 -1654
  190. package/mcps/davinci-resolve-mcp/src/granular/resolve_control.py +0 -538
  191. package/mcps/davinci-resolve-mcp/src/granular/timeline.py +0 -1075
  192. package/mcps/davinci-resolve-mcp/src/granular/timeline_item.py +0 -2251
  193. package/mcps/davinci-resolve-mcp/src/resolve_mcp_server.py +0 -43
  194. package/mcps/davinci-resolve-mcp/src/server.py +0 -24116
  195. package/mcps/davinci-resolve-mcp/src/utils/__init__.py +0 -3
  196. package/mcps/davinci-resolve-mcp/src/utils/actor_identity.py +0 -46
  197. package/mcps/davinci-resolve-mcp/src/utils/analysis_caps.py +0 -678
  198. package/mcps/davinci-resolve-mcp/src/utils/analysis_memory.py +0 -755
  199. package/mcps/davinci-resolve-mcp/src/utils/analysis_runs.py +0 -307
  200. package/mcps/davinci-resolve-mcp/src/utils/analysis_store.py +0 -945
  201. package/mcps/davinci-resolve-mcp/src/utils/api_truth.py +0 -525
  202. package/mcps/davinci-resolve-mcp/src/utils/app_control.py +0 -319
  203. package/mcps/davinci-resolve-mcp/src/utils/audio_fairlight_live_probe.py +0 -263
  204. package/mcps/davinci-resolve-mcp/src/utils/brain_edits.py +0 -387
  205. package/mcps/davinci-resolve-mcp/src/utils/bridge_metrics.py +0 -76
  206. package/mcps/davinci-resolve-mcp/src/utils/cdl.py +0 -20
  207. package/mcps/davinci-resolve-mcp/src/utils/clip_query.py +0 -85
  208. package/mcps/davinci-resolve-mcp/src/utils/cloud_operations.py +0 -192
  209. package/mcps/davinci-resolve-mcp/src/utils/color_grade_live_probe.py +0 -444
  210. package/mcps/davinci-resolve-mcp/src/utils/contracts.py +0 -102
  211. package/mcps/davinci-resolve-mcp/src/utils/cut_ir.py +0 -115
  212. package/mcps/davinci-resolve-mcp/src/utils/dctl_templates.py +0 -368
  213. package/mcps/davinci-resolve-mcp/src/utils/deep_vision.py +0 -643
  214. package/mcps/davinci-resolve-mcp/src/utils/destructive_hook.py +0 -606
  215. package/mcps/davinci-resolve-mcp/src/utils/edit_engine.py +0 -737
  216. package/mcps/davinci-resolve-mcp/src/utils/embeddings.py +0 -922
  217. package/mcps/davinci-resolve-mcp/src/utils/entities.py +0 -579
  218. package/mcps/davinci-resolve-mcp/src/utils/extension_authoring_live_probe.py +0 -292
  219. package/mcps/davinci-resolve-mcp/src/utils/failure_tracker.py +0 -119
  220. package/mcps/davinci-resolve-mcp/src/utils/fuse_templates.py +0 -1968
  221. package/mcps/davinci-resolve-mcp/src/utils/fusion_composition_live_probe.py +0 -284
  222. package/mcps/davinci-resolve-mcp/src/utils/fusion_group_settings.py +0 -334
  223. package/mcps/davinci-resolve-mcp/src/utils/layout_presets.py +0 -333
  224. package/mcps/davinci-resolve-mcp/src/utils/mcp_stdio.py +0 -32
  225. package/mcps/davinci-resolve-mcp/src/utils/mcp_transport.py +0 -128
  226. package/mcps/davinci-resolve-mcp/src/utils/media_analysis.py +0 -7690
  227. package/mcps/davinci-resolve-mcp/src/utils/media_analysis_jobs.py +0 -805
  228. package/mcps/davinci-resolve-mcp/src/utils/media_pool_changes.py +0 -121
  229. package/mcps/davinci-resolve-mcp/src/utils/media_pool_ingest_live_probe.py +0 -592
  230. package/mcps/davinci-resolve-mcp/src/utils/multicam.py +0 -393
  231. package/mcps/davinci-resolve-mcp/src/utils/object_inspection.py +0 -301
  232. package/mcps/davinci-resolve-mcp/src/utils/page_lock.py +0 -75
  233. package/mcps/davinci-resolve-mcp/src/utils/platform.py +0 -157
  234. package/mcps/davinci-resolve-mcp/src/utils/proc.py +0 -26
  235. package/mcps/davinci-resolve-mcp/src/utils/project_cleanup.py +0 -73
  236. package/mcps/davinci-resolve-mcp/src/utils/project_lifecycle_live_probe.py +0 -376
  237. package/mcps/davinci-resolve-mcp/src/utils/project_lint.py +0 -131
  238. package/mcps/davinci-resolve-mcp/src/utils/project_properties.py +0 -601
  239. package/mcps/davinci-resolve-mcp/src/utils/project_spec.py +0 -459
  240. package/mcps/davinci-resolve-mcp/src/utils/readback.py +0 -91
  241. package/mcps/davinci-resolve-mcp/src/utils/render_deliver_live_probe.py +0 -384
  242. package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_governance.py +0 -214
  243. package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_ledger.py +0 -244
  244. package/mcps/davinci-resolve-mcp/src/utils/resolve_busy.py +0 -171
  245. package/mcps/davinci-resolve-mcp/src/utils/resolve_connection.py +0 -77
  246. package/mcps/davinci-resolve-mcp/src/utils/review_annotation_live_probe.py +0 -352
  247. package/mcps/davinci-resolve-mcp/src/utils/script_templates.py +0 -1193
  248. package/mcps/davinci-resolve-mcp/src/utils/shot_relationships.py +0 -544
  249. package/mcps/davinci-resolve-mcp/src/utils/structural_diff.py +0 -175
  250. package/mcps/davinci-resolve-mcp/src/utils/sync_detection.py +0 -889
  251. package/mcps/davinci-resolve-mcp/src/utils/timeline_brain_db.py +0 -826
  252. package/mcps/davinci-resolve-mcp/src/utils/timeline_conform_live_probe.py +0 -280
  253. package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_live_probe.py +0 -1092
  254. package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_probe.py +0 -185
  255. package/mcps/davinci-resolve-mcp/src/utils/timeline_title_text.py +0 -87
  256. package/mcps/davinci-resolve-mcp/src/utils/timeline_versioning.py +0 -730
  257. package/mcps/davinci-resolve-mcp/src/utils/update_check.py +0 -685
  258. package/mcps/vectorworks-mcp/.dockerignore +0 -8
  259. package/mcps/vectorworks-mcp/Dockerfile +0 -28
  260. package/mcps/vectorworks-mcp/README.md +0 -156
  261. package/mcps/vectorworks-mcp/app/__init__.py +0 -2
  262. package/mcps/vectorworks-mcp/app/api.py +0 -52
  263. package/mcps/vectorworks-mcp/app/chunking.py +0 -56
  264. package/mcps/vectorworks-mcp/app/config.py +0 -29
  265. package/mcps/vectorworks-mcp/app/embeddings.py +0 -28
  266. package/mcps/vectorworks-mcp/app/indexer.py +0 -106
  267. package/mcps/vectorworks-mcp/app/main.py +0 -33
  268. package/mcps/vectorworks-mcp/app/mcp_server.py +0 -71
  269. package/mcps/vectorworks-mcp/app/search.py +0 -54
  270. package/mcps/vectorworks-mcp/app/utils.py +0 -14
  271. package/mcps/vectorworks-mcp/data/.gitkeep +0 -1
  272. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_PluginScript.htm +0 -95
  273. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_ScriptEditor.htm +0 -266
  274. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_Scripting.htm +0 -106
  275. package/mcps/vectorworks-mcp/data/vw-app-help/VW2023_CreatingScriptedPlugins.htm +0 -327
  276. package/mcps/vectorworks-mcp/data/vw-app-help/VW2024_RunningScripts.htm +0 -116
  277. package/mcps/vectorworks-mcp/data/vw-devwiki/VS_Function_Reference_category.html +0 -2129
  278. package/mcps/vectorworks-mcp/data/vw-jp-ref/ObjectsSymbols.html +0 -2035
  279. package/mcps/vectorworks-mcp/data/vw-jp-ref/ScriptFunctionReference.html +0 -29
  280. package/mcps/vectorworks-mcp/design.md +0 -57
  281. package/mcps/vectorworks-mcp/docker-compose.yml +0 -18
  282. package/mcps/vectorworks-mcp/index/.gitkeep +0 -1
  283. package/mcps/vectorworks-mcp/index/meta.jsonl +0 -3956
  284. package/mcps/vectorworks-mcp/index/vw.faiss +0 -0
  285. package/mcps/vectorworks-mcp/requirements.txt +0 -10
  286. package/mcps/vectorworks-mcp/scripts/fetch_docs_minimal.sh +0 -84
  287. package/mcps/vectorworks-mcp/scripts/fetch_github_vectorworks.sh +0 -85
  288. package/mcps/vectorworks-mcp/templates/index.html +0 -40
  289. package/scripts/ecosystem-health-audit.js +0 -257
  290. package/skills/bdb-dev-os-skill/SKILL.md +0 -49
  291. package/skills/bdb-dev-os-skill/package.json +0 -11
  292. package/skills/bdbsaastraining/SKILL.md +0 -316
  293. package/skills/bdbsaastraining/references/exam-pool.md +0 -313
  294. package/skills/bdbsaastraining/references/interaction-modes.md +0 -94
  295. package/skills/bdbsaastraining/references/track-a-ai-agent.md +0 -111
  296. package/skills/bdbsaastraining/references/track-b-wordpress.md +0 -111
  297. package/skills/bdbsaastraining/references/track-c-mailserver.md +0 -107
  298. package/skills/bdbsaastraining/references/track-d-debian.md +0 -109
  299. package/skills/bdbsaastraining/references/track-e-custom.md +0 -83
  300. package/skills/bdbsaastraining/scripts/build_profile.py +0 -529
  301. package/skills/bdbsaastraining/scripts/generate_certificate.py +0 -161
  302. package/skills/bdbsaastraining/scripts/preflight_check.sh +0 -150
  303. package/skills/bdbsaastraining/templates/certificate_template.html +0 -508
  304. package/skills/global_config/bdb-ecosystem-health/SKILL.md +0 -68
  305. package/skills/global_config/bdbsaas-ops/SKILL.md +0 -16
  306. package/skills/global_config/bdbsaashost/SKILL.md +0 -125
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Native NAPI module loader — loads the compiled .node addon.
3
+ * Supports macOS (darwin) and Windows (win32) with platform-specific binaries.
4
+ */
5
+ export interface AXBounds {
6
+ x: number;
7
+ y: number;
8
+ width: number;
9
+ height: number;
10
+ }
11
+ export interface AXElement {
12
+ role: string;
13
+ label: string | null;
14
+ value: string | null;
15
+ bounds: AXBounds;
16
+ actions: string[];
17
+ /** Present on full tree nodes; omitted by flat find_element results. */
18
+ children?: AXElement[];
19
+ /** Present on find_element results — indices from the walk root. */
20
+ path?: number[];
21
+ /** Set when a subtree or the whole tree hit the depth / node cap. */
22
+ truncated?: boolean;
23
+ }
24
+ export interface MenuItem {
25
+ title: string;
26
+ enabled: boolean;
27
+ shortcut?: string;
28
+ submenu?: MenuItem[];
29
+ }
30
+ export interface MenuBarEntry {
31
+ title: string;
32
+ enabled: boolean;
33
+ items: MenuItem[];
34
+ }
35
+ export interface WindowRecord {
36
+ windowId: number;
37
+ bundleId: string | null;
38
+ displayName: string;
39
+ pid: number;
40
+ title: string | null;
41
+ bounds: AXBounds;
42
+ isOnScreen: boolean;
43
+ isFocused: boolean;
44
+ displayId: number;
45
+ }
46
+ export interface NativeModule {
47
+ mouseMove(x: number, y: number): void;
48
+ mouseClick(x: number, y: number, button: string, count: number): void;
49
+ mouseButton(action: string, x: number, y: number): void;
50
+ mouseScroll(dy: number, dx: number): void;
51
+ mouseDrag(x: number, y: number): void;
52
+ cursorPosition(): {
53
+ x: number;
54
+ y: number;
55
+ };
56
+ keyPress(combo: string, repeat?: number): void;
57
+ typeText(text: string): void;
58
+ holdKey(keys: string[], durationMs: number): void;
59
+ activateApp(bundleId: string, timeoutMs?: number): {
60
+ bundleId: string;
61
+ activated: boolean;
62
+ displayName?: string;
63
+ };
64
+ getFrontmostApp(): {
65
+ bundleId: string;
66
+ displayName: string;
67
+ pid: number;
68
+ } | null;
69
+ getWindow(windowId: number): WindowRecord | null;
70
+ getCursorWindow(): WindowRecord | null;
71
+ activateWindow(windowId: number, timeoutMs?: number): {
72
+ windowId: number;
73
+ activated: boolean;
74
+ reason: string | null;
75
+ };
76
+ listWindows(bundleId?: string): Array<WindowRecord>;
77
+ listRunningApps(): Array<{
78
+ bundleId: string;
79
+ displayName: string;
80
+ pid: number;
81
+ isHidden: boolean;
82
+ }>;
83
+ hideApp(bundleId: string): boolean;
84
+ unhideApp(bundleId: string): boolean;
85
+ getDisplaySize(displayId?: number): {
86
+ width: number;
87
+ height: number;
88
+ pixelWidth: number;
89
+ pixelHeight: number;
90
+ scaleFactor: number;
91
+ displayId: number;
92
+ };
93
+ listDisplays(): Array<{
94
+ width: number;
95
+ height: number;
96
+ scaleFactor: number;
97
+ displayId: number;
98
+ }>;
99
+ takeScreenshot(width?: number, targetApp?: string, quality?: number, previousHash?: string, windowId?: number): {
100
+ base64?: string;
101
+ width: number;
102
+ height: number;
103
+ mimeType: string;
104
+ hash: string;
105
+ unchanged: boolean;
106
+ };
107
+ /** Depth-limited AX tree rooted at the window; caps at 500 nodes. */
108
+ getUiTree(windowId: number, maxDepth?: number): AXElement;
109
+ /** Currently focused AX element (or null). */
110
+ getFocusedElement(): AXElement | null;
111
+ /** Depth-first search within the window's AX tree. */
112
+ findElement(windowId: number, role?: string, label?: string, value?: string, maxResults?: number): AXElement[];
113
+ /** Perform an AX action (e.g. AXPress) on the first (role, label) match. */
114
+ performAction(windowId: number, role: string, label: string, action: string): {
115
+ performed: boolean;
116
+ reason?: string;
117
+ bounds?: AXBounds;
118
+ };
119
+ /** Set AXValue on the first (role, label) match. */
120
+ setElementValue(windowId: number, role: string, label: string, value: string): {
121
+ set: boolean;
122
+ reason?: string;
123
+ };
124
+ /** Walk the app's menu bar and return nested menu structure. */
125
+ getMenuBar(bundleId: string): MenuBarEntry[];
126
+ /** Press a named menu item, optionally nested under a submenu. */
127
+ pressMenuItem(bundleId: string, menu: string, item: string, submenu?: string): {
128
+ pressed: boolean;
129
+ reason?: string;
130
+ };
131
+ /** List user Spaces grouped by display, with the active Space ID. */
132
+ listSpaces(): {
133
+ supported: boolean;
134
+ reason?: string;
135
+ active_space_id: number | null;
136
+ displays: Array<{
137
+ display_id: string;
138
+ spaces: Array<{
139
+ id: number;
140
+ type: number;
141
+ uuid: string;
142
+ }>;
143
+ }>;
144
+ };
145
+ /** Active Space ID or null if CGS is unreachable. */
146
+ getActiveSpace(): number | null;
147
+ /** Create a new Space. Reports `attached: false` when the created Space is
148
+ * orphaned (not visible in Mission Control). */
149
+ createAgentSpace(): {
150
+ supported: boolean;
151
+ spaceId?: number;
152
+ attached?: boolean;
153
+ reason?: string;
154
+ note?: string;
155
+ };
156
+ /** Move a window into a Space. `verified: true` only when the window
157
+ * visibly disappears from the on-screen window list. */
158
+ moveWindowToSpace(windowId: number, spaceId: number): {
159
+ moved: boolean;
160
+ verified?: boolean;
161
+ reason?: string;
162
+ note?: string;
163
+ window_on_screen_before?: boolean;
164
+ window_on_screen_after?: boolean;
165
+ };
166
+ /** Remove a window from a Space (restores visibility). */
167
+ removeWindowFromSpace(windowId: number, spaceId: number): {
168
+ removed: boolean;
169
+ reason?: string;
170
+ };
171
+ /** Destroy a Space created via createAgentSpace. */
172
+ destroySpace(spaceId: number): {
173
+ destroyed: boolean;
174
+ reason?: string;
175
+ };
176
+ /**
177
+ * Pump the main CFRunLoop once. Used by the session layer during a CU
178
+ * session to keep NSWorkspace / AX state fresh. Cheap when idle.
179
+ */
180
+ drainRunloop(): void;
181
+ /** Read clipboard text (Windows native). Undefined on macOS. */
182
+ readClipboard?(): string;
183
+ /** Write text to clipboard (Windows native). Undefined on macOS. */
184
+ writeClipboard?(text: string): void;
185
+ /** Draw annotations and grid lines on an image. Cross-platform. */
186
+ annotateImage(base64Jpeg: string, annotations: string | null, gridCols: number | null, gridRows: number | null, quality: number | null): {
187
+ base64: string;
188
+ width: number;
189
+ height: number;
190
+ mimeType: string;
191
+ };
192
+ /** Crop a region from a base64 image at full resolution. Cross-platform. */
193
+ cropImage(base64Image: string, x1: number, y1: number, x2: number, y2: number, quality: number | null): {
194
+ base64: string;
195
+ width: number;
196
+ height: number;
197
+ mimeType: string;
198
+ };
199
+ /**
200
+ * Hide every regular running app except the target and the keep-visible
201
+ * set. Defends against focus-stealing background apps (screenshot
202
+ * watchers, notification panels) before input dispatch.
203
+ *
204
+ * Returns the bundle IDs we actually hid — apps already hidden are NOT
205
+ * included, so callers can restore exactly the state they changed.
206
+ */
207
+ prepareDisplay(targetBundleId: string, keepVisible: string[]): {
208
+ targetBundleId: string;
209
+ hiddenBundleIds: string[];
210
+ };
211
+ }
212
+ export declare function loadNative(): NativeModule;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Native NAPI module loader — loads the compiled .node addon.
3
+ * Supports macOS (darwin) and Windows (win32) with platform-specific binaries.
4
+ */
5
+ import { createRequire } from 'module';
6
+ import { existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ /**
10
+ * Supported platform + architecture combinations.
11
+ * Each entry maps to a binary named `computer-use-napi.${platform}-${arch}.node`.
12
+ */
13
+ const SUPPORTED_TARGETS = [
14
+ { platform: 'darwin', arch: 'arm64' },
15
+ { platform: 'darwin', arch: 'x64' },
16
+ { platform: 'win32', arch: 'x64' },
17
+ { platform: 'linux', arch: 'x64' },
18
+ { platform: 'linux', arch: 'arm64' },
19
+ ];
20
+ /**
21
+ * Resolve the path to the platform-specific native binary.
22
+ * Throws a descriptive error on unsupported platforms or missing binaries.
23
+ */
24
+ function resolveAddonPath() {
25
+ const platform = process.platform;
26
+ const arch = process.arch;
27
+ const isSupported = SUPPORTED_TARGETS.some((t) => t.platform === platform && t.arch === arch);
28
+ if (!isSupported) {
29
+ const supported = SUPPORTED_TARGETS.map((t) => `${t.platform}-${t.arch}`).join(', ');
30
+ throw new Error(`Unsupported platform: ${platform}-${arch}. ` +
31
+ `Supported platforms: ${supported}.`);
32
+ }
33
+ const binaryName = `computer-use-napi.${platform}-${arch}.node`;
34
+ const binaryPath = join(fileURLToPath(import.meta.url), '..', '..', binaryName);
35
+ if (!existsSync(binaryPath)) {
36
+ throw new Error(`Native binary not found: ${binaryName}. ` +
37
+ `Expected at ${binaryPath}. ` +
38
+ `Run the appropriate build script to compile the native module for ${platform}-${arch}.`);
39
+ }
40
+ return binaryPath;
41
+ }
42
+ const require = createRequire(import.meta.url);
43
+ const ADDON_PATH = resolveAddonPath();
44
+ let cached;
45
+ export function loadNative() {
46
+ if (cached)
47
+ return cached;
48
+ cached = require(ADDON_PATH);
49
+ return cached;
50
+ }
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Computer Use MCP Server — exposes tools over MCP protocol.
4
+ * Backed by in-process Rust NAPI module via session.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { type Session, type SessionOptions } from './session.js';
8
+ /**
9
+ * v5.2 — How each tool reaches the target app.
10
+ *
11
+ * - `scripting`: executes via AppleScript / JXA (`osascript`). Works even when
12
+ * the target app is backgrounded or hidden. Cheapest path for scriptable
13
+ * apps (Mail, Safari, Finder, Numbers, Music, Messages, Notes, Calendar).
14
+ * - `ax`: reads or mutates via the AXUIElement (Accessibility) API. Needs
15
+ * Accessibility permission. Reads are always safe; mutations typically
16
+ * require the target frontmost but some apps allow background AXPress.
17
+ * - `cgevent`: synthesizes keyboard / mouse events via CGEvent. **Requires
18
+ * the target app to be frontmost** — events route to whatever has focus.
19
+ * - `none`: pure observation of system state (clipboard, display size,
20
+ * cursor position). No target needed.
21
+ */
22
+ export type FocusRequired = 'scripting' | 'ax' | 'cgevent' | 'none';
23
+ export interface ToolMeta {
24
+ focusRequired: FocusRequired;
25
+ /** Whether this tool is classified as mutating by the session layer. */
26
+ mutates: boolean;
27
+ }
28
+ export interface ServerOptions extends SessionOptions {
29
+ /** Override session instance for tests */
30
+ session?: Session;
31
+ }
32
+ export declare function createComputerUseServer(opts?: ServerOptions): McpServer;
@@ -0,0 +1,342 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Computer Use MCP Server — exposes tools over MCP protocol.
4
+ * Backed by in-process Rust NAPI module via session.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { z } from 'zod';
9
+ import { createSession } from './session.js';
10
+ import { isStdioEntrypoint } from './entrypoint.js';
11
+ const targetAppParam = z.string().optional().describe('Bundle ID of target app (auto-focuses before action)');
12
+ const targetWindowIdParam = z.number().int().optional().describe('CGWindowID to target. Takes precedence over target_app.');
13
+ const focusStrategyParam = z.enum(['strict', 'best_effort', 'none', 'prepare_display']).optional().describe('Focus strategy: strict (fail if unconfirmed), best_effort (try and proceed), none (skip activation), prepare_display (hide every non-target app before acting — v5.2, defeats focus-stealing background apps)');
14
+ const coord = { coordinate: z.tuple([z.number(), z.number()]).describe('[x, y] pixels') };
15
+ const withTargeting = (schema) => ({
16
+ ...schema,
17
+ target_app: targetAppParam,
18
+ target_window_id: targetWindowIdParam,
19
+ focus_strategy: focusStrategyParam,
20
+ });
21
+ const PROVIDERS = ['anthropic', 'openai', 'openai-low', 'gemini', 'llama', 'grok', 'mistral', 'qwen', 'nova', 'deepseek-vl', 'phi', 'auto'];
22
+ export function createComputerUseServer(opts = {}) {
23
+ const server = new McpServer({ name: 'computer-use', version: '6.1.0' });
24
+ const session = opts.session ?? createSession({
25
+ vision: opts.vision ?? (process.env.COMPUTER_USE_VISION !== 'false'),
26
+ provider: opts.provider ?? process.env.COMPUTER_USE_PROVIDER,
27
+ native: opts.native,
28
+ });
29
+ // v5.2: Per-tool metadata registry. Populated as each `tool()` call runs.
30
+ // Exposed to clients via the new `get_tool_metadata` tool and appended to
31
+ // each tool's description as `[focusRequired: X]` so agents that read
32
+ // descriptions can filter without a separate call.
33
+ const toolMeta = new Map();
34
+ // Shorthand for common metadata combos, so each tool() call stays readable.
35
+ const CG_MUT = { focusRequired: 'cgevent', mutates: true };
36
+ const AX_MUT = { focusRequired: 'ax', mutates: true };
37
+ const AX_READ = { focusRequired: 'ax', mutates: false };
38
+ const SCRIPTING = { focusRequired: 'scripting', mutates: true };
39
+ const SCRIPT_READ = { focusRequired: 'scripting', mutates: false };
40
+ const NONE_READ = { focusRequired: 'none', mutates: false };
41
+ const NONE_MUT = { focusRequired: 'none', mutates: true };
42
+ const tool = (name, desc, schema, meta) => {
43
+ toolMeta.set(name, meta);
44
+ const tagged = `${desc} [focusRequired: ${meta.focusRequired}]`;
45
+ server.tool(name, tagged, schema, async (args) => {
46
+ const result = await session.dispatch(name, args);
47
+ return {
48
+ content: result.content.map(c => c.type === 'image'
49
+ ? { type: 'image', data: c.data, mimeType: c.mimeType }
50
+ : { type: 'text', text: c.text }),
51
+ isError: result.isError,
52
+ };
53
+ });
54
+ };
55
+ tool('screenshot', 'Capture the screen or a specific window. BEFORE using this, consider get_ui_tree or find_element to discover UI by role/label — structured queries are cheaper than visual parsing. Auto-targets the active session window when no explicit target is given.', {
56
+ width: z.number().int().positive().optional()
57
+ .describe('Override width in pixels. Omit to use provider-optimal default.'),
58
+ quality: z.number().int().min(0).max(100).optional()
59
+ .describe('Image quality. 1-100 = JPEG quality. 0 = PNG (lossless). Default: 80 (JPEG).'),
60
+ target_app: z.string().optional()
61
+ .describe('Bundle ID of app to capture (window only). Omit for full screen.'),
62
+ target_window_id: targetWindowIdParam,
63
+ provider: z.enum(PROVIDERS).optional()
64
+ .describe('AI provider — sets optimal default width. anthropic=1024px, openai=1024px, gemini=768px, qwen/deepseek-vl/phi=896px. Default: auto (1024px).'),
65
+ }, NONE_READ);
66
+ tool('zoom', 'View a specific region of the screen at full resolution. Useful for reading small text, inspecting UI details, or verifying pixel-level content. Returns the cropped region without downscaling.', {
67
+ region: z.tuple([z.number().int(), z.number().int(), z.number().int(), z.number().int()])
68
+ .describe('[x1, y1, x2, y2] — top-left and bottom-right corners of the region to inspect'),
69
+ quality: z.number().int().min(0).max(100).optional()
70
+ .describe('Image quality. 0 = PNG (lossless, best for text). 1-100 = JPEG. Default: 0 (PNG).'),
71
+ }, NONE_READ);
72
+ // Pointer / keyboard — CGEvent, target must be frontmost.
73
+ tool('left_click', 'Left-click at coordinates', withTargeting(coord), CG_MUT);
74
+ tool('right_click', 'Right-click at coordinates', withTargeting(coord), CG_MUT);
75
+ tool('middle_click', 'Middle-click at coordinates', withTargeting(coord), CG_MUT);
76
+ tool('double_click', 'Double-click at coordinates', withTargeting(coord), CG_MUT);
77
+ tool('triple_click', 'Triple-click at coordinates', withTargeting(coord), CG_MUT);
78
+ tool('mouse_move', 'Move cursor to coordinates', withTargeting(coord), CG_MUT);
79
+ tool('left_click_drag', 'Click and drag', withTargeting({
80
+ coordinate: z.tuple([z.number(), z.number()]),
81
+ start_coordinate: z.tuple([z.number(), z.number()]).optional(),
82
+ }), CG_MUT);
83
+ tool('cursor_position', 'Get current cursor position', {}, NONE_READ);
84
+ tool('left_mouse_down', 'Press left mouse button', withTargeting(coord), CG_MUT);
85
+ tool('left_mouse_up', 'Release left mouse button', withTargeting(coord), CG_MUT);
86
+ tool('scroll', 'Scroll at position', {
87
+ ...coord,
88
+ direction: z.enum(['up', 'down', 'left', 'right']),
89
+ amount: z.number().int().positive().default(3),
90
+ target_app: targetAppParam,
91
+ target_window_id: targetWindowIdParam,
92
+ focus_strategy: focusStrategyParam,
93
+ }, CG_MUT);
94
+ tool('type', 'Type text into the focused app. For form fields, prefer set_value or fill_form — accessibility-based writes are more reliable and need no click-to-focus.', {
95
+ text: z.string(),
96
+ clear: z.boolean().optional().describe('Clear existing text before typing (Ctrl+A, Delete)'),
97
+ press_enter: z.boolean().optional().describe('Press Enter/Return after typing to submit'),
98
+ caret_position: z.enum(['start', 'end', 'idle']).optional().describe('Move caret before typing: start (Home), end (End), idle (leave as-is)'),
99
+ target_app: targetAppParam,
100
+ target_window_id: targetWindowIdParam,
101
+ focus_strategy: focusStrategyParam,
102
+ }, CG_MUT);
103
+ tool('key', 'Press a key combination (e.g. "command+c", "return"). Tab and Shift+Tab navigate between form fields; keyboard shortcuts are usually faster than coordinate-based clicks.', {
104
+ text: z.string().describe('Key combo like "command+c" or "return"'),
105
+ repeat: z.number().int().positive().optional(),
106
+ target_app: targetAppParam,
107
+ target_window_id: targetWindowIdParam,
108
+ focus_strategy: focusStrategyParam,
109
+ }, CG_MUT);
110
+ tool('hold_key', 'Hold keys for a duration', {
111
+ keys: z.array(z.string()),
112
+ duration: z.number().positive().describe('Seconds'),
113
+ target_app: targetAppParam,
114
+ target_window_id: targetWindowIdParam,
115
+ focus_strategy: focusStrategyParam,
116
+ }, CG_MUT);
117
+ // Clipboard — touches pasteboard only, no focus dependency.
118
+ tool('read_clipboard', 'Read clipboard contents', {}, NONE_READ);
119
+ tool('write_clipboard', 'Write text to clipboard', { text: z.string() }, NONE_MUT);
120
+ // App / window lifecycle — NSWorkspace/AX mutations.
121
+ tool('open_application', 'Open and focus an app by bundle ID', {
122
+ bundle_id: z.string().describe('macOS bundle ID e.g. "com.apple.Safari"'),
123
+ }, AX_MUT);
124
+ tool('get_frontmost_app', 'Get the currently frontmost app', {}, AX_READ);
125
+ tool('list_windows', 'List visible on-screen windows, optionally filtered by bundle ID', {
126
+ bundle_id: z.string().optional().describe('Bundle ID to filter windows by'),
127
+ }, AX_READ);
128
+ tool('list_running_apps', 'List all running regular applications', {}, AX_READ);
129
+ tool('hide_app', 'Hide an app by bundle ID', { bundle_id: z.string() }, AX_MUT);
130
+ tool('unhide_app', 'Unhide an app by bundle ID', { bundle_id: z.string() }, AX_MUT);
131
+ tool('get_display_size', 'Get display dimensions and scale factor', {
132
+ display_id: z.number().optional().describe('Display ID (omit for main display)'),
133
+ }, NONE_READ);
134
+ tool('list_displays', 'List all connected displays', {}, NONE_READ);
135
+ tool('get_window', 'Look up a window by its CGWindowID', {
136
+ window_id: z.number().int().describe('CGWindowID of the window to look up'),
137
+ }, AX_READ);
138
+ tool('get_cursor_window', 'Get the window currently under the mouse cursor', {}, AX_READ);
139
+ tool('activate_app', 'Activate an app and return structured before/after diagnostics', {
140
+ bundle_id: z.string().describe('macOS bundle ID'),
141
+ timeout_ms: z.number().int().positive().optional().describe('Activation polling timeout in ms'),
142
+ }, AX_MUT);
143
+ tool('activate_window', 'Raise a specific window by CGWindowID', {
144
+ window_id: z.number().int().describe('CGWindowID of the window to raise'),
145
+ timeout_ms: z.number().int().positive().optional().describe('Activation polling timeout in ms'),
146
+ }, AX_MUT);
147
+ tool('resize_window', 'Resize and/or move a window. Omit window_name to target the foreground window.', {
148
+ window_name: z.string().optional().describe('Window title or process name to target (omit for foreground)'),
149
+ window_id: z.number().int().optional().describe('Window ID to target (takes precedence over window_name)'),
150
+ window_size: z.tuple([z.number().int(), z.number().int()]).optional().describe('[width, height] in pixels'),
151
+ window_loc: z.tuple([z.number().int(), z.number().int()]).optional().describe('[x, y] top-left position'),
152
+ }, AX_MUT);
153
+ tool('wait', 'Wait for N seconds', { duration: z.number().positive().max(300) }, NONE_READ);
154
+ tool('snapshot', 'Combined screenshot + UI tree + window list + desktop info in one call. Returns structured text with all desktop state. Set use_vision=true to include screenshot image. Set use_annotation=true to draw bounding boxes on UI elements. Set grid_lines=[cols,rows] to overlay reference grid.', {
155
+ use_vision: z.boolean().optional().default(false).describe('Include screenshot image in response'),
156
+ use_annotation: z.boolean().optional().default(false).describe('Draw bounding boxes on detected UI elements'),
157
+ grid_lines: z.tuple([z.number().int(), z.number().int()]).optional().describe('[columns, rows] for reference grid overlay'),
158
+ display: z.array(z.number().int()).optional().describe('Monitor indices to capture (omit for all)'),
159
+ width: z.number().int().positive().optional().describe('Resize screenshot width'),
160
+ target_app: targetAppParam,
161
+ target_window_id: targetWindowIdParam,
162
+ }, NONE_READ);
163
+ // ── v5: Accessibility observation ───────────────────────────────────────
164
+ tool('get_ui_tree', 'Get the accessibility tree for a window — discover UI elements by role/label instead of parsing pixels. Returns role, label, value, bounds, actions, children per node. Capped at 500 nodes.', {
165
+ window_id: z.number().int().describe('CGWindowID to introspect'),
166
+ max_depth: z.number().int().positive().max(20).optional().describe('Maximum tree depth (default 10, max 20)'),
167
+ }, AX_READ);
168
+ tool('get_focused_element', 'Get the currently focused UI element — where typed text will go. Returns null if no element has focus.', {}, AX_READ);
169
+ tool('find_element', 'Search for UI elements in a window by role, label, or value (AND of the provided criteria). Faster than walking the full tree.', {
170
+ window_id: z.number().int().describe('CGWindowID to search within'),
171
+ role: z.string().optional().describe('AX role — e.g. AXButton, AXTextField, AXStaticText, AXMenuItem'),
172
+ label: z.string().optional().describe('Element label (AXTitle or AXDescription); case-insensitive substring match'),
173
+ value: z.string().optional().describe('Element value (AXValue); case-insensitive substring match'),
174
+ max_results: z.number().int().positive().max(100).optional().describe('Max matches to return (default 25)'),
175
+ }, AX_READ);
176
+ // ── v5: Semantic actions ────────────────────────────────────────────────
177
+ tool('click_element', 'Click a UI element by role and label — more reliable than pixel clicks (survives window moves and resolution changes). Falls back to coordinate click if AXPress is unsupported.', {
178
+ window_id: z.number().int().describe('CGWindowID of the window containing the element'),
179
+ role: z.string().describe('AX role of the element to click (e.g. AXButton)'),
180
+ label: z.string().describe('Element label — matched against AXTitle/AXDescription'),
181
+ focus_strategy: focusStrategyParam,
182
+ }, AX_MUT);
183
+ tool('set_value', 'Set a UI element\'s value directly (e.g. text field content). Avoids the click → type dance. Defaults to strict focus since it writes text.', {
184
+ window_id: z.number().int().describe('CGWindowID of the window containing the element'),
185
+ role: z.string().describe('AX role (usually AXTextField or AXTextArea)'),
186
+ label: z.string().describe('Element label'),
187
+ value: z.string().describe('New value to set'),
188
+ focus_strategy: focusStrategyParam,
189
+ }, AX_MUT);
190
+ tool('press_button', 'Press a button by its label. Shortcut over click_element for role=AXButton.', {
191
+ window_id: z.number().int().describe('CGWindowID of the window containing the button'),
192
+ label: z.string().describe('Button label'),
193
+ focus_strategy: focusStrategyParam,
194
+ }, AX_MUT);
195
+ tool('select_menu_item', 'Select an app menu item programmatically — walks AXMenuBar. Returns list of available menus on miss.', {
196
+ bundle_id: z.string().describe('Bundle ID of the app'),
197
+ menu: z.string().describe('Top-level menu title (e.g. "File")'),
198
+ item: z.string().describe('Menu item title (e.g. "New")'),
199
+ submenu: z.string().optional().describe('Submenu title when the item is nested'),
200
+ }, AX_MUT);
201
+ tool('fill_form', 'Set multiple UI element values in a single call — collapses click+type loops into one tool call. Partial failures are reported per field without aborting the batch.', {
202
+ window_id: z.number().int().describe('CGWindowID of the form window'),
203
+ fields: z.array(z.object({
204
+ role: z.string(),
205
+ label: z.string(),
206
+ value: z.string(),
207
+ })).describe('Ordered list of fields to fill'),
208
+ focus_strategy: focusStrategyParam,
209
+ }, AX_MUT);
210
+ // ── v5: Scripting bridge ────────────────────────────────────────────────
211
+ tool('run_script', 'Execute a script and return the output. On macOS: AppleScript or JXA for scriptable apps. On Windows: PowerShell. Bounded by timeout_ms.', {
212
+ language: z.enum(['applescript', 'javascript', 'powershell']).describe('Scripting language (applescript/javascript on macOS, powershell on Windows)'),
213
+ script: z.string().describe('Script body to execute'),
214
+ timeout_ms: z.number().int().positive().max(120_000).optional().describe('Hard timeout in ms (default 30000, max 120000)'),
215
+ }, SCRIPTING);
216
+ tool('get_app_dictionary', 'Get a scriptable app\'s dictionary (suites, commands, classes). Returns summarized names by default; pass `suite` for full details of one suite.', {
217
+ bundle_id: z.string().describe('Bundle ID of the scriptable app'),
218
+ suite: z.string().optional().describe('Limit to a specific suite; omit for a summary'),
219
+ }, SCRIPT_READ);
220
+ // ── v5.1: Menu bar introspection ────────────────────────────────────────
221
+ tool('list_menu_bar', 'List an app\'s full menu bar structure with keyboard shortcuts. Use this BEFORE select_menu_item to see what menus / items / shortcuts exist — agents can then press the shortcut directly (faster than walking the menu) or pass the exact item title to select_menu_item.', {
222
+ bundle_id: z.string().describe('Bundle ID of the app whose menu bar to read'),
223
+ }, AX_READ);
224
+ // ── v5: Strategy advisor ────────────────────────────────────────────────
225
+ tool('get_tool_guide', 'Recommend the best automation approach for a task. Call this BEFORE committing to screenshot-and-click — it suggests scripting or accessibility paths when they exist.', {
226
+ task_description: z.string().describe('Natural-language description of the task to automate'),
227
+ }, NONE_READ);
228
+ tool('get_app_capabilities', 'Discover what automation approaches work for an app: scriptable? accessible? running? hidden?', {
229
+ bundle_id: z.string().describe('Bundle ID to probe'),
230
+ }, AX_READ);
231
+ // ── v5: Agent Spaces ────────────────────────────────────────────────────
232
+ // macOS Space mutation uses best-effort backends selected by
233
+ // COMPUTER_USE_SPACES_BACKEND: yabai, Mission Control gestures, then CGS.
234
+ // CGS-created Spaces can be orphaned on SIP-enabled Macs.
235
+ tool('list_spaces', 'List user Spaces grouped by display. Always works — pure read via CGS.', {}, NONE_READ);
236
+ tool('get_active_space', 'Get the currently active Space ID.', {}, NONE_READ);
237
+ tool('create_agent_space', 'Create a new virtual desktop/Space. On macOS, auto-selects yabai, Mission Control gesture automation, or CGS fallback. On Windows uses Ctrl+Win+D keyboard shortcut.', {}, AX_MUT);
238
+ tool('move_window_to_space', 'Move a window to a virtual desktop/Space. On macOS, prefers yabai and falls back to private CGS APIs.', {
239
+ window_id: z.number().int().describe('Window ID to move'),
240
+ space_id: z.number().int().describe('Target Space/desktop ID'),
241
+ }, AX_MUT);
242
+ tool('remove_window_from_space', 'Remove a window from a virtual desktop/Space. Best effort on macOS because private CGS APIs may no-op without elevated entitlements.', {
243
+ window_id: z.number().int().describe('Window ID to remove'),
244
+ space_id: z.number().int().describe('Space/desktop ID to remove the window from'),
245
+ }, AX_MUT);
246
+ tool('destroy_space', 'Close a virtual desktop/Space. On macOS, prefers yabai and falls back to private CGS APIs. On Windows uses Ctrl+Win+F4.', {
247
+ space_id: z.number().int().optional().describe('Space ID to destroy (ignored on Windows — always closes current)'),
248
+ }, AX_MUT);
249
+ // ── v5.2: Tool metadata introspection ───────────────────────────────────
250
+ //
251
+ // This is the only tool that doesn't go through session.dispatch —
252
+ // it reads directly from the toolMeta registry populated by each
253
+ // tool() registration above. Pure read; no side effects.
254
+ server.tool('get_tool_metadata', 'Get structured metadata for a tool: focusRequired (scripting|ax|cgevent|none) and mutates (bool). Useful for agents that want to filter tools by their focus requirements — e.g. "show me only tools I can use while Safari is backgrounded". [focusRequired: none]', { tool_name: z.string().describe('Name of the tool to inspect') }, async (args) => {
255
+ const name = typeof args.tool_name === 'string' ? args.tool_name : '';
256
+ const meta = toolMeta.get(name);
257
+ if (!meta) {
258
+ return {
259
+ content: [{
260
+ type: 'text',
261
+ text: JSON.stringify({ error: 'unknown_tool', tool_name: name }),
262
+ }],
263
+ isError: true,
264
+ };
265
+ }
266
+ return {
267
+ content: [{ type: 'text', text: JSON.stringify({ tool_name: name, ...meta }) }],
268
+ };
269
+ });
270
+ toolMeta.set('get_tool_metadata', { focusRequired: 'none', mutates: false });
271
+ // ── Windows-parity tools (cross-platform where possible) ────────────────
272
+ // FileSystem tool — Node.js fs, cross-platform
273
+ tool('filesystem', 'File and directory operations: read, write, copy, move, delete, list, search, info. Relative paths resolve from Desktop.', {
274
+ mode: z.enum(['read', 'write', 'copy', 'move', 'delete', 'list', 'search', 'info']).describe('Operation mode'),
275
+ path: z.string().describe('File or directory path'),
276
+ destination: z.string().optional().describe('Destination path for copy/move'),
277
+ content: z.string().optional().describe('Content for write mode'),
278
+ pattern: z.string().optional().describe('Glob pattern for list/search'),
279
+ recursive: z.boolean().optional().default(false).describe('Recursive delete/list/search'),
280
+ append: z.boolean().optional().default(false).describe('Append instead of overwrite'),
281
+ overwrite: z.boolean().optional().default(false).describe('Overwrite existing for copy/move'),
282
+ offset: z.number().int().optional().describe('Line offset for read'),
283
+ limit: z.number().int().optional().describe('Line limit for read'),
284
+ encoding: z.string().optional().default('utf-8').describe('File encoding'),
285
+ show_hidden: z.boolean().optional().default(false).describe('Show hidden files in list'),
286
+ }, NONE_MUT);
287
+ // Process tool — list and kill processes
288
+ tool('process_kill', 'List and kill running processes. mode=list for process listing, mode=kill to terminate by name or PID.', {
289
+ mode: z.enum(['list', 'kill']).describe('Operation mode'),
290
+ name: z.string().optional().describe('Process name to filter/kill'),
291
+ pid: z.number().int().optional().describe('Process ID to kill'),
292
+ force: z.boolean().optional().default(false).describe('Force kill without graceful close'),
293
+ sort_by: z.enum(['memory', 'cpu', 'name']).optional().default('memory').describe('Sort field for list'),
294
+ limit: z.number().int().optional().default(20).describe('Max processes to list'),
295
+ }, NONE_MUT);
296
+ // Registry tool — Windows only
297
+ tool('registry', 'Windows Registry operations: get, set, delete, list. Paths use PowerShell format (HKCU:\\Software\\...). Windows only.', {
298
+ mode: z.enum(['get', 'set', 'delete', 'list']).describe('Operation mode'),
299
+ path: z.string().describe('Registry path in PowerShell format'),
300
+ name: z.string().optional().describe('Value name'),
301
+ value: z.string().optional().describe('Value data for set mode'),
302
+ type: z.enum(['String', 'DWord', 'QWord', 'Binary', 'MultiString', 'ExpandString']).optional().default('String').describe('Value type for set'),
303
+ }, NONE_MUT);
304
+ // Notification tool — Windows only
305
+ tool('notification', 'Send a Windows toast notification. Windows only.', {
306
+ title: z.string().describe('Notification title'),
307
+ message: z.string().describe('Notification body text'),
308
+ app_id: z.string().optional().describe('Application User Model ID'),
309
+ }, NONE_MUT);
310
+ // MultiSelect tool — batch click with optional Ctrl hold
311
+ tool('multi_select', 'Select multiple items by clicking coordinates or UI element labels. Set press_ctrl=true for additive selection.', {
312
+ locs: z.array(z.tuple([z.number(), z.number()])).optional().describe('List of [x,y] coordinates'),
313
+ labels: z.array(z.string()).optional().describe('List of UI element labels'),
314
+ press_ctrl: z.boolean().optional().default(true).describe('Hold Ctrl for additive selection'),
315
+ target_app: targetAppParam,
316
+ target_window_id: targetWindowIdParam,
317
+ focus_strategy: focusStrategyParam,
318
+ }, CG_MUT);
319
+ // MultiEdit tool — batch click+type
320
+ tool('multi_edit', 'Enter text into multiple fields. Provide locs as [[x,y,text],...] or labels as [[label,text],...].', {
321
+ locs: z.array(z.tuple([z.number(), z.number(), z.string()])).optional().describe('List of [x,y,text] tuples'),
322
+ labels: z.array(z.tuple([z.string(), z.string()])).optional().describe('List of [label,text] tuples'),
323
+ target_app: targetAppParam,
324
+ target_window_id: targetWindowIdParam,
325
+ focus_strategy: focusStrategyParam,
326
+ }, CG_MUT);
327
+ // Scrape tool — fetch web page content
328
+ tool('scrape', 'Fetch and extract content from a URL. Returns clean text from web pages. Set use_dom=true to extract from active browser tab DOM instead of HTTP fetch.', {
329
+ url: z.string().describe('URL to fetch'),
330
+ query: z.string().optional().describe('Focus extraction on specific information'),
331
+ use_dom: z.boolean().optional().default(false).describe('Extract from active browser tab DOM instead of HTTP'),
332
+ }, NONE_READ);
333
+ return server;
334
+ }
335
+ // Standalone stdio entrypoint. Detection lives in ./entrypoint.ts so it is
336
+ // unit-testable without loading the native NAPI binary.
337
+ if (isStdioEntrypoint(process.argv[1])) {
338
+ const server = createComputerUseServer();
339
+ const transport = new StdioServerTransport();
340
+ server.connect(transport).then(() => console.error('[computer-use-mcp] Server running'))
341
+ .catch(err => { console.error('Fatal:', err); process.exit(1); });
342
+ }