bwc-cli
Version:
CLI tool for installing Claude Code subagents and commands
29 lines • 89.6 kB
JavaScript
#!/usr/bin/env node
import{c as we,e as be,f as Pe,g as X,h as P,i as de,j as V,k as J,l as B,m as H,n as me}from"./chunk-U73Y3UWD.js";import{b as W,c as j}from"./chunk-6ILY6GGY.js";import{Command as Lo}from"commander";import No from"update-notifier";import{readFileSync as Fo}from"fs";import{fileURLToPath as Uo}from"url";import{dirname as Vo,join as Bo}from"path";import{Command as Mt}from"commander";import R from"path";import N from"process";import Se from"os";import{existsSync as bt,readFileSync as Pt}from"fs";var Me={version:"1.0",registry:"https://buildwithclaude.com/registry.json",paths:{subagents:be,commands:Pe},installed:{subagents:[],commands:[],mcpServers:[]}},$e={version:"1.0",registry:"https://buildwithclaude.com/registry.json",paths:{subagents:".claude/agents/",commands:".claude/commands/"},installed:{subagents:[],commands:[],mcpServers:[]}},k=class o{static instance=null;config=null;configPath=null;isProjectLevel=!1;forceUser=!1;static getInstance(){return o.instance||(o.instance=new o),o.instance}async findProjectConfig(){let e=["bwc.config.json",".bwc/config.json"],t=N.cwd();for(;t!==R.dirname(t);){for(let n of e){let r=R.join(t,n);if(await P(r))return r}t=R.dirname(t)}return null}async init(e){if(e!=null&&e.project){let t=R.join(N.cwd(),"bwc.config.json");if(await P(t)&&!e.force)throw new Error("Project configuration already exists. Use --force to overwrite.");await B(t,$e),this.config=$e,this.configPath=t,this.isProjectLevel=!0}else{let t=N.env.BWC_CONFIG_PATH||R.join(N.env.BWC_TEST_HOME||Se.homedir(),".bwc","config.json"),n=R.dirname(t);if(await X(n),await P(t)&&!(e!=null&&e.force))throw new Error("Configuration already exists. Use --force to overwrite.");await B(t,Me),this.config=Me,this.configPath=t,this.isProjectLevel=!1}}async load(){if(this.config)return this.config;if(!this.forceUser){let n=await this.findProjectConfig();if(n){let r=await J(n);return this.config=await this.migrateConfig(r),this.configPath=n,this.isProjectLevel=!0,this.config}}let e=N.env.BWC_CONFIG_PATH||R.join(N.env.BWC_TEST_HOME||Se.homedir(),".bwc","config.json");if(!await P(e))throw new Error('Configuration not found. Run "bwc init" first.');let t=await J(e);return this.config=await this.migrateConfig(t),this.configPath=e,this.isProjectLevel=!1,this.config}async migrateConfig(e){var t;if((t=e.installed)!=null&&t.mcpServers&&Array.isArray(e.installed.mcpServers)&&e.installed.mcpServers.every(r=>typeof r=="string")){let r={};for(let s of e.installed.mcpServers)r[s]={provider:"docker",transport:"stdio",scope:"local",installedAt:new Date().toISOString()};e.installed.mcpServers=r}return e}async save(){if(!this.config||!this.configPath)throw new Error("No configuration loaded");await B(this.configPath,this.config)}async getSubagentsPath(){let t=(await this.load()).paths.subagents;if(t=H(t),this.isProjectLevel&&!R.isAbsolute(t)){let n=R.dirname(this.configPath);t=R.join(n,t)}return await X(t),t}async getCommandsPath(){let t=(await this.load()).paths.commands;if(t=H(t),this.isProjectLevel&&!R.isAbsolute(t)){let n=R.dirname(this.configPath);t=R.join(n,t)}return await X(t),t}async addInstalledSubagent(e){let t=await this.load();t.installed.subagents.includes(e)||(t.installed.subagents.push(e),await this.save())}async addInstalledCommand(e){let t=await this.load();t.installed.commands.includes(e)||(t.installed.commands.push(e),await this.save())}async removeInstalledSubagent(e){let t=await this.load();t.installed.subagents=t.installed.subagents.filter(n=>n!==e),await this.save()}async removeInstalledCommand(e){let t=await this.load();t.installed.commands=t.installed.commands.filter(n=>n!==e),await this.save()}async getInstalledSubagents(){return(await this.load()).installed.subagents}async getInstalledCommands(){return(await this.load()).installed.commands}async addInstalledMCPServer(e,t){let n=await this.load();if(n.installed.mcpServers||(n.installed.mcpServers={}),Array.isArray(n.installed.mcpServers)){let s=n.installed.mcpServers,i={};for(let c of s)i[c]={provider:"docker",transport:"stdio",scope:"local",installedAt:new Date().toISOString()};n.installed.mcpServers=i}let r=n.installed.mcpServers;r[e]=t||{provider:"docker",transport:"stdio",scope:"local",installedAt:new Date().toISOString()},await this.save()}async removeInstalledMCPServer(e){let t=await this.load();t.installed.mcpServers&&(Array.isArray(t.installed.mcpServers)?t.installed.mcpServers=t.installed.mcpServers.filter(n=>n!==e):delete t.installed.mcpServers[e],await this.save())}async getInstalledMCPServers(){let e=await this.load();return e.installed.mcpServers?Array.isArray(e.installed.mcpServers)?e.installed.mcpServers:Object.keys(e.installed.mcpServers):[]}async getMCPServerConfig(e){let t=await this.load();return t.installed.mcpServers?Array.isArray(t.installed.mcpServers)?t.installed.mcpServers.includes(e)?{provider:"docker",transport:"stdio",scope:"local",installedAt:new Date().toISOString()}:null:t.installed.mcpServers[e]||null:null}async getAllMCPServerConfigs(){let e=await this.load();if(!e.installed.mcpServers)return{};if(Array.isArray(e.installed.mcpServers)){let t={};for(let n of e.installed.mcpServers)t[n]={provider:"docker",transport:"stdio",scope:"local",installedAt:new Date().toISOString()};return t}else return e.installed.mcpServers}async getRegistryUrl(){return(await this.load()).registry}async isUsingProjectConfig(){return await this.load(),this.isProjectLevel}async getConfigLocation(){return await this.load(),this.configPath||we}async getAllDependencies(){let e=await this.load(),t=await this.getInstalledMCPServers();return{subagents:e.installed.subagents||[],commands:e.installed.commands||[],mcpServers:t}}async getConfig(){return this.config||await this.load(),this.config}getProjectConfig(){if(this.isProjectLevel&&this.config)return this.config;let e=R.join(N.cwd(),"bwc.config.json");if(bt(e))try{return JSON.parse(Pt(e,"utf8"))}catch{return null}return null}async saveConfig(e){return this.config=e,this.save()}async loadUserConfig(){this.config=null,this.forceUser=!0;try{return await this.load()}finally{this.forceUser=!1}}resetToDefault(){this.config=null,this.forceUser=!1}static resetInstance(){o.instance=null}};import F from"chalk";import St from"ora";var a={info:o=>console.log(F.blue("\u2139"),o),success:o=>console.log(F.green("\u2713"),o),error:o=>console.log(F.red("\u2717"),o),warn:o=>console.log(F.yellow("\u26A0"),o),heading:o=>console.log(`
`+F.bold(o)),list:o=>{o.forEach(e=>console.log(` ${F.gray("\u2022")} ${e}`))},code:o=>console.log(F.gray(o)),spinner:o=>St(o).start()};function ke(){return new Mt("init").description("Initialize bwc configuration").option("-f, --force","overwrite existing configuration").option("-p, --project","create project-level configuration").action(async e=>{try{let t=new k,n=e.project,r=n?"project":"global",s=a.spinner(`Initializing ${r} bwc configuration...`);try{await t.init({project:n,force:e.force}),s.succeed(`${r} configuration initialized successfully!`);let i=await t.getConfigLocation();a.info(`Configuration saved to: ${i}`),n?(a.info("Project-level configuration created."),a.info("Subagents and commands will be installed to this project."),a.info(""),a.info("Consider adding .claude/ to your .gitignore:"),a.code('echo ".claude/" >> .gitignore')):a.info('You can now use "bwc add" to install subagents and commands.')}catch(i){throw s.fail(`Failed to initialize ${r} configuration`),i}}catch(t){a.error(t instanceof Error?t.message:"Unknown error"),process.exit(1)}})}import{Command as Qt}from"commander";import $ from"inquirer";import He from"path";import je from"got";import{z as y}from"zod";import{z as g}from"zod";var $t=g.object({exists:g.boolean().optional(),is_directory:g.boolean().optional(),is_file:g.boolean().optional(),pattern:g.string().optional(),min:g.number().optional(),max:g.number().optional(),min_length:g.number().optional(),max_length:g.number().optional(),options:g.array(g.string()).optional()}),kt=g.object({name:g.string(),display_name:g.string(),type:g.enum(["path","string","boolean","number","url","select","password"]),description:g.string(),required:g.boolean().default(!0),default:g.any().optional(),placeholder:g.string().optional(),validation:$t.optional(),env_var:g.string().optional(),arg_position:g.number().optional(),config_path:g.string().optional()}),xt=g.object({type:g.enum(["github","smithery","docker","mcpmarket","manual","community"]),url:g.string().optional(),id:g.string().optional(),last_fetched:g.string().optional(),auto_update:g.boolean().default(!0),verified_by:g.string().optional()}),It=g.object({auth_type:g.enum(["none","oauth2","oauth2.1","api-key"]),permissions:g.array(g.string()),resource_indicators:g.boolean().optional(),elicitation_schema:g.any().nullable().optional()}),jt=g.object({status:g.enum(["verified","community","experimental"]),last_tested:g.string(),tested_with:g.array(g.string()),security_audit:g.boolean().optional()}),Rt=g.object({official:g.string().optional(),docker:g.string().optional(),npm:g.string().optional(),marketplace:g.object({smithery:g.string().url().optional(),mcpmarket:g.string().url().optional()}).optional()}),Dt=g.object({github_stars:g.number().optional(),docker_pulls:g.number().optional(),npm_downloads:g.number().optional(),last_updated:g.string().optional()}),At=g.object({type:g.enum(["docker","npm","manual","binary","bwc","claude-cli"]),recommended:g.boolean().optional(),command:g.string().optional(),config_example:g.string().optional(),steps:g.array(g.string()).optional(),requirements:g.array(g.string()).optional()}),fe=g.object({name:g.string(),display_name:g.string(),category:g.enum(["databases","file-systems","apis","monitoring","development","ai-tools","productivity","web","web-search","browser-automation","memory-management","email-integration","blockchain-crypto","ai-task-management","developer-tools","api-development","version-control","database","file-system","cloud-infrastructure","content-management","social-media","research-education","media-generation","data-extraction","finance-trading","analytics","official","utilities"]),description:g.string(),server_type:g.enum(["stdio","streaming-http","websocket","sse","http"]),protocol_version:g.string(),execution_type:g.enum(["local","remote","hybrid"]).optional(),security:It,sources:Rt,verification:jt,stats:Dt.optional(),installation_methods:g.array(At),config_schema:g.any().optional(),tags:g.array(g.string()).default([]),badges:g.array(g.string()).optional(),file:g.string(),path:g.string(),user_inputs:g.array(kt).optional(),source_registry:xt.optional()}),dn=g.object({$schema:g.string(),version:g.string(),lastUpdated:g.string(),subagents:g.array(g.any()),commands:g.array(g.any()),mcpServers:g.array(fe)});var K={github:{icon:"\u{1F4E6}",label:"GitHub",color:"#24292e",description:"Official MCP Repository"},smithery:{icon:"\u{1F3EA}",label:"Smithery",color:"#7c3aed",description:"Smithery.ai Registry"},docker:{icon:"\u{1F433}",label:"Docker",color:"#2496ed",description:"Docker Hub"},mcpmarket:{icon:"\u{1F6D2}",label:"MCPMarket",color:"#10b981",description:"MCP Market"},manual:{icon:"\u{1F6E0}\uFE0F",label:"Manual",color:"#6b7280",description:"Manually Added"},community:{icon:"\u{1F465}",label:"Community",color:"#f59e0b",description:"Community Contribution"}},q={local:{icon:"\u{1F5A5}\uFE0F",label:"Local",description:"Runs on your machine"},remote:{icon:"\u2601\uFE0F",label:"Remote",description:"Runs on external server"},hybrid:{icon:"\u{1F504}",label:"Hybrid",description:"Can run locally or remotely"}};var _t=y.object({name:y.string(),category:y.string(),description:y.string(),version:y.string().default("1.0.0"),file:y.string(),tools:y.array(y.string()),path:y.string(),tags:y.array(y.string()).default([]),sha:y.string().optional()}),Tt=y.object({name:y.string(),category:y.string(),description:y.string(),version:y.string().default("1.0.0"),file:y.string(),path:y.string(),argumentHint:y.string(),model:y.string(),prefix:y.string().default("/"),tags:y.array(y.string()).default([]),sha:y.string().optional()}),xe=y.object({$schema:y.string().optional(),version:y.string(),lastUpdated:y.string(),subagents:y.array(_t),commands:y.array(Tt),mcpServers:y.array(fe).optional()});import{HttpProxyAgent as Et}from"http-proxy-agent";import{HttpsProxyAgent as Ot}from"https-proxy-agent";function Lt(o,e){if(!e)return!1;let t=new URL(o).hostname.toLowerCase(),n=e.split(",").map(r=>r.trim().toLowerCase());for(let r of n)if(r)if(r.startsWith("*.")){let s=r.slice(2);if(t.endsWith(s))return!0}else{if(t===r||t.endsWith("."+r))return!0;if(r==="localhost"&&(t==="localhost"||t==="127.0.0.1"||t==="::1"))return!0}return!1}function Q(o){let e=o==="https"?process.env.HTTPS_PROXY||process.env.https_proxy:process.env.HTTP_PROXY||process.env.http_proxy;if(e)return e;if(o==="https")return process.env.HTTP_PROXY||process.env.http_proxy}function Nt(o){let e={},t=process.env.NO_PROXY||process.env.no_proxy;if(o&&Lt(o,t))return e;let n=Q("http");n&&(e.httpAgent=new Et(n,{keepAlive:!0,keepAliveMsecs:1e3,maxSockets:256,maxFreeSockets:256}));let r=Q("https");return r&&(e.httpsAgent=new Ot(r,{keepAlive:!0,keepAliveMsecs:1e3,maxSockets:256,maxFreeSockets:256,...process.env.NODE_EXTRA_CA_CERTS?{ca:process.env.NODE_EXTRA_CA_CERTS}:{}})),e}function ge(o){let e=Nt(o);return!e.httpAgent&&!e.httpsAgent?{}:{agent:{...e.httpAgent&&{http:e.httpAgent},...e.httpsAgent&&{https:e.httpsAgent}}}}function ue(){return!!(process.env.HTTP_PROXY||process.env.http_proxy||process.env.HTTPS_PROXY||process.env.https_proxy)}function Ie(){if(!ue())return"No proxy configured";let o=[],e=Q("http"),t=Q("https"),n=process.env.NO_PROXY||process.env.no_proxy;return e&&o.push(`HTTP: ${e}`),t&&t!==e&&o.push(`HTTPS: ${t}`),n&&o.push(`NO_PROXY: ${n}`),o.join(", ")}var _=class o{static instance=null;configManager;constructor(e){this.configManager=e}static getInstance(){return o.instance||(o.instance=new o(k.getInstance())),o.instance}async fetchRegistry(){let e=await this.configManager.getRegistryUrl(),t=ge(e);try{let n=await je(e,t).json();return xe.parse(n)}catch(n){throw n instanceof Error?new Error(`Failed to fetch registry: ${n.message}`):n}}async getSubagents(){return(await this.fetchRegistry()).subagents}async getCommands(){return(await this.fetchRegistry()).commands}async findSubagent(e){return(await this.getSubagents()).find(n=>n.name===e)}async findCommand(e){return(await this.getCommands()).find(n=>n.name===e)}async searchSubagents(e){let t=await this.getSubagents(),n=e.toLowerCase();return t.filter(r=>r.name.toLowerCase().includes(n)||r.description.toLowerCase().includes(n)||r.tags.some(s=>s.toLowerCase().includes(n)))}async searchCommands(e){let t=await this.getCommands(),n=e.toLowerCase();return t.filter(r=>r.name.toLowerCase().includes(n)||r.description.toLowerCase().includes(n)||r.tags.some(s=>s.toLowerCase().includes(n)))}async fetchFileContent(e){let n="https://raw.githubusercontent.com/davepoon/claude-code-subagents-collection/main/"+e,r=ge(n);try{return await je(n,r).text()}catch(s){throw s instanceof Error?new Error(`Failed to fetch file content: ${s.message}`):s}}async getMCPServers(){return(await this.fetchRegistry()).mcpServers||[]}async getMCPServer(e){return(await this.getMCPServers()).find(n=>n.name===e)}async listMCPServers(){return this.getMCPServers()}async searchMCPServers(e){let t=await this.getMCPServers(),n=e.toLowerCase();return t.filter(r=>r.name.toLowerCase().includes(n)||r.display_name.toLowerCase().includes(n)||r.description.toLowerCase().includes(n)||r.tags.some(s=>s.toLowerCase().includes(n))||r.category.toLowerCase().includes(n))}async findMCPServer(e){return(await this.getMCPServers()).find(n=>n.name===e)}};import{execa as ve}from"execa";import Z from"chalk";import{existsSync as Ft,readFileSync as Ut}from"fs";import Vt from"process";function Bt(){try{if(Vt.env.WSL_DISTRO_NAME)return!0;if(Ft("/proc/version")){let o=Ut("/proc/version","utf8").toLowerCase();if(o.includes("microsoft")||o.includes("wsl"))return!0}}catch{}return!1}function x(){return Bt()?"docker.exe":"docker"}async function ee(o,e){switch(e.type){case"docker":await Re(o,e);break;case"npm":await De(o,e);break;case"manual":Ae(o,e);break;case"bwc":await Ht(o,e);break;default:throw new Error(`Unsupported installation method: ${e.type}`)}}async function Re(o,e){try{await ve(x(),["--version"])}catch{throw new Error("Docker is not installed or not running. Please install Docker Desktop and ensure it is running.")}a.info(`
Checking Docker setup for ${o.name}...`);try{let t=o.sources.docker;t&&(a.info(`Docker image to be used: ${t}`),a.info("The image will be pulled automatically when Claude Code starts the MCP server")),a.success("Docker configuration verified")}catch(t){throw t instanceof Error?new Error(`Docker setup failed: ${t.message}`):t}}async function De(o,e){var n,r,s;try{await ve("npm",["--version"])}catch{throw new Error("npm is not installed. Please install Node.js and npm first.")}let t=o.sources.npm;if(!t)throw new Error("No npm package specified for this MCP server");a.info(`
Setting up npm-based MCP server: ${t}`);try{(n=e.config_example)!=null&&n.includes("npx")?(a.info(`${t} will be run using npx when Claude Code starts`),a.info("No pre-installation needed - npx will download and cache the package automatically"),a.success("NPM configuration verified")):(r=e.command)!=null&&r.includes("-g")||(s=e.command)!=null&&s.includes("--global")?(a.info(`Installing ${t} globally...`),await ve("npm",["install","-g",t]),a.success(`Installed ${t} globally`)):(a.info(`${t} will be run using npx`),a.success("NPM configuration verified"))}catch(i){throw i instanceof Error?new Error(`NPM setup failed: ${i.message}`):i}}function Ae(o,e){a.info(`
${Z.bold("Manual installation required for "+o.name)}`),e.requirements&&e.requirements.length>0&&(a.info(`
Requirements:`),e.requirements.forEach(t=>{console.log(` - ${t}`)})),e.steps&&e.steps.length>0&&(a.info(`
Installation steps:`),e.steps.forEach((t,n)=>{console.log(`${n+1}. ${t}`)})),a.info(`
After completing these steps, configure Claude Code with the provided configuration.`)}async function Ht(o,e){let t=o.installation_methods.filter(r=>r.type!=="bwc"),n=t.find(r=>r.recommended);if(n||(n=t.find(r=>r.type==="docker"&&o.sources.docker),n||(n=t.find(r=>r.type==="npm"&&o.sources.npm)),n||(n=t.find(r=>r.type==="manual"))),!n)throw new Error("No suitable installation method found");switch(n.type){case"docker":await Re(o,n);break;case"npm":await De(o,n);break;case"manual":Ae(o,n);break;default:throw new Error(`Unsupported installation method: ${n.type}`)}e._actualMethod=n}async function Wt(){return W()}async function te(o,e,t={scope:"local",envVars:[]}){if(!await Wt()){a.warn("Claude CLI is not installed. Please install Claude Code first."),a.info("Visit https://claude.ai/download to install Claude Code"),pe(e.config_example||"");return}let r=o.installation_methods.find(s=>s.type==="claude-cli");if(r&&r.command)try{let s=r.command.split(" "),i=s.indexOf("mcp"),c=s.indexOf("add");if(i!==-1&&c!==-1){let d=["mcp","add"],l=t.scope||"local";d.push("--scope",l);let m=s.indexOf("--transport");m!==-1&&s[m+1]&&d.push("--transport",s[m+1]);for(let w of t.envVars)d.push("--env",w);let f=c+1;for(;f<s.length&&s[f].startsWith("--");)s[f]==="--transport"||s[f]==="--scope"||s[f]==="--env"?f+=2:f+=1;let v=s[f]||o.name;d.push(v);let p=s.indexOf("--",f);if(p!==-1)d.push("--",...s.slice(p+1));else if(f+1<s.length){let w=s.slice(f+1);w.length>0&&!w[0].startsWith("--")&&d.push(...w)}a.info(`
Configuring MCP server with Claude Code...`),a.info(`Running: claude ${d.join(" ")}`);let C=await j(d);a.success(`MCP server "${o.name}" configured successfully (${l} scope)`),C.stdout&&a.info(C.stdout)}else throw new Error("Invalid claude-cli command format")}catch(s){a.error(`Failed to configure with Claude CLI: ${s.message}`),s.stderr&&a.error(s.stderr),a.info(`
Falling back to manual configuration...`),pe(e.config_example||"")}else a.info(`
No Claude CLI command available for this server.`),pe(e.config_example||"")}function pe(o){if(o){a.info(`
`+Z.bold("Configuration for Claude Desktop:"));try{let e=JSON.parse(o);console.log(Z.gray(JSON.stringify(e,null,2)))}catch{console.log(Z.gray(o))}a.info(`
To use this MCP server:`),a.info("1. Open Claude Desktop settings"),a.info("2. Navigate to Developer > MCP Servers"),a.info("3. Add the above configuration to your MCP settings")}}import _e from"path";async function Te(){let o=_e.join(process.cwd(),".mcp.json");if(!await P(o))return null;try{return await J(o)}catch(e){throw a.error("Failed to read .mcp.json file"),e}}async function Ee(o){let e=_e.join(process.cwd(),".mcp.json");try{await B(e,o),a.success("Updated .mcp.json file")}catch(t){throw a.error("Failed to write .mcp.json file"),t}}async function Y(o,e,t=[]){var s;let n=await Te()||{mcpServers:{}},r;try{if(r=(s=(typeof e=="string"?JSON.parse(e):e).mcpServers)==null?void 0:s[o.name],!r)throw new Error("Invalid configuration format")}catch{throw new Error("Failed to parse server configuration")}if(t.length>0){r.env||(r.env={});for(let i of t){let[c,d]=i.split("=");c&&d!==void 0&&(r.env[c]=d.includes("$")?d:`\${${c}:-${d}}`)}}n.mcpServers[o.name]=r,await Ee(n),a.info(`
Added ${o.name} to .mcp.json`),a.info("This configuration will be available to all team members"),a.info("Remember to commit .mcp.json to version control"),o.verification.status==="experimental"&&(a.warn(`
\u26A0\uFE0F Security Warning:`),a.warn("This is an experimental server. Please review its code and security implications"),a.warn("before committing to version control."))}async function Oe(o){let e=await Te();return!e||!(o in e.mcpServers)?!1:(delete e.mcpServers[o],await Ee(e),a.info(`Removed ${o} from .mcp.json`),!0)}import zt from"inquirer";import oe from"chalk";import Le from"path";import{homedir as Gt}from"os";var ne=class{async collectInputs(e){if(!e.user_inputs||e.user_inputs.length===0)return{};a.info(`
${oe.bold(`Configuring ${e.display_name}`)}`),a.info(`This server requires some configuration:
`);let t={};for(let n of e.user_inputs){let r=await this.promptForInput(n);t[n.name]=r}return t}async applyInputsToConfig(e,t,n){if(!n.user_inputs)return e;let r=JSON.parse(JSON.stringify(e));for(let c of n.user_inputs){let d=t[c.name];if(d!==void 0){if(c.env_var&&this.setNestedValue(r,`mcpServers.${n.name}.env.${c.env_var}`,d),c.arg_position!==void 0){let l=`mcpServers.${n.name}.args`,m=this.getNestedValue(r,l)||[];m[c.arg_position]=d,this.setNestedValue(r,l,m)}c.config_path&&this.setNestedValue(r,c.config_path,d)}}let s=JSON.stringify(r),i=this.replacePlaceholders(s,t);return JSON.parse(i)}async promptForInput(e){var r;let t={type:this.getPromptType(e.type),name:"value",message:`${e.display_name}:`,default:e.default};switch(e.description&&(t.message=`${e.display_name} (${e.description}):`),e.type){case"path":t.validate=async s=>{var i,c,d;if(!s&&e.required)return"This field is required";if(s){let l=this.expandPath(s);if((i=e.validation)!=null&&i.exists&&!await P(l))return`Path does not exist: ${l}`;if((c=e.validation)!=null&&c.is_directory&&l.includes(".")&&l.lastIndexOf(".")>l.lastIndexOf("/"))return"Path must be a directory, not a file";if((d=e.validation)!=null&&d.is_file&&(!l.includes(".")||l.lastIndexOf(".")<l.lastIndexOf("/")))return"Path must be a file, not a directory"}return!0},t.filter=s=>this.expandPath(s);break;case"string":case"password":t.validate=s=>{var i,c,d;return!s&&e.required?"This field is required":s&&((i=e.validation)!=null&&i.pattern)&&!new RegExp(e.validation.pattern).test(s)?`Value must match pattern: ${e.validation.pattern}`:s&&((c=e.validation)!=null&&c.min_length)&&s.length<e.validation.min_length?`Minimum length is ${e.validation.min_length}`:s&&((d=e.validation)!=null&&d.max_length)&&s.length>e.validation.max_length?`Maximum length is ${e.validation.max_length}`:!0};break;case"number":t.validate=s=>{var c,d;let i=parseFloat(s);return isNaN(i)?"Please enter a valid number":((c=e.validation)==null?void 0:c.min)!==void 0&&i<e.validation.min?`Minimum value is ${e.validation.min}`:((d=e.validation)==null?void 0:d.max)!==void 0&&i>e.validation.max?`Maximum value is ${e.validation.max}`:!0},t.filter=s=>parseFloat(s);break;case"boolean":t.default=e.default!==void 0?e.default:!1;break;case"url":t.validate=s=>{if(!s&&e.required)return"This field is required";if(s)try{return new URL(s),!0}catch{return"Please enter a valid URL"}return!0};break;case"select":(r=e.validation)!=null&&r.options&&(t.type="list",t.choices=e.validation.options);break}e.placeholder&&(t.message+=oe.gray(` (e.g., ${e.placeholder})`));let{value:n}=await zt.prompt([t]);return n}getPromptType(e){switch(e){case"password":return"password";case"boolean":return"confirm";case"select":return"list";default:return"input"}}expandPath(e){return e.startsWith("~/")&&(e=Le.join(Gt(),e.slice(2))),e=e.replace(/\$([A-Z_]+[A-Z0-9_]*)/g,(t,n)=>process.env[n]||`$${n}`),Le.resolve(e)}replacePlaceholders(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]!==void 0?t[r]:n)}getNestedValue(e,t){return t.split(".").reduce((n,r)=>n==null?void 0:n[r],e)}setNestedValue(e,t,n){let r=t.split("."),s=r.pop(),i=r.reduce((c,d)=>(c[d]||(c[d]={}),c[d]),e);i[s]=n}async validateInputs(e,t){var r,s,i,c;let n=[];if(!t.user_inputs)return{valid:!0,errors:[]};for(let d of t.user_inputs){let l=e[d.name];if(d.required&&(l==null||l==="")){n.push(`${d.display_name} is required`);continue}if(l)switch(d.type){case"path":if((r=d.validation)!=null&&r.exists){let m=this.expandPath(l);await P(m)||n.push(`${d.display_name}: Path does not exist - ${m}`)}break;case"string":case"password":(s=d.validation)!=null&&s.pattern&&(new RegExp(d.validation.pattern).test(l)||n.push(`${d.display_name}: Does not match required pattern`));break;case"number":typeof l!="number"?n.push(`${d.display_name}: Must be a number`):(((i=d.validation)==null?void 0:i.min)!==void 0&&l<d.validation.min&&n.push(`${d.display_name}: Must be at least ${d.validation.min}`),((c=d.validation)==null?void 0:c.max)!==void 0&&l>d.validation.max&&n.push(`${d.display_name}: Must be at most ${d.validation.max}`));break;case"url":try{new URL(l)}catch{n.push(`${d.display_name}: Must be a valid URL`)}break}}return{valid:n.length===0,errors:n}}showInputSummary(e,t){if(!(!t.user_inputs||Object.keys(e).length===0)){a.info(`
`+oe.bold("Configuration Summary:"));for(let n of t.user_inputs){let r=e[n.name];if(r!==void 0){let s=n.type==="password"?"********":r;a.info(` ${n.display_name}: ${oe.cyan(s)}`)}}a.info("")}}};function re(o,e){let t={mcpServers:{[o]:{}}},n=t.mcpServers[o];return e.transport==="stdio"?(e.command&&(n.command=e.command),e.args&&(n.args=e.args),e.env&&(n.env=e.env)):(e.transport==="sse"||e.transport==="http")&&(n.type=e.transport,e.url&&(n.url=e.url),e.headers&&(n.headers=e.headers),e.env&&(n.env=e.env)),t}function ae(o){return o.scope==="project"&&o.provider!=="docker"}import{execa as E}from"execa";var se={ai:{id:"ai",name:"AI & ML",icon:"\u{1F916}",description:"AI models, LLMs, and machine learning services"},data:{id:"data",name:"Data & Databases",icon:"\u{1F5C4}\uFE0F",description:"Databases, data processing, and analytics"},devops:{id:"devops",name:"DevOps",icon:"\u{1F527}",description:"CI/CD, build tools, and monitoring"},productivity:{id:"productivity",name:"Productivity",icon:"\u{1F4DD}",description:"Task management, note-taking, and documentation"},communication:{id:"communication",name:"Communication",icon:"\u{1F4AC}",description:"Chat, email, and messaging platforms"},search:{id:"search",name:"Search",icon:"\u{1F50D}",description:"Search engines, indexing, and discovery"},security:{id:"security",name:"Security",icon:"\u{1F512}",description:"Security scanning, authentication, and compliance"},cloud:{id:"cloud",name:"Cloud",icon:"\u2601\uFE0F",description:"Cloud providers and infrastructure"},api:{id:"api",name:"APIs",icon:"\u{1F50C}",description:"API management, REST, and GraphQL"},browser:{id:"browser",name:"Browser & Web",icon:"\u{1F310}",description:"Web automation and scraping"},finance:{id:"finance",name:"Finance",icon:"\u{1F4B0}",description:"Financial data, trading, and crypto"},media:{id:"media",name:"Media",icon:"\u{1F3AC}",description:"Audio, video, and image processing"},other:{id:"other",name:"Other",icon:"\u{1F4E6}",description:"Miscellaneous tools and services"}};function he(o,e){let t=`${o} ${e}`.toLowerCase();return t.match(/\b(ai|artificial intelligence|llm|gpt|claude|model|machine learning|ml|neural|deep learning|nlp|natural language|vision|opencv|tensorflow|pytorch|hugging|transformer|bert|embedding|vector|semantic|chatbot|assistant)\b/)?"ai":t.match(/\b(database|db|sql|sqlite|mysql|postgres|postgresql|mongo|mongodb|redis|elastic|elasticsearch|clickhouse|couchbase|cockroach|astra|cassandra|dynamo|firestore|supabase|prisma|orm|data warehouse|analytics|etl|bigquery|snowflake|databricks|spark|hadoop)\b/)?"data":t.match(/\b(aws|amazon web|azure|gcp|google cloud|cloud|terraform|cdk|cloudformation|kubernetes|k8s|docker|container|serverless|lambda|functions|ec2|s3|vpc|iam|infrastructure|iaas|paas|saas|deployment|provision)\b/)?"cloud":t.match(/\b(github|gitlab|git|version control|ci|cd|continuous|jenkins|circleci|buildkite|travis|pipeline|build|deploy|devops|monitoring|logging|observability|metrics|grafana|prometheus|datadog|new relic|sentry|rollbar|automation)\b/)?"devops":t.match(/\b(security|auth|authentication|authorization|oauth|jwt|token|certificate|ssl|tls|encryption|decrypt|hash|vulnerability|scan|audit|compliance|firewall|vpn|penetration|pentest|beagle|shodan|nmap|metasploit|burp|owasp|cve|threat|malware|virus|antivirus|password|credential|secret|vault|keychain)\b/)?"security":t.match(/\b(api|rest|restful|graphql|openapi|swagger|webhook|endpoint|http|https|request|response|postman|insomnia|soap|rpc|grpc|websocket|socket|integration|connector|gateway|proxy|rate limit|throttle)\b/)?"api":t.match(/\b(search|index|indexing|elastic|algolia|solr|lucene|query|find|discover|explore|brave search|google search|bing|duckduckgo|retrieval|rag|vector search|similarity|relevance|ranking)\b/)?"search":t.match(/\b(slack|discord|teams|telegram|whatsapp|sms|email|mail|smtp|imap|twilio|sendgrid|mailgun|chat|message|messaging|notification|alert|webhook|communication|collaborate|conversation)\b/)?"communication":t.match(/\b(notion|todo|task|project|jira|confluence|atlassian|asana|trello|monday|clickup|linear|airtable|spreadsheet|excel|sheets|docs|document|wiki|knowledge|note|notebook|markdown|obsidian|roam|productivity|workflow|automation|zapier|ifttt|make|n8n)\b/)?"productivity":t.match(/\b(browser|chrome|firefox|safari|edge|web|scrape|scraping|crawl|crawler|puppeteer|playwright|selenium|webdriver|automation|bot|headless|dom|html|css|javascript|jquery|react|vue|angular|website|webpage)\b/)?"browser":t.match(/\b(finance|financial|trading|trade|stock|equity|forex|crypto|cryptocurrency|bitcoin|ethereum|blockchain|defi|nft|market|ticker|price|portfolio|investment|banking|payment|stripe|paypal|square|plaid|coinbase|binance|kraken)\b/)?"finance":t.match(/\b(video|audio|image|media|youtube|vimeo|spotify|soundcloud|mp3|mp4|avi|mov|jpg|jpeg|png|gif|svg|pdf|ffmpeg|transcod|stream|broadcast|podcast|music|photo|picture|gallery|edit|filter|compress|resize|thumbnail)\b/)?"media":t.match(/\b(arxiv|research|paper|academic|journal|publication|scholar|pubmed|doi|citation|bibliography|latex|scientific|study|experiment|hypothesis|peer review)\b/)?"ai":t.match(/\b(documentation|docs|manual|guide|tutorial|reference|wiki|knowledge base|help|support|faq|readme|context|atlas-docs)\b/)?"productivity":"other"}function ye(o){return se[o]||se.other}function Jt(o){return o.replace(/\u001b\[[0-9;]*m/g,"")}function ie(o){var r;let e=o.split(`
`),t=[],n=null;for(let s=0;s<e.length;s++){let i=e[s],c=Jt(i).trim();if(!c||c.includes("MCP Server Directory")||c.includes("servers available")||c.match(/^[─-]+$/))continue;let d=c.match(/^([a-zA-Z0-9_-]+):\s*(.+)$/);if(d){t.push({name:d[1],description:d[2]});continue}let l=((r=i.match(/^( *)/))==null?void 0:r[1].length)||0;l===2&&c.length>0?(n&&n.name&&t.push(n),n={name:c,description:""}):n&&l>=4&&c.length>0&&(n.description&&(n.description+=" "),n.description+=c)}return n&&n.name&&t.push(n),t}async function qt(){try{let{stdout:o}=await E(x(),["--version"]);return o.includes("Docker version")}catch{return!1}}async function Yt(){try{let{stdout:o}=await E(x(),["mcp","--version"]);return!0}catch{return!1}}async function ce(o="project"){a.info("Setting up Docker MCP Toolkit gateway...");try{let e=["mcp","add","docker-toolkit","--scope",o,"--",x(),"mcp","gateway","run"],{stdout:t}=await j(e);a.success("Docker MCP gateway configured in Claude Code"),t&&a.info(t),a.info(`
\u2139\uFE0F Restart Claude Code to activate the Docker MCP gateway`)}catch(e){throw new Error(`Failed to setup Docker MCP gateway: ${e.message}`)}}async function Ne(){try{let{stdout:o}=await E(x(),["mcp","catalog","show"]);return ie(o).map(t=>t.name)}catch(o){return a.warn("Failed to fetch Docker MCP catalog"),a.debug(`Error details: ${o.message}`),[]}}async function D(){try{let{stdout:o}=await E(x(),["mcp","server","list"]);return!o||o.trim()===""?[]:o.split(",").map(e=>e.trim()).filter(Boolean)}catch{return a.warn("Failed to list installed Docker MCP servers"),[]}}async function le(o){a.info(`Enabling Docker MCP server: ${o}`);try{await E(x(),["mcp","server","enable",o]),a.success(`Server "${o}" enabled in Docker MCP Toolkit`),(await D()).includes(o)&&a.success(`\u2713 Server "${o}" is now available through the Docker MCP gateway`)}catch(e){throw new Error(`Failed to enable server "${o}": ${e.message}`)}}async function Fe(o){a.info(`Disabling Docker MCP server: ${o}`);try{await E(x(),["mcp","server","disable",o]),a.success(`Server "${o}" disabled in Docker MCP Toolkit`)}catch(e){throw new Error(`Failed to disable server "${o}": ${e.message}`)}}async function Ue(o){try{let{stdout:e}=await E(x(),["mcp","catalog","show"]),n=ie(e).find(r=>r.name===o);return n?n.description:null}catch{return null}}async function A(){let o=await qt(),e=o&&await Yt(),t=!1;try{let{stdout:r}=await j(["mcp","get","docker-toolkit"]);t=r.includes("Connected")}catch{}let n=e?await D():[];return{dockerInstalled:o,mcpToolkitAvailable:e,gatewayConfigured:t,installedServers:n}}async function Ve(o){try{let{stdout:e}=await E(x(),["mcp","catalog","show"]),t=ie(e),n=[],r=o.toLowerCase();for(let s of t)(s.name.toLowerCase().includes(r)||s.description.toLowerCase().includes(r))&&n.push({name:s.name,description:s.description,category:he(s.name,s.description),dockerHubUrl:`https://hub.docker.com/r/mcp/${s.name}`});return n}catch(e){return a.warn("Failed to search Docker MCP catalog"),a.debug(`Error details: ${e.message}`),[]}}async function Xt(){try{let{stdout:o}=await E(x(),["mcp","catalog","show"]);return ie(o)}catch(o){return a.warn("Failed to fetch Docker MCP catalog"),a.debug(`Error details: ${o.message}`),[]}}async function Kt(){return(await Xt()).map(e=>({name:e.name,description:e.description,category:he(e.name,e.description),dockerHubUrl:`https://hub.docker.com/r/mcp/${e.name}`}))}async function Be(){let o=await Kt(),e={};for(let t of o)e[t.category]||(e[t.category]=[]),e[t.category].push(t);return e}function We(){return new Qt("add").description("Add subagents, commands, or MCP servers").option("-a, --agent <name>","add a specific subagent").option("-c, --command <name>","add a specific command").option("-m, --mcp <name>","add a specific MCP server").option("-u, --user","force user-level installation (for subagents/commands)").option("-p, --project","force project-level installation (for subagents/commands)").option("-s, --scope <scope>",'configuration scope for MCP servers: local, user, or project (default: "local")').option("-e, --env <env...>","set environment variables for MCP servers (e.g. -e KEY=value)").option("--setup","setup Docker MCP gateway in Claude Code").option("--docker-mcp","use Docker MCP Toolkit for MCP servers").option("--transport <type>","transport type for MCP servers: stdio, sse, or http").option("--url <url>","URL for remote MCP servers (required for sse/http transport)").option("--header <header...>",'headers for remote MCP servers (e.g. --header "Authorization: Bearer token")').action(async e=>{try{let t=k.getInstance(),n=new _(t);ue()&&a.info(`Using proxy: ${Ie()}`);let r=e.user,s=e.project,i;if(s?(t.getProjectConfig()||(a.error('No project configuration found. Run "bwc init --project" first.'),process.exit(1)),i=!0,a.info("Installing to project configuration")):r?(await t.loadUserConfig(),i=!1,a.info("Installing to user configuration")):(i=await t.isUsingProjectConfig(),i&&a.info("Installing to project configuration")),e.setup){await ro(e.scope||"project");return}if(e.agent)await ze(e.agent,t,n,r,s);else if(e.command)await Ge(e.command,t,n,r,s);else if(e.mcp){let c=["local","user","project"],d=e.scope||"local";if(!c.includes(d))throw new Error(`Invalid scope: ${d}. Must be one of: ${c.join(", ")}`);e.dockerMcp?await Ye(e.mcp,t,d):e.transport||e.url?await qe(e.mcp,t,{scope:d,transport:e.transport,url:e.url,headers:e.header||[],envVars:e.env||[]}):await Je(e.mcp,t,n,{scope:d,envVars:e.env||[]})}else await Zt(t,n,r,s)}catch(t){a.error(t instanceof Error?t.message:"Unknown error"),process.exit(1)}})}async function ze(o,e,t,n=!1,r=!1){let s=a.spinner(`Fetching subagent: ${o}`);try{let i=await t.findSubagent(o);if(!i){s.fail(`Subagent "${o}" not found`);return}s.text=`Downloading ${i.name}...`;let c=await t.fetchFileContent(i.file),d=await e.getSubagentsPath(),l=He.join(d,`${i.name}.md`),{fileExists:m}=await import("./files-5RZ6LETJ.js");if(await m(l)){s.stop();let{action:f}=await $.prompt([{type:"list",name:"action",message:`Subagent "${i.name}" already exists. What would you like to do?`,choices:[{name:"Overwrite - Replace the existing file with the new one",value:"overwrite"},{name:"Skip - Skip this item and continue with other installations",value:"skip"},{name:"Abort - Stop the entire installation process",value:"abort"}]}]);if(f==="skip"){a.info(`Skipped subagent: ${i.name}`);return}else f==="abort"&&(a.info("Installation aborted"),process.exit(0));s.start(`Installing ${i.name}...`)}await V(l,c),await e.addInstalledSubagent(i.name),s.succeed(`Successfully installed subagent: ${i.name}`),a.info(`Location: ${l}`),a.info(`Tools: ${i.tools.join(", ")}`)}catch(i){throw s.fail("Failed to add subagent"),i}}async function Ge(o,e,t,n=!1,r=!1){let s=a.spinner(`Fetching command: ${o}`);try{let i=await t.findCommand(o);if(!i){s.fail(`Command "${o}" not found`);return}s.text=`Downloading ${i.name}...`;let c=await t.fetchFileContent(i.file),d=await e.getCommandsPath(),l=He.join(d,`${i.name}.md`),{fileExists:m}=await import("./files-5RZ6LETJ.js");if(await m(l)){s.stop();let{action:f}=await $.prompt([{type:"list",name:"action",message:`Command "${i.name}" already exists. What would you like to do?`,choices:[{name:"Overwrite - Replace the existing file with the new one",value:"overwrite"},{name:"Skip - Skip this item and continue with other installations",value:"skip"},{name:"Abort - Stop the entire installation process",value:"abort"}]}]);if(f==="skip"){a.info(`Skipped command: ${i.name}`);return}else f==="abort"&&(a.info("Installation aborted"),process.exit(0));s.start(`Installing ${i.name}...`)}await V(l,c),await e.addInstalledCommand(i.name),s.succeed(`Successfully installed command: ${i.prefix}${i.name}`),a.info(`Location: ${l}`)}catch(i){throw s.fail("Failed to add command"),i}}async function Zt(o,e,t=!1,n=!1){try{let{type:r}=await $.prompt([{type:"list",name:"type",message:"What would you like to add?",choices:[{name:"Subagent",value:"subagent"},{name:"Command",value:"command"},{name:"MCP Server",value:"mcp"}]}]);r==="subagent"?await eo(o,e,t,n):r==="command"?await to(o,e,t,n):await oo(o,e)}catch(r){if(r instanceof Error&&r.message.includes("fetch registry"))a.error("Failed to connect to registry. Please check your internet connection."),a.info("Registry URL: "+await o.getRegistryUrl());else throw r}}async function eo(o,e,t=!1,n=!1){let r=await e.getSubagents(),s=[...new Set(r.map(l=>l.category))].sort(),{category:i}=await $.prompt([{type:"list",name:"category",message:"Select a category:",choices:["All",...s]}]),c=i==="All"?r:r.filter(l=>l.category===i);a.info("Use SPACE to select/deselect, ENTER to confirm");let{selected:d}=await $.prompt([{type:"checkbox",name:"selected",message:"Select subagents to install:",choices:c.map(l=>({name:`${l.name} - ${l.description}`,value:l.name,short:l.name})),validate:l=>l.length<1?"You must select at least one subagent!":!0}]);if(!d||d.length===0){a.warn("No subagents selected");return}a.info(`Installing ${d.length} subagent(s)...`);for(let l of d)await ze(l,o,e,t,n)}async function to(o,e,t=!1,n=!1){let r=await e.getCommands(),s=[...new Set(r.map(l=>l.category))].sort(),{category:i}=await $.prompt([{type:"list",name:"category",message:"Select a category:",choices:["All",...s]}]),c=i==="All"?r:r.filter(l=>l.category===i);a.info("Use SPACE to select/deselect, ENTER to confirm");let{selected:d}=await $.prompt([{type:"checkbox",name:"selected",message:"Select commands to install:",choices:c.map(l=>({name:`${l.prefix}${l.name} - ${l.description}`,value:l.name,short:l.name})),validate:l=>l.length<1?"You must select at least one command!":!0}]);if(!d||d.length===0){a.warn("No commands selected");return}a.info(`Installing ${d.length} command(s)...`);for(let l of d)await Ge(l,o,e,t,n)}async function Je(o,e,t,n={scope:"local",envVars:[]}){let r=a.spinner(`Fetching MCP server: ${o}`);try{let s=await t.findMCPServer(o);if(!s){r.fail(`MCP server "${o}" not found`);return}r.stop(),a.info(`
${s.display_name} - ${s.description}`),a.info(`Verification: ${s.verification.status}`),s.verification.status==="experimental"&&a.warn("\u26A0\uFE0F This is an experimental server. Use with caution.");let i=s.installation_methods.find(l=>l.type==="claude-cli"&&l.recommended);if(i||(s.user_inputs&&s.user_inputs.length>0?i=s.installation_methods.find(l=>l.type!=="bwc"&&l.recommended)||s.installation_methods.find(l=>l.type!=="bwc"):i=s.installation_methods.find(l=>l.recommended)||s.installation_methods[0]),!i){a.error("No installation methods available for this server");return}let c={},d=i.config_example;if(s.user_inputs&&s.user_inputs.length>0){r.stop();let l=new ne;c=await l.collectInputs(s);let m=await l.validateInputs(c,s);if(!m.valid)throw a.error("Invalid inputs:"),m.errors.forEach(f=>a.error(` - ${f}`)),new Error("Invalid configuration inputs");if(l.showInputSummary(c,s),i.config_example)try{let f=JSON.parse(i.config_example),v=await l.applyInputsToConfig(f,c,s);d=JSON.stringify(v,null,2),i={...i,config_example:d}}catch(f){a.warn("Could not apply user inputs to config automatically"),a.warn(`Error: ${f instanceof Error?f.message:String(f)}`)}r.start()}r.text=`Installing ${s.name} using ${i.type}...`;try{await ee(s,i),r.succeed(`Successfully installed ${s.name}`),n.scope==="project"&&await Y(s,d,n.envVars),await e.addInstalledMCPServer(s.name),await te(s,i,n),a.info(`
MCP server configured with ${n.scope} scope`),n.scope==="project"?a.info("The server is now available to all team members via .mcp.json"):n.scope==="user"?a.info("The server is now available across all your projects"):a.info("The server is available for this project only")}catch(l){throw r.fail(`Failed to install ${s.name}`),l}}catch(s){throw r.isSpinning&&r.fail("Failed to add MCP server"),s}}async function qe(o,e,t){let n=a.spinner(`Adding remote MCP server: ${o}`);try{if(t.transport&&!["stdio","sse","http"].includes(t.transport))throw new Error(`Invalid transport: ${t.transport}. Must be stdio, sse, or http`);if((t.transport==="sse"||t.transport==="http")&&!t.url)throw new Error(`URL is required for ${t.transport} transport`);n.stop(),a.info(`
Adding remote MCP server: ${o}`),a.info(`Transport: ${t.transport||"stdio"}`),t.url&&a.info(`URL: ${t.url}`),a.info(`Scope: ${t.scope}`);let r={};if(t.headers)for(let l of t.headers){let[m,...f]=l.split(":");m&&f.length>0&&(r[m.trim()]=f.join(":").trim())}let s={};if(t.envVars)for(let l of t.envVars){let[m,f]=l.split("=");m&&f&&(s[m]=f)}n.start();let i={provider:"claude",transport:t.transport||"stdio",scope:t.scope,installedAt:new Date().toISOString(),...t.url&&{url:t.url},...Object.keys(r).length>0&&{headers:r},...Object.keys(s).length>0&&{env:s}};await e.addInstalledMCPServer(o,i);let{isClaudeCLIAvailable:c,execClaudeCLI:d}=await import("./claude-cli-3CK2S7LO.js");if(await c()){n.text=`Configuring ${o} in Claude Code...`;let l=["mcp","add","--scope",t.scope];t.transport&&l.push("--transport",t.transport);for(let[m,f]of Object.entries(r))l.push("--header",`${m}: ${f}`);for(let[m,f]of Object.entries(s))l.push("--env",`${m}=${f}`);l.push(o),t.url&&l.push(t.url);try{await d(l),n.succeed(`Successfully configured ${o} in Claude Code`)}catch{n.warn("Could not configure in Claude Code automatically"),a.info("Please restart Claude Code to apply changes")}}else n.succeed("Server configuration saved"),a.info(`
Claude CLI not found. Please install it to configure servers automatically:`),a.info("npm install -g @anthropic/claude-cli");if(a.info(`
Remote MCP server configured with ${t.scope} scope`),ae(i)){let l=re(o,i);await Y({name:o,verification:{status:"community"}},JSON.stringify(l),[])}}catch(r){throw n.fail("Failed to add remote MCP server"),r}}async function oo(o,e){let t=await A();if(t.dockerInstalled&&t.mcpToolkitAvailable){let{provider:p}=await $.prompt([{type:"list",name:"provider",message:"Select MCP provider:",choices:[{name:"Docker MCP (containerized local servers)",value:"docker"},{name:"Claude CLI (remote servers via SSE/HTTP)",value:"claude"}]}]);if(p==="docker"){await ao(o);return}else if(p==="claude"){await no(o);return}}let{scope:r}=await $.prompt([{type:"list",name:"scope",message:"Select configuration scope for MCP servers:",choices:[{name:"Local (this project only)",value:"local"},{name:"Project (shared with team via .mcp.json)",value:"project"},{name:"User (across all your projects)",value:"user"}],default:"local"}]),s=await e.getMCPServers(),i=s.reduce((p,C)=>{let w=C.verification.status;return p[w]||(p[w]=[]),p[w].push(C),p},{}),{verification:c}=await $.prompt([{type:"list",name:"verification",message:"Select verification status:",choices:["All","verified","community","experimental"]}]),d=c==="All"?s:i[c]||[];a.info("Use SPACE to select/deselect, ENTER to confirm");let{selected:l}=await $.prompt([{type:"checkbox",name:"selected",message:"Select MCP servers to install:",choices:d.map(p=>({name:`${p.name} - ${p.description}`,value:p.name,short:p.name})),validate:p=>p.length<1?"You must select at least one MCP server!":!0}]);if(!l||l.length===0){a.warn("No MCP servers selected");return}let m=[];if(r==="project"){let{hasEnvVars:p}=await $.prompt([{type:"confirm",name:"hasEnvVars",message:"Do you need to set environment variables?",default:!1}]);if(p){let{envInput:C}=await $.prompt([{type:"input",name:"envInput",message:"Enter environment variables (e.g., API_KEY=value SECRET=value):",validate:w=>w.trim()?!0:"Please enter at least one environment variable"}]);m=C.split(" ").filter(w=>w.includes("="))}}a.info(`Installing ${l.length} MCP server(s) with ${r} scope...`);let f=0,v=0;for(let p of l)try{await Je(p,o,e,{scope:r,envVars:m}),f++}catch(C){a.error(`Failed to install ${p}: ${C instanceof Error?C.message:"Unknown error"}`),v++}f>0&&a.success(`
Successfully installed ${f} MCP server(s)`),v>0&&a.warn(`Failed to install ${v} MCP server(s)`)}async function no(o){a.heading("Add Remote MCP Server");let{name:e,transport:t}=await $.prompt([{type:"input",name:"name",message:"Server name:",validate:d=>d.trim()?!0:"Server name is required"},{type:"list",name:"transport",message:"Transport type:",choices:[{name:"SSE (Server-Sent Events)",value:"sse"},{name:"HTTP (REST API)",value:"http"},{name:"STDIO (Standard I/O)",value:"stdio"}]}]),n,r=[];if(t==="sse"||t==="http"){let{serverUrl:d,hasHeaders:l}=await $.prompt([{type:"input",name:"serverUrl",message:"Server URL:",validate:m=>{if(!m.trim())return"URL is required for "+t;try{return new URL(m),!0}catch{return"Please enter a valid URL"}}},{type:"confirm",name:"hasHeaders",message:"Do you need to add authentication headers?",default:!1}]);if(n=d,l){let m=!0;for(;m;){let{header:f,more:v}=await $.prompt([{type:"input",name:"header",message:'Enter header (e.g., "Authorization: Bearer token"):',validate:p=>p.includes(":")?!0:'Header must be in format "Key: Value"'},{type:"confirm",name:"more",message:"Add another header?",default:!1}]);r.push(f),m=v}}}let{scope:s}=await $.prompt([{type:"list",name:"scope",message:"Configuration scope:",choices:[{name:"Local (this project only)",value:"local"},{name:"User (across all projects)",value:"user"},{name:"Project (shared with team)",value:"project"}],default:"local"}]),{hasEnvVars:i}=await $.prompt([{type:"confirm",name:"hasEnvVars",message:"Do you need to set environment variables?",default:!1}]),c=[];if(i){let{envInput:d}=await $.prompt([{type:"input",name:"envInput",message:"Enter environment variables (e.g., API_KEY=value SECRET=value):",validate:l=>l.trim()?!0:"Please enter at least one environment variable"}]);c=d.split(" ").filter(l=>l.includes("="))}await qe(e,o,{scope:s,transport:t,url:n,headers:r,envVars:c})}async function ro(o){a.heading("Setting up Docker MCP Gateway");try{await ce(o),a.success(`
\u2705 Docker MCP gateway configured!`),a.info(`
Next steps:`),a.info("1. Restart Claude Code to activate the gateway"),a.info('2. Run "bwc add --mcp <server-name>" to add servers'),a.info('3. Or run "bwc add" for interactive mode')}catch(e){a.error(`Failed to setup gateway: ${e.message}`)}}async function Ye(o,e,t="local"){let n=a.spinner(`Adding Docker MCP server: ${o}`);try{let r=await Ue(o);if(!r){n.fail(`Server "${o}" not found in Docker MCP catalog`),a.info('Run "bwc list --mcps" to see available servers');return}if(n.stop(),