@wootsup/yt-builder-mcp 1.1.6 → 1.2.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.
- package/README.md +7 -7
- package/bin/yt-builder-mcp.js +55 -40
- package/dist/auth.d.ts +137 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +244 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/invocation-decision.d.ts +57 -0
- package/dist/cli/invocation-decision.d.ts.map +1 -0
- package/dist/cli/invocation-decision.js +86 -0
- package/dist/cli/invocation-decision.js.map +1 -0
- package/dist/client.d.ts +112 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +190 -0
- package/dist/client.js.map +1 -0
- package/dist/clients/claude-code.d.ts +18 -0
- package/dist/clients/claude-code.d.ts.map +1 -0
- package/dist/clients/claude-code.js +55 -0
- package/dist/clients/claude-code.js.map +1 -0
- package/dist/clients/claude-desktop.d.ts +19 -0
- package/dist/clients/claude-desktop.d.ts.map +1 -0
- package/dist/clients/claude-desktop.js +58 -0
- package/dist/clients/claude-desktop.js.map +1 -0
- package/dist/clients/cline.d.ts +26 -0
- package/dist/clients/cline.d.ts.map +1 -0
- package/dist/clients/cline.js +82 -0
- package/dist/clients/cline.js.map +1 -0
- package/dist/clients/codex-cli.d.ts +42 -0
- package/dist/clients/codex-cli.d.ts.map +1 -0
- package/dist/clients/codex-cli.js +292 -0
- package/dist/clients/codex-cli.js.map +1 -0
- package/dist/clients/continue.d.ts +13 -0
- package/dist/clients/continue.d.ts.map +1 -0
- package/dist/clients/continue.js +121 -0
- package/dist/clients/continue.js.map +1 -0
- package/dist/clients/cursor.d.ts +12 -0
- package/dist/clients/cursor.d.ts.map +1 -0
- package/dist/clients/cursor.js +40 -0
- package/dist/clients/cursor.js.map +1 -0
- package/dist/clients/gemini-cli.d.ts +18 -0
- package/dist/clients/gemini-cli.d.ts.map +1 -0
- package/dist/clients/gemini-cli.js +46 -0
- package/dist/clients/gemini-cli.js.map +1 -0
- package/dist/clients/home.d.ts +14 -0
- package/dist/clients/home.d.ts.map +1 -0
- package/dist/clients/home.js +20 -0
- package/dist/clients/home.js.map +1 -0
- package/dist/clients/index.d.ts +156 -0
- package/dist/clients/index.d.ts.map +1 -0
- package/dist/clients/index.js +213 -0
- package/dist/clients/index.js.map +1 -0
- package/dist/clients/roo-code.d.ts +23 -0
- package/dist/clients/roo-code.d.ts.map +1 -0
- package/dist/clients/roo-code.js +71 -0
- package/dist/clients/roo-code.js.map +1 -0
- package/dist/clients/zed.d.ts +12 -0
- package/dist/clients/zed.d.ts.map +1 -0
- package/dist/clients/zed.js +43 -0
- package/dist/clients/zed.js.map +1 -0
- package/dist/errors/hints.d.ts +51 -0
- package/dist/errors/hints.d.ts.map +1 -0
- package/dist/errors/hints.js +95 -0
- package/dist/errors/hints.js.map +1 -0
- package/dist/errors/mask.d.ts +35 -0
- package/dist/errors/mask.d.ts.map +1 -0
- package/dist/errors/mask.js +49 -0
- package/dist/errors/mask.js.map +1 -0
- package/dist/errors/sanitize.d.ts +31 -0
- package/dist/errors/sanitize.d.ts.map +1 -0
- package/dist/errors/sanitize.js +100 -0
- package/dist/errors/sanitize.js.map +1 -0
- package/dist/errors.d.ts +42 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +61 -0
- package/dist/errors.js.map +1 -0
- package/dist/gateway/advanced-tool/discovery.d.ts +19 -0
- package/dist/gateway/advanced-tool/discovery.d.ts.map +1 -0
- package/dist/gateway/advanced-tool/discovery.js +53 -0
- package/dist/gateway/advanced-tool/discovery.js.map +1 -0
- package/dist/gateway/advanced-tool/domains.d.ts +47 -0
- package/dist/gateway/advanced-tool/domains.d.ts.map +1 -0
- package/dist/gateway/advanced-tool/domains.js +94 -0
- package/dist/gateway/advanced-tool/domains.js.map +1 -0
- package/dist/gateway/advanced-tool/execute.d.ts +29 -0
- package/dist/gateway/advanced-tool/execute.d.ts.map +1 -0
- package/dist/gateway/advanced-tool/execute.js +54 -0
- package/dist/gateway/advanced-tool/execute.js.map +1 -0
- package/dist/gateway/advanced-tool/index.d.ts +36 -0
- package/dist/gateway/advanced-tool/index.d.ts.map +1 -0
- package/dist/gateway/advanced-tool/index.js +39 -0
- package/dist/gateway/advanced-tool/index.js.map +1 -0
- package/dist/gateway/advanced-tool/register.d.ts +18 -0
- package/dist/gateway/advanced-tool/register.d.ts.map +1 -0
- package/dist/gateway/advanced-tool/register.js +69 -0
- package/dist/gateway/advanced-tool/register.js.map +1 -0
- package/dist/gateway/advanced-tool.d.ts +13 -0
- package/dist/gateway/advanced-tool.d.ts.map +1 -0
- package/dist/gateway/advanced-tool.js +13 -0
- package/dist/gateway/advanced-tool.js.map +1 -0
- package/dist/gateway/capturing-server.d.ts +117 -0
- package/dist/gateway/capturing-server.d.ts.map +1 -0
- package/dist/gateway/capturing-server.js +103 -0
- package/dist/gateway/capturing-server.js.map +1 -0
- package/dist/gateway/essentials.d.ts +50 -0
- package/dist/gateway/essentials.d.ts.map +1 -0
- package/dist/gateway/essentials.js +108 -0
- package/dist/gateway/essentials.js.map +1 -0
- package/dist/gateway/test-support.d.ts +41 -0
- package/dist/gateway/test-support.d.ts.map +1 -0
- package/dist/gateway/test-support.js +60 -0
- package/dist/gateway/test-support.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -0
- package/dist/install-skill.d.ts +43 -0
- package/dist/install-skill.d.ts.map +1 -0
- package/dist/install-skill.js +118 -0
- package/dist/install-skill.js.map +1 -0
- package/dist/platform/detect.d.ts +64 -0
- package/dist/platform/detect.d.ts.map +1 -0
- package/dist/platform/detect.js +98 -0
- package/dist/platform/detect.js.map +1 -0
- package/dist/platform/index.d.ts +121 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +176 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/joomla.d.ts +44 -0
- package/dist/platform/joomla.d.ts.map +1 -0
- package/dist/platform/joomla.js +46 -0
- package/dist/platform/joomla.js.map +1 -0
- package/dist/server.d.ts +110 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +274 -0
- package/dist/server.js.map +1 -0
- package/dist/setup-cli-confirm.d.ts +36 -0
- package/dist/setup-cli-confirm.d.ts.map +1 -0
- package/dist/setup-cli-confirm.js +59 -0
- package/dist/setup-cli-confirm.js.map +1 -0
- package/dist/setup-cli.d.ts +193 -0
- package/dist/setup-cli.d.ts.map +1 -0
- package/dist/setup-cli.js +1032 -0
- package/dist/setup-cli.js.map +1 -0
- package/dist/setup-prompts.d.ts +64 -0
- package/dist/setup-prompts.d.ts.map +1 -0
- package/dist/setup-prompts.js +221 -0
- package/dist/setup-prompts.js.map +1 -0
- package/dist/setup-token.d.ts +38 -0
- package/dist/setup-token.d.ts.map +1 -0
- package/dist/setup-token.js +106 -0
- package/dist/setup-token.js.map +1 -0
- package/dist/setup-wizard-defaults.d.ts +43 -0
- package/dist/setup-wizard-defaults.d.ts.map +1 -0
- package/dist/setup-wizard-defaults.js +160 -0
- package/dist/setup-wizard-defaults.js.map +1 -0
- package/dist/setup-wizard-handshake.d.ts +25 -0
- package/dist/setup-wizard-handshake.d.ts.map +1 -0
- package/dist/setup-wizard-handshake.js +103 -0
- package/dist/setup-wizard-handshake.js.map +1 -0
- package/dist/setup-wizard-types.d.ts +164 -0
- package/dist/setup-wizard-types.d.ts.map +1 -0
- package/dist/setup-wizard-types.js +11 -0
- package/dist/setup-wizard-types.js.map +1 -0
- package/dist/setup-wizard.d.ts +33 -0
- package/dist/setup-wizard.d.ts.map +1 -0
- package/dist/setup-wizard.js +199 -0
- package/dist/setup-wizard.js.map +1 -0
- package/dist/setup.d.ts +17 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +33 -0
- package/dist/setup.js.map +1 -0
- package/dist/sites/bootstrap.d.ts +41 -0
- package/dist/sites/bootstrap.d.ts.map +1 -0
- package/dist/sites/bootstrap.js +58 -0
- package/dist/sites/bootstrap.js.map +1 -0
- package/dist/sites/cli/add-site.d.ts +106 -0
- package/dist/sites/cli/add-site.d.ts.map +1 -0
- package/dist/sites/cli/add-site.js +185 -0
- package/dist/sites/cli/add-site.js.map +1 -0
- package/dist/sites/cli/list-sites.d.ts +40 -0
- package/dist/sites/cli/list-sites.d.ts.map +1 -0
- package/dist/sites/cli/list-sites.js +116 -0
- package/dist/sites/cli/list-sites.js.map +1 -0
- package/dist/sites/cli/remove-site.d.ts +60 -0
- package/dist/sites/cli/remove-site.d.ts.map +1 -0
- package/dist/sites/cli/remove-site.js +120 -0
- package/dist/sites/cli/remove-site.js.map +1 -0
- package/dist/sites/cli/set-default.d.ts +47 -0
- package/dist/sites/cli/set-default.d.ts.map +1 -0
- package/dist/sites/cli/set-default.js +69 -0
- package/dist/sites/cli/set-default.js.map +1 -0
- package/dist/sites/cli/test-site.d.ts +77 -0
- package/dist/sites/cli/test-site.d.ts.map +1 -0
- package/dist/sites/cli/test-site.js +146 -0
- package/dist/sites/cli/test-site.js.map +1 -0
- package/dist/sites/client-pool.d.ts +157 -0
- package/dist/sites/client-pool.d.ts.map +1 -0
- package/dist/sites/client-pool.js +222 -0
- package/dist/sites/client-pool.js.map +1 -0
- package/dist/sites/env-bridge.d.ts +55 -0
- package/dist/sites/env-bridge.d.ts.map +1 -0
- package/dist/sites/env-bridge.js +94 -0
- package/dist/sites/env-bridge.js.map +1 -0
- package/dist/sites/paths.d.ts +21 -0
- package/dist/sites/paths.d.ts.map +1 -0
- package/dist/sites/paths.js +37 -0
- package/dist/sites/paths.js.map +1 -0
- package/dist/sites/probe.d.ts +60 -0
- package/dist/sites/probe.d.ts.map +1 -0
- package/dist/sites/probe.js +112 -0
- package/dist/sites/probe.js.map +1 -0
- package/dist/sites/registry.d.ts +142 -0
- package/dist/sites/registry.d.ts.map +1 -0
- package/dist/sites/registry.js +163 -0
- package/dist/sites/registry.js.map +1 -0
- package/dist/sites/schema.d.ts +90 -0
- package/dist/sites/schema.d.ts.map +1 -0
- package/dist/sites/schema.js +71 -0
- package/dist/sites/schema.js.map +1 -0
- package/dist/sites/secret-resolver.d.ts +115 -0
- package/dist/sites/secret-resolver.d.ts.map +1 -0
- package/dist/sites/secret-resolver.js +225 -0
- package/dist/sites/secret-resolver.js.map +1 -0
- package/dist/sites/store.d.ts +82 -0
- package/dist/sites/store.d.ts.map +1 -0
- package/dist/sites/store.js +198 -0
- package/dist/sites/store.js.map +1 -0
- package/dist/sites/tools/index.d.ts +28 -0
- package/dist/sites/tools/index.d.ts.map +1 -0
- package/dist/sites/tools/index.js +38 -0
- package/dist/sites/tools/index.js.map +1 -0
- package/dist/sites/tools/sites-list.d.ts +48 -0
- package/dist/sites/tools/sites-list.d.ts.map +1 -0
- package/dist/sites/tools/sites-list.js +137 -0
- package/dist/sites/tools/sites-list.js.map +1 -0
- package/dist/sites/tools/sites-test.d.ts +47 -0
- package/dist/sites/tools/sites-test.d.ts.map +1 -0
- package/dist/sites/tools/sites-test.js +148 -0
- package/dist/sites/tools/sites-test.js.map +1 -0
- package/dist/sites/tools/use-site.d.ts +47 -0
- package/dist/sites/tools/use-site.d.ts.map +1 -0
- package/dist/sites/tools/use-site.js +183 -0
- package/dist/sites/tools/use-site.js.map +1 -0
- package/dist/skill-loader.d.ts +111 -0
- package/dist/skill-loader.d.ts.map +1 -0
- package/dist/skill-loader.js +191 -0
- package/dist/skill-loader.js.map +1 -0
- package/dist/tools/elements/builders.d.ts +24 -0
- package/dist/tools/elements/builders.d.ts.map +1 -0
- package/dist/tools/elements/builders.js +208 -0
- package/dist/tools/elements/builders.js.map +1 -0
- package/dist/tools/elements/handlers-write.d.ts +49 -0
- package/dist/tools/elements/handlers-write.d.ts.map +1 -0
- package/dist/tools/elements/handlers-write.js +341 -0
- package/dist/tools/elements/handlers-write.js.map +1 -0
- package/dist/tools/elements/handlers.d.ts +70 -0
- package/dist/tools/elements/handlers.d.ts.map +1 -0
- package/dist/tools/elements/handlers.js +292 -0
- package/dist/tools/elements/handlers.js.map +1 -0
- package/dist/tools/elements/index.d.ts +28 -0
- package/dist/tools/elements/index.d.ts.map +1 -0
- package/dist/tools/elements/index.js +27 -0
- package/dist/tools/elements/index.js.map +1 -0
- package/dist/tools/elements.d.ts +13 -0
- package/dist/tools/elements.d.ts.map +1 -0
- package/dist/tools/elements.js +13 -0
- package/dist/tools/elements.js.map +1 -0
- package/dist/tools/elicitation.d.ts +87 -0
- package/dist/tools/elicitation.d.ts.map +1 -0
- package/dist/tools/elicitation.js +100 -0
- package/dist/tools/elicitation.js.map +1 -0
- package/dist/tools/format/elements-format.d.ts +40 -0
- package/dist/tools/format/elements-format.d.ts.map +1 -0
- package/dist/tools/format/elements-format.js +193 -0
- package/dist/tools/format/elements-format.js.map +1 -0
- package/dist/tools/format/health-format.d.ts +79 -0
- package/dist/tools/format/health-format.d.ts.map +1 -0
- package/dist/tools/format/health-format.js +181 -0
- package/dist/tools/format/health-format.js.map +1 -0
- package/dist/tools/format/inspection-format.d.ts +70 -0
- package/dist/tools/format/inspection-format.d.ts.map +1 -0
- package/dist/tools/format/inspection-format.js +359 -0
- package/dist/tools/format/inspection-format.js.map +1 -0
- package/dist/tools/format/pages-format.d.ts +57 -0
- package/dist/tools/format/pages-format.d.ts.map +1 -0
- package/dist/tools/format/pages-format.js +157 -0
- package/dist/tools/format/pages-format.js.map +1 -0
- package/dist/tools/format/sources-format.d.ts +44 -0
- package/dist/tools/format/sources-format.d.ts.map +1 -0
- package/dist/tools/format/sources-format.js +242 -0
- package/dist/tools/format/sources-format.js.map +1 -0
- package/dist/tools/health.d.ts +22 -0
- package/dist/tools/health.d.ts.map +1 -0
- package/dist/tools/health.js +220 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/index.d.ts +30 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +39 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inspection.d.ts +14 -0
- package/dist/tools/inspection.d.ts.map +1 -0
- package/dist/tools/inspection.js +401 -0
- package/dist/tools/inspection.js.map +1 -0
- package/dist/tools/layout-flatten.d.ts +75 -0
- package/dist/tools/layout-flatten.d.ts.map +1 -0
- package/dist/tools/layout-flatten.js +107 -0
- package/dist/tools/layout-flatten.js.map +1 -0
- package/dist/tools/multi-items/builders.d.ts +23 -0
- package/dist/tools/multi-items/builders.d.ts.map +1 -0
- package/dist/tools/multi-items/builders.js +84 -0
- package/dist/tools/multi-items/builders.js.map +1 -0
- package/dist/tools/multi-items/clean-implode-handler.d.ts +36 -0
- package/dist/tools/multi-items/clean-implode-handler.d.ts.map +1 -0
- package/dist/tools/multi-items/clean-implode-handler.js +57 -0
- package/dist/tools/multi-items/clean-implode-handler.js.map +1 -0
- package/dist/tools/multi-items/format/inspection-format.d.ts +41 -0
- package/dist/tools/multi-items/format/inspection-format.d.ts.map +1 -0
- package/dist/tools/multi-items/format/inspection-format.js +64 -0
- package/dist/tools/multi-items/format/inspection-format.js.map +1 -0
- package/dist/tools/multi-items/index.d.ts +18 -0
- package/dist/tools/multi-items/index.d.ts.map +1 -0
- package/dist/tools/multi-items/index.js +18 -0
- package/dist/tools/multi-items/index.js.map +1 -0
- package/dist/tools/multi-items/inspect-handler.d.ts +76 -0
- package/dist/tools/multi-items/inspect-handler.d.ts.map +1 -0
- package/dist/tools/multi-items/inspect-handler.js +133 -0
- package/dist/tools/multi-items/inspect-handler.js.map +1 -0
- package/dist/tools/multi-items/inspection-cache.d.ts +85 -0
- package/dist/tools/multi-items/inspection-cache.d.ts.map +1 -0
- package/dist/tools/multi-items/inspection-cache.js +126 -0
- package/dist/tools/multi-items/inspection-cache.js.map +1 -0
- package/dist/tools/multi-items/item-container-map.d.ts +41 -0
- package/dist/tools/multi-items/item-container-map.d.ts.map +1 -0
- package/dist/tools/multi-items/item-container-map.js +73 -0
- package/dist/tools/multi-items/item-container-map.js.map +1 -0
- package/dist/tools/pages/builders.d.ts +43 -0
- package/dist/tools/pages/builders.d.ts.map +1 -0
- package/dist/tools/pages/builders.js +229 -0
- package/dist/tools/pages/builders.js.map +1 -0
- package/dist/tools/pages/handlers-read.d.ts +33 -0
- package/dist/tools/pages/handlers-read.d.ts.map +1 -0
- package/dist/tools/pages/handlers-read.js +260 -0
- package/dist/tools/pages/handlers-read.js.map +1 -0
- package/dist/tools/pages/handlers-write.d.ts +63 -0
- package/dist/tools/pages/handlers-write.d.ts.map +1 -0
- package/dist/tools/pages/handlers-write.js +127 -0
- package/dist/tools/pages/handlers-write.js.map +1 -0
- package/dist/tools/pages/index.d.ts +17 -0
- package/dist/tools/pages/index.d.ts.map +1 -0
- package/dist/tools/pages/index.js +17 -0
- package/dist/tools/pages/index.js.map +1 -0
- package/dist/tools/pages/schemas.d.ts +157 -0
- package/dist/tools/pages/schemas.d.ts.map +1 -0
- package/dist/tools/pages/schemas.js +232 -0
- package/dist/tools/pages/schemas.js.map +1 -0
- package/dist/tools/pages.d.ts +13 -0
- package/dist/tools/pages.d.ts.map +1 -0
- package/dist/tools/pages.js +13 -0
- package/dist/tools/pages.js.map +1 -0
- package/dist/tools/pool-resolve-helper.d.ts +83 -0
- package/dist/tools/pool-resolve-helper.d.ts.map +1 -0
- package/dist/tools/pool-resolve-helper.js +148 -0
- package/dist/tools/pool-resolve-helper.js.map +1 -0
- package/dist/tools/progress-phases.d.ts +46 -0
- package/dist/tools/progress-phases.d.ts.map +1 -0
- package/dist/tools/progress-phases.js +48 -0
- package/dist/tools/progress-phases.js.map +1 -0
- package/dist/tools/shared-schemas.d.ts +25 -0
- package/dist/tools/shared-schemas.d.ts.map +1 -0
- package/dist/tools/shared-schemas.js +72 -0
- package/dist/tools/shared-schemas.js.map +1 -0
- package/dist/tools/sources/builders.d.ts +13 -0
- package/dist/tools/sources/builders.d.ts.map +1 -0
- package/dist/tools/sources/builders.js +118 -0
- package/dist/tools/sources/builders.js.map +1 -0
- package/dist/tools/sources/handlers-bind.d.ts +28 -0
- package/dist/tools/sources/handlers-bind.d.ts.map +1 -0
- package/dist/tools/sources/handlers-bind.js +181 -0
- package/dist/tools/sources/handlers-bind.js.map +1 -0
- package/dist/tools/sources/handlers.d.ts +47 -0
- package/dist/tools/sources/handlers.d.ts.map +1 -0
- package/dist/tools/sources/handlers.js +108 -0
- package/dist/tools/sources/handlers.js.map +1 -0
- package/dist/tools/sources/index.d.ts +19 -0
- package/dist/tools/sources/index.d.ts.map +1 -0
- package/dist/tools/sources/index.js +18 -0
- package/dist/tools/sources/index.js.map +1 -0
- package/dist/tools/sources.d.ts +14 -0
- package/dist/tools/sources.d.ts.map +1 -0
- package/dist/tools/sources.js +14 -0
- package/dist/tools/sources.js.map +1 -0
- package/dist/tools/sparse-fields.d.ts +106 -0
- package/dist/tools/sparse-fields.d.ts.map +1 -0
- package/dist/tools/sparse-fields.js +165 -0
- package/dist/tools/sparse-fields.js.map +1 -0
- package/dist/tools/tool-builder/annotations.d.ts +55 -0
- package/dist/tools/tool-builder/annotations.d.ts.map +1 -0
- package/dist/tools/tool-builder/annotations.js +86 -0
- package/dist/tools/tool-builder/annotations.js.map +1 -0
- package/dist/tools/tool-builder/define.d.ts +31 -0
- package/dist/tools/tool-builder/define.d.ts.map +1 -0
- package/dist/tools/tool-builder/define.js +31 -0
- package/dist/tools/tool-builder/define.js.map +1 -0
- package/dist/tools/tool-builder/index.d.ts +28 -0
- package/dist/tools/tool-builder/index.d.ts.map +1 -0
- package/dist/tools/tool-builder/index.js +27 -0
- package/dist/tools/tool-builder/index.js.map +1 -0
- package/dist/tools/tool-builder/results.d.ts +104 -0
- package/dist/tools/tool-builder/results.d.ts.map +1 -0
- package/dist/tools/tool-builder/results.js +224 -0
- package/dist/tools/tool-builder/results.js.map +1 -0
- package/dist/tools/tool-builder/types.d.ts +97 -0
- package/dist/tools/tool-builder/types.d.ts.map +1 -0
- package/dist/tools/tool-builder/types.js +9 -0
- package/dist/tools/tool-builder/types.js.map +1 -0
- package/dist/tools/tool-builder.d.ts +16 -0
- package/dist/tools/tool-builder.d.ts.map +1 -0
- package/dist/tools/tool-builder.js +16 -0
- package/dist/tools/tool-builder.js.map +1 -0
- package/dist/uninstall-skill.d.ts +52 -0
- package/dist/uninstall-skill.d.ts.map +1 -0
- package/dist/uninstall-skill.js +146 -0
- package/dist/uninstall-skill.js.map +1 -0
- package/dist/uninstall.d.ts +73 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +82 -0
- package/dist/uninstall.js.map +1 -0
- package/icon.png +0 -0
- package/manifest.json +10 -10
- package/package.json +4 -1
- package/skills/yt-builder-mcp/SKILL.md +30 -26
|
@@ -0,0 +1,1032 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Top-level CLI dispatcher for `@wootsup/yt-builder-mcp`.
|
|
4
|
+
*
|
|
5
|
+
* Round-1 audit I5 fix (2026-05-22): the wizard implementation lives in
|
|
6
|
+
* `setup-wizard.ts`; this file is the thin dispatcher (`runCli`) plus
|
|
7
|
+
* the ESM main-guard. Both have their own deps-bag (`WizardDeps` /
|
|
8
|
+
* `RunCliDeps`) so unit tests can drive them independently.
|
|
9
|
+
*
|
|
10
|
+
* Subcommands:
|
|
11
|
+
*
|
|
12
|
+
* setup (default) — runWizard (see `setup-wizard.ts`)
|
|
13
|
+
* install-skill — copy the bundled skill into ~/.claude/skills/
|
|
14
|
+
* and append a marker block to ~/AGENTS.md.
|
|
15
|
+
* --help / help — print usage.
|
|
16
|
+
* --version / -v — print the package version.
|
|
17
|
+
*
|
|
18
|
+
* Re-exports `runWizard`, `majorMinor` and the wizard public types so
|
|
19
|
+
* existing callers (and tests that already import from `./setup-cli`)
|
|
20
|
+
* keep working with a one-line import.
|
|
21
|
+
*
|
|
22
|
+
* @license MIT
|
|
23
|
+
*/
|
|
24
|
+
import { ALL_CLIENTS } from './clients/index.js';
|
|
25
|
+
import { installSkill as defaultInstallSkill } from './install-skill.js';
|
|
26
|
+
import { SERVER_VERSION } from './server.js';
|
|
27
|
+
import { confirmTTY as defaultConfirmTTY } from './setup-cli-confirm.js';
|
|
28
|
+
import { defaultUninstallPrompt } from './setup-prompts.js';
|
|
29
|
+
import { DEFAULT_WIZARD_DEPS, runWizard as runWizardImpl } from './setup-wizard.js';
|
|
30
|
+
import { detectInstalledClients as defaultDetectInstalled, DEFAULT_UNINSTALL_DEPS, runUninstall, } from './uninstall.js';
|
|
31
|
+
import { addSiteCommand, AddSiteError, DEFAULT_ADD_SITE_DEPS, } from './sites/cli/add-site.js';
|
|
32
|
+
import { DEFAULT_LIST_SITES_DEPS, listSitesCommand, } from './sites/cli/list-sites.js';
|
|
33
|
+
import { DEFAULT_REMOVE_SITE_DEPS, removeSiteCommand, RemoveSiteError, } from './sites/cli/remove-site.js';
|
|
34
|
+
import { DEFAULT_SET_DEFAULT_DEPS, setDefaultCommand, SetDefaultError, } from './sites/cli/set-default.js';
|
|
35
|
+
import { DEFAULT_TEST_SITE_DEPS, renderTestSiteLines, testSiteCommand, TestSiteError, } from './sites/cli/test-site.js';
|
|
36
|
+
import { defaultSitesFilePath } from './sites/paths.js';
|
|
37
|
+
// Re-export the wizard surface so consumers that imported from
|
|
38
|
+
// `./setup-cli` before the I5 split keep working without changes.
|
|
39
|
+
export { DEFAULT_WIZARD_DEPS, majorMinor, runWizard, } from './setup-wizard.js';
|
|
40
|
+
const HELP_TEXT = `Usage: yt-builder-mcp <command> [flags]
|
|
41
|
+
|
|
42
|
+
Commands:
|
|
43
|
+
setup Interactive first-run wizard (default if no command)
|
|
44
|
+
install-skill Copy the bundled YOOtheme Builder skill into
|
|
45
|
+
~/.claude/skills/ and register it in ~/AGENTS.md.
|
|
46
|
+
Note: ~/.claude/skills/ is the universal-marker path
|
|
47
|
+
recognised by Claude Desktop and other AI clients.
|
|
48
|
+
uninstall Reverse of setup: pick which AI clients to remove the
|
|
49
|
+
(alias: remove) yt-builder-mcp server entry from (interactive checklist,
|
|
50
|
+
all detected clients pre-checked) and optionally remove
|
|
51
|
+
the installed skill. Flags: --all (every detected client
|
|
52
|
+
+ skill, no prompts), --yes/-y (skip the final confirm).
|
|
53
|
+
|
|
54
|
+
Multi-site commands (W9):
|
|
55
|
+
add-site Add a site to ~/.config/yt-builder-mcp/sites.json.
|
|
56
|
+
Flags: --url <url>, --token <bearer> OR --token-ref
|
|
57
|
+
<op://...>, --platform auto|wordpress|joomla,
|
|
58
|
+
--label "...", --site-id <slug>, --default, --yes.
|
|
59
|
+
list-sites Show the configured sites (no network calls).
|
|
60
|
+
remove-site <id> Remove a site; auto-promotes the next as default.
|
|
61
|
+
Flag: --yes to skip the confirmation prompt.
|
|
62
|
+
set-default <id> Flip is_default to the given site_id.
|
|
63
|
+
test-site <id> Probe /health (no auth) + /etag (auth) for one site.
|
|
64
|
+
|
|
65
|
+
--version, -v Print the package version.
|
|
66
|
+
--help, -h, help Show this message.
|
|
67
|
+
|
|
68
|
+
Setup flags (for non-interactive / CI usage):
|
|
69
|
+
--non-interactive Skip all prompts; fail-fast on missing input.
|
|
70
|
+
--url <site-url> Site base URL (required with --non-interactive).
|
|
71
|
+
WordPress or Joomla — the wizard auto-detects the
|
|
72
|
+
platform from the URL shape.
|
|
73
|
+
--token <bearer> Bearer key (required with --non-interactive).
|
|
74
|
+
--client <id> AI client id to configure; repeatable. Valid ids:
|
|
75
|
+
claude-desktop, claude-code, cursor, zed, continue,
|
|
76
|
+
cline, roo-code, codex-cli, gemini-cli.
|
|
77
|
+
|
|
78
|
+
Example (non-interactive):
|
|
79
|
+
npx -y @wootsup/yt-builder-mcp setup \\
|
|
80
|
+
--non-interactive \\
|
|
81
|
+
--client cursor --client claude-desktop \\
|
|
82
|
+
--url https://example.com \\
|
|
83
|
+
--token "$YTB_TOKEN"
|
|
84
|
+
|
|
85
|
+
Pickup mode (one-click setup from the admin "Setup wizard" flow):
|
|
86
|
+
--pickup <url> Pickup URL revealed by the host CMS admin (WordPress:
|
|
87
|
+
wp-admin → Tools → "YT Builder MCP"; Joomla:
|
|
88
|
+
Administrator → Components → "YT Builder MCP").
|
|
89
|
+
WordPress: https://example.com/wp-json/yt-builder-mcp/v1/setup/pickup
|
|
90
|
+
Joomla: https://example.com/api/index.php/v1/yt-builder-mcp/setup/pickup
|
|
91
|
+
--nonce <code> One-shot nonce revealed alongside the pickup URL.
|
|
92
|
+
Pairs 1:1 with --pickup (both or neither).
|
|
93
|
+
|
|
94
|
+
When --pickup + --nonce are passed, the wizard fetches the freshly-minted
|
|
95
|
+
Bearer + canonical URL from the plugin in a single POST and skips the
|
|
96
|
+
URL/token prompts entirely. The pickup is IP-bound, single-use, and
|
|
97
|
+
expires after 5 minutes. If --url or --token are also passed they are
|
|
98
|
+
ignored (a warning is printed to stderr).
|
|
99
|
+
|
|
100
|
+
Example (pickup — WordPress):
|
|
101
|
+
npx -y @wootsup/yt-builder-mcp setup \\
|
|
102
|
+
--pickup https://example.com/wp-json/yt-builder-mcp/v1/setup/pickup \\
|
|
103
|
+
--nonce "$NONCE" \\
|
|
104
|
+
--client claude-desktop
|
|
105
|
+
|
|
106
|
+
Example (pickup — Joomla):
|
|
107
|
+
npx -y @wootsup/yt-builder-mcp setup \\
|
|
108
|
+
--pickup https://example.com/api/index.php/v1/yt-builder-mcp/setup/pickup \\
|
|
109
|
+
--nonce "$NONCE" \\
|
|
110
|
+
--client claude-desktop
|
|
111
|
+
|
|
112
|
+
Environment (when launched by an AI client):
|
|
113
|
+
YTB_MCP_SITE_URL Host CMS base URL (e.g. https://example.com).
|
|
114
|
+
Works for BOTH WordPress and Joomla.
|
|
115
|
+
YTB_MCP_WP_URL DEPRECATED alias for YTB_MCP_SITE_URL — still
|
|
116
|
+
honoured for pre-Wave-7 configurations.
|
|
117
|
+
YTB_MCP_BEARER_TOKEN Bearer key from:
|
|
118
|
+
- WordPress: wp-admin → Tools → "YT Builder MCP"
|
|
119
|
+
- Joomla: Administrator → Components → "YT Builder MCP"
|
|
120
|
+
Format: ytb_(live|test)_<payload>.<signature>
|
|
121
|
+
YTB_MCP_PLATFORM Optional explicit platform: 'wordpress' or 'joomla'.
|
|
122
|
+
Set this to 'joomla' when YTB_MCP_SITE_URL is an
|
|
123
|
+
origin-only Joomla URL (no /api/index.php/ in path).
|
|
124
|
+
Defaults to URL-shape auto-detection.
|
|
125
|
+
YTB_MCP_TEST_MODE=1 Print the registered tool list to stderr and exit 0
|
|
126
|
+
without starting the stdio loop (smoke-test probe).
|
|
127
|
+
|
|
128
|
+
Documentation: https://github.com/wootsup/yt-builder-mcp
|
|
129
|
+
`;
|
|
130
|
+
/**
|
|
131
|
+
* Parse the `setup` subcommand argv tail. Pure function; does no I/O.
|
|
132
|
+
*
|
|
133
|
+
* Accepts both `--key value` and `--key=value` styles. Unknown flags
|
|
134
|
+
* are reported as errors so typos don't silently disable validation.
|
|
135
|
+
*/
|
|
136
|
+
export function parseSetupArgs(argv) {
|
|
137
|
+
let nonInteractive = false;
|
|
138
|
+
let url = '';
|
|
139
|
+
let token = '';
|
|
140
|
+
let pickup = '';
|
|
141
|
+
let nonce = '';
|
|
142
|
+
const clients = [];
|
|
143
|
+
const errors = [];
|
|
144
|
+
const warnings = [];
|
|
145
|
+
function consumeValue(name, inline, i) {
|
|
146
|
+
if (inline !== undefined) {
|
|
147
|
+
return { value: inline, nextIndex: i };
|
|
148
|
+
}
|
|
149
|
+
const next = argv[i + 1];
|
|
150
|
+
if (next === undefined || next.startsWith('--')) {
|
|
151
|
+
errors.push(`Flag ${name} requires a value.`);
|
|
152
|
+
return { value: '', nextIndex: i };
|
|
153
|
+
}
|
|
154
|
+
return { value: next, nextIndex: i + 1 };
|
|
155
|
+
}
|
|
156
|
+
for (let i = 0; i < argv.length; i++) {
|
|
157
|
+
const raw = argv[i];
|
|
158
|
+
const eq = raw.indexOf('=');
|
|
159
|
+
const flag = eq >= 0 ? raw.slice(0, eq) : raw;
|
|
160
|
+
const inline = eq >= 0 ? raw.slice(eq + 1) : undefined;
|
|
161
|
+
switch (flag) {
|
|
162
|
+
case '--non-interactive': {
|
|
163
|
+
nonInteractive = true;
|
|
164
|
+
if (inline !== undefined) {
|
|
165
|
+
errors.push('Flag --non-interactive does not take a value.');
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case '--url': {
|
|
170
|
+
const { value, nextIndex } = consumeValue('--url', inline, i);
|
|
171
|
+
url = value.trim().replace(/\/+$/, '');
|
|
172
|
+
i = nextIndex;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case '--token': {
|
|
176
|
+
const { value, nextIndex } = consumeValue('--token', inline, i);
|
|
177
|
+
token = value.trim();
|
|
178
|
+
i = nextIndex;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
case '--pickup': {
|
|
182
|
+
const { value, nextIndex } = consumeValue('--pickup', inline, i);
|
|
183
|
+
pickup = value.trim();
|
|
184
|
+
i = nextIndex;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case '--nonce': {
|
|
188
|
+
const { value, nextIndex } = consumeValue('--nonce', inline, i);
|
|
189
|
+
nonce = value.trim();
|
|
190
|
+
i = nextIndex;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case '--client': {
|
|
194
|
+
const { value, nextIndex } = consumeValue('--client', inline, i);
|
|
195
|
+
if (value !== '')
|
|
196
|
+
clients.push(value.trim());
|
|
197
|
+
i = nextIndex;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
default: {
|
|
201
|
+
errors.push(`Unknown setup flag: ${flag}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Pickup mode validation (Wave C). Pickup pairs 1:1 with nonce; when
|
|
206
|
+
// both are present, the wizard fetches token + URL from the plugin and
|
|
207
|
+
// ignores --url/--token (with a warning so typos don't go silent).
|
|
208
|
+
const pickupMode = pickup !== '' || nonce !== '';
|
|
209
|
+
if (pickupMode) {
|
|
210
|
+
if (pickup === '')
|
|
211
|
+
errors.push('--pickup is required when --nonce is given.');
|
|
212
|
+
if (nonce === '')
|
|
213
|
+
errors.push('--nonce is required when --pickup is given.');
|
|
214
|
+
if (url !== '')
|
|
215
|
+
warnings.push('--url is ignored in pickup mode (the plugin returns the canonical URL).');
|
|
216
|
+
if (token !== '')
|
|
217
|
+
warnings.push('--token is ignored in pickup mode (the plugin returns the Bearer token).');
|
|
218
|
+
if (clients.length === 0) {
|
|
219
|
+
errors.push('--client is required with --pickup (at least one).');
|
|
220
|
+
}
|
|
221
|
+
const knownIds = new Set(ALL_CLIENTS.map((c) => c.id));
|
|
222
|
+
for (const id of clients) {
|
|
223
|
+
if (!knownIds.has(id)) {
|
|
224
|
+
errors.push(`Unknown --client id "${id}". Valid: ${[...knownIds].sort().join(', ')}.`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (nonInteractive) {
|
|
229
|
+
if (url === '')
|
|
230
|
+
errors.push('--url is required with --non-interactive.');
|
|
231
|
+
if (token === '')
|
|
232
|
+
errors.push('--token is required with --non-interactive.');
|
|
233
|
+
if (clients.length === 0)
|
|
234
|
+
errors.push('--client is required with --non-interactive (at least one).');
|
|
235
|
+
const knownIds = new Set(ALL_CLIENTS.map((c) => c.id));
|
|
236
|
+
for (const id of clients) {
|
|
237
|
+
if (!knownIds.has(id)) {
|
|
238
|
+
errors.push(`Unknown --client id "${id}". Valid: ${[...knownIds].sort().join(', ')}.`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return { nonInteractive, url, token, pickup, nonce, clients, errors, warnings };
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Build a `WizardDeps` bag that answers prompts from CLI flags instead
|
|
246
|
+
* of asking a human. Reuses every other dependency (probes, writes,
|
|
247
|
+
* handshake) from `DEFAULT_WIZARD_DEPS` so the wizard's exit-code
|
|
248
|
+
* contract (0/2/3/4/5) stays identical.
|
|
249
|
+
*
|
|
250
|
+
* `confirmContinue` always returns `false` — there is no human to ask,
|
|
251
|
+
* so a probe failure cleanly aborts with the documented exit code.
|
|
252
|
+
*/
|
|
253
|
+
export function buildNonInteractiveDeps(parsed, base = DEFAULT_WIZARD_DEPS) {
|
|
254
|
+
const answers = {
|
|
255
|
+
wpUrl: parsed.url,
|
|
256
|
+
bearer: parsed.token,
|
|
257
|
+
selectedClients: parsed.clients,
|
|
258
|
+
};
|
|
259
|
+
return {
|
|
260
|
+
...base,
|
|
261
|
+
prompt: async () => answers,
|
|
262
|
+
confirmContinue: async () => false,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Build a `WizardDeps` bag for the Wave-C pickup flow. The wizard's
|
|
267
|
+
* `prompt` step calls `base.fetchPickup(url, nonce)` once, then
|
|
268
|
+
* synthesises the `WizardAnswers` from the response — the actual answers
|
|
269
|
+
* (token + canonical WordPress URL) come straight from the plugin via
|
|
270
|
+
* a 256-bit one-shot nonce, never through chat history / provider logs.
|
|
271
|
+
*
|
|
272
|
+
* On `fetchPickup` failure the prompt resolves to `null` so the wizard
|
|
273
|
+
* exits cleanly with code 130 (user-cancel equivalent — we treat
|
|
274
|
+
* an unrecoverable pickup as "the conversation ends here"). The
|
|
275
|
+
* thrown error is logged via the `log` dep so the operator sees why.
|
|
276
|
+
*
|
|
277
|
+
* `confirmContinue` returns `false` (same rationale as non-interactive).
|
|
278
|
+
*/
|
|
279
|
+
export function buildPickupDeps(parsed, base = DEFAULT_WIZARD_DEPS) {
|
|
280
|
+
const pickupUrl = parsed.pickup ?? '';
|
|
281
|
+
const nonce = parsed.nonce ?? '';
|
|
282
|
+
const fetchPickup = base.fetchPickup;
|
|
283
|
+
const logFn = base.log;
|
|
284
|
+
return {
|
|
285
|
+
...base,
|
|
286
|
+
prompt: async () => {
|
|
287
|
+
if (fetchPickup === undefined) {
|
|
288
|
+
const msg = 'Pickup mode requested but no fetchPickup is wired in this WizardDeps bag.';
|
|
289
|
+
if (logFn !== undefined)
|
|
290
|
+
logFn(msg);
|
|
291
|
+
else
|
|
292
|
+
process.stderr.write(`${msg}\n`);
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
const result = await fetchPickup(pickupUrl, nonce);
|
|
297
|
+
return {
|
|
298
|
+
wpUrl: result.siteurl,
|
|
299
|
+
bearer: result.token,
|
|
300
|
+
selectedClients: parsed.clients,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
catch (e) {
|
|
304
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
305
|
+
if (logFn !== undefined)
|
|
306
|
+
logFn(`Pickup failed: ${msg}`);
|
|
307
|
+
else
|
|
308
|
+
process.stderr.write(`Pickup failed: ${msg}\n`);
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
confirmContinue: async () => false,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Parse `add-site` flags from the tail of argv. Accepts both
|
|
317
|
+
* `--key value` and `--key=value` styles. Unknown flags are reported
|
|
318
|
+
* as errors so typos never silently disable validation.
|
|
319
|
+
*/
|
|
320
|
+
export function parseAddSiteArgs(argv) {
|
|
321
|
+
let url = '';
|
|
322
|
+
let token = '';
|
|
323
|
+
let tokenRef = '';
|
|
324
|
+
let label = '';
|
|
325
|
+
let siteId = '';
|
|
326
|
+
let platform;
|
|
327
|
+
let isDefault = false;
|
|
328
|
+
let yes = false;
|
|
329
|
+
let sitesFile;
|
|
330
|
+
const errors = [];
|
|
331
|
+
function consume(name, inline, i) {
|
|
332
|
+
if (inline !== undefined)
|
|
333
|
+
return { value: inline, nextIndex: i };
|
|
334
|
+
const next = argv[i + 1];
|
|
335
|
+
if (next === undefined || next.startsWith('--')) {
|
|
336
|
+
errors.push(`Flag ${name} requires a value.`);
|
|
337
|
+
return { value: '', nextIndex: i };
|
|
338
|
+
}
|
|
339
|
+
return { value: next, nextIndex: i + 1 };
|
|
340
|
+
}
|
|
341
|
+
for (let i = 0; i < argv.length; i++) {
|
|
342
|
+
const raw = argv[i];
|
|
343
|
+
const eq = raw.indexOf('=');
|
|
344
|
+
const flag = eq >= 0 ? raw.slice(0, eq) : raw;
|
|
345
|
+
const inline = eq >= 0 ? raw.slice(eq + 1) : undefined;
|
|
346
|
+
switch (flag) {
|
|
347
|
+
case '--url': {
|
|
348
|
+
const r = consume('--url', inline, i);
|
|
349
|
+
url = r.value.trim().replace(/\/+$/, '');
|
|
350
|
+
i = r.nextIndex;
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
case '--token': {
|
|
354
|
+
const r = consume('--token', inline, i);
|
|
355
|
+
token = r.value.trim();
|
|
356
|
+
i = r.nextIndex;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
case '--token-ref': {
|
|
360
|
+
const r = consume('--token-ref', inline, i);
|
|
361
|
+
tokenRef = r.value.trim();
|
|
362
|
+
i = r.nextIndex;
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
case '--platform': {
|
|
366
|
+
const r = consume('--platform', inline, i);
|
|
367
|
+
const v = r.value.trim();
|
|
368
|
+
if (v === 'auto' || v === 'wordpress' || v === 'joomla') {
|
|
369
|
+
platform = v;
|
|
370
|
+
}
|
|
371
|
+
else if (v.length > 0) {
|
|
372
|
+
errors.push(`--platform must be one of auto, wordpress, joomla (got "${v}").`);
|
|
373
|
+
}
|
|
374
|
+
i = r.nextIndex;
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
case '--label': {
|
|
378
|
+
const r = consume('--label', inline, i);
|
|
379
|
+
label = r.value;
|
|
380
|
+
i = r.nextIndex;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
case '--site-id': {
|
|
384
|
+
const r = consume('--site-id', inline, i);
|
|
385
|
+
siteId = r.value.trim();
|
|
386
|
+
i = r.nextIndex;
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
case '--default': {
|
|
390
|
+
isDefault = true;
|
|
391
|
+
if (inline !== undefined) {
|
|
392
|
+
errors.push('Flag --default does not take a value.');
|
|
393
|
+
}
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
case '--yes':
|
|
397
|
+
case '-y': {
|
|
398
|
+
yes = true;
|
|
399
|
+
if (inline !== undefined) {
|
|
400
|
+
errors.push(`Flag ${flag} does not take a value.`);
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
case '--sites-file': {
|
|
405
|
+
const r = consume('--sites-file', inline, i);
|
|
406
|
+
sitesFile = r.value.trim();
|
|
407
|
+
i = r.nextIndex;
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
case '--help':
|
|
411
|
+
case '-h': {
|
|
412
|
+
errors.push('HELP_REQUESTED');
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
default: {
|
|
416
|
+
errors.push(`Unknown add-site flag: ${flag}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const parsed = {
|
|
421
|
+
url,
|
|
422
|
+
token,
|
|
423
|
+
tokenRef,
|
|
424
|
+
label,
|
|
425
|
+
siteId: siteId.length > 0 ? siteId : 'default',
|
|
426
|
+
default: isDefault,
|
|
427
|
+
yes,
|
|
428
|
+
...(platform !== undefined ? { platform } : {}),
|
|
429
|
+
...(sitesFile !== undefined ? { sitesFile } : {}),
|
|
430
|
+
errors,
|
|
431
|
+
};
|
|
432
|
+
return parsed;
|
|
433
|
+
}
|
|
434
|
+
const ADD_SITE_HELP = `Usage: yt-builder-mcp add-site [flags]\n\n` +
|
|
435
|
+
`Flags:\n` +
|
|
436
|
+
` --url <url> (required) Site base URL (WordPress or Joomla origin).\n` +
|
|
437
|
+
` --token <bearer> Inline bearer (mutually exclusive with --token-ref).\n` +
|
|
438
|
+
` --token-ref <op://...> 1Password Secret Reference for the bearer.\n` +
|
|
439
|
+
` --platform <kind> auto|wordpress|joomla (default: auto).\n` +
|
|
440
|
+
` --label "<text>" Human-readable label (≤120 chars).\n` +
|
|
441
|
+
` --site-id <slug> Registry key (default: "default").\n` +
|
|
442
|
+
` --default Mark this site as the default.\n` +
|
|
443
|
+
` --yes, -y Overwrite an existing site_id without confirming.\n` +
|
|
444
|
+
` --sites-file <path> Override sites.json location.\n\n` +
|
|
445
|
+
`Notes:\n` +
|
|
446
|
+
` - The first site you add becomes the default automatically.\n` +
|
|
447
|
+
` - Use --token OR --token-ref, not both.\n` +
|
|
448
|
+
` - URL is normalised (trailing slashes stripped).\n\n` +
|
|
449
|
+
`Example:\n` +
|
|
450
|
+
` yt-builder-mcp add-site --url https://acme.example.com \\\n` +
|
|
451
|
+
` --token "$YTB_TOKEN" --site-id wp-acme --label "ACME WP"\n`;
|
|
452
|
+
const REMOVE_SITE_HELP = `Usage: yt-builder-mcp remove-site <site_id> [--yes] [--sites-file <path>]\n\n` +
|
|
453
|
+
`Removes the site from sites.json. If the default site is removed and at\n` +
|
|
454
|
+
`least one other site remains, the next site in insertion order becomes\n` +
|
|
455
|
+
`the new default. Removing the only site clears default_site_id and\n` +
|
|
456
|
+
`leaves an empty registry.\n\n` +
|
|
457
|
+
`Confirmation is required unless --yes is passed. In non-TTY contexts\n` +
|
|
458
|
+
`(CI, piped stdin) the subcommand fails with CONFIRM_REQUIRED rather\n` +
|
|
459
|
+
`than silently deleting.\n\n` +
|
|
460
|
+
`Example:\n` +
|
|
461
|
+
` yt-builder-mcp remove-site wp-acme --yes\n`;
|
|
462
|
+
const SET_DEFAULT_HELP = `Usage: yt-builder-mcp set-default <site_id> [--yes] [--sites-file <path>]\n\n` +
|
|
463
|
+
`Changes which site every subsequent tool call routes to by default\n` +
|
|
464
|
+
`when site_id is omitted. Confirmation is required unless --yes is\n` +
|
|
465
|
+
`passed — in non-TTY contexts the subcommand fails with\n` +
|
|
466
|
+
`SET_DEFAULT_CONFIRM_REQUIRED rather than silently flipping.\n\n` +
|
|
467
|
+
`Example:\n` +
|
|
468
|
+
` yt-builder-mcp set-default wp-beta --yes\n`;
|
|
469
|
+
const TEST_SITE_HELP = `Usage: yt-builder-mcp test-site <site_id> [--sites-file <path>]\n\n` +
|
|
470
|
+
`Probes /health (unauthenticated) and /etag (authenticated) in parallel\n` +
|
|
471
|
+
`against the configured Bearer. Returns plugin reachability + Bearer\n` +
|
|
472
|
+
`validity in one call. Does NOT mutate the registry or the site.\n\n` +
|
|
473
|
+
`Example:\n` +
|
|
474
|
+
` yt-builder-mcp test-site wp-acme\n`;
|
|
475
|
+
const LIST_SITES_HELP = `Usage: yt-builder-mcp list-sites [--sites-file <path>]\n\n` +
|
|
476
|
+
`Prints the configured sites table (site_id, url, platform, label,\n` +
|
|
477
|
+
`bearer_source, is_default). No network calls — pure registry read.\n\n` +
|
|
478
|
+
`Example:\n` +
|
|
479
|
+
` yt-builder-mcp list-sites\n`;
|
|
480
|
+
const UNINSTALL_HELP = `Usage: yt-builder-mcp uninstall [--all] [--yes]\n` +
|
|
481
|
+
` yt-builder-mcp remove [--all] [--yes] (alias)\n\n` +
|
|
482
|
+
`Reverse of \`setup\`. Detects which AI clients currently have the\n` +
|
|
483
|
+
`yt-builder-mcp MCP server entry and removes it. Each client's config is\n` +
|
|
484
|
+
`edited in place — every other server + unrelated setting is preserved.\n\n` +
|
|
485
|
+
`Interactive (default):\n` +
|
|
486
|
+
` Shows a checklist of the detected clients (ALL pre-checked, so a\n` +
|
|
487
|
+
` single Enter performs a complete uninstall), each labelled with its\n` +
|
|
488
|
+
` config path, plus a prompt to also remove the installed skill (and\n` +
|
|
489
|
+
` the ~/AGENTS.md marker). Nothing detected → "Nothing to uninstall.".\n\n` +
|
|
490
|
+
`Flags:\n` +
|
|
491
|
+
` --all Non-interactive: remove from EVERY detected client and\n` +
|
|
492
|
+
` remove the skill, with no prompts.\n` +
|
|
493
|
+
` --yes, -y Skip the final confirmation prompt (interactive mode).\n\n` +
|
|
494
|
+
`Examples:\n` +
|
|
495
|
+
` yt-builder-mcp uninstall # interactive checklist\n` +
|
|
496
|
+
` yt-builder-mcp uninstall --all # remove everything, no prompts\n` +
|
|
497
|
+
` yt-builder-mcp remove --yes # interactive, no final confirm\n`;
|
|
498
|
+
/**
|
|
499
|
+
* Parse the `uninstall` / `remove` argv tail. Pure; does no I/O. Accepts
|
|
500
|
+
* only boolean flags — `--all`, `--yes`/`-y`, `--help`/`-h`. Any value
|
|
501
|
+
* (`--all=x`) or unknown flag is an error so typos don't silently change
|
|
502
|
+
* the destructive behaviour.
|
|
503
|
+
*/
|
|
504
|
+
export function parseUninstallArgs(argv) {
|
|
505
|
+
let all = false;
|
|
506
|
+
let yes = false;
|
|
507
|
+
let helpRequested = false;
|
|
508
|
+
const errors = [];
|
|
509
|
+
for (const raw of argv) {
|
|
510
|
+
const eq = raw.indexOf('=');
|
|
511
|
+
const flag = eq >= 0 ? raw.slice(0, eq) : raw;
|
|
512
|
+
const hasInline = eq >= 0;
|
|
513
|
+
switch (flag) {
|
|
514
|
+
case '--all': {
|
|
515
|
+
all = true;
|
|
516
|
+
if (hasInline)
|
|
517
|
+
errors.push('Flag --all does not take a value.');
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
case '--yes':
|
|
521
|
+
case '-y': {
|
|
522
|
+
yes = true;
|
|
523
|
+
if (hasInline)
|
|
524
|
+
errors.push(`Flag ${flag} does not take a value.`);
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
case '--help':
|
|
528
|
+
case '-h': {
|
|
529
|
+
helpRequested = true;
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
default: {
|
|
533
|
+
errors.push(`Unknown uninstall flag: ${flag}`);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return { all, yes, helpRequested, errors };
|
|
538
|
+
}
|
|
539
|
+
function parseIdArgs(argv, allowYes) {
|
|
540
|
+
let siteId = '';
|
|
541
|
+
let yes = false;
|
|
542
|
+
let sitesFile;
|
|
543
|
+
const errors = [];
|
|
544
|
+
let helpRequested = false;
|
|
545
|
+
for (let i = 0; i < argv.length; i++) {
|
|
546
|
+
const raw = argv[i];
|
|
547
|
+
const eq = raw.indexOf('=');
|
|
548
|
+
const flag = eq >= 0 ? raw.slice(0, eq) : raw;
|
|
549
|
+
const inline = eq >= 0 ? raw.slice(eq + 1) : undefined;
|
|
550
|
+
if (flag === '--help' || flag === '-h') {
|
|
551
|
+
helpRequested = true;
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
if (flag === '--yes' || flag === '-y') {
|
|
555
|
+
if (!allowYes) {
|
|
556
|
+
errors.push(`Unknown flag for this subcommand: ${flag}`);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
yes = true;
|
|
560
|
+
}
|
|
561
|
+
if (inline !== undefined)
|
|
562
|
+
errors.push(`Flag ${flag} does not take a value.`);
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if (flag === '--sites-file') {
|
|
566
|
+
const next = inline ?? argv[i + 1];
|
|
567
|
+
if (next === undefined || next.startsWith('--')) {
|
|
568
|
+
errors.push('Flag --sites-file requires a value.');
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
sitesFile = next.trim();
|
|
572
|
+
if (inline === undefined)
|
|
573
|
+
i += 1;
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (flag.startsWith('--') || flag.startsWith('-')) {
|
|
577
|
+
errors.push(`Unknown flag: ${flag}`);
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if (siteId !== '') {
|
|
581
|
+
errors.push(`Too many positional arguments; got "${siteId}" and "${flag}".`);
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
siteId = flag.trim();
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
siteId,
|
|
588
|
+
yes,
|
|
589
|
+
...(sitesFile !== undefined ? { sitesFile } : {}),
|
|
590
|
+
errors,
|
|
591
|
+
helpRequested,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
export async function runCli(argv, deps) {
|
|
595
|
+
const out = deps?.log ?? ((s) => process.stdout.write(`${s}\n`));
|
|
596
|
+
const err = deps?.error ?? ((s) => process.stderr.write(`${s}\n`));
|
|
597
|
+
const wizard = deps?.runWizard ?? ((wizDeps) => runWizardImpl(wizDeps));
|
|
598
|
+
const install = deps?.installSkill ?? defaultInstallSkill;
|
|
599
|
+
const resolveSitesPath = deps?.resolveSitesPath ?? (() => defaultSitesFilePath());
|
|
600
|
+
const addSiteDeps = deps?.addSiteDeps ?? DEFAULT_ADD_SITE_DEPS;
|
|
601
|
+
const listSitesDeps = deps?.listSitesDeps ?? DEFAULT_LIST_SITES_DEPS;
|
|
602
|
+
// W12-R2A: wire a TTY confirm hook into the destructive-subcommand
|
|
603
|
+
// deps bags. Tests that supply `removeSiteDeps`/`setDefaultDeps`
|
|
604
|
+
// directly retain full control over the confirm channel (so the
|
|
605
|
+
// existing unit-tests keep working unchanged); only the default
|
|
606
|
+
// dispatcher path gets the `defaultConfirmTTY` injection.
|
|
607
|
+
const confirmHook = deps?.confirm ?? defaultConfirmTTY;
|
|
608
|
+
const removeSiteDeps = deps?.removeSiteDeps
|
|
609
|
+
?? { ...DEFAULT_REMOVE_SITE_DEPS, confirm: confirmHook };
|
|
610
|
+
const setDefaultDeps = deps?.setDefaultDeps
|
|
611
|
+
?? { ...DEFAULT_SET_DEFAULT_DEPS, confirm: confirmHook };
|
|
612
|
+
const testSiteDeps = deps?.testSiteDeps ?? DEFAULT_TEST_SITE_DEPS;
|
|
613
|
+
const addSiteFromWizard = deps?.addSiteFromWizard
|
|
614
|
+
?? ((args, path) => addSiteCommand(args, path, addSiteDeps));
|
|
615
|
+
const uninstallDeps = deps?.uninstallDeps ?? DEFAULT_UNINSTALL_DEPS;
|
|
616
|
+
const detectInstalled = deps?.detectInstalled ?? defaultDetectInstalled;
|
|
617
|
+
const promptUninstall = deps?.promptUninstall ?? defaultUninstallPrompt;
|
|
618
|
+
const [subcommand] = argv;
|
|
619
|
+
// Build a `persistSite` callback for the wizard that translates
|
|
620
|
+
// the collected WizardAnswers into an `addSiteCommand` call so the
|
|
621
|
+
// sites.json registry stays in sync with the env-var path. This is
|
|
622
|
+
// the W9 "wizard internally invokes add-site" wiring.
|
|
623
|
+
const buildPersistSite = () => {
|
|
624
|
+
return async (answers) => {
|
|
625
|
+
const siteId = (answers.siteId !== undefined && answers.siteId.length > 0)
|
|
626
|
+
? answers.siteId
|
|
627
|
+
: 'default';
|
|
628
|
+
const path = resolveSitesPath();
|
|
629
|
+
const args = {
|
|
630
|
+
url: answers.wpUrl,
|
|
631
|
+
token: answers.bearer,
|
|
632
|
+
siteId,
|
|
633
|
+
default: true,
|
|
634
|
+
yes: true,
|
|
635
|
+
platform: 'auto',
|
|
636
|
+
};
|
|
637
|
+
await addSiteFromWizard(args, path);
|
|
638
|
+
};
|
|
639
|
+
};
|
|
640
|
+
if (subcommand === undefined || subcommand === 'setup') {
|
|
641
|
+
const setupArgs = argv[0] === 'setup' ? argv.slice(1) : argv;
|
|
642
|
+
const parsed = parseSetupArgs(setupArgs);
|
|
643
|
+
// Surface non-fatal warnings (e.g. "--url ignored in pickup mode").
|
|
644
|
+
for (const line of parsed.warnings)
|
|
645
|
+
err(`yt-builder-mcp: warning: ${line}`);
|
|
646
|
+
const pickupMode = (parsed.pickup ?? '') !== '' || (parsed.nonce ?? '') !== '';
|
|
647
|
+
const persistSite = buildPersistSite();
|
|
648
|
+
function withPersist(base) {
|
|
649
|
+
return { ...base, persistSite };
|
|
650
|
+
}
|
|
651
|
+
if (pickupMode) {
|
|
652
|
+
if (parsed.errors.length > 0) {
|
|
653
|
+
for (const line of parsed.errors)
|
|
654
|
+
err(`yt-builder-mcp: ${line}`);
|
|
655
|
+
err(HELP_TEXT);
|
|
656
|
+
return 2;
|
|
657
|
+
}
|
|
658
|
+
return wizard(withPersist(buildPickupDeps(parsed)));
|
|
659
|
+
}
|
|
660
|
+
if (parsed.nonInteractive) {
|
|
661
|
+
if (parsed.errors.length > 0) {
|
|
662
|
+
for (const line of parsed.errors)
|
|
663
|
+
err(`yt-builder-mcp: ${line}`);
|
|
664
|
+
err(HELP_TEXT);
|
|
665
|
+
return 2;
|
|
666
|
+
}
|
|
667
|
+
return wizard(withPersist(buildNonInteractiveDeps(parsed)));
|
|
668
|
+
}
|
|
669
|
+
if (parsed.errors.length > 0) {
|
|
670
|
+
for (const line of parsed.errors)
|
|
671
|
+
err(`yt-builder-mcp: ${line}`);
|
|
672
|
+
err(HELP_TEXT);
|
|
673
|
+
return 1;
|
|
674
|
+
}
|
|
675
|
+
return wizard(withPersist(DEFAULT_WIZARD_DEPS));
|
|
676
|
+
}
|
|
677
|
+
switch (subcommand) {
|
|
678
|
+
case 'install-skill':
|
|
679
|
+
case 'install': {
|
|
680
|
+
try {
|
|
681
|
+
const result = await install();
|
|
682
|
+
if (result.markerAlreadyPresent) {
|
|
683
|
+
out(`yt-builder-mcp: skill refreshed at ${result.skillTargetDir} (marker already in AGENTS.md).`);
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
out(`yt-builder-mcp: skill installed at ${result.skillTargetDir}; ${result.agentsFile} updated.`);
|
|
687
|
+
}
|
|
688
|
+
return 0;
|
|
689
|
+
}
|
|
690
|
+
catch (e) {
|
|
691
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
692
|
+
err(`yt-builder-mcp: install-skill failed: ${msg}`);
|
|
693
|
+
return 2;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
case 'uninstall':
|
|
697
|
+
case 'remove': {
|
|
698
|
+
const tail = argv.slice(1);
|
|
699
|
+
const parsed = parseUninstallArgs(tail);
|
|
700
|
+
if (parsed.helpRequested) {
|
|
701
|
+
out(UNINSTALL_HELP);
|
|
702
|
+
return 0;
|
|
703
|
+
}
|
|
704
|
+
if (parsed.errors.length > 0) {
|
|
705
|
+
for (const line of parsed.errors)
|
|
706
|
+
err(`yt-builder-mcp: ${line}`);
|
|
707
|
+
err(UNINSTALL_HELP);
|
|
708
|
+
return 2;
|
|
709
|
+
}
|
|
710
|
+
try {
|
|
711
|
+
const detected = await detectInstalled(uninstallDeps.clients);
|
|
712
|
+
const skillInstalled = uninstallDeps.isSkillInstalled();
|
|
713
|
+
if (detected.length === 0 && !skillInstalled) {
|
|
714
|
+
out('Nothing to uninstall — no AI client carries the yt-builder-mcp server entry and no skill is installed.');
|
|
715
|
+
return 0;
|
|
716
|
+
}
|
|
717
|
+
let selection;
|
|
718
|
+
if (parsed.all) {
|
|
719
|
+
// Non-interactive: remove from every detected client +
|
|
720
|
+
// the skill, no prompts.
|
|
721
|
+
selection = {
|
|
722
|
+
clientIds: detected.map((d) => d.id),
|
|
723
|
+
removeSkill: skillInstalled,
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
const picked = await promptUninstall({
|
|
728
|
+
detected,
|
|
729
|
+
skillInstalled,
|
|
730
|
+
skipFinalConfirm: parsed.yes,
|
|
731
|
+
});
|
|
732
|
+
if (picked === null) {
|
|
733
|
+
// User cancelled — clean exit (SIGINT convention).
|
|
734
|
+
return 130;
|
|
735
|
+
}
|
|
736
|
+
selection = picked;
|
|
737
|
+
}
|
|
738
|
+
if (selection.clientIds.length === 0 && !selection.removeSkill) {
|
|
739
|
+
out('Nothing to uninstall — no targets selected.');
|
|
740
|
+
return 0;
|
|
741
|
+
}
|
|
742
|
+
const result = await runUninstall(selection, uninstallDeps);
|
|
743
|
+
// Summary.
|
|
744
|
+
out('Uninstall summary:');
|
|
745
|
+
if (result.clientResults.length === 0) {
|
|
746
|
+
out(' (no AI client configs changed)');
|
|
747
|
+
}
|
|
748
|
+
for (const r of result.clientResults) {
|
|
749
|
+
if (r.error !== undefined) {
|
|
750
|
+
out(` ✗ ${r.label}: FAILED — ${r.error} (${r.configPath})`);
|
|
751
|
+
}
|
|
752
|
+
else if (r.removed) {
|
|
753
|
+
const keys = r.removedKeys.join(', ');
|
|
754
|
+
out(` ✓ ${r.label}: removed [${keys}] from ${r.configPath}`);
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
out(` • ${r.label}: nothing to remove (${r.configPath})`);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (result.skillResult !== undefined) {
|
|
761
|
+
const s = result.skillResult;
|
|
762
|
+
if (s.skillRemoved || s.markerRemoved) {
|
|
763
|
+
const bits = [];
|
|
764
|
+
if (s.skillRemoved)
|
|
765
|
+
bits.push(`skill dir (${s.skillTargetDir})`);
|
|
766
|
+
if (s.markerRemoved)
|
|
767
|
+
bits.push(`AGENTS.md marker (${s.agentsFile})`);
|
|
768
|
+
out(` ✓ Skill: removed ${bits.join(' + ')}`);
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
out(' • Skill: nothing to remove');
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
const anyFailed = result.clientResults.some((r) => r.error !== undefined);
|
|
775
|
+
if (anyFailed) {
|
|
776
|
+
err('yt-builder-mcp: one or more client removals failed (see summary).');
|
|
777
|
+
return 2;
|
|
778
|
+
}
|
|
779
|
+
out('Restart your AI client(s) to drop the removed server.');
|
|
780
|
+
return 0;
|
|
781
|
+
}
|
|
782
|
+
catch (e) {
|
|
783
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
784
|
+
err(`yt-builder-mcp: uninstall failed: ${msg}`);
|
|
785
|
+
return 2;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
case 'add-site': {
|
|
789
|
+
const tail = argv.slice(1);
|
|
790
|
+
const parsed = parseAddSiteArgs(tail);
|
|
791
|
+
if (parsed.errors.some((e) => e === 'HELP_REQUESTED')) {
|
|
792
|
+
out(ADD_SITE_HELP);
|
|
793
|
+
return 0;
|
|
794
|
+
}
|
|
795
|
+
if (parsed.errors.length > 0) {
|
|
796
|
+
for (const line of parsed.errors)
|
|
797
|
+
err(`yt-builder-mcp: ${line}`);
|
|
798
|
+
err(ADD_SITE_HELP);
|
|
799
|
+
return 2;
|
|
800
|
+
}
|
|
801
|
+
const path = parsed.sitesFile ?? resolveSitesPath();
|
|
802
|
+
const args = {
|
|
803
|
+
url: parsed.url,
|
|
804
|
+
...(parsed.token.length > 0 ? { token: parsed.token } : {}),
|
|
805
|
+
...(parsed.tokenRef.length > 0 ? { tokenRef: parsed.tokenRef } : {}),
|
|
806
|
+
...(parsed.platform !== undefined ? { platform: parsed.platform } : {}),
|
|
807
|
+
...(parsed.label.length > 0 ? { label: parsed.label } : {}),
|
|
808
|
+
siteId: parsed.siteId,
|
|
809
|
+
default: parsed.default,
|
|
810
|
+
yes: parsed.yes,
|
|
811
|
+
};
|
|
812
|
+
try {
|
|
813
|
+
const result = await addSiteCommand(args, path, addSiteDeps);
|
|
814
|
+
const stateBits = [];
|
|
815
|
+
if (result.becameDefault)
|
|
816
|
+
stateBits.push('default — first site');
|
|
817
|
+
else if (result.defaultRequested)
|
|
818
|
+
stateBits.push('default');
|
|
819
|
+
if (result.overwritten)
|
|
820
|
+
stateBits.push('overwritten');
|
|
821
|
+
const state = stateBits.length > 0 ? ` (${stateBits.join(', ')})` : '';
|
|
822
|
+
const verb = result.overwritten ? 'updated' : 'added';
|
|
823
|
+
out(`✓ Site "${result.siteId}" ${verb}${state}.`);
|
|
824
|
+
out(` Path: ${result.path}`);
|
|
825
|
+
out('Restart your AI client to pick up the new site list.');
|
|
826
|
+
return 0;
|
|
827
|
+
}
|
|
828
|
+
catch (e) {
|
|
829
|
+
if (e instanceof AddSiteError) {
|
|
830
|
+
err(`yt-builder-mcp: add-site failed [${e.code}]: ${e.message}`);
|
|
831
|
+
return 2;
|
|
832
|
+
}
|
|
833
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
834
|
+
err(`yt-builder-mcp: add-site failed: ${msg}`);
|
|
835
|
+
return 2;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
case 'list-sites': {
|
|
839
|
+
const tail = argv.slice(1);
|
|
840
|
+
const parsed = parseIdArgs(tail, false);
|
|
841
|
+
// list-sites takes no positional id; if one slipped in it's
|
|
842
|
+
// a usage error (parseIdArgs allows zero or one).
|
|
843
|
+
if (parsed.helpRequested) {
|
|
844
|
+
out(LIST_SITES_HELP);
|
|
845
|
+
return 0;
|
|
846
|
+
}
|
|
847
|
+
if (parsed.siteId !== '') {
|
|
848
|
+
err(`yt-builder-mcp: list-sites takes no positional argument (got "${parsed.siteId}").`);
|
|
849
|
+
err(LIST_SITES_HELP);
|
|
850
|
+
return 2;
|
|
851
|
+
}
|
|
852
|
+
if (parsed.errors.length > 0) {
|
|
853
|
+
for (const line of parsed.errors)
|
|
854
|
+
err(`yt-builder-mcp: ${line}`);
|
|
855
|
+
err(LIST_SITES_HELP);
|
|
856
|
+
return 2;
|
|
857
|
+
}
|
|
858
|
+
const path = parsed.sitesFile ?? resolveSitesPath();
|
|
859
|
+
try {
|
|
860
|
+
const lines = await listSitesCommand(path, listSitesDeps);
|
|
861
|
+
for (const line of lines)
|
|
862
|
+
out(line);
|
|
863
|
+
return 0;
|
|
864
|
+
}
|
|
865
|
+
catch (e) {
|
|
866
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
867
|
+
err(`yt-builder-mcp: list-sites failed: ${msg}`);
|
|
868
|
+
return 2;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
case 'remove-site': {
|
|
872
|
+
const tail = argv.slice(1);
|
|
873
|
+
const parsed = parseIdArgs(tail, true);
|
|
874
|
+
if (parsed.helpRequested) {
|
|
875
|
+
out(REMOVE_SITE_HELP);
|
|
876
|
+
return 0;
|
|
877
|
+
}
|
|
878
|
+
if (parsed.siteId === '') {
|
|
879
|
+
err('yt-builder-mcp: remove-site requires a <site_id> argument.');
|
|
880
|
+
err(REMOVE_SITE_HELP);
|
|
881
|
+
return 2;
|
|
882
|
+
}
|
|
883
|
+
if (parsed.errors.length > 0) {
|
|
884
|
+
for (const line of parsed.errors)
|
|
885
|
+
err(`yt-builder-mcp: ${line}`);
|
|
886
|
+
err(REMOVE_SITE_HELP);
|
|
887
|
+
return 2;
|
|
888
|
+
}
|
|
889
|
+
const path = parsed.sitesFile ?? resolveSitesPath();
|
|
890
|
+
try {
|
|
891
|
+
const result = await removeSiteCommand(parsed.siteId, path, { yes: parsed.yes }, removeSiteDeps);
|
|
892
|
+
if (result.cancelled) {
|
|
893
|
+
out(`Cancelled — site "${result.siteId}" not removed.`);
|
|
894
|
+
return 0;
|
|
895
|
+
}
|
|
896
|
+
out(`✓ Site "${result.siteId}" removed.`);
|
|
897
|
+
if (result.promoted !== undefined) {
|
|
898
|
+
out(` Default promoted: ${result.promoted}`);
|
|
899
|
+
}
|
|
900
|
+
if (result.nowEmpty) {
|
|
901
|
+
out(' (registry is now empty)');
|
|
902
|
+
}
|
|
903
|
+
out(` Path: ${result.path}`);
|
|
904
|
+
out('Restart your AI client to pick up the new site list.');
|
|
905
|
+
return 0;
|
|
906
|
+
}
|
|
907
|
+
catch (e) {
|
|
908
|
+
if (e instanceof RemoveSiteError) {
|
|
909
|
+
err(`yt-builder-mcp: remove-site failed [${e.code}]: ${e.message}`);
|
|
910
|
+
return 2;
|
|
911
|
+
}
|
|
912
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
913
|
+
err(`yt-builder-mcp: remove-site failed: ${msg}`);
|
|
914
|
+
return 2;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
case 'set-default': {
|
|
918
|
+
const tail = argv.slice(1);
|
|
919
|
+
// W12-R2A: set-default is a routing-destructive op (every
|
|
920
|
+
// subsequent default-routed tool call lands on a different
|
|
921
|
+
// site). Allow --yes so CI can flip without a prompt.
|
|
922
|
+
const parsed = parseIdArgs(tail, true);
|
|
923
|
+
if (parsed.helpRequested) {
|
|
924
|
+
out(SET_DEFAULT_HELP);
|
|
925
|
+
return 0;
|
|
926
|
+
}
|
|
927
|
+
if (parsed.siteId === '') {
|
|
928
|
+
err('yt-builder-mcp: set-default requires a <site_id> argument.');
|
|
929
|
+
err(SET_DEFAULT_HELP);
|
|
930
|
+
return 2;
|
|
931
|
+
}
|
|
932
|
+
if (parsed.errors.length > 0) {
|
|
933
|
+
for (const line of parsed.errors)
|
|
934
|
+
err(`yt-builder-mcp: ${line}`);
|
|
935
|
+
err(SET_DEFAULT_HELP);
|
|
936
|
+
return 2;
|
|
937
|
+
}
|
|
938
|
+
const path = parsed.sitesFile ?? resolveSitesPath();
|
|
939
|
+
try {
|
|
940
|
+
const result = await setDefaultCommand(parsed.siteId, path, { yes: parsed.yes }, setDefaultDeps);
|
|
941
|
+
if (result.cancelled) {
|
|
942
|
+
out(`Cancelled — default unchanged.`);
|
|
943
|
+
return 0;
|
|
944
|
+
}
|
|
945
|
+
const prior = result.previousDefault !== null
|
|
946
|
+
? `(was: ${result.previousDefault})`
|
|
947
|
+
: '(no previous default)';
|
|
948
|
+
out(`✓ Default set to "${result.siteId}" ${prior}.`);
|
|
949
|
+
out(` Path: ${result.path}`);
|
|
950
|
+
out('Restart your AI client to pick up the new site list.');
|
|
951
|
+
return 0;
|
|
952
|
+
}
|
|
953
|
+
catch (e) {
|
|
954
|
+
if (e instanceof SetDefaultError) {
|
|
955
|
+
err(`yt-builder-mcp: set-default failed [${e.code}]: ${e.message}`);
|
|
956
|
+
return 2;
|
|
957
|
+
}
|
|
958
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
959
|
+
err(`yt-builder-mcp: set-default failed: ${msg}`);
|
|
960
|
+
return 2;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
case 'test-site': {
|
|
964
|
+
const tail = argv.slice(1);
|
|
965
|
+
const parsed = parseIdArgs(tail, false);
|
|
966
|
+
if (parsed.helpRequested) {
|
|
967
|
+
out(TEST_SITE_HELP);
|
|
968
|
+
return 0;
|
|
969
|
+
}
|
|
970
|
+
if (parsed.siteId === '') {
|
|
971
|
+
err('yt-builder-mcp: test-site requires a <site_id> argument.');
|
|
972
|
+
err(TEST_SITE_HELP);
|
|
973
|
+
return 2;
|
|
974
|
+
}
|
|
975
|
+
if (parsed.errors.length > 0) {
|
|
976
|
+
for (const line of parsed.errors)
|
|
977
|
+
err(`yt-builder-mcp: ${line}`);
|
|
978
|
+
err(TEST_SITE_HELP);
|
|
979
|
+
return 2;
|
|
980
|
+
}
|
|
981
|
+
const path = parsed.sitesFile ?? resolveSitesPath();
|
|
982
|
+
try {
|
|
983
|
+
const result = await testSiteCommand(parsed.siteId, path, testSiteDeps);
|
|
984
|
+
for (const line of renderTestSiteLines(result))
|
|
985
|
+
out(line);
|
|
986
|
+
const exitCode = result.unknownSite
|
|
987
|
+
|| !result.pluginReachable
|
|
988
|
+
|| !result.bearerValid
|
|
989
|
+
? 2
|
|
990
|
+
: 0;
|
|
991
|
+
return exitCode;
|
|
992
|
+
}
|
|
993
|
+
catch (e) {
|
|
994
|
+
if (e instanceof TestSiteError) {
|
|
995
|
+
err(`yt-builder-mcp: test-site failed [${e.code}]: ${e.message}`);
|
|
996
|
+
return 2;
|
|
997
|
+
}
|
|
998
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
999
|
+
err(`yt-builder-mcp: test-site failed: ${msg}`);
|
|
1000
|
+
return 2;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
case '--version':
|
|
1004
|
+
case '-v': {
|
|
1005
|
+
out(SERVER_VERSION);
|
|
1006
|
+
return 0;
|
|
1007
|
+
}
|
|
1008
|
+
case 'help':
|
|
1009
|
+
case '--help':
|
|
1010
|
+
case '-h': {
|
|
1011
|
+
out(HELP_TEXT);
|
|
1012
|
+
return 0;
|
|
1013
|
+
}
|
|
1014
|
+
default: {
|
|
1015
|
+
err(`yt-builder-mcp: unknown command "${subcommand}".`);
|
|
1016
|
+
err(HELP_TEXT);
|
|
1017
|
+
return 1;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
// ── direct CLI entry ────────────────────────────────────────────────────
|
|
1022
|
+
const isMain = typeof process !== 'undefined' &&
|
|
1023
|
+
process.argv[1] !== undefined &&
|
|
1024
|
+
import.meta.url === `file://${process.argv[1]}`;
|
|
1025
|
+
if (isMain) {
|
|
1026
|
+
runCli(process.argv.slice(2)).then((code) => process.exit(code), (err) => {
|
|
1027
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1028
|
+
process.stderr.write(`yt-builder-mcp: fatal: ${msg}\n`);
|
|
1029
|
+
process.exit(99);
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
//# sourceMappingURL=setup-cli.js.map
|