@agimon-ai/po-mcp-proxy 0.0.1-alpha.24 → 0.0.1-alpha.26
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/dist/cli.cjs +4 -4
- package/dist/cli.mjs +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +1 -1
- package/dist/src-B7q2gdrL.mjs +72 -0
- package/dist/src-Cs1NjdyA.cjs +72 -0
- package/package.json +2 -2
- package/dist/src-CJDMGW8P.mjs +0 -72
- package/dist/src-CnZh2vG2.cjs +0 -72
package/dist/cli.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const e=require("./src-
|
|
2
|
+
const e=require("./src-Cs1NjdyA.cjs");let t=require("node:fs/promises"),n=require("node:path"),r=require("node:crypto"),i=require("@agimon-ai/foundation-process-registry"),a=require("js-yaml");a=e.ft(a,1);let o=require("@agimon-ai/foundation-port-registry"),s=require("liquidjs"),c=require("commander"),l=require("node:fs");function u(e){return`runtime:${e}`}function d(e){return e instanceof Error?e.message:String(e)}async function f(e){let t=await e.listProcesses({serviceName:`mcp-proxy-http`,liveOnly:!0}),n=/* @__PURE__ */ new Set;for(let e of t){let t=e.metadata?.serverId;typeof t==`string`&&n.add(t)}return n}async function p(e,t){let n=await e.listProcesses({serviceType:`tool`,tags:[`mcp-proxy-stdio-http-bridge`],liveOnly:!0}),r=u(t);return n.filter(e=>e.tags?.includes(r)).length}async function m(t){let n=t.probe??(async(t,n)=>(await e.b(t,n)).ok),r={stopped:[],removedFiles:[],kept:[]},i=await f(t.processRegistry),a=await t.runtimeStateService.listOrphans(i);for(let e of a){let i={serverId:e.serverId,host:e.host,port:e.port,reason:``};if(!await n(e.host,e.port)){i.reason=`unreachable runtime; removed stale state file`,t.dryRun||await t.runtimeStateService.remove(e.serverId),r.removedFiles.push(i);continue}if(e.runtimeLifecycle!==`stdio-http-managed`){i.reason=`manual runtime; left untouched`,r.kept.push(i);continue}let a=await p(t.processRegistry,e.serverId);if(a>0)i.reason=`managed runtime with ${a} live bridge(s); kept`,r.kept.push(i);else{if(i.reason=`orphaned stdio-http-managed runtime (no live bridges); stopped`,!t.dryRun)try{await t.stopServerService.stop({serverId:e.serverId,force:!0}),await t.runtimeStateService.remove(e.serverId).catch(()=>void 0)}catch(e){i.reason=`failed to stop orphaned runtime: ${d(e)}`,r.kept.push(i);continue}r.stopped.push(i)}}return r}function h(e,t){let n=t?`Would stop`:`Stopped`;for(let t of e.stopped)console.log(`${n} orphaned runtime '${t.serverId}' (http://${t.host}:${t.port}) — ${t.reason}`);let r=t?`Would remove`:`Removed`;for(let t of e.removedFiles)console.log(`${r} stale state for '${t.serverId}' (http://${t.host}:${t.port})`);for(let t of e.kept)console.log(`Kept '${t.serverId}' (http://${t.host}:${t.port}) — ${t.reason}`);console.log(`Summary: ${e.stopped.length} stopped, ${e.removedFiles.length} stale file(s), ${e.kept.length} kept.`)}const g=new c.Command(`cleanup`).description(`Reap orphaned/stale mcp-proxy HTTP runtimes and their leftover state files`).option(`-n, --dry-run`,`Report what would be done without stopping or removing anything`,!1).option(`-j, --json`,`Output as JSON`,!1).action(async t=>{try{let n=await m({runtimeStateService:new e.T,processRegistry:new i.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH),stopServerService:new e.C,dryRun:t.dryRun});if(t.json){console.log(JSON.stringify({dryRun:t.dryRun,...n},null,2));return}h(n,t.dryRun)}catch(e){let n=`Error executing cleanup: ${d(e)}`;t.json?console.log(JSON.stringify({ok:!1,error:n},null,2)):console.error(n),process.exit(1)}});function _(e){return e instanceof Error?e.message:String(e)}async function v(e,t){try{return(await fetch(`http://${e}:${t}/health`,{signal:AbortSignal.timeout(3e3)})).ok}catch{return!1}}async function y(t,n,r,i,a){let o=n.proxy?.host??`localhost`,s=n.proxy?.port,c=`http://${o}:${s}/mcp`;await v(o,s)||(i.json||console.error(`Starting HTTP proxy server in background...`),await e.y({host:o,port:s,config:r,cache:i.useCache!==!1,clearDefinitionsCache:!1,proxyMode:`flat`}));let l=await t.createClientManagerService();try{await l.connectToServer(`proxy`,{name:`proxy`,transport:`http`,config:{url:c}}),i.json||console.error(`✓ Connected to proxy at ${c}`)}catch(e){throw Error(`Failed to connect to proxy server at ${c}: ${_(e)}`)}try{return await a({container:t,configFilePaths:r,config:n,clientManager:l})}finally{await l.disconnectAll()}}async function b(e,t,n,r,i){let a=await e.createClientManagerService();if(await Promise.all(Object.entries(t.mcpServers).map(async([e,t])=>{try{await a.connectToServer(e,t),r.json||console.error(`✓ Connected to ${e}`)}catch(t){r.json||console.error(`✗ Failed to connect to ${e}: ${_(t)}`)}})),a.getAllClients().length===0)throw Error(`No MCP servers connected`);try{return await i({container:e,configFilePaths:n,config:t,clientManager:a})}finally{await a.disconnectAll()}}async function x(t,n){let r=(e,t)=>{t===void 0?console.error(e):console.error(e,t)},i=t.json?{trace:r,debug:r,info:r,warn:r,error:r}:console,a=e.o(i),o=e.I(t.config),s=o.length>0?null:await e.P(),c=s?[s]:o;if(c.length===0)throw Error(`No config file found. Use --config or create mcp-config.yaml`);let l=await a.createConfigFetcherService({configSources:e.L(c),useCache:t.useCache}).fetchConfiguration();return l.proxy?.port?await y(a,l,c,t,n):await b(a,l,c,t,n)}function S(e){return e instanceof Error?e.message:String(e)}const C=new c.Command(`describe-tools`).description(`Describe specific MCP tools`).argument(`<toolNames...>`,`Tool names to describe`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await x(t,async({container:n,config:r,clientManager:i})=>{let a=t.server?[i.getClient(t.server)].filter(e=>e!==void 0):i.getAllClients();if(t.server&&a.length===0)throw Error(`Server "${t.server}" not found`);let o=process.env.PROJECT_PATH||process.cwd(),s=r.skills?.paths||[],c=s.length>0?n.createSkillService(o,s):void 0,l=[],u=[],d=[...e],f=await Promise.all(a.map(async e=>{try{return{client:e,tools:await e.listTools(),error:null}}catch(t){return{client:e,tools:[],error:t}}}));for(let{client:n,tools:r,error:i}of f)if(i)t.json||console.error(`Failed to list tools from ${n.serverName}:`,i);else for(let t of e){let e=r.find(e=>e.name===t);if(e){l.push({server:n.serverName,name:e.name,description:e.description,inputSchema:e.inputSchema});let r=d.indexOf(t);r>-1&&d.splice(r,1)}}if(c&&d.length>0){let e=await Promise.all([...d].map(async e=>{let t=e.startsWith(`skill__`)?e.slice(7):e;return{toolName:e,skill:await c.getSkill(t)}}));for(let{toolName:t,skill:n}of e)if(n){u.push({name:n.name,location:n.basePath,instructions:n.content});let e=d.indexOf(t);e>-1&&d.splice(e,1)}}let p=[];if(l.length>0&&p.push(`For MCP tools: Use the use_tool function with toolName and toolArgs based on the inputSchema above.`),u.length>0&&p.push(`For skill, just follow skill's description to continue.`),t.json){let e={};l.length>0&&(e.tools=l),u.length>0&&(e.skills=u),p.length>0&&(e.nextSteps=p),d.length>0&&(e.notFound=d),console.log(JSON.stringify(e,null,2))}else{if(l.length>0){console.log(`
|
|
3
3
|
Found tools:
|
|
4
4
|
`);for(let e of l)console.log(`Server: ${e.server}`),console.log(`Tool: ${e.name}`),console.log(`Description: ${e.description||`No description`}`),console.log(`Input Schema:`),console.log(JSON.stringify(e.inputSchema,null,2)),console.log(``)}if(u.length>0){console.log(`
|
|
5
5
|
Found skills:
|
|
6
6
|
`);for(let e of u)console.log(`Skill: ${e.name}`),console.log(`Location: ${e.location}`),console.log(`Instructions:\n${e.instructions}`),console.log(``)}if(p.length>0){console.log(`
|
|
7
|
-
Next steps:`);for(let e of p)console.log(` • ${e}`);console.log(``)}d.length>0&&console.error(`\nTools/skills not found: ${d.join(`, `)}`),l.length===0&&u.length===0&&(console.error(`No tools or skills found`),process.exit(1))}})}catch(e){console.error(`Error executing describe-tools: ${S(e)}`),process.exit(1)}});function w(e){return e instanceof Error?e.message:String(e)}const ee=new
|
|
7
|
+
Next steps:`);for(let e of p)console.log(` • ${e}`);console.log(``)}d.length>0&&console.error(`\nTools/skills not found: ${d.join(`, `)}`),l.length===0&&u.length===0&&(console.error(`No tools or skills found`),process.exit(1))}})}catch(e){console.error(`Error executing describe-tools: ${S(e)}`),process.exit(1)}});function w(e){return e instanceof Error?e.message:String(e)}const ee=new c.Command(`get-prompt`).description(`Get a prompt by name from a connected MCP server`).argument(`<promptName>`,`Prompt name to fetch`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Server name (required if prompt exists on multiple servers)`).option(`-a, --args <json>`,`Prompt arguments as JSON string`,`{}`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{let n={};try{n=JSON.parse(t.args)}catch{throw Error(`Invalid JSON in --args`)}await x(t,async({clientManager:r})=>{let i=r.getAllClients();if(t.server){let i=r.getClient(t.server);if(!i)throw Error(`Server "${t.server}" not found`);let a=await i.getPrompt(e,n);if(t.json)console.log(JSON.stringify(a,null,2));else for(let e of a.messages){let t=e.content;typeof t==`object`&&t&&`text`in t?console.log(t.text):console.log(JSON.stringify(e,null,2))}return}let a=[];if(await Promise.all(i.map(async n=>{try{(await n.listPrompts()).some(t=>t.name===e)&&a.push(n.serverName)}catch(e){t.json||console.error(`Failed to list prompts from ${n.serverName}: ${w(e)}`)}})),a.length===0)throw Error(`Prompt "${e}" not found on any connected server`);if(a.length>1)throw Error(`Prompt "${e}" found on multiple servers: ${a.join(`, `)}. Use --server to disambiguate`);let o=r.getClient(a[0]);if(!o)throw Error(`Internal error: Server "${a[0]}" not connected`);let s=await o.getPrompt(e,n);if(t.json)console.log(JSON.stringify(s,null,2));else for(let e of s.messages){let t=e.content;typeof t==`object`&&t&&`text`in t?console.log(t.text):console.log(JSON.stringify(e,null,2))}})}catch(e){console.error(`Error executing get-prompt: ${w(e)}`),process.exit(1)}});var te=`{
|
|
8
8
|
"_comment": "MCP Server Configuration - Use \${VAR_NAME} syntax for environment variable interpolation",
|
|
9
9
|
"_instructions": "config.instruction: Server's default instruction | instruction: User override (takes precedence)",
|
|
10
10
|
"mcpServers": {
|
|
@@ -138,9 +138,9 @@ mcpServers:
|
|
|
138
138
|
# # omitToolDescription: true
|
|
139
139
|
# # instruction: Optional user override
|
|
140
140
|
{% endif %}
|
|
141
|
-
`;function T(e=``){console.log(e)}function E(e,t){console.error(t?`${e} ${t}`:e)}const D={info:e=>T(e),error:(e,t)=>E(e,t)},O={info:e=>T(e),warning:e=>T(`Warning: ${e}`),error:e=>E(e),success:e=>T(e),newline:()=>T(),header:e=>T(e),item:e=>T(`- ${e}`),indent:e=>T(` ${e}`)},re=new l.Command(`init`).description(`Initialize MCP configuration file`).option(`-o, --output <path>`,`Output file path`,`mcp-config.yaml`).option(`--json`,`Generate JSON config instead of YAML`,!1).option(`-f, --force`,`Overwrite existing config file`,!1).option(`--mcp-servers <json>`,`JSON string of MCP servers to add to config (optional)`).action(async e=>{try{let t=(0,n.resolve)(e.output),r=!e.json&&(t.endsWith(`.yaml`)||t.endsWith(`.yml`)),a;if(r){let t=new c.Liquid,n=null;if(e.mcpServers)try{let t=JSON.parse(e.mcpServers);n=Object.entries(t).map(([e,t])=>({name:e,command:t.command,args:t.args}))}catch(e){D.error(`Failed to parse --mcp-servers JSON:`,e instanceof Error?e.message:String(e)),process.exit(1)}a=await t.parseAndRender(ne,{mcpServers:n})}else a=te;try{await(0,i.writeFile)(t,a,{encoding:`utf-8`,flag:e.force?`w`:`wx`})}catch(e){throw e&&typeof e==`object`&&`code`in e&&e.code===`EEXIST`&&(D.error(`Config file already exists: ${t}`),D.info(`Use --force to overwrite`),process.exit(1)),e}D.info(`MCP configuration file created: ${t}`),D.info(`Next steps:`),D.info(`1. Edit the configuration file to add your MCP servers`),D.info(`2. Run: po-mcp-proxy mcp-serve --config ${t}`)}catch(e){D.error(`Error executing init:`,e instanceof Error?e.message:String(e)),process.exit(1)}});function k(e){return e instanceof Error?e.message:String(e)}const ie=new l.Command(`list-prompts`).description(`List all available prompts from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await x(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={};if(await Promise.all(n.map(async t=>{try{r[t.serverName]=await t.listPrompts()}catch(n){r[t.serverName]=[],e.json||console.error(`Failed to list prompts from ${t.serverName}: ${k(n)}`)}})),e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No prompts available`);else for(let e of t)if(console.log(` - ${e.name}: ${e.description||`No description`}`),e.arguments&&e.arguments.length>0){let t=e.arguments.map(e=>`${e.name}${e.required?` (required)`:``}`).join(`, `);console.log(` args: ${t}`)}})}catch(e){console.error(`Error executing list-prompts: ${k(e)}`),process.exit(1)}});function A(e){return e instanceof Error?e.message:String(e)}const ae=new l.Command(`list-resources`).description(`List all available resources from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await x(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={},i=await Promise.all(n.map(async e=>{try{let t=await e.listResources();return{serverName:e.serverName,resources:t,error:null}}catch(t){return{serverName:e.serverName,resources:[],error:t}}}));for(let{serverName:t,resources:n,error:a}of i)a&&!e.json&&console.error(`Failed to list resources from ${t}: ${A(a)}`),r[t]=n;if(e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No resources available`);else for(let e of t){let t=e.name?`${e.name} (${e.uri})`:e.uri;console.log(` - ${t}${e.description?`: ${e.description}`:``}`)}})}catch(e){console.error(`Error executing list-resources: ${A(e)}`),process.exit(1)}});function oe(e){return e instanceof Error?e.message:String(e)}function se(e){for(let t of e.servers)if(console.log(`\n${t.server}:`),t.capabilities&&t.capabilities.length>0&&console.log(` capabilities: ${t.capabilities.join(`, `)}`),t.summary&&console.log(` summary: ${t.summary}`),t.tools.length===0)console.log(` no tools`);else for(let e of t.tools){let t=e.capabilities&&e.capabilities.length>0?` [${e.capabilities.join(`, `)}]`:``;console.log(` - ${e.name}${t}`),e.description&&console.log(` ${e.description}`)}}const ce=new l.Command(`search-tools`).description(`Search proxied MCP tools by capability or server`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`--capability <name>`,`Filter by capability tag, summary, tool name, or description`).option(`--definitions-cache <path>`,`Path to definitions cache file`).option(`-j, --json`,`Output as JSON`,!1).action(async t=>{try{await x(t,async({container:n,config:r,clientManager:i,configFilePaths:a})=>{i.registerServerConfigs(r.mcpServers);let o=t.definitionsCache||e.j.getDefaultCachePath(a),s;try{s=await e.j.readFromFile(o)}catch{s=void 0}let c=n.createDefinitionsCacheService(i,void 0,{cacheData:s}),l=(await n.createSearchListToolsTool(i,c).execute({capability:t.capability,serverName:t.server})).content.find(e=>e.type===`text`),u=l?.type===`text`?JSON.parse(l.text):{servers:[]};if(t.json)console.log(JSON.stringify(u,null,2));else{if(!u.servers||u.servers.length===0)throw Error(`No tools matched the requested filters`);se(u)}})}catch(e){console.error(`Error executing search-tools: ${oe(e)}`),process.exit(1)}}),j=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],M=`/mcp`,N=`localhost`,P=`stdio`,F=`http`,I=`stdio-http`,L=`mcp-proxy-http`,R=`service`;function le(){return e.dt()}const z=`mcp-proxy-stdio-http-bridge`,B=`stdio-http-managed`,V=`manual`,H=`MCP_PROXY_IDLE_SHUTDOWN_MINUTES`;function U(){return le()}function W(e){return e instanceof Error?e.message:String(e)}function ue(e){let t=process.env[H],n=e??(t?Number.parseFloat(t):void 0);return n===void 0||!Number.isFinite(n)||n<=0?0:Math.round(n*6e4)}function G(e){return e===P||e===F||e===I}function de(e){return e===`meta`||e===`flat`||e===`search`||e===`group`}async function K(e){try{return await(0,i.access)(e,t.constants.F_OK),!0}catch{return!1}}async function fe(){try{let e=process.env.PROJECT_PATH;if(e)for(let t of j){let r=(0,n.resolve)(e,t);if(await K(r))return r}let t=process.cwd();for(let e=0;e<=3;e++){for(let e of j){let r=(0,n.join)(t,e);if(await K(r))return r}let e=(0,n.dirname)(t);if(e===t)break;t=e}return null}catch(e){throw Error(`Failed to discover MCP config file: ${W(e)}`)}}function pe(e){try{let n=(0,t.readFileSync)(e,`utf-8`),r=(e.endsWith(`.yaml`)||e.endsWith(`.yml`)?o.load(n):JSON.parse(n))?.proxy;if(!r||typeof r!=`object`)return{};let i=r;return{type:typeof i.type==`string`?i.type:void 0,port:typeof i.port==`number`&&Number.isInteger(i.port)&&i.port>0?i.port:void 0,host:typeof i.host==`string`?i.host:void 0,keepAlive:typeof i.keepAlive==`boolean`?i.keepAlive:void 0}}catch{return{}}}function me(e){let t={};for(let n of e){let e=pe(n);e.type!==void 0&&(t.type=e.type),e.port!==void 0&&(t.port=e.port),e.host!==void 0&&(t.host=e.host),e.keepAlive!==void 0&&(t.keepAlive=e.keepAlive)}return t}async function he(t,n){let r=e.o();if(t.id)return t.id;if(n.length>0)try{let i=await r.createConfigFetcherService({configSources:e.L(n),useCache:t.cache!==!1}).fetchConfiguration(t.cache===!1);if(i.id)return i.id}catch(e){throw Error(`Failed to resolve server ID from config '${n.join(`, `)}': ${W(e)}`)}return e.N()}function ge(e){if(!G(e))throw Error(`Unknown transport type: '${e}'. Valid options: ${P}, ${F}, ${I}`);return e}function _e(e){if(!de(e))throw Error(`Unknown proxy mode: '${String(e)}'. Valid options: meta, flat, search, group`)}function ve(e){return e===B?B:V}function q(e,t,n){let r=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0;return{mode:t,port:e.port??(Number.isFinite(r)?r:void 0)??n?.port,host:e.host??process.env.MCP_HOST??n?.host??N}}function J(){let e=(e,t)=>{t===void 0?console.error(e):console.error(e,t)};return{trace:e,debug:e,info:e,warn:e,error:e}}function ye(e,t,n){return{configFilePath:t.length>0?t:void 0,noCache:e.cache===!1,serverId:n,definitionsCachePath:e.definitionsCache,clearDefinitionsCache:e.clearDefinitionsCache,proxyMode:e.proxyMode}}function be(e,t,n,r){let i=W(r);return e===P?`Failed to start MCP server with transport '${e}': ${i}`:`Failed to start MCP server with transport '${e}' on ${n===void 0?`${t} (dynamic port)`:`${t}:${n}`}: ${i}`}function xe(e,t,n,r,i,a=V){return{serverId:e,host:t.host??N,port:n,transport:`http`,shutdownToken:r,startedAt:(/* @__PURE__ */ new Date()).toISOString(),pid:process.pid,configPath:i,runtimeLifecycle:a}}function Se(){return new s.PortRegistryService(process.env.PORT_REGISTRY_PATH)}function Y(){return process.env.NODE_ENV??`development`}async function Ce(e,t,n,r,i,a,o=n===void 0?s.DEFAULT_PORT_RANGE:{min:n,max:n}){let c=Se(),l=await c.reservePort({repositoryPath:U(),serviceName:e,serviceType:R,environment:Y(),pid:process.pid,host:t,preferredPort:n,portRange:o,force:!0,metadata:{transport:i,serverId:r,...a?{configPath:a}:{}}});if(!l.success||!l.record){let e=n===void 0?`dynamic port`:`port ${n}`;throw Error(l.error||`Failed to reserve ${e} in port registry`)}let u=!1;return{port:l.record.port,release:async()=>{if(u)return;u=!0;let t=await c.releasePort({repositoryPath:U(),serviceName:e,serviceType:R,pid:process.pid,environment:Y(),force:!0});if(!t.success&&t.error&&!t.error.includes(`No matching registry entry`))throw Error(t.error||`Failed to release port for ${e}`)}}}async function we(e){e&&await e.release()}function Te(e,t,n,r,i){return{serverId:e,shutdownToken:t,onShutdownRequested:n,runtimeLifecycle:r,idleShutdownMs:i}}async function X(e,t){try{await e.remove(t)}catch(e){throw Error(`Failed to remove runtime state for '${t}': ${W(e)}`)}}async function Ee(e,t){try{await e.write(t)}catch(e){throw Error(`Failed to persist runtime state for '${t.serverId}': ${W(e)}`)}}async function De(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop owned HTTP transport '${n}': ${W(e)}`)}}finally{await r?.release({kill:!1}),await X(t,n)}}async function Oe(e,t,n){await n?.release({kill:!1}),await X(e,t)}async function ke(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop HTTP transport during cleanup for '${n}': ${W(e)}`)}}finally{await r?.release({kill:!1}),await X(t,n)}}async function Z(e,t,n={}){try{await e.start()}catch(e){throw Error(`Failed to start transport handler: ${W(e)}`)}let r=!1,i=async n=>{if(!r){r=!0,console.error(`\nReceived ${n}, shutting down gracefully...`);try{await e.stop(),t&&await t(),process.exit(0)}catch(e){console.error(`Failed to gracefully stop transport during ${n}: ${W(e)}`),process.exit(1)}}};process.on(`SIGINT`,async()=>await i(`SIGINT`)),process.on(`SIGTERM`,async()=>await i(`SIGTERM`)),n.shutdownOnStdinClose&&(process.stdin.on(`end`,async()=>await i(`stdin end`)),process.stdin.on(`close`,async()=>await i(`stdin close`)))}async function Ae(t,n,i,o){e.M();let c=i[0],l=await e.l(t),u=new e.T,d=(0,r.randomUUID)(),f=t.serverId??e.N(),p=ve(process.env.MCP_PROXY_RUNTIME_LIFECYCLE),m=n.port,h=m===void 0?s.DEFAULT_PORT_RANGE:{min:m,max:m},g=await Ce(L,n.host??N,m,f,F,c,h),_=g.port,v={...n,port:_},y=await(0,a.createProcessLease)({repositoryPath:U(),serviceName:`mcp-proxy-http`,serviceType:`service`,environment:Y(),host:v.host??N,port:_,command:process.argv[1],args:process.argv.slice(2),...e.v()?{processGroupId:process.pid,terminationMode:`process-group`}:{terminationMode:`direct`},metadata:{transport:F,serverId:f,runtimeLifecycle:p,...c?{configPath:c}:{}}}),b=async()=>{await we(g??null),b=async()=>void 0},x=xe(f,v,_,d,c,p),S,C=!1,w=async()=>{if(!C){C=!0;try{await De(S,u,x.serverId,y),await b(),await l.dispose(),process.exit(0)}catch(e){throw Error(`Failed to stop HTTP runtime '${x.serverId}' from admin shutdown: ${W(e)}`)}}};try{let t=Te(x.serverId,d,w,p,o);S=new e.S(()=>e.r(l),v,t)}catch(e){throw await b(),await y.release({kill:!1}),await l.dispose(),Error(`Failed to create HTTP runtime server: ${W(e)}`)}try{await Z(S,async()=>{await b(),await l.dispose(),await Oe(u,x.serverId,y)}),await Ee(u,x)}catch(e){throw await b(),await l.dispose(),await ke(S,u,x.serverId,y),Error(`Failed to start HTTP runtime '${x.serverId}': ${W(e)}`)}console.error(`Runtime state: http://${x.host}:${x.port} (${x.serverId})`)}async function je(t){let n;try{n=await e.n(t),await Z(new e.d(n,J()),async()=>{await n?.dispose?.()},{shutdownOnStdinClose:!0})}catch(e){throw await n?.dispose?.(),Error(`Failed to start stdio transport: ${W(e)}`)}}async function Me(t){if(t)try{return(await new e.T().read(t))?.runtimeLifecycle}catch{return}}function Ne(t){if(!t)return e.g;let n=Number.parseInt(t,10);return Number.isInteger(n)&&n>0?n:e.g}function Q(e,t){let i=a.ProcessRegistryService.resolveRegistryPath(process.env.PROCESS_REGISTRY_PATH),o=(0,r.createHash)(`sha1`).update(`${(0,a.normalizeRepositoryPath)(e)}|${t}`).digest(`hex`);return(0,n.join)((0,n.dirname)(i),`mcp-proxy-runtime-${o.slice(0,16)}.lock`)}async function $(e,t,n){if(e.port!==void 0)return{endpoint:new URL(`http://${e.host??N}:${e.port}${M}`),runtimeLifecycle:V};let r=U(),i=Ne(t.timeoutMs)+1e4;return await(0,a.withFileLock)(Q(r,L),async()=>Pe(r,e,t,n),{staleAfterMs:i,retryDelayMs:250,maxRetries:Math.ceil(i/250)})}async function Pe(t,n,r,i){let a=await e._(t);if(a){let e=n.host??a.host,t=a.serverId===`unknown`?void 0:a.serverId;return{endpoint:new URL(`http://${e}:${a.port}${M}`),runtimeServerId:t,runtimeLifecycle:a.runtimeLifecycle??await Me(t)??V}}let o=await e.y({host:n.host??N,config:i,cache:r.cache,definitionsCache:r.definitionsCache,clearDefinitionsCache:r.clearDefinitionsCache,proxyMode:r.proxyMode,runtimeLifecycle:B,idleShutdownMinutes:r.idleShutdownMinutes});return{endpoint:new URL(`http://${o.host}:${o.port}${M}`),runtimeServerId:o.serverId,runtimeLifecycle:o.runtimeLifecycle??V}}async function Fe(e,t,n){let{endpoint:r}=await $(e,t,n);return r}function Ie(e){return`runtime:${e}`}async function Le(e){if(e.runtimeLifecycle===B&&e.runtimeServerId)return await(0,a.createProcessLease)({repositoryPath:U(),serviceName:`mcp-proxy-stdio-http-bridge:${(0,r.randomUUID)()}`,serviceType:`tool`,environment:Y(),pid:process.pid,command:process.argv[1],args:process.argv.slice(2),tags:[z,Ie(e.runtimeServerId)],metadata:{transport:I,runtimeServerId:e.runtimeServerId,runtimeLifecycle:e.runtimeLifecycle,endpoint:e.endpoint.toString()},force:!1})}function Re(e){return e.pid===process.pid}async function ze(e){return await new a.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:U(),serviceType:`tool`,tags:[z,Ie(e)],environment:Y(),liveOnly:!0})}async function Be(e){return(await ze(e)).filter(e=>!Re(e)).length>0?!1:(await new Promise(e=>setTimeout(e,500)),(await ze(e)).filter(e=>!Re(e)).length===0)}async function Ve(t){if(t.runtimeLifecycle!==B||!t.runtimeServerId)return;let n=t.runtimeServerId,r=Q(U(),L);try{await(0,a.withFileLock)(r,async()=>{await Be(n)&&await new e.C().stop({serverId:n,force:!0})})}catch(e){console.error(`Failed to stop managed stdio-http runtime; leaving it alive: ${W(e)}`)}}async function He(t,n,r,i){let a=n.autoDisconnect?!0:i?.keepAlive!==void 0&&!i.keepAlive,o,s;try{o=await $(t,n,r),s=await Le(o);let{endpoint:i}=o;await Z(new e.u({endpoint:i,resolveEndpoint:async()=>await Fe(t,n,r)},J()),async()=>{try{await s?.release({kill:!1,releasePort:!1})}catch(e){console.error(`Failed to release stdio-http bridge lease; leaving runtime alive: ${W(e)}`);return}a&&o&&await Ve(o)},{shutdownOnStdinClose:!0})}catch(e){try{await s?.release({kill:!1,releasePort:!1})}catch(t){throw Error(`Failed to start stdio-http transport: ${W(e)}; also failed to release bridge lease: ${W(t)}`)}throw Error(`Failed to start stdio-http transport: ${W(e)}`)}}async function Ue(t,n,r,i,a){try{if(t===P){await je(i);return}if(t===F){await Ae(i,q(n,e.t.HTTP,a),r,ue(n.idleShutdownMinutes));return}await He(q(n,e.t.HTTP,a),n,r,a)}catch(e){throw Error(`Failed to start transport '${t}': ${W(e)}`)}}async function We(t,n){try{let r=await e.y({id:t.id,host:t.host??N,port:t.port,config:n,cache:t.cache,definitionsCache:t.definitionsCache,clearDefinitionsCache:t.clearDefinitionsCache,proxyMode:t.proxyMode,timeoutMs:t.timeoutMs,idleShutdownMinutes:t.idleShutdownMinutes});e.x(r)}catch(e){console.error(`Failed to prestart HTTP runtime '${t.id||`generated-server-id`}': ${W(e)}`),process.exit(1)}}const Ge=new l.Command(`mcp-serve`).description(`Start MCP server with specified transport or prestart the HTTP runtime in the background`).option(`-t, --type <type>`,`Transport type: ${P}, ${F}, or ${I}`).option(`-p, --port <port>`,`Port to listen on (http) or backend port for stdio-http`,e=>Number.parseInt(e,10)).option(`--host <host>`,`Host to bind to (http) or backend host for stdio-http`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`--no-cache`,`Disable configuration caching, always reload from config file`).option(`--definitions-cache <path>`,`Path to prefetched tool/prompt/skill definitions cache file`).option(`--clear-definitions-cache`,`Delete definitions cache before startup`,!1).option(`--proxy-mode <mode>`,`How mcp-proxy exposes downstream tools: meta, flat, search, or group`,`meta`).option(`--id <id>`,`Unique server identifier (overrides config file id, auto-generated if not provided)`).option(`--auto-disconnect`,`Stop the managed HTTP runtime when the last stdio-http bridge exits (default: keep runtime alive for reuse)`,!1).option(`--idle-shutdown-minutes <minutes>`,`Stop the HTTP runtime after N minutes with no MCP session and no request (0 disables; overrides ${H})`,e=>Number.parseFloat(e)).option(`--prestart-http`,`Prestart the HTTP runtime in the background and exit after it becomes healthy`,!1).option(`--timeout-ms <ms>`,`How long to wait for the HTTP runtime to become healthy`,String(e.g)).action(async t=>{try{let n=e.I(t.config),r=n.length>0?null:await fe(),i=r?[r]:n;if(t.prestartHttp){await We(t,i);return}let a=me(i),o=ge((t.type??a.type??P).toLowerCase());_e(t.proxyMode),await Ue(o,t,i,ye(t,i,await he(t,i)),a)}catch(e){let n=(t.type??P).toLowerCase(),r=G(n)?n:P,i=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0,a=t.port??(Number.isFinite(i)?i:void 0);console.error(be(r,t.host??N,a,e)),process.exit(1)}}),Ke=new l.Command(`prefetch`).description(`Pre-download packages used by MCP servers (npx, pnpx, uvx, uv)`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-p, --parallel`,`Run prefetch commands in parallel`,!1).option(`-d, --dry-run`,`Show what would be prefetched without executing`,!1).option(`-f, --filter <type>`,`Filter by package manager type: npx, pnpx, uvx, or uv`).option(`--definitions-out <path>`,`Write discovered definitions to a JSON or YAML cache file`).option(`--skip-packages`,`Skip package prefetch and only build definitions cache`,!1).option(`--clear-definitions-cache`,`Delete the definitions cache file before continuing`,!1).action(async t=>{try{let n=e.o(),r=e.I(t.config),i=r.length>0?null:e.P(),a=i?[i]:r;a.length===0&&(O.error(`No MCP configuration file found.`),O.info(`Use --config <path> to specify a config file, or run "po-mcp-proxy init" to create one.`),process.exit(1)),O.info(`Loading configuration from: ${a.join(`, `)}`);let o=await n.createConfigFetcherService({configSources:e.L(a),useCache:!1}).fetchConfiguration(!0),s=o.id||e.N(),c=e.j.generateConfigHash(o),l=t.definitionsOut||e.j.getDefaultCachePath(a),u=n.createPrefetchService({mcpConfig:o,filter:t.filter,parallel:t.parallel}),d=u.extractPackages(),f=!t.skipPackages,p=!!t.definitionsOut;if(t.clearDefinitionsCache&&(t.dryRun?O.info(`Would clear definitions cache: ${l}`):(await e.j.clearFile(l),O.success(`Cleared definitions cache: ${l}`))),f){if(d.length===0)O.warning(`No packages found to prefetch.`),O.info(`Prefetch supports: npx, pnpx, uvx, and uv run commands`);else{O.info(`Found ${d.length} package(s) to prefetch:`);for(let e of d)O.item(`${e.serverName}: ${e.packageManager} ${e.packageName}`)}}if(!f&&!p){O.warning(`Nothing to do. Use package prefetch or provide --definitions-out.`);return}if(t.dryRun){if(f&&d.length>0){O.newline(),O.header(`Dry run mode - commands that would be executed:`);for(let e of d)O.indent(e.fullCommand.join(` `))}p&&(O.newline(),O.info(`Would write definitions cache to: ${l}`));return}let m=!1;if(f&&d.length>0){O.newline(),O.info(`Prefetching packages...`);let e=await u.prefetch();if(O.newline(),e.failed===0?O.success(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`):O.warning(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`),e.failed>0){m=!0,O.newline(),O.error(`Failed packages:`);for(let t of e.results.filter(e=>!e.success))O.item(`${t.package.serverName} (${t.package.packageName}): ${t.output.trim()}`)}}if(p){O.newline(),O.info(`Collecting definitions cache...`);let t=n.createClientManagerService(),r=o.skills?.paths||[],i=r.length>0?n.createSkillService(process.cwd(),r):void 0,u=n.createDefinitionsCacheService(t,i);await Promise.all(Object.entries(o.mcpServers).map(async([e,n])=>{try{await t.connectToServer(e,n),O.item(`Connected for definitions: ${e}`)}catch(t){O.warning(`Failed to connect for definitions: ${e} (${t instanceof Error?t.message:String(t)})`)}}));let d=await u.collectForCache({configPath:a[0],configHash:c,oneMcpVersion:e.h,serverId:s});await e.j.writeToFile(l,d),O.success(`Definitions cache written: ${l} (${Object.keys(d.servers).length} servers, ${d.skills.length} skills)`),d.failures.length>0&&O.warning(`Definitions cache completed with ${d.failures.length} server failure(s)`),await t.disconnectAll()}m&&process.exit(1)}catch(e){O.error(`Error executing prefetch: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});function qe(e){return e instanceof Error?e.message:String(e)}const Je=new l.Command(`read-resource`).description(`Read a resource by URI from a connected MCP server`).argument(`<uri>`,`Resource URI to read`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Server name (required if resource exists on multiple servers)`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await x(t,async({clientManager:n})=>{let r=n.getAllClients();if(t.server){let r=n.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Reading ${e} from ${t.server}...`);let i=await r.readResource(e);if(t.json)console.log(JSON.stringify(i,null,2));else for(let e of i.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2));return}let i=await Promise.all(r.map(async t=>{try{let n=(await t.listResources()).some(t=>t.uri===e);return{serverName:t.serverName,hasResource:n,error:null}}catch(e){return{serverName:t.serverName,hasResource:!1,error:e}}})),a=[];for(let{serverName:e,hasResource:t,error:n}of i)n?console.error(`Failed to list resources from ${e}: ${qe(n)}`):t&&a.push(e);if(a.length===0)throw Error(`Resource "${e}" not found on any connected server`);if(a.length>1)throw Error(`Resource "${e}" found on multiple servers: ${a.join(`, `)}. Use --server to disambiguate`);let o=a[0],s=n.getClient(o);if(!s)throw Error(`Internal error: Server "${o}" not connected`);t.json||console.error(`Reading ${e} from ${o}...`);let c=await s.readResource(e);if(t.json)console.log(JSON.stringify(c,null,2));else for(let e of c.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2))})}catch(e){console.error(`Error executing read-resource: ${qe(e)}`),process.exit(1)}});function Ye(e){return e instanceof Error?e.message:String(e)}function Xe(e){console.log(`Stopped mcp-proxy server '${e.serverId}'.`),console.log(`Endpoint: http://${e.host}:${e.port}`),console.log(`Result: ${e.message}`)}const Ze=new l.Command(`stop`).description(`Stop a running HTTP mcp-proxy server`).option(`--id <id>`,`Target server ID from the runtime registry`).option(`--host <host>`,`Target runtime host`).option(`--port <port>`,`Target runtime port`,e=>Number.parseInt(e,10)).option(`-c, --config <path>`,`Reserved for future config-based targeting support`).option(`--token <token>`,`Override the persisted shutdown token`).option(`--force`,`Skip server ID verification against the /health response`,!1).option(`-j, --json`,`Output as JSON`,!1).option(`--timeout <ms>`,`Maximum time to wait for shutdown completion`,e=>Number.parseInt(e,10),5e3).action(async t=>{try{t.config&&console.error(`Warning: --config is not used yet; runtime resolution uses the persisted registry.`);let n=await e.o().createStopServerService().stop({serverId:t.id,host:t.host,port:t.port,token:t.token,force:t.force,timeoutMs:t.timeout});if(t.json){console.log(JSON.stringify(n,null,2));return}Xe(n)}catch(e){let n=`Error executing stop: ${Ye(e)}`;t.json?console.log(JSON.stringify({ok:!1,error:n},null,2)):console.error(n),process.exit(1)}});function Qe(e){return e instanceof Error?e.message:String(e)}const $e=new l.Command(`use-tool`).description(`Execute an MCP tool with arguments`).argument(`<toolName>`,`Tool name to execute`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Server name (required if tool exists on multiple servers)`).option(`-a, --args <json>`,`Tool arguments as JSON string`,`{}`).option(`-t, --timeout <ms>`,`Request timeout in milliseconds for tool execution (default: 60000)`,Number.parseInt).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{let n={};try{n=JSON.parse(t.args)}catch{console.error(`Error: Invalid JSON in --args`),process.exit(1)}await x(t,async({container:r,config:i,clientManager:a})=>{let o=a.getAllClients();if(t.server){let r=a.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Executing ${e} on ${t.server}...`);let i=t.timeout?{timeout:t.timeout}:void 0,o=await r.callTool(e,n,i);if(t.json)console.log(JSON.stringify(o,null,2));else{if(console.log(`
|
|
141
|
+
`;function T(e=``){console.log(e)}function E(e,t){console.error(t?`${e} ${t}`:e)}const D={info:e=>T(e),error:(e,t)=>E(e,t)},O={info:e=>T(e),warning:e=>T(`Warning: ${e}`),error:e=>E(e),success:e=>T(e),newline:()=>T(),header:e=>T(e),item:e=>T(`- ${e}`),indent:e=>T(` ${e}`)},re=new c.Command(`init`).description(`Initialize MCP configuration file`).option(`-o, --output <path>`,`Output file path`,`mcp-config.yaml`).option(`--json`,`Generate JSON config instead of YAML`,!1).option(`-f, --force`,`Overwrite existing config file`,!1).option(`--mcp-servers <json>`,`JSON string of MCP servers to add to config (optional)`).action(async e=>{try{let r=(0,n.resolve)(e.output),i=!e.json&&(r.endsWith(`.yaml`)||r.endsWith(`.yml`)),a;if(i){let t=new s.Liquid,n=null;if(e.mcpServers)try{let t=JSON.parse(e.mcpServers);n=Object.entries(t).map(([e,t])=>({name:e,command:t.command,args:t.args}))}catch(e){D.error(`Failed to parse --mcp-servers JSON:`,e instanceof Error?e.message:String(e)),process.exit(1)}a=await t.parseAndRender(ne,{mcpServers:n})}else a=te;try{await(0,t.writeFile)(r,a,{encoding:`utf-8`,flag:e.force?`w`:`wx`})}catch(e){throw e&&typeof e==`object`&&`code`in e&&e.code===`EEXIST`&&(D.error(`Config file already exists: ${r}`),D.info(`Use --force to overwrite`),process.exit(1)),e}D.info(`MCP configuration file created: ${r}`),D.info(`Next steps:`),D.info(`1. Edit the configuration file to add your MCP servers`),D.info(`2. Run: po-mcp-proxy mcp-serve --config ${r}`)}catch(e){D.error(`Error executing init:`,e instanceof Error?e.message:String(e)),process.exit(1)}});function k(e){return e instanceof Error?e.message:String(e)}const ie=new c.Command(`list-prompts`).description(`List all available prompts from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await x(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={};if(await Promise.all(n.map(async t=>{try{r[t.serverName]=await t.listPrompts()}catch(n){r[t.serverName]=[],e.json||console.error(`Failed to list prompts from ${t.serverName}: ${k(n)}`)}})),e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No prompts available`);else for(let e of t)if(console.log(` - ${e.name}: ${e.description||`No description`}`),e.arguments&&e.arguments.length>0){let t=e.arguments.map(e=>`${e.name}${e.required?` (required)`:``}`).join(`, `);console.log(` args: ${t}`)}})}catch(e){console.error(`Error executing list-prompts: ${k(e)}`),process.exit(1)}});function A(e){return e instanceof Error?e.message:String(e)}const ae=new c.Command(`list-resources`).description(`List all available resources from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await x(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={},i=await Promise.all(n.map(async e=>{try{let t=await e.listResources();return{serverName:e.serverName,resources:t,error:null}}catch(t){return{serverName:e.serverName,resources:[],error:t}}}));for(let{serverName:t,resources:n,error:a}of i)a&&!e.json&&console.error(`Failed to list resources from ${t}: ${A(a)}`),r[t]=n;if(e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No resources available`);else for(let e of t){let t=e.name?`${e.name} (${e.uri})`:e.uri;console.log(` - ${t}${e.description?`: ${e.description}`:``}`)}})}catch(e){console.error(`Error executing list-resources: ${A(e)}`),process.exit(1)}});function oe(e){return e instanceof Error?e.message:String(e)}function se(e){for(let t of e.servers)if(console.log(`\n${t.server}:`),t.capabilities&&t.capabilities.length>0&&console.log(` capabilities: ${t.capabilities.join(`, `)}`),t.summary&&console.log(` summary: ${t.summary}`),t.tools.length===0)console.log(` no tools`);else for(let e of t.tools){let t=e.capabilities&&e.capabilities.length>0?` [${e.capabilities.join(`, `)}]`:``;console.log(` - ${e.name}${t}`),e.description&&console.log(` ${e.description}`)}}const ce=new c.Command(`search-tools`).description(`Search proxied MCP tools by capability or server`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Filter by server name`).option(`--capability <name>`,`Filter by capability tag, summary, tool name, or description`).option(`--definitions-cache <path>`,`Path to definitions cache file`).option(`-j, --json`,`Output as JSON`,!1).action(async t=>{try{await x(t,async({container:n,config:r,clientManager:i,configFilePaths:a})=>{i.registerServerConfigs(r.mcpServers);let o=t.definitionsCache||e.j.getDefaultCachePath(a),s;try{s=await e.j.readFromFile(o)}catch{s=void 0}let c=n.createDefinitionsCacheService(i,void 0,{cacheData:s}),l=(await n.createSearchListToolsTool(i,c).execute({capability:t.capability,serverName:t.server})).content.find(e=>e.type===`text`),u=l?.type===`text`?JSON.parse(l.text):{servers:[]};if(t.json)console.log(JSON.stringify(u,null,2));else{if(!u.servers||u.servers.length===0)throw Error(`No tools matched the requested filters`);se(u)}})}catch(e){console.error(`Error executing search-tools: ${oe(e)}`),process.exit(1)}}),j=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],M=`/mcp`,N=`localhost`,P=`stdio`,F=`http`,I=`stdio-http`,L=`mcp-proxy-http`,R=`service`;async function le(){return e.dt()}const z=`mcp-proxy-stdio-http-bridge`,B=`stdio-http-managed`,V=`manual`,H=`MCP_PROXY_IDLE_SHUTDOWN_MINUTES`;async function U(){return le()}function W(e){return e instanceof Error?e.message:String(e)}function ue(e){let t=process.env[H],n=e??(t?Number.parseFloat(t):void 0);return n===void 0||!Number.isFinite(n)||n<=0?0:Math.round(n*6e4)}function G(e){return e===P||e===F||e===I}function de(e){return e===`meta`||e===`flat`||e===`search`||e===`group`}async function K(e){try{return await(0,t.access)(e,l.constants.F_OK),!0}catch{return!1}}async function fe(){try{let e=process.env.PROJECT_PATH;if(e)for(let t of j){let r=(0,n.resolve)(e,t);if(await K(r))return r}let t=process.cwd();for(let e=0;e<=3;e++){for(let e of j){let r=(0,n.join)(t,e);if(await K(r))return r}let e=(0,n.dirname)(t);if(e===t)break;t=e}return null}catch(e){throw Error(`Failed to discover MCP config file: ${W(e)}`)}}async function pe(e){try{let n=await(0,t.readFile)(e,`utf-8`),r=(e.endsWith(`.yaml`)||e.endsWith(`.yml`)?a.load(n):JSON.parse(n))?.proxy;if(!r||typeof r!=`object`)return{};let i=r;return{type:typeof i.type==`string`?i.type:void 0,port:typeof i.port==`number`&&Number.isInteger(i.port)&&i.port>0?i.port:void 0,host:typeof i.host==`string`?i.host:void 0,keepAlive:typeof i.keepAlive==`boolean`?i.keepAlive:void 0}}catch{return{}}}async function me(e){let t={};for(let n of e){let e=await pe(n);e.type!==void 0&&(t.type=e.type),e.port!==void 0&&(t.port=e.port),e.host!==void 0&&(t.host=e.host),e.keepAlive!==void 0&&(t.keepAlive=e.keepAlive)}return t}async function he(t,n){let r=e.o();if(t.id)return t.id;if(n.length>0)try{let i=await r.createConfigFetcherService({configSources:e.L(n),useCache:t.cache!==!1}).fetchConfiguration(t.cache===!1);if(i.id)return i.id}catch(e){throw Error(`Failed to resolve server ID from config '${n.join(`, `)}': ${W(e)}`)}return e.N()}function ge(e){if(!G(e))throw Error(`Unknown transport type: '${e}'. Valid options: ${P}, ${F}, ${I}`);return e}function _e(e){if(!de(e))throw Error(`Unknown proxy mode: '${String(e)}'. Valid options: meta, flat, search, group`)}function ve(e){return e===B?B:V}function q(e,t,n){let r=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0;return{mode:t,port:e.port??(Number.isFinite(r)?r:void 0)??n?.port,host:e.host??process.env.MCP_HOST??n?.host??N}}function J(){let e=(e,t)=>{t===void 0?console.error(e):console.error(e,t)};return{trace:e,debug:e,info:e,warn:e,error:e}}function ye(e,t,n){return{configFilePath:t.length>0?t:void 0,noCache:e.cache===!1,serverId:n,definitionsCachePath:e.definitionsCache,clearDefinitionsCache:e.clearDefinitionsCache,proxyMode:e.proxyMode}}function be(e,t,n,r){let i=W(r);return e===P?`Failed to start MCP server with transport '${e}': ${i}`:`Failed to start MCP server with transport '${e}' on ${n===void 0?`${t} (dynamic port)`:`${t}:${n}`}: ${i}`}function xe(e,t,n,r,i,a=V){return{serverId:e,host:t.host??N,port:n,transport:`http`,shutdownToken:r,startedAt:(/* @__PURE__ */ new Date()).toISOString(),pid:process.pid,configPath:i,runtimeLifecycle:a}}function Se(){return new o.PortRegistryService(process.env.PORT_REGISTRY_PATH)}function Y(){return process.env.NODE_ENV??`development`}async function Ce(e,t,n,r,i,a,s=n===void 0?o.DEFAULT_PORT_RANGE:{min:n,max:n}){let c=Se(),l=await c.reservePort({repositoryPath:await U(),serviceName:e,serviceType:R,environment:Y(),pid:process.pid,host:t,preferredPort:n,portRange:s,force:!0,metadata:{transport:i,serverId:r,...a?{configPath:a}:{}}});if(!l.success||!l.record){let e=n===void 0?`dynamic port`:`port ${n}`;throw Error(l.error||`Failed to reserve ${e} in port registry`)}let u=!1;return{port:l.record.port,release:async()=>{if(u)return;u=!0;let t=await c.releasePort({repositoryPath:await U(),serviceName:e,serviceType:R,pid:process.pid,environment:Y(),force:!0});if(!t.success&&t.error&&!t.error.includes(`No matching registry entry`))throw Error(t.error||`Failed to release port for ${e}`)}}}async function we(e){e&&await e.release()}function Te(e,t,n,r,i){return{serverId:e,shutdownToken:t,onShutdownRequested:n,runtimeLifecycle:r,idleShutdownMs:i}}async function X(e,t){try{await e.remove(t)}catch(e){throw Error(`Failed to remove runtime state for '${t}': ${W(e)}`)}}async function Ee(e,t){try{await e.write(t)}catch(e){throw Error(`Failed to persist runtime state for '${t.serverId}': ${W(e)}`)}}async function De(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop owned HTTP transport '${n}': ${W(e)}`)}}finally{await r?.release({kill:!1}),await X(t,n)}}async function Oe(e,t,n){await n?.release({kill:!1}),await X(e,t)}async function ke(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop HTTP transport during cleanup for '${n}': ${W(e)}`)}}finally{await r?.release({kill:!1}),await X(t,n)}}async function Z(e,t,n={}){try{await e.start()}catch(e){throw Error(`Failed to start transport handler: ${W(e)}`)}let r=!1,i=async n=>{if(!r){r=!0,console.error(`\nReceived ${n}, shutting down gracefully...`);try{await e.stop(),t&&await t(),process.exit(0)}catch(e){console.error(`Failed to gracefully stop transport during ${n}: ${W(e)}`),process.exit(1)}}};process.on(`SIGINT`,async()=>await i(`SIGINT`)),process.on(`SIGTERM`,async()=>await i(`SIGTERM`)),n.shutdownOnStdinClose&&(process.stdin.on(`end`,async()=>await i(`stdin end`)),process.stdin.on(`close`,async()=>await i(`stdin close`)))}async function Ae(t,n,a,s){e.M();let c=a[0],l=await e.l(t),u=new e.T,d=(0,r.randomUUID)(),f=t.serverId??e.N(),p=ve(process.env.MCP_PROXY_RUNTIME_LIFECYCLE),m=n.port,h=m===void 0?o.DEFAULT_PORT_RANGE:{min:m,max:m},g=await Ce(L,n.host??N,m,f,F,c,h),_=g.port,v={...n,port:_},y=await(0,i.createProcessLease)({repositoryPath:await U(),serviceName:`mcp-proxy-http`,serviceType:`service`,environment:Y(),host:v.host??N,port:_,command:process.argv[1],args:process.argv.slice(2),...e.v()?{processGroupId:process.pid,terminationMode:`process-group`}:{terminationMode:`direct`},metadata:{transport:F,serverId:f,runtimeLifecycle:p,...c?{configPath:c}:{}}}),b=async()=>{await we(g??null),b=async()=>void 0},x=xe(f,v,_,d,c,p),S,C=!1,w=async()=>{if(!C){C=!0;try{await De(S,u,x.serverId,y),await b(),await l.dispose(),process.exit(0)}catch(e){throw Error(`Failed to stop HTTP runtime '${x.serverId}' from admin shutdown: ${W(e)}`)}}};try{let t=Te(x.serverId,d,w,p,s);S=new e.S(()=>e.r(l),v,t)}catch(e){throw await b(),await y.release({kill:!1}),await l.dispose(),Error(`Failed to create HTTP runtime server: ${W(e)}`)}try{await Z(S,async()=>{await b(),await l.dispose(),await Oe(u,x.serverId,y)}),await Ee(u,x)}catch(e){throw await b(),await l.dispose(),await ke(S,u,x.serverId,y),Error(`Failed to start HTTP runtime '${x.serverId}': ${W(e)}`)}console.error(`Runtime state: http://${x.host}:${x.port} (${x.serverId})`)}async function je(t){let n;try{n=await e.n(t),await Z(new e.d(n,J()),async()=>{await n?.dispose?.()},{shutdownOnStdinClose:!0})}catch(e){throw await n?.dispose?.(),Error(`Failed to start stdio transport: ${W(e)}`)}}async function Me(t){if(t)try{return(await new e.T().read(t))?.runtimeLifecycle}catch{return}}function Ne(t){if(!t)return e.g;let n=Number.parseInt(t,10);return Number.isInteger(n)&&n>0?n:e.g}function Q(e,t){let a=i.ProcessRegistryService.resolveRegistryPath(process.env.PROCESS_REGISTRY_PATH),o=(0,r.createHash)(`sha1`).update(`${(0,i.normalizeRepositoryPath)(e)}|${t}`).digest(`hex`);return(0,n.join)((0,n.dirname)(a),`mcp-proxy-runtime-${o.slice(0,16)}.lock`)}async function $(e,t,n){if(e.port!==void 0)return{endpoint:new URL(`http://${e.host??N}:${e.port}${M}`),runtimeLifecycle:V};let r=await U(),a=Ne(t.timeoutMs)+1e4;return await(0,i.withFileLock)(Q(r,L),async()=>Pe(r,e,t,n),{staleAfterMs:a,retryDelayMs:250,maxRetries:Math.ceil(a/250)})}async function Pe(t,n,r,i){let a=await e._(t);if(a){let e=n.host??a.host,t=a.serverId===`unknown`?void 0:a.serverId;return{endpoint:new URL(`http://${e}:${a.port}${M}`),runtimeServerId:t,runtimeLifecycle:a.runtimeLifecycle??await Me(t)??V}}let o=await e.y({host:n.host??N,config:i,cache:r.cache,definitionsCache:r.definitionsCache,clearDefinitionsCache:r.clearDefinitionsCache,proxyMode:r.proxyMode,runtimeLifecycle:B,idleShutdownMinutes:r.idleShutdownMinutes});return{endpoint:new URL(`http://${o.host}:${o.port}${M}`),runtimeServerId:o.serverId,runtimeLifecycle:o.runtimeLifecycle??V}}async function Fe(e,t,n){let{endpoint:r}=await $(e,t,n);return r}function Ie(e){return`runtime:${e}`}async function Le(e){if(e.runtimeLifecycle===B&&e.runtimeServerId)return await(0,i.createProcessLease)({repositoryPath:await U(),serviceName:`mcp-proxy-stdio-http-bridge:${(0,r.randomUUID)()}`,serviceType:`tool`,environment:Y(),pid:process.pid,command:process.argv[1],args:process.argv.slice(2),tags:[z,Ie(e.runtimeServerId)],metadata:{transport:I,runtimeServerId:e.runtimeServerId,runtimeLifecycle:e.runtimeLifecycle,endpoint:e.endpoint.toString()},force:!1})}function Re(e){return e.pid===process.pid}async function ze(e){return await new i.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:await U(),serviceType:`tool`,tags:[z,Ie(e)],environment:Y(),liveOnly:!0})}async function Be(e){return(await ze(e)).filter(e=>!Re(e)).length>0?!1:(await new Promise(e=>setTimeout(e,500)),(await ze(e)).filter(e=>!Re(e)).length===0)}async function Ve(t){if(t.runtimeLifecycle!==B||!t.runtimeServerId)return;let n=t.runtimeServerId,r=Q(await U(),L);try{await(0,i.withFileLock)(r,async()=>{await Be(n)&&await new e.C().stop({serverId:n,force:!0})})}catch(e){console.error(`Failed to stop managed stdio-http runtime; leaving it alive: ${W(e)}`)}}async function He(t,n,r,i){let a=n.autoDisconnect?!0:i?.keepAlive!==void 0&&!i.keepAlive,o,s;try{o=await $(t,n,r),s=await Le(o);let{endpoint:i}=o;await Z(new e.u({endpoint:i,resolveEndpoint:async()=>await Fe(t,n,r)},J()),async()=>{try{await s?.release({kill:!1,releasePort:!1})}catch(e){console.error(`Failed to release stdio-http bridge lease; leaving runtime alive: ${W(e)}`);return}a&&o&&await Ve(o)},{shutdownOnStdinClose:!0})}catch(e){try{await s?.release({kill:!1,releasePort:!1})}catch(t){throw Error(`Failed to start stdio-http transport: ${W(e)}; also failed to release bridge lease: ${W(t)}`)}throw Error(`Failed to start stdio-http transport: ${W(e)}`)}}async function Ue(t,n,r,i,a){try{if(t===P){await je(i);return}if(t===F){await Ae(i,q(n,e.t.HTTP,a),r,ue(n.idleShutdownMinutes));return}await He(q(n,e.t.HTTP,a),n,r,a)}catch(e){throw Error(`Failed to start transport '${t}': ${W(e)}`)}}async function We(t,n){try{let r=await e.y({id:t.id,host:t.host??N,port:t.port,config:n,cache:t.cache,definitionsCache:t.definitionsCache,clearDefinitionsCache:t.clearDefinitionsCache,proxyMode:t.proxyMode,timeoutMs:t.timeoutMs,idleShutdownMinutes:t.idleShutdownMinutes});e.x(r)}catch(e){console.error(`Failed to prestart HTTP runtime '${t.id||`generated-server-id`}': ${W(e)}`),process.exit(1)}}const Ge=new c.Command(`mcp-serve`).description(`Start MCP server with specified transport or prestart the HTTP runtime in the background`).option(`-t, --type <type>`,`Transport type: ${P}, ${F}, or ${I}`).option(`-p, --port <port>`,`Port to listen on (http) or backend port for stdio-http`,e=>Number.parseInt(e,10)).option(`--host <host>`,`Host to bind to (http) or backend host for stdio-http`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`--no-cache`,`Disable configuration caching, always reload from config file`).option(`--definitions-cache <path>`,`Path to prefetched tool/prompt/skill definitions cache file`).option(`--clear-definitions-cache`,`Delete definitions cache before startup`,!1).option(`--proxy-mode <mode>`,`How mcp-proxy exposes downstream tools: meta, flat, search, or group`,`meta`).option(`--id <id>`,`Unique server identifier (overrides config file id, auto-generated if not provided)`).option(`--auto-disconnect`,`Stop the managed HTTP runtime when the last stdio-http bridge exits (default: keep runtime alive for reuse)`,!1).option(`--idle-shutdown-minutes <minutes>`,`Stop the HTTP runtime after N minutes with no MCP session and no request (0 disables; overrides ${H})`,e=>Number.parseFloat(e)).option(`--prestart-http`,`Prestart the HTTP runtime in the background and exit after it becomes healthy`,!1).option(`--timeout-ms <ms>`,`How long to wait for the HTTP runtime to become healthy`,String(e.g)).action(async t=>{try{let n=e.I(t.config),r=n.length>0?null:await fe(),i=r?[r]:n;if(t.prestartHttp){await We(t,i);return}let a=await me(i),o=ge((t.type??a.type??P).toLowerCase());_e(t.proxyMode),await Ue(o,t,i,ye(t,i,await he(t,i)),a)}catch(e){let n=(t.type??P).toLowerCase(),r=G(n)?n:P,i=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0,a=t.port??(Number.isFinite(i)?i:void 0);console.error(be(r,t.host??N,a,e)),process.exit(1)}}),Ke=new c.Command(`prefetch`).description(`Pre-download packages used by MCP servers (npx, pnpx, uvx, uv)`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-p, --parallel`,`Run prefetch commands in parallel`,!1).option(`-d, --dry-run`,`Show what would be prefetched without executing`,!1).option(`-f, --filter <type>`,`Filter by package manager type: npx, pnpx, uvx, or uv`).option(`--definitions-out <path>`,`Write discovered definitions to a JSON or YAML cache file`).option(`--skip-packages`,`Skip package prefetch and only build definitions cache`,!1).option(`--clear-definitions-cache`,`Delete the definitions cache file before continuing`,!1).action(async t=>{try{let n=e.o(),r=e.I(t.config),i=r.length>0?null:await e.P(),a=i?[i]:r;a.length===0&&(O.error(`No MCP configuration file found.`),O.info(`Use --config <path> to specify a config file, or run "po-mcp-proxy init" to create one.`),process.exit(1)),O.info(`Loading configuration from: ${a.join(`, `)}`);let o=await n.createConfigFetcherService({configSources:e.L(a),useCache:!1}).fetchConfiguration(!0),s=o.id||e.N(),c=e.j.generateConfigHash(o),l=t.definitionsOut||e.j.getDefaultCachePath(a),u=n.createPrefetchService({mcpConfig:o,filter:t.filter,parallel:t.parallel}),d=u.extractPackages(),f=!t.skipPackages,p=!!t.definitionsOut;if(t.clearDefinitionsCache&&(t.dryRun?O.info(`Would clear definitions cache: ${l}`):(await e.j.clearFile(l),O.success(`Cleared definitions cache: ${l}`))),f){if(d.length===0)O.warning(`No packages found to prefetch.`),O.info(`Prefetch supports: npx, pnpx, uvx, and uv run commands`);else{O.info(`Found ${d.length} package(s) to prefetch:`);for(let e of d)O.item(`${e.serverName}: ${e.packageManager} ${e.packageName}`)}}if(!f&&!p){O.warning(`Nothing to do. Use package prefetch or provide --definitions-out.`);return}if(t.dryRun){if(f&&d.length>0){O.newline(),O.header(`Dry run mode - commands that would be executed:`);for(let e of d)O.indent(e.fullCommand.join(` `))}p&&(O.newline(),O.info(`Would write definitions cache to: ${l}`));return}let m=!1;if(f&&d.length>0){O.newline(),O.info(`Prefetching packages...`);let e=await u.prefetch();if(O.newline(),e.failed===0?O.success(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`):O.warning(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`),e.failed>0){m=!0,O.newline(),O.error(`Failed packages:`);for(let t of e.results.filter(e=>!e.success))O.item(`${t.package.serverName} (${t.package.packageName}): ${t.output.trim()}`)}}if(p){O.newline(),O.info(`Collecting definitions cache...`);let t=await n.createClientManagerService(),r=o.skills?.paths||[],i=r.length>0?n.createSkillService(process.cwd(),r):void 0,u=n.createDefinitionsCacheService(t,i);await Promise.all(Object.entries(o.mcpServers).map(async([e,n])=>{try{await t.connectToServer(e,n),O.item(`Connected for definitions: ${e}`)}catch(t){O.warning(`Failed to connect for definitions: ${e} (${t instanceof Error?t.message:String(t)})`)}}));let d=await u.collectForCache({configPath:a[0],configHash:c,oneMcpVersion:e.h,serverId:s});await e.j.writeToFile(l,d),O.success(`Definitions cache written: ${l} (${Object.keys(d.servers).length} servers, ${d.skills.length} skills)`),d.failures.length>0&&O.warning(`Definitions cache completed with ${d.failures.length} server failure(s)`),await t.disconnectAll()}m&&process.exit(1)}catch(e){O.error(`Error executing prefetch: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});function qe(e){return e instanceof Error?e.message:String(e)}const Je=new c.Command(`read-resource`).description(`Read a resource by URI from a connected MCP server`).argument(`<uri>`,`Resource URI to read`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Server name (required if resource exists on multiple servers)`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await x(t,async({clientManager:n})=>{let r=n.getAllClients();if(t.server){let r=n.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Reading ${e} from ${t.server}...`);let i=await r.readResource(e);if(t.json)console.log(JSON.stringify(i,null,2));else for(let e of i.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2));return}let i=await Promise.all(r.map(async t=>{try{let n=(await t.listResources()).some(t=>t.uri===e);return{serverName:t.serverName,hasResource:n,error:null}}catch(e){return{serverName:t.serverName,hasResource:!1,error:e}}})),a=[];for(let{serverName:e,hasResource:t,error:n}of i)n?console.error(`Failed to list resources from ${e}: ${qe(n)}`):t&&a.push(e);if(a.length===0)throw Error(`Resource "${e}" not found on any connected server`);if(a.length>1)throw Error(`Resource "${e}" found on multiple servers: ${a.join(`, `)}. Use --server to disambiguate`);let o=a[0],s=n.getClient(o);if(!s)throw Error(`Internal error: Server "${o}" not connected`);t.json||console.error(`Reading ${e} from ${o}...`);let c=await s.readResource(e);if(t.json)console.log(JSON.stringify(c,null,2));else for(let e of c.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2))})}catch(e){console.error(`Error executing read-resource: ${qe(e)}`),process.exit(1)}});function Ye(e){return e instanceof Error?e.message:String(e)}function Xe(e){console.log(`Stopped mcp-proxy server '${e.serverId}'.`),console.log(`Endpoint: http://${e.host}:${e.port}`),console.log(`Result: ${e.message}`)}const Ze=new c.Command(`stop`).description(`Stop a running HTTP mcp-proxy server`).option(`--id <id>`,`Target server ID from the runtime registry`).option(`--host <host>`,`Target runtime host`).option(`--port <port>`,`Target runtime port`,e=>Number.parseInt(e,10)).option(`-c, --config <path>`,`Reserved for future config-based targeting support`).option(`--token <token>`,`Override the persisted shutdown token`).option(`--force`,`Skip server ID verification against the /health response`,!1).option(`-j, --json`,`Output as JSON`,!1).option(`--timeout <ms>`,`Maximum time to wait for shutdown completion`,e=>Number.parseInt(e,10),5e3).action(async t=>{try{t.config&&console.error(`Warning: --config is not used yet; runtime resolution uses the persisted registry.`);let n=await e.o().createStopServerService().stop({serverId:t.id,host:t.host,port:t.port,token:t.token,force:t.force,timeoutMs:t.timeout});if(t.json){console.log(JSON.stringify(n,null,2));return}Xe(n)}catch(e){let n=`Error executing stop: ${Ye(e)}`;t.json?console.log(JSON.stringify({ok:!1,error:n},null,2)):console.error(n),process.exit(1)}});function Qe(e){return e instanceof Error?e.message:String(e)}const $e=new c.Command(`use-tool`).description(`Execute an MCP tool with arguments`).argument(`<toolName>`,`Tool name to execute`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,e.F).option(`-s, --server <name>`,`Server name (required if tool exists on multiple servers)`).option(`-a, --args <json>`,`Tool arguments as JSON string`,`{}`).option(`-t, --timeout <ms>`,`Request timeout in milliseconds for tool execution (default: 60000)`,Number.parseInt).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{let n={};try{n=JSON.parse(t.args)}catch{console.error(`Error: Invalid JSON in --args`),process.exit(1)}await x(t,async({container:r,config:i,clientManager:a})=>{let o=a.getAllClients();if(t.server){let r=a.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Executing ${e} on ${t.server}...`);let i=t.timeout?{timeout:t.timeout}:void 0,o=await r.callTool(e,n,i);if(t.json)console.log(JSON.stringify(o,null,2));else{if(console.log(`
|
|
142
142
|
Result:`),o.content)for(let e of o.content)e.type===`text`?console.log(e.text):console.log(JSON.stringify(e,null,2));o.isError&&(console.error(`
|
|
143
143
|
⚠️ Tool execution returned an error`),process.exit(1))}return}let s=await Promise.all(o.map(async t=>{try{let n=(await t.listTools()).some(t=>t.name===e);return{serverName:t.serverName,hasTool:n,error:null}}catch(e){return{serverName:t.serverName,hasTool:!1,error:e}}})),c=[];for(let{serverName:e,hasTool:n,error:r}of s)r?t.json||console.error(`Failed to list tools from ${e}:`,r):n&&c.push(e);if(c.length===0){let n=i.skills?.paths||[];if(n.length>0)try{let i=process.env.PROJECT_PATH||process.cwd(),a=r.createSkillService(i,n),o=e.startsWith(`skill__`)?e.slice(7):e,s=await a.getSkill(o);if(s){let e={content:[{type:`text`,text:s.content}]};t.json?console.log(JSON.stringify(e,null,2)):(console.log(`
|
|
144
144
|
Skill content:`),console.log(s.content));return}}catch(n){t.json||console.error(`Failed to lookup skill "${e}":`,n)}throw Error(`Tool or skill "${e}" not found on any connected server or configured skill paths`)}if(c.length>1)throw Error(`Tool "${e}" found on multiple servers: ${c.join(`, `)}`);let l=c[0],u=a.getClient(l);if(!u)throw Error(`Internal error: Server "${l}" not connected`);t.json||console.error(`Executing ${e} on ${l}...`);let d=t.timeout?{timeout:t.timeout}:void 0,f=await u.callTool(e,n,d);if(t.json)console.log(JSON.stringify(f,null,2));else{if(console.log(`
|
|
145
145
|
Result:`),f.content)for(let e of f.content)e.type===`text`?console.log(e.text):console.log(JSON.stringify(e,null,2));f.isError&&(console.error(`
|
|
146
|
-
⚠️ Tool execution returned an error`),process.exit(1))}})}catch(e){console.error(`Error executing use-tool: ${Qe(e)}`),process.exit(1)}});async function et(){try{let t=new
|
|
146
|
+
⚠️ Tool execution returned an error`),process.exit(1))}})}catch(e){console.error(`Error executing use-tool: ${Qe(e)}`),process.exit(1)}});async function et(){try{let t=new c.Command;t.name(`po-mcp-proxy`).description(`MCP proxy server package`).version(e.h),t.addCommand(re),t.addCommand(Ge),t.addCommand(ce),t.addCommand(C),t.addCommand($e),t.addCommand(ae),t.addCommand(Je),t.addCommand(ie),t.addCommand(ee),t.addCommand(Ke),t.addCommand(Ze),t.addCommand(g),await t.parseAsync(process.argv)}catch(e){console.error(`CLI execution failed: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}et().catch(e=>{console.error(`Fatal error: ${e instanceof Error?e.message:String(e)}`),process.exit(1)});
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{C as e,F as t,I as n,L as r,M as i,N as a,P as o,S as s,T as c,_ as l,b as u,d,dt as f,g as p,h as m,j as h,l as g,n as _,o as v,r as y,t as b,u as x,v as ee,x as S,y as C}from"./src-
|
|
2
|
+
import{C as e,F as t,I as n,L as r,M as i,N as a,P as o,S as s,T as c,_ as l,b as u,d,dt as f,g as p,h as m,j as h,l as g,n as _,o as v,r as y,t as b,u as x,v as ee,x as S,y as C}from"./src-B7q2gdrL.mjs";import{access as w,readFile as T,writeFile as te}from"node:fs/promises";import{dirname as E,join as D,resolve as O}from"node:path";import{createHash as ne,randomUUID as re}from"node:crypto";import{ProcessRegistryService as k,createProcessLease as ie,normalizeRepositoryPath as ae,withFileLock as oe}from"@agimon-ai/foundation-process-registry";import*as se from"js-yaml";import{DEFAULT_PORT_RANGE as ce,PortRegistryService as le}from"@agimon-ai/foundation-port-registry";import{Liquid as ue}from"liquidjs";import{Command as A}from"commander";import{constants as de}from"node:fs";function fe(e){return`runtime:${e}`}function pe(e){return e instanceof Error?e.message:String(e)}async function me(e){let t=await e.listProcesses({serviceName:`mcp-proxy-http`,liveOnly:!0}),n=/* @__PURE__ */ new Set;for(let e of t){let t=e.metadata?.serverId;typeof t==`string`&&n.add(t)}return n}async function he(e,t){let n=await e.listProcesses({serviceType:`tool`,tags:[`mcp-proxy-stdio-http-bridge`],liveOnly:!0}),r=fe(t);return n.filter(e=>e.tags?.includes(r)).length}async function ge(e){let t=e.probe??(async(e,t)=>(await u(e,t)).ok),n={stopped:[],removedFiles:[],kept:[]},r=await me(e.processRegistry),i=await e.runtimeStateService.listOrphans(r);for(let r of i){let i={serverId:r.serverId,host:r.host,port:r.port,reason:``};if(!await t(r.host,r.port)){i.reason=`unreachable runtime; removed stale state file`,e.dryRun||await e.runtimeStateService.remove(r.serverId),n.removedFiles.push(i);continue}if(r.runtimeLifecycle!==`stdio-http-managed`){i.reason=`manual runtime; left untouched`,n.kept.push(i);continue}let a=await he(e.processRegistry,r.serverId);if(a>0)i.reason=`managed runtime with ${a} live bridge(s); kept`,n.kept.push(i);else{if(i.reason=`orphaned stdio-http-managed runtime (no live bridges); stopped`,!e.dryRun)try{await e.stopServerService.stop({serverId:r.serverId,force:!0}),await e.runtimeStateService.remove(r.serverId).catch(()=>void 0)}catch(e){i.reason=`failed to stop orphaned runtime: ${pe(e)}`,n.kept.push(i);continue}n.stopped.push(i)}}return n}function _e(e,t){let n=t?`Would stop`:`Stopped`;for(let t of e.stopped)console.log(`${n} orphaned runtime '${t.serverId}' (http://${t.host}:${t.port}) — ${t.reason}`);let r=t?`Would remove`:`Removed`;for(let t of e.removedFiles)console.log(`${r} stale state for '${t.serverId}' (http://${t.host}:${t.port})`);for(let t of e.kept)console.log(`Kept '${t.serverId}' (http://${t.host}:${t.port}) — ${t.reason}`);console.log(`Summary: ${e.stopped.length} stopped, ${e.removedFiles.length} stale file(s), ${e.kept.length} kept.`)}const ve=new A(`cleanup`).description(`Reap orphaned/stale mcp-proxy HTTP runtimes and their leftover state files`).option(`-n, --dry-run`,`Report what would be done without stopping or removing anything`,!1).option(`-j, --json`,`Output as JSON`,!1).action(async t=>{try{let n=await ge({runtimeStateService:new c,processRegistry:new k(process.env.PROCESS_REGISTRY_PATH),stopServerService:new e,dryRun:t.dryRun});if(t.json){console.log(JSON.stringify({dryRun:t.dryRun,...n},null,2));return}_e(n,t.dryRun)}catch(e){let n=`Error executing cleanup: ${pe(e)}`;t.json?console.log(JSON.stringify({ok:!1,error:n},null,2)):console.error(n),process.exit(1)}});function j(e){return e instanceof Error?e.message:String(e)}async function ye(e,t){try{return(await fetch(`http://${e}:${t}/health`,{signal:AbortSignal.timeout(3e3)})).ok}catch{return!1}}async function be(e,t,n,r,i){let a=t.proxy?.host??`localhost`,o=t.proxy?.port,s=`http://${a}:${o}/mcp`;await ye(a,o)||(r.json||console.error(`Starting HTTP proxy server in background...`),await C({host:a,port:o,config:n,cache:r.useCache!==!1,clearDefinitionsCache:!1,proxyMode:`flat`}));let c=await e.createClientManagerService();try{await c.connectToServer(`proxy`,{name:`proxy`,transport:`http`,config:{url:s}}),r.json||console.error(`✓ Connected to proxy at ${s}`)}catch(e){throw Error(`Failed to connect to proxy server at ${s}: ${j(e)}`)}try{return await i({container:e,configFilePaths:n,config:t,clientManager:c})}finally{await c.disconnectAll()}}async function xe(e,t,n,r,i){let a=await e.createClientManagerService();if(await Promise.all(Object.entries(t.mcpServers).map(async([e,t])=>{try{await a.connectToServer(e,t),r.json||console.error(`✓ Connected to ${e}`)}catch(t){r.json||console.error(`✗ Failed to connect to ${e}: ${j(t)}`)}})),a.getAllClients().length===0)throw Error(`No MCP servers connected`);try{return await i({container:e,configFilePaths:n,config:t,clientManager:a})}finally{await a.disconnectAll()}}async function M(e,t){let i=(e,t)=>{t===void 0?console.error(e):console.error(e,t)},a=e.json?{trace:i,debug:i,info:i,warn:i,error:i}:console,s=v(a),c=n(e.config),l=c.length>0?null:await o(),u=l?[l]:c;if(u.length===0)throw Error(`No config file found. Use --config or create mcp-config.yaml`);let d=await s.createConfigFetcherService({configSources:r(u),useCache:e.useCache}).fetchConfiguration();return d.proxy?.port?await be(s,d,u,e,t):await xe(s,d,u,e,t)}function Se(e){return e instanceof Error?e.message:String(e)}const Ce=new A(`describe-tools`).description(`Describe specific MCP tools`).argument(`<toolNames...>`,`Tool names to describe`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await M(t,async({container:n,config:r,clientManager:i})=>{let a=t.server?[i.getClient(t.server)].filter(e=>e!==void 0):i.getAllClients();if(t.server&&a.length===0)throw Error(`Server "${t.server}" not found`);let o=process.env.PROJECT_PATH||process.cwd(),s=r.skills?.paths||[],c=s.length>0?n.createSkillService(o,s):void 0,l=[],u=[],d=[...e],f=await Promise.all(a.map(async e=>{try{return{client:e,tools:await e.listTools(),error:null}}catch(t){return{client:e,tools:[],error:t}}}));for(let{client:n,tools:r,error:i}of f)if(i)t.json||console.error(`Failed to list tools from ${n.serverName}:`,i);else for(let t of e){let e=r.find(e=>e.name===t);if(e){l.push({server:n.serverName,name:e.name,description:e.description,inputSchema:e.inputSchema});let r=d.indexOf(t);r>-1&&d.splice(r,1)}}if(c&&d.length>0){let e=await Promise.all([...d].map(async e=>{let t=e.startsWith(`skill__`)?e.slice(7):e;return{toolName:e,skill:await c.getSkill(t)}}));for(let{toolName:t,skill:n}of e)if(n){u.push({name:n.name,location:n.basePath,instructions:n.content});let e=d.indexOf(t);e>-1&&d.splice(e,1)}}let p=[];if(l.length>0&&p.push(`For MCP tools: Use the use_tool function with toolName and toolArgs based on the inputSchema above.`),u.length>0&&p.push(`For skill, just follow skill's description to continue.`),t.json){let e={};l.length>0&&(e.tools=l),u.length>0&&(e.skills=u),p.length>0&&(e.nextSteps=p),d.length>0&&(e.notFound=d),console.log(JSON.stringify(e,null,2))}else{if(l.length>0){console.log(`
|
|
3
3
|
Found tools:
|
|
4
4
|
`);for(let e of l)console.log(`Server: ${e.server}`),console.log(`Tool: ${e.name}`),console.log(`Description: ${e.description||`No description`}`),console.log(`Input Schema:`),console.log(JSON.stringify(e.inputSchema,null,2)),console.log(``)}if(u.length>0){console.log(`
|
|
5
5
|
Found skills:
|
|
@@ -138,7 +138,7 @@ mcpServers:
|
|
|
138
138
|
# # omitToolDescription: true
|
|
139
139
|
# # instruction: Optional user override
|
|
140
140
|
{% endif %}
|
|
141
|
-
`;function P(e=``){console.log(e)}function F(e,t){console.error(t?`${e} ${t}`:e)}const I={info:e=>P(e),error:(e,t)=>F(e,t)},L={info:e=>P(e),warning:e=>P(`Warning: ${e}`),error:e=>F(e),success:e=>P(e),newline:()=>P(),header:e=>P(e),item:e=>P(`- ${e}`),indent:e=>P(` ${e}`)},De=new A(`init`).description(`Initialize MCP configuration file`).option(`-o, --output <path>`,`Output file path`,`mcp-config.yaml`).option(`--json`,`Generate JSON config instead of YAML`,!1).option(`-f, --force`,`Overwrite existing config file`,!1).option(`--mcp-servers <json>`,`JSON string of MCP servers to add to config (optional)`).action(async e=>{try{let t=D(e.output),n=!e.json&&(t.endsWith(`.yaml`)||t.endsWith(`.yml`)),r;if(n){let t=new de,n=null;if(e.mcpServers)try{let t=JSON.parse(e.mcpServers);n=Object.entries(t).map(([e,t])=>({name:e,command:t.command,args:t.args}))}catch(e){I.error(`Failed to parse --mcp-servers JSON:`,e instanceof Error?e.message:String(e)),process.exit(1)}r=await t.parseAndRender(Ee,{mcpServers:n})}else r=Te;try{await ie(t,r,{encoding:`utf-8`,flag:e.force?`w`:`wx`})}catch(e){throw e&&typeof e==`object`&&`code`in e&&e.code===`EEXIST`&&(I.error(`Config file already exists: ${t}`),I.info(`Use --force to overwrite`),process.exit(1)),e}I.info(`MCP configuration file created: ${t}`),I.info(`Next steps:`),I.info(`1. Edit the configuration file to add your MCP servers`),I.info(`2. Run: po-mcp-proxy mcp-serve --config ${t}`)}catch(e){I.error(`Error executing init:`,e instanceof Error?e.message:String(e)),process.exit(1)}});function R(e){return e instanceof Error?e.message:String(e)}const Oe=new A(`list-prompts`).description(`List all available prompts from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await M(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={};if(await Promise.all(n.map(async t=>{try{r[t.serverName]=await t.listPrompts()}catch(n){r[t.serverName]=[],e.json||console.error(`Failed to list prompts from ${t.serverName}: ${R(n)}`)}})),e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No prompts available`);else for(let e of t)if(console.log(` - ${e.name}: ${e.description||`No description`}`),e.arguments&&e.arguments.length>0){let t=e.arguments.map(e=>`${e.name}${e.required?` (required)`:``}`).join(`, `);console.log(` args: ${t}`)}})}catch(e){console.error(`Error executing list-prompts: ${R(e)}`),process.exit(1)}});function ke(e){return e instanceof Error?e.message:String(e)}const Ae=new A(`list-resources`).description(`List all available resources from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await M(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={},i=await Promise.all(n.map(async e=>{try{let t=await e.listResources();return{serverName:e.serverName,resources:t,error:null}}catch(t){return{serverName:e.serverName,resources:[],error:t}}}));for(let{serverName:t,resources:n,error:a}of i)a&&!e.json&&console.error(`Failed to list resources from ${t}: ${ke(a)}`),r[t]=n;if(e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No resources available`);else for(let e of t){let t=e.name?`${e.name} (${e.uri})`:e.uri;console.log(` - ${t}${e.description?`: ${e.description}`:``}`)}})}catch(e){console.error(`Error executing list-resources: ${ke(e)}`),process.exit(1)}});function je(e){return e instanceof Error?e.message:String(e)}function Me(e){for(let t of e.servers)if(console.log(`\n${t.server}:`),t.capabilities&&t.capabilities.length>0&&console.log(` capabilities: ${t.capabilities.join(`, `)}`),t.summary&&console.log(` summary: ${t.summary}`),t.tools.length===0)console.log(` no tools`);else for(let e of t.tools){let t=e.capabilities&&e.capabilities.length>0?` [${e.capabilities.join(`, `)}]`:``;console.log(` - ${e.name}${t}`),e.description&&console.log(` ${e.description}`)}}const Ne=new A(`search-tools`).description(`Search proxied MCP tools by capability or server`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`--capability <name>`,`Filter by capability tag, summary, tool name, or description`).option(`--definitions-cache <path>`,`Path to definitions cache file`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await M(e,async({container:t,config:n,clientManager:r,configFilePaths:i})=>{r.registerServerConfigs(n.mcpServers);let a=e.definitionsCache||h.getDefaultCachePath(i),o;try{o=await h.readFromFile(a)}catch{o=void 0}let s=t.createDefinitionsCacheService(r,void 0,{cacheData:o}),c=(await t.createSearchListToolsTool(r,s).execute({capability:e.capability,serverName:e.server})).content.find(e=>e.type===`text`),l=c?.type===`text`?JSON.parse(c.text):{servers:[]};if(e.json)console.log(JSON.stringify(l,null,2));else{if(!l.servers||l.servers.length===0)throw Error(`No tools matched the requested filters`);Me(l)}})}catch(e){console.error(`Error executing search-tools: ${je(e)}`),process.exit(1)}}),Pe=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],z=`/mcp`,B=`localhost`,V=`stdio`,H=`http`,U=`stdio-http`,W=`mcp-proxy-http`,Fe=`service`;function Ie(){return f()}const G=`mcp-proxy-stdio-http-bridge`,K=`stdio-http-managed`,q=`manual`,Le=`MCP_PROXY_IDLE_SHUTDOWN_MINUTES`;function J(){return Ie()}function Y(e){return e instanceof Error?e.message:String(e)}function Re(e){let t=process.env[Le],n=e??(t?Number.parseFloat(t):void 0);return n===void 0||!Number.isFinite(n)||n<=0?0:Math.round(n*6e4)}function ze(e){return e===V||e===H||e===U}function Be(e){return e===`meta`||e===`flat`||e===`search`||e===`group`}async function Ve(e){try{return await re(e,w.F_OK),!0}catch{return!1}}async function He(){try{let e=process.env.PROJECT_PATH;if(e)for(let t of Pe){let n=D(e,t);if(await Ve(n))return n}let t=process.cwd();for(let e=0;e<=3;e++){for(let e of Pe){let n=te(t,e);if(await Ve(n))return n}let e=E(t);if(e===t)break;t=e}return null}catch(e){throw Error(`Failed to discover MCP config file: ${Y(e)}`)}}function Ue(e){try{let t=T(e,`utf-8`),n=(e.endsWith(`.yaml`)||e.endsWith(`.yml`)?ce.load(t):JSON.parse(t))?.proxy;if(!n||typeof n!=`object`)return{};let r=n;return{type:typeof r.type==`string`?r.type:void 0,port:typeof r.port==`number`&&Number.isInteger(r.port)&&r.port>0?r.port:void 0,host:typeof r.host==`string`?r.host:void 0,keepAlive:typeof r.keepAlive==`boolean`?r.keepAlive:void 0}}catch{return{}}}function We(e){let t={};for(let n of e){let e=Ue(n);e.type!==void 0&&(t.type=e.type),e.port!==void 0&&(t.port=e.port),e.host!==void 0&&(t.host=e.host),e.keepAlive!==void 0&&(t.keepAlive=e.keepAlive)}return t}async function Ge(e,t){let n=v();if(e.id)return e.id;if(t.length>0)try{let i=await n.createConfigFetcherService({configSources:r(t),useCache:e.cache!==!1}).fetchConfiguration(e.cache===!1);if(i.id)return i.id}catch(e){throw Error(`Failed to resolve server ID from config '${t.join(`, `)}': ${Y(e)}`)}return a()}function Ke(e){if(!ze(e))throw Error(`Unknown transport type: '${e}'. Valid options: ${V}, ${H}, ${U}`);return e}function qe(e){if(!Be(e))throw Error(`Unknown proxy mode: '${String(e)}'. Valid options: meta, flat, search, group`)}function Je(e){return e===K?K:q}function Ye(e,t,n){let r=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0;return{mode:t,port:e.port??(Number.isFinite(r)?r:void 0)??n?.port,host:e.host??process.env.MCP_HOST??n?.host??B}}function Xe(){let e=(e,t)=>{t===void 0?console.error(e):console.error(e,t)};return{trace:e,debug:e,info:e,warn:e,error:e}}function Ze(e,t,n){return{configFilePath:t.length>0?t:void 0,noCache:e.cache===!1,serverId:n,definitionsCachePath:e.definitionsCache,clearDefinitionsCache:e.clearDefinitionsCache,proxyMode:e.proxyMode}}function Qe(e,t,n,r){let i=Y(r);return e===V?`Failed to start MCP server with transport '${e}': ${i}`:`Failed to start MCP server with transport '${e}' on ${n===void 0?`${t} (dynamic port)`:`${t}:${n}`}: ${i}`}function $e(e,t,n,r,i,a=q){return{serverId:e,host:t.host??B,port:n,transport:`http`,shutdownToken:r,startedAt:(/* @__PURE__ */ new Date()).toISOString(),pid:process.pid,configPath:i,runtimeLifecycle:a}}function et(){return new ue(process.env.PORT_REGISTRY_PATH)}function X(){return process.env.NODE_ENV??`development`}async function tt(e,t,n,r,i,a,o=n===void 0?le:{min:n,max:n}){let s=et(),c=await s.reservePort({repositoryPath:J(),serviceName:e,serviceType:Fe,environment:X(),pid:process.pid,host:t,preferredPort:n,portRange:o,force:!0,metadata:{transport:i,serverId:r,...a?{configPath:a}:{}}});if(!c.success||!c.record){let e=n===void 0?`dynamic port`:`port ${n}`;throw Error(c.error||`Failed to reserve ${e} in port registry`)}let l=!1;return{port:c.record.port,release:async()=>{if(l)return;l=!0;let t=await s.releasePort({repositoryPath:J(),serviceName:e,serviceType:Fe,pid:process.pid,environment:X(),force:!0});if(!t.success&&t.error&&!t.error.includes(`No matching registry entry`))throw Error(t.error||`Failed to release port for ${e}`)}}}async function nt(e){e&&await e.release()}function rt(e,t,n,r,i){return{serverId:e,shutdownToken:t,onShutdownRequested:n,runtimeLifecycle:r,idleShutdownMs:i}}async function Z(e,t){try{await e.remove(t)}catch(e){throw Error(`Failed to remove runtime state for '${t}': ${Y(e)}`)}}async function it(e,t){try{await e.write(t)}catch(e){throw Error(`Failed to persist runtime state for '${t.serverId}': ${Y(e)}`)}}async function at(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop owned HTTP transport '${n}': ${Y(e)}`)}}finally{await r?.release({kill:!1}),await Z(t,n)}}async function ot(e,t,n){await n?.release({kill:!1}),await Z(e,t)}async function st(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop HTTP transport during cleanup for '${n}': ${Y(e)}`)}}finally{await r?.release({kill:!1}),await Z(t,n)}}async function Q(e,t,n={}){try{await e.start()}catch(e){throw Error(`Failed to start transport handler: ${Y(e)}`)}let r=!1,i=async n=>{if(!r){r=!0,console.error(`\nReceived ${n}, shutting down gracefully...`);try{await e.stop(),t&&await t(),process.exit(0)}catch(e){console.error(`Failed to gracefully stop transport during ${n}: ${Y(e)}`),process.exit(1)}}};process.on(`SIGINT`,async()=>await i(`SIGINT`)),process.on(`SIGTERM`,async()=>await i(`SIGTERM`)),n.shutdownOnStdinClose&&(process.stdin.on(`end`,async()=>await i(`stdin end`)),process.stdin.on(`close`,async()=>await i(`stdin close`)))}async function ct(e,t,n,r){i();let o=n[0],l=await g(e),u=new c,d=O(),f=e.serverId??a(),p=Je(process.env.MCP_PROXY_RUNTIME_LIFECYCLE),m=t.port,h=m===void 0?le:{min:m,max:m},_=await tt(W,t.host??B,m,f,H,o,h),v=_.port,b={...t,port:v},x=await ae({repositoryPath:J(),serviceName:`mcp-proxy-http`,serviceType:`service`,environment:X(),host:b.host??B,port:v,command:process.argv[1],args:process.argv.slice(2),...ee()?{processGroupId:process.pid,terminationMode:`process-group`}:{terminationMode:`direct`},metadata:{transport:H,serverId:f,runtimeLifecycle:p,...o?{configPath:o}:{}}}),S=async()=>{await nt(_??null),S=async()=>void 0},C=$e(f,b,v,d,o,p),w,T=!1,E=async()=>{if(!T){T=!0;try{await at(w,u,C.serverId,x),await S(),await l.dispose(),process.exit(0)}catch(e){throw Error(`Failed to stop HTTP runtime '${C.serverId}' from admin shutdown: ${Y(e)}`)}}};try{let e=rt(C.serverId,d,E,p,r);w=new s(()=>y(l),b,e)}catch(e){throw await S(),await x.release({kill:!1}),await l.dispose(),Error(`Failed to create HTTP runtime server: ${Y(e)}`)}try{await Q(w,async()=>{await S(),await l.dispose(),await ot(u,C.serverId,x)}),await it(u,C)}catch(e){throw await S(),await l.dispose(),await st(w,u,C.serverId,x),Error(`Failed to start HTTP runtime '${C.serverId}': ${Y(e)}`)}console.error(`Runtime state: http://${C.host}:${C.port} (${C.serverId})`)}async function lt(e){let t;try{t=await _(e),await Q(new d(t,Xe()),async()=>{await t?.dispose?.()},{shutdownOnStdinClose:!0})}catch(e){throw await t?.dispose?.(),Error(`Failed to start stdio transport: ${Y(e)}`)}}async function ut(e){if(e)try{return(await new c().read(e))?.runtimeLifecycle}catch{return}}function dt(e){if(!e)return p;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0?t:p}function ft(e,t){let n=k.resolveRegistryPath(process.env.PROCESS_REGISTRY_PATH),r=ne(`sha1`).update(`${oe(e)}|${t}`).digest(`hex`);return te(E(n),`mcp-proxy-runtime-${r.slice(0,16)}.lock`)}async function pt(e,t,n){if(e.port!==void 0)return{endpoint:new URL(`http://${e.host??B}:${e.port}${z}`),runtimeLifecycle:q};let r=J(),i=dt(t.timeoutMs)+1e4;return await se(ft(r,W),async()=>mt(r,e,t,n),{staleAfterMs:i,retryDelayMs:250,maxRetries:Math.ceil(i/250)})}async function mt(e,t,n,r){let i=await l(e);if(i){let e=t.host??i.host,n=i.serverId===`unknown`?void 0:i.serverId;return{endpoint:new URL(`http://${e}:${i.port}${z}`),runtimeServerId:n,runtimeLifecycle:i.runtimeLifecycle??await ut(n)??q}}let a=await C({host:t.host??B,config:r,cache:n.cache,definitionsCache:n.definitionsCache,clearDefinitionsCache:n.clearDefinitionsCache,proxyMode:n.proxyMode,runtimeLifecycle:K,idleShutdownMinutes:n.idleShutdownMinutes});return{endpoint:new URL(`http://${a.host}:${a.port}${z}`),runtimeServerId:a.serverId,runtimeLifecycle:a.runtimeLifecycle??q}}async function ht(e,t,n){let{endpoint:r}=await pt(e,t,n);return r}function gt(e){return`runtime:${e}`}async function _t(e){if(e.runtimeLifecycle===K&&e.runtimeServerId)return await ae({repositoryPath:J(),serviceName:`mcp-proxy-stdio-http-bridge:${O()}`,serviceType:`tool`,environment:X(),pid:process.pid,command:process.argv[1],args:process.argv.slice(2),tags:[G,gt(e.runtimeServerId)],metadata:{transport:U,runtimeServerId:e.runtimeServerId,runtimeLifecycle:e.runtimeLifecycle,endpoint:e.endpoint.toString()},force:!1})}function vt(e){return e.pid===process.pid}async function yt(e){return await new k(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:J(),serviceType:`tool`,tags:[G,gt(e)],environment:X(),liveOnly:!0})}async function bt(e){return(await yt(e)).filter(e=>!vt(e)).length>0?!1:(await new Promise(e=>setTimeout(e,500)),(await yt(e)).filter(e=>!vt(e)).length===0)}async function xt(t){if(t.runtimeLifecycle!==K||!t.runtimeServerId)return;let n=t.runtimeServerId,r=ft(J(),W);try{await se(r,async()=>{await bt(n)&&await new e().stop({serverId:n,force:!0})})}catch(e){console.error(`Failed to stop managed stdio-http runtime; leaving it alive: ${Y(e)}`)}}async function St(e,t,n,r){let i=t.autoDisconnect?!0:r?.keepAlive!==void 0&&!r.keepAlive,a,o;try{a=await pt(e,t,n),o=await _t(a);let{endpoint:r}=a;await Q(new x({endpoint:r,resolveEndpoint:async()=>await ht(e,t,n)},Xe()),async()=>{try{await o?.release({kill:!1,releasePort:!1})}catch(e){console.error(`Failed to release stdio-http bridge lease; leaving runtime alive: ${Y(e)}`);return}i&&a&&await xt(a)},{shutdownOnStdinClose:!0})}catch(e){try{await o?.release({kill:!1,releasePort:!1})}catch(t){throw Error(`Failed to start stdio-http transport: ${Y(e)}; also failed to release bridge lease: ${Y(t)}`)}throw Error(`Failed to start stdio-http transport: ${Y(e)}`)}}async function Ct(e,t,n,r,i){try{if(e===V){await lt(r);return}if(e===H){await ct(r,Ye(t,b.HTTP,i),n,Re(t.idleShutdownMinutes));return}await St(Ye(t,b.HTTP,i),t,n,i)}catch(t){throw Error(`Failed to start transport '${e}': ${Y(t)}`)}}async function wt(e,t){try{let n=await C({id:e.id,host:e.host??B,port:e.port,config:t,cache:e.cache,definitionsCache:e.definitionsCache,clearDefinitionsCache:e.clearDefinitionsCache,proxyMode:e.proxyMode,timeoutMs:e.timeoutMs,idleShutdownMinutes:e.idleShutdownMinutes});S(n)}catch(t){console.error(`Failed to prestart HTTP runtime '${e.id||`generated-server-id`}': ${Y(t)}`),process.exit(1)}}const Tt=new A(`mcp-serve`).description(`Start MCP server with specified transport or prestart the HTTP runtime in the background`).option(`-t, --type <type>`,`Transport type: ${V}, ${H}, or ${U}`).option(`-p, --port <port>`,`Port to listen on (http) or backend port for stdio-http`,e=>Number.parseInt(e,10)).option(`--host <host>`,`Host to bind to (http) or backend host for stdio-http`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`--no-cache`,`Disable configuration caching, always reload from config file`).option(`--definitions-cache <path>`,`Path to prefetched tool/prompt/skill definitions cache file`).option(`--clear-definitions-cache`,`Delete definitions cache before startup`,!1).option(`--proxy-mode <mode>`,`How mcp-proxy exposes downstream tools: meta, flat, search, or group`,`meta`).option(`--id <id>`,`Unique server identifier (overrides config file id, auto-generated if not provided)`).option(`--auto-disconnect`,`Stop the managed HTTP runtime when the last stdio-http bridge exits (default: keep runtime alive for reuse)`,!1).option(`--idle-shutdown-minutes <minutes>`,`Stop the HTTP runtime after N minutes with no MCP session and no request (0 disables; overrides ${Le})`,e=>Number.parseFloat(e)).option(`--prestart-http`,`Prestart the HTTP runtime in the background and exit after it becomes healthy`,!1).option(`--timeout-ms <ms>`,`How long to wait for the HTTP runtime to become healthy`,String(p)).action(async e=>{try{let t=n(e.config),r=t.length>0?null:await He(),i=r?[r]:t;if(e.prestartHttp){await wt(e,i);return}let a=We(i),o=Ke((e.type??a.type??V).toLowerCase());qe(e.proxyMode),await Ct(o,e,i,Ze(e,i,await Ge(e,i)),a)}catch(t){let n=(e.type??V).toLowerCase(),r=ze(n)?n:V,i=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0,a=e.port??(Number.isFinite(i)?i:void 0);console.error(Qe(r,e.host??B,a,t)),process.exit(1)}}),Et=new A(`prefetch`).description(`Pre-download packages used by MCP servers (npx, pnpx, uvx, uv)`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-p, --parallel`,`Run prefetch commands in parallel`,!1).option(`-d, --dry-run`,`Show what would be prefetched without executing`,!1).option(`-f, --filter <type>`,`Filter by package manager type: npx, pnpx, uvx, or uv`).option(`--definitions-out <path>`,`Write discovered definitions to a JSON or YAML cache file`).option(`--skip-packages`,`Skip package prefetch and only build definitions cache`,!1).option(`--clear-definitions-cache`,`Delete the definitions cache file before continuing`,!1).action(async e=>{try{let t=v(),i=n(e.config),s=i.length>0?null:o(),c=s?[s]:i;c.length===0&&(L.error(`No MCP configuration file found.`),L.info(`Use --config <path> to specify a config file, or run "po-mcp-proxy init" to create one.`),process.exit(1)),L.info(`Loading configuration from: ${c.join(`, `)}`);let l=await t.createConfigFetcherService({configSources:r(c),useCache:!1}).fetchConfiguration(!0),u=l.id||a(),d=h.generateConfigHash(l),f=e.definitionsOut||h.getDefaultCachePath(c),p=t.createPrefetchService({mcpConfig:l,filter:e.filter,parallel:e.parallel}),g=p.extractPackages(),_=!e.skipPackages,y=!!e.definitionsOut;if(e.clearDefinitionsCache&&(e.dryRun?L.info(`Would clear definitions cache: ${f}`):(await h.clearFile(f),L.success(`Cleared definitions cache: ${f}`))),_){if(g.length===0)L.warning(`No packages found to prefetch.`),L.info(`Prefetch supports: npx, pnpx, uvx, and uv run commands`);else{L.info(`Found ${g.length} package(s) to prefetch:`);for(let e of g)L.item(`${e.serverName}: ${e.packageManager} ${e.packageName}`)}}if(!_&&!y){L.warning(`Nothing to do. Use package prefetch or provide --definitions-out.`);return}if(e.dryRun){if(_&&g.length>0){L.newline(),L.header(`Dry run mode - commands that would be executed:`);for(let e of g)L.indent(e.fullCommand.join(` `))}y&&(L.newline(),L.info(`Would write definitions cache to: ${f}`));return}let b=!1;if(_&&g.length>0){L.newline(),L.info(`Prefetching packages...`);let e=await p.prefetch();if(L.newline(),e.failed===0?L.success(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`):L.warning(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`),e.failed>0){b=!0,L.newline(),L.error(`Failed packages:`);for(let t of e.results.filter(e=>!e.success))L.item(`${t.package.serverName} (${t.package.packageName}): ${t.output.trim()}`)}}if(y){L.newline(),L.info(`Collecting definitions cache...`);let e=t.createClientManagerService(),n=l.skills?.paths||[],r=n.length>0?t.createSkillService(process.cwd(),n):void 0,i=t.createDefinitionsCacheService(e,r);await Promise.all(Object.entries(l.mcpServers).map(async([t,n])=>{try{await e.connectToServer(t,n),L.item(`Connected for definitions: ${t}`)}catch(e){L.warning(`Failed to connect for definitions: ${t} (${e instanceof Error?e.message:String(e)})`)}}));let a=await i.collectForCache({configPath:c[0],configHash:d,oneMcpVersion:m,serverId:u});await h.writeToFile(f,a),L.success(`Definitions cache written: ${f} (${Object.keys(a.servers).length} servers, ${a.skills.length} skills)`),a.failures.length>0&&L.warning(`Definitions cache completed with ${a.failures.length} server failure(s)`),await e.disconnectAll()}b&&process.exit(1)}catch(e){L.error(`Error executing prefetch: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});function $(e){return e instanceof Error?e.message:String(e)}const Dt=new A(`read-resource`).description(`Read a resource by URI from a connected MCP server`).argument(`<uri>`,`Resource URI to read`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Server name (required if resource exists on multiple servers)`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await M(t,async({clientManager:n})=>{let r=n.getAllClients();if(t.server){let r=n.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Reading ${e} from ${t.server}...`);let i=await r.readResource(e);if(t.json)console.log(JSON.stringify(i,null,2));else for(let e of i.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2));return}let i=await Promise.all(r.map(async t=>{try{let n=(await t.listResources()).some(t=>t.uri===e);return{serverName:t.serverName,hasResource:n,error:null}}catch(e){return{serverName:t.serverName,hasResource:!1,error:e}}})),a=[];for(let{serverName:e,hasResource:t,error:n}of i)n?console.error(`Failed to list resources from ${e}: ${$(n)}`):t&&a.push(e);if(a.length===0)throw Error(`Resource "${e}" not found on any connected server`);if(a.length>1)throw Error(`Resource "${e}" found on multiple servers: ${a.join(`, `)}. Use --server to disambiguate`);let o=a[0],s=n.getClient(o);if(!s)throw Error(`Internal error: Server "${o}" not connected`);t.json||console.error(`Reading ${e} from ${o}...`);let c=await s.readResource(e);if(t.json)console.log(JSON.stringify(c,null,2));else for(let e of c.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2))})}catch(e){console.error(`Error executing read-resource: ${$(e)}`),process.exit(1)}});function Ot(e){return e instanceof Error?e.message:String(e)}function kt(e){console.log(`Stopped mcp-proxy server '${e.serverId}'.`),console.log(`Endpoint: http://${e.host}:${e.port}`),console.log(`Result: ${e.message}`)}const At=new A(`stop`).description(`Stop a running HTTP mcp-proxy server`).option(`--id <id>`,`Target server ID from the runtime registry`).option(`--host <host>`,`Target runtime host`).option(`--port <port>`,`Target runtime port`,e=>Number.parseInt(e,10)).option(`-c, --config <path>`,`Reserved for future config-based targeting support`).option(`--token <token>`,`Override the persisted shutdown token`).option(`--force`,`Skip server ID verification against the /health response`,!1).option(`-j, --json`,`Output as JSON`,!1).option(`--timeout <ms>`,`Maximum time to wait for shutdown completion`,e=>Number.parseInt(e,10),5e3).action(async e=>{try{e.config&&console.error(`Warning: --config is not used yet; runtime resolution uses the persisted registry.`);let t=await v().createStopServerService().stop({serverId:e.id,host:e.host,port:e.port,token:e.token,force:e.force,timeoutMs:e.timeout});if(e.json){console.log(JSON.stringify(t,null,2));return}kt(t)}catch(t){let n=`Error executing stop: ${Ot(t)}`;e.json?console.log(JSON.stringify({ok:!1,error:n},null,2)):console.error(n),process.exit(1)}});function jt(e){return e instanceof Error?e.message:String(e)}const Mt=new A(`use-tool`).description(`Execute an MCP tool with arguments`).argument(`<toolName>`,`Tool name to execute`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Server name (required if tool exists on multiple servers)`).option(`-a, --args <json>`,`Tool arguments as JSON string`,`{}`).option(`-t, --timeout <ms>`,`Request timeout in milliseconds for tool execution (default: 60000)`,Number.parseInt).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{let n={};try{n=JSON.parse(t.args)}catch{console.error(`Error: Invalid JSON in --args`),process.exit(1)}await M(t,async({container:r,config:i,clientManager:a})=>{let o=a.getAllClients();if(t.server){let r=a.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Executing ${e} on ${t.server}...`);let i=t.timeout?{timeout:t.timeout}:void 0,o=await r.callTool(e,n,i);if(t.json)console.log(JSON.stringify(o,null,2));else{if(console.log(`
|
|
141
|
+
`;function P(e=``){console.log(e)}function F(e,t){console.error(t?`${e} ${t}`:e)}const I={info:e=>P(e),error:(e,t)=>F(e,t)},L={info:e=>P(e),warning:e=>P(`Warning: ${e}`),error:e=>F(e),success:e=>P(e),newline:()=>P(),header:e=>P(e),item:e=>P(`- ${e}`),indent:e=>P(` ${e}`)},De=new A(`init`).description(`Initialize MCP configuration file`).option(`-o, --output <path>`,`Output file path`,`mcp-config.yaml`).option(`--json`,`Generate JSON config instead of YAML`,!1).option(`-f, --force`,`Overwrite existing config file`,!1).option(`--mcp-servers <json>`,`JSON string of MCP servers to add to config (optional)`).action(async e=>{try{let t=O(e.output),n=!e.json&&(t.endsWith(`.yaml`)||t.endsWith(`.yml`)),r;if(n){let t=new ue,n=null;if(e.mcpServers)try{let t=JSON.parse(e.mcpServers);n=Object.entries(t).map(([e,t])=>({name:e,command:t.command,args:t.args}))}catch(e){I.error(`Failed to parse --mcp-servers JSON:`,e instanceof Error?e.message:String(e)),process.exit(1)}r=await t.parseAndRender(Ee,{mcpServers:n})}else r=Te;try{await te(t,r,{encoding:`utf-8`,flag:e.force?`w`:`wx`})}catch(e){throw e&&typeof e==`object`&&`code`in e&&e.code===`EEXIST`&&(I.error(`Config file already exists: ${t}`),I.info(`Use --force to overwrite`),process.exit(1)),e}I.info(`MCP configuration file created: ${t}`),I.info(`Next steps:`),I.info(`1. Edit the configuration file to add your MCP servers`),I.info(`2. Run: po-mcp-proxy mcp-serve --config ${t}`)}catch(e){I.error(`Error executing init:`,e instanceof Error?e.message:String(e)),process.exit(1)}});function R(e){return e instanceof Error?e.message:String(e)}const Oe=new A(`list-prompts`).description(`List all available prompts from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await M(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={};if(await Promise.all(n.map(async t=>{try{r[t.serverName]=await t.listPrompts()}catch(n){r[t.serverName]=[],e.json||console.error(`Failed to list prompts from ${t.serverName}: ${R(n)}`)}})),e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No prompts available`);else for(let e of t)if(console.log(` - ${e.name}: ${e.description||`No description`}`),e.arguments&&e.arguments.length>0){let t=e.arguments.map(e=>`${e.name}${e.required?` (required)`:``}`).join(`, `);console.log(` args: ${t}`)}})}catch(e){console.error(`Error executing list-prompts: ${R(e)}`),process.exit(1)}});function ke(e){return e instanceof Error?e.message:String(e)}const Ae=new A(`list-resources`).description(`List all available resources from connected MCP servers`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await M(e,async({clientManager:t})=>{let n=e.server?[t.getClient(e.server)].filter(e=>e!==void 0):t.getAllClients();if(e.server&&n.length===0)throw Error(`Server "${e.server}" not found`);let r={},i=await Promise.all(n.map(async e=>{try{let t=await e.listResources();return{serverName:e.serverName,resources:t,error:null}}catch(t){return{serverName:e.serverName,resources:[],error:t}}}));for(let{serverName:t,resources:n,error:a}of i)a&&!e.json&&console.error(`Failed to list resources from ${t}: ${ke(a)}`),r[t]=n;if(e.json)console.log(JSON.stringify(r,null,2));else for(let[e,t]of Object.entries(r))if(console.log(`\n${e}:`),t.length===0)console.log(` No resources available`);else for(let e of t){let t=e.name?`${e.name} (${e.uri})`:e.uri;console.log(` - ${t}${e.description?`: ${e.description}`:``}`)}})}catch(e){console.error(`Error executing list-resources: ${ke(e)}`),process.exit(1)}});function je(e){return e instanceof Error?e.message:String(e)}function Me(e){for(let t of e.servers)if(console.log(`\n${t.server}:`),t.capabilities&&t.capabilities.length>0&&console.log(` capabilities: ${t.capabilities.join(`, `)}`),t.summary&&console.log(` summary: ${t.summary}`),t.tools.length===0)console.log(` no tools`);else for(let e of t.tools){let t=e.capabilities&&e.capabilities.length>0?` [${e.capabilities.join(`, `)}]`:``;console.log(` - ${e.name}${t}`),e.description&&console.log(` ${e.description}`)}}const Ne=new A(`search-tools`).description(`Search proxied MCP tools by capability or server`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Filter by server name`).option(`--capability <name>`,`Filter by capability tag, summary, tool name, or description`).option(`--definitions-cache <path>`,`Path to definitions cache file`).option(`-j, --json`,`Output as JSON`,!1).action(async e=>{try{await M(e,async({container:t,config:n,clientManager:r,configFilePaths:i})=>{r.registerServerConfigs(n.mcpServers);let a=e.definitionsCache||h.getDefaultCachePath(i),o;try{o=await h.readFromFile(a)}catch{o=void 0}let s=t.createDefinitionsCacheService(r,void 0,{cacheData:o}),c=(await t.createSearchListToolsTool(r,s).execute({capability:e.capability,serverName:e.server})).content.find(e=>e.type===`text`),l=c?.type===`text`?JSON.parse(c.text):{servers:[]};if(e.json)console.log(JSON.stringify(l,null,2));else{if(!l.servers||l.servers.length===0)throw Error(`No tools matched the requested filters`);Me(l)}})}catch(e){console.error(`Error executing search-tools: ${je(e)}`),process.exit(1)}}),Pe=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],z=`/mcp`,B=`localhost`,V=`stdio`,H=`http`,U=`stdio-http`,W=`mcp-proxy-http`,Fe=`service`;async function Ie(){return f()}const G=`mcp-proxy-stdio-http-bridge`,K=`stdio-http-managed`,q=`manual`,Le=`MCP_PROXY_IDLE_SHUTDOWN_MINUTES`;async function J(){return Ie()}function Y(e){return e instanceof Error?e.message:String(e)}function Re(e){let t=process.env[Le],n=e??(t?Number.parseFloat(t):void 0);return n===void 0||!Number.isFinite(n)||n<=0?0:Math.round(n*6e4)}function ze(e){return e===V||e===H||e===U}function Be(e){return e===`meta`||e===`flat`||e===`search`||e===`group`}async function Ve(e){try{return await w(e,de.F_OK),!0}catch{return!1}}async function He(){try{let e=process.env.PROJECT_PATH;if(e)for(let t of Pe){let n=O(e,t);if(await Ve(n))return n}let t=process.cwd();for(let e=0;e<=3;e++){for(let e of Pe){let n=D(t,e);if(await Ve(n))return n}let e=E(t);if(e===t)break;t=e}return null}catch(e){throw Error(`Failed to discover MCP config file: ${Y(e)}`)}}async function Ue(e){try{let t=await T(e,`utf-8`),n=(e.endsWith(`.yaml`)||e.endsWith(`.yml`)?se.load(t):JSON.parse(t))?.proxy;if(!n||typeof n!=`object`)return{};let r=n;return{type:typeof r.type==`string`?r.type:void 0,port:typeof r.port==`number`&&Number.isInteger(r.port)&&r.port>0?r.port:void 0,host:typeof r.host==`string`?r.host:void 0,keepAlive:typeof r.keepAlive==`boolean`?r.keepAlive:void 0}}catch{return{}}}async function We(e){let t={};for(let n of e){let e=await Ue(n);e.type!==void 0&&(t.type=e.type),e.port!==void 0&&(t.port=e.port),e.host!==void 0&&(t.host=e.host),e.keepAlive!==void 0&&(t.keepAlive=e.keepAlive)}return t}async function Ge(e,t){let n=v();if(e.id)return e.id;if(t.length>0)try{let i=await n.createConfigFetcherService({configSources:r(t),useCache:e.cache!==!1}).fetchConfiguration(e.cache===!1);if(i.id)return i.id}catch(e){throw Error(`Failed to resolve server ID from config '${t.join(`, `)}': ${Y(e)}`)}return a()}function Ke(e){if(!ze(e))throw Error(`Unknown transport type: '${e}'. Valid options: ${V}, ${H}, ${U}`);return e}function qe(e){if(!Be(e))throw Error(`Unknown proxy mode: '${String(e)}'. Valid options: meta, flat, search, group`)}function Je(e){return e===K?K:q}function Ye(e,t,n){let r=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0;return{mode:t,port:e.port??(Number.isFinite(r)?r:void 0)??n?.port,host:e.host??process.env.MCP_HOST??n?.host??B}}function Xe(){let e=(e,t)=>{t===void 0?console.error(e):console.error(e,t)};return{trace:e,debug:e,info:e,warn:e,error:e}}function Ze(e,t,n){return{configFilePath:t.length>0?t:void 0,noCache:e.cache===!1,serverId:n,definitionsCachePath:e.definitionsCache,clearDefinitionsCache:e.clearDefinitionsCache,proxyMode:e.proxyMode}}function Qe(e,t,n,r){let i=Y(r);return e===V?`Failed to start MCP server with transport '${e}': ${i}`:`Failed to start MCP server with transport '${e}' on ${n===void 0?`${t} (dynamic port)`:`${t}:${n}`}: ${i}`}function $e(e,t,n,r,i,a=q){return{serverId:e,host:t.host??B,port:n,transport:`http`,shutdownToken:r,startedAt:(/* @__PURE__ */ new Date()).toISOString(),pid:process.pid,configPath:i,runtimeLifecycle:a}}function et(){return new le(process.env.PORT_REGISTRY_PATH)}function X(){return process.env.NODE_ENV??`development`}async function tt(e,t,n,r,i,a,o=n===void 0?ce:{min:n,max:n}){let s=et(),c=await s.reservePort({repositoryPath:await J(),serviceName:e,serviceType:Fe,environment:X(),pid:process.pid,host:t,preferredPort:n,portRange:o,force:!0,metadata:{transport:i,serverId:r,...a?{configPath:a}:{}}});if(!c.success||!c.record){let e=n===void 0?`dynamic port`:`port ${n}`;throw Error(c.error||`Failed to reserve ${e} in port registry`)}let l=!1;return{port:c.record.port,release:async()=>{if(l)return;l=!0;let t=await s.releasePort({repositoryPath:await J(),serviceName:e,serviceType:Fe,pid:process.pid,environment:X(),force:!0});if(!t.success&&t.error&&!t.error.includes(`No matching registry entry`))throw Error(t.error||`Failed to release port for ${e}`)}}}async function nt(e){e&&await e.release()}function rt(e,t,n,r,i){return{serverId:e,shutdownToken:t,onShutdownRequested:n,runtimeLifecycle:r,idleShutdownMs:i}}async function Z(e,t){try{await e.remove(t)}catch(e){throw Error(`Failed to remove runtime state for '${t}': ${Y(e)}`)}}async function it(e,t){try{await e.write(t)}catch(e){throw Error(`Failed to persist runtime state for '${t.serverId}': ${Y(e)}`)}}async function at(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop owned HTTP transport '${n}': ${Y(e)}`)}}finally{await r?.release({kill:!1}),await Z(t,n)}}async function ot(e,t,n){await n?.release({kill:!1}),await Z(e,t)}async function st(e,t,n,r){try{try{await e.stop()}catch(e){throw Error(`Failed to stop HTTP transport during cleanup for '${n}': ${Y(e)}`)}}finally{await r?.release({kill:!1}),await Z(t,n)}}async function Q(e,t,n={}){try{await e.start()}catch(e){throw Error(`Failed to start transport handler: ${Y(e)}`)}let r=!1,i=async n=>{if(!r){r=!0,console.error(`\nReceived ${n}, shutting down gracefully...`);try{await e.stop(),t&&await t(),process.exit(0)}catch(e){console.error(`Failed to gracefully stop transport during ${n}: ${Y(e)}`),process.exit(1)}}};process.on(`SIGINT`,async()=>await i(`SIGINT`)),process.on(`SIGTERM`,async()=>await i(`SIGTERM`)),n.shutdownOnStdinClose&&(process.stdin.on(`end`,async()=>await i(`stdin end`)),process.stdin.on(`close`,async()=>await i(`stdin close`)))}async function ct(e,t,n,r){i();let o=n[0],l=await g(e),u=new c,d=re(),f=e.serverId??a(),p=Je(process.env.MCP_PROXY_RUNTIME_LIFECYCLE),m=t.port,h=m===void 0?ce:{min:m,max:m},_=await tt(W,t.host??B,m,f,H,o,h),v=_.port,b={...t,port:v},x=await ie({repositoryPath:await J(),serviceName:`mcp-proxy-http`,serviceType:`service`,environment:X(),host:b.host??B,port:v,command:process.argv[1],args:process.argv.slice(2),...ee()?{processGroupId:process.pid,terminationMode:`process-group`}:{terminationMode:`direct`},metadata:{transport:H,serverId:f,runtimeLifecycle:p,...o?{configPath:o}:{}}}),S=async()=>{await nt(_??null),S=async()=>void 0},C=$e(f,b,v,d,o,p),w,T=!1,te=async()=>{if(!T){T=!0;try{await at(w,u,C.serverId,x),await S(),await l.dispose(),process.exit(0)}catch(e){throw Error(`Failed to stop HTTP runtime '${C.serverId}' from admin shutdown: ${Y(e)}`)}}};try{let e=rt(C.serverId,d,te,p,r);w=new s(()=>y(l),b,e)}catch(e){throw await S(),await x.release({kill:!1}),await l.dispose(),Error(`Failed to create HTTP runtime server: ${Y(e)}`)}try{await Q(w,async()=>{await S(),await l.dispose(),await ot(u,C.serverId,x)}),await it(u,C)}catch(e){throw await S(),await l.dispose(),await st(w,u,C.serverId,x),Error(`Failed to start HTTP runtime '${C.serverId}': ${Y(e)}`)}console.error(`Runtime state: http://${C.host}:${C.port} (${C.serverId})`)}async function lt(e){let t;try{t=await _(e),await Q(new d(t,Xe()),async()=>{await t?.dispose?.()},{shutdownOnStdinClose:!0})}catch(e){throw await t?.dispose?.(),Error(`Failed to start stdio transport: ${Y(e)}`)}}async function ut(e){if(e)try{return(await new c().read(e))?.runtimeLifecycle}catch{return}}function dt(e){if(!e)return p;let t=Number.parseInt(e,10);return Number.isInteger(t)&&t>0?t:p}function ft(e,t){let n=k.resolveRegistryPath(process.env.PROCESS_REGISTRY_PATH),r=ne(`sha1`).update(`${ae(e)}|${t}`).digest(`hex`);return D(E(n),`mcp-proxy-runtime-${r.slice(0,16)}.lock`)}async function pt(e,t,n){if(e.port!==void 0)return{endpoint:new URL(`http://${e.host??B}:${e.port}${z}`),runtimeLifecycle:q};let r=await J(),i=dt(t.timeoutMs)+1e4;return await oe(ft(r,W),async()=>mt(r,e,t,n),{staleAfterMs:i,retryDelayMs:250,maxRetries:Math.ceil(i/250)})}async function mt(e,t,n,r){let i=await l(e);if(i){let e=t.host??i.host,n=i.serverId===`unknown`?void 0:i.serverId;return{endpoint:new URL(`http://${e}:${i.port}${z}`),runtimeServerId:n,runtimeLifecycle:i.runtimeLifecycle??await ut(n)??q}}let a=await C({host:t.host??B,config:r,cache:n.cache,definitionsCache:n.definitionsCache,clearDefinitionsCache:n.clearDefinitionsCache,proxyMode:n.proxyMode,runtimeLifecycle:K,idleShutdownMinutes:n.idleShutdownMinutes});return{endpoint:new URL(`http://${a.host}:${a.port}${z}`),runtimeServerId:a.serverId,runtimeLifecycle:a.runtimeLifecycle??q}}async function ht(e,t,n){let{endpoint:r}=await pt(e,t,n);return r}function gt(e){return`runtime:${e}`}async function _t(e){if(e.runtimeLifecycle===K&&e.runtimeServerId)return await ie({repositoryPath:await J(),serviceName:`mcp-proxy-stdio-http-bridge:${re()}`,serviceType:`tool`,environment:X(),pid:process.pid,command:process.argv[1],args:process.argv.slice(2),tags:[G,gt(e.runtimeServerId)],metadata:{transport:U,runtimeServerId:e.runtimeServerId,runtimeLifecycle:e.runtimeLifecycle,endpoint:e.endpoint.toString()},force:!1})}function vt(e){return e.pid===process.pid}async function yt(e){return await new k(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:await J(),serviceType:`tool`,tags:[G,gt(e)],environment:X(),liveOnly:!0})}async function bt(e){return(await yt(e)).filter(e=>!vt(e)).length>0?!1:(await new Promise(e=>setTimeout(e,500)),(await yt(e)).filter(e=>!vt(e)).length===0)}async function xt(t){if(t.runtimeLifecycle!==K||!t.runtimeServerId)return;let n=t.runtimeServerId,r=ft(await J(),W);try{await oe(r,async()=>{await bt(n)&&await new e().stop({serverId:n,force:!0})})}catch(e){console.error(`Failed to stop managed stdio-http runtime; leaving it alive: ${Y(e)}`)}}async function St(e,t,n,r){let i=t.autoDisconnect?!0:r?.keepAlive!==void 0&&!r.keepAlive,a,o;try{a=await pt(e,t,n),o=await _t(a);let{endpoint:r}=a;await Q(new x({endpoint:r,resolveEndpoint:async()=>await ht(e,t,n)},Xe()),async()=>{try{await o?.release({kill:!1,releasePort:!1})}catch(e){console.error(`Failed to release stdio-http bridge lease; leaving runtime alive: ${Y(e)}`);return}i&&a&&await xt(a)},{shutdownOnStdinClose:!0})}catch(e){try{await o?.release({kill:!1,releasePort:!1})}catch(t){throw Error(`Failed to start stdio-http transport: ${Y(e)}; also failed to release bridge lease: ${Y(t)}`)}throw Error(`Failed to start stdio-http transport: ${Y(e)}`)}}async function Ct(e,t,n,r,i){try{if(e===V){await lt(r);return}if(e===H){await ct(r,Ye(t,b.HTTP,i),n,Re(t.idleShutdownMinutes));return}await St(Ye(t,b.HTTP,i),t,n,i)}catch(t){throw Error(`Failed to start transport '${e}': ${Y(t)}`)}}async function wt(e,t){try{let n=await C({id:e.id,host:e.host??B,port:e.port,config:t,cache:e.cache,definitionsCache:e.definitionsCache,clearDefinitionsCache:e.clearDefinitionsCache,proxyMode:e.proxyMode,timeoutMs:e.timeoutMs,idleShutdownMinutes:e.idleShutdownMinutes});S(n)}catch(t){console.error(`Failed to prestart HTTP runtime '${e.id||`generated-server-id`}': ${Y(t)}`),process.exit(1)}}const Tt=new A(`mcp-serve`).description(`Start MCP server with specified transport or prestart the HTTP runtime in the background`).option(`-t, --type <type>`,`Transport type: ${V}, ${H}, or ${U}`).option(`-p, --port <port>`,`Port to listen on (http) or backend port for stdio-http`,e=>Number.parseInt(e,10)).option(`--host <host>`,`Host to bind to (http) or backend host for stdio-http`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`--no-cache`,`Disable configuration caching, always reload from config file`).option(`--definitions-cache <path>`,`Path to prefetched tool/prompt/skill definitions cache file`).option(`--clear-definitions-cache`,`Delete definitions cache before startup`,!1).option(`--proxy-mode <mode>`,`How mcp-proxy exposes downstream tools: meta, flat, search, or group`,`meta`).option(`--id <id>`,`Unique server identifier (overrides config file id, auto-generated if not provided)`).option(`--auto-disconnect`,`Stop the managed HTTP runtime when the last stdio-http bridge exits (default: keep runtime alive for reuse)`,!1).option(`--idle-shutdown-minutes <minutes>`,`Stop the HTTP runtime after N minutes with no MCP session and no request (0 disables; overrides ${Le})`,e=>Number.parseFloat(e)).option(`--prestart-http`,`Prestart the HTTP runtime in the background and exit after it becomes healthy`,!1).option(`--timeout-ms <ms>`,`How long to wait for the HTTP runtime to become healthy`,String(p)).action(async e=>{try{let t=n(e.config),r=t.length>0?null:await He(),i=r?[r]:t;if(e.prestartHttp){await wt(e,i);return}let a=await We(i),o=Ke((e.type??a.type??V).toLowerCase());qe(e.proxyMode),await Ct(o,e,i,Ze(e,i,await Ge(e,i)),a)}catch(t){let n=(e.type??V).toLowerCase(),r=ze(n)?n:V,i=process.env.MCP_PORT?Number(process.env.MCP_PORT):void 0,a=e.port??(Number.isFinite(i)?i:void 0);console.error(Qe(r,e.host??B,a,t)),process.exit(1)}}),Et=new A(`prefetch`).description(`Pre-download packages used by MCP servers (npx, pnpx, uvx, uv)`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-p, --parallel`,`Run prefetch commands in parallel`,!1).option(`-d, --dry-run`,`Show what would be prefetched without executing`,!1).option(`-f, --filter <type>`,`Filter by package manager type: npx, pnpx, uvx, or uv`).option(`--definitions-out <path>`,`Write discovered definitions to a JSON or YAML cache file`).option(`--skip-packages`,`Skip package prefetch and only build definitions cache`,!1).option(`--clear-definitions-cache`,`Delete the definitions cache file before continuing`,!1).action(async e=>{try{let t=v(),i=n(e.config),s=i.length>0?null:await o(),c=s?[s]:i;c.length===0&&(L.error(`No MCP configuration file found.`),L.info(`Use --config <path> to specify a config file, or run "po-mcp-proxy init" to create one.`),process.exit(1)),L.info(`Loading configuration from: ${c.join(`, `)}`);let l=await t.createConfigFetcherService({configSources:r(c),useCache:!1}).fetchConfiguration(!0),u=l.id||a(),d=h.generateConfigHash(l),f=e.definitionsOut||h.getDefaultCachePath(c),p=t.createPrefetchService({mcpConfig:l,filter:e.filter,parallel:e.parallel}),g=p.extractPackages(),_=!e.skipPackages,y=!!e.definitionsOut;if(e.clearDefinitionsCache&&(e.dryRun?L.info(`Would clear definitions cache: ${f}`):(await h.clearFile(f),L.success(`Cleared definitions cache: ${f}`))),_){if(g.length===0)L.warning(`No packages found to prefetch.`),L.info(`Prefetch supports: npx, pnpx, uvx, and uv run commands`);else{L.info(`Found ${g.length} package(s) to prefetch:`);for(let e of g)L.item(`${e.serverName}: ${e.packageManager} ${e.packageName}`)}}if(!_&&!y){L.warning(`Nothing to do. Use package prefetch or provide --definitions-out.`);return}if(e.dryRun){if(_&&g.length>0){L.newline(),L.header(`Dry run mode - commands that would be executed:`);for(let e of g)L.indent(e.fullCommand.join(` `))}y&&(L.newline(),L.info(`Would write definitions cache to: ${f}`));return}let b=!1;if(_&&g.length>0){L.newline(),L.info(`Prefetching packages...`);let e=await p.prefetch();if(L.newline(),e.failed===0?L.success(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`):L.warning(`Package prefetch complete: ${e.successful} succeeded, ${e.failed} failed`),e.failed>0){b=!0,L.newline(),L.error(`Failed packages:`);for(let t of e.results.filter(e=>!e.success))L.item(`${t.package.serverName} (${t.package.packageName}): ${t.output.trim()}`)}}if(y){L.newline(),L.info(`Collecting definitions cache...`);let e=await t.createClientManagerService(),n=l.skills?.paths||[],r=n.length>0?t.createSkillService(process.cwd(),n):void 0,i=t.createDefinitionsCacheService(e,r);await Promise.all(Object.entries(l.mcpServers).map(async([t,n])=>{try{await e.connectToServer(t,n),L.item(`Connected for definitions: ${t}`)}catch(e){L.warning(`Failed to connect for definitions: ${t} (${e instanceof Error?e.message:String(e)})`)}}));let a=await i.collectForCache({configPath:c[0],configHash:d,oneMcpVersion:m,serverId:u});await h.writeToFile(f,a),L.success(`Definitions cache written: ${f} (${Object.keys(a.servers).length} servers, ${a.skills.length} skills)`),a.failures.length>0&&L.warning(`Definitions cache completed with ${a.failures.length} server failure(s)`),await e.disconnectAll()}b&&process.exit(1)}catch(e){L.error(`Error executing prefetch: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});function $(e){return e instanceof Error?e.message:String(e)}const Dt=new A(`read-resource`).description(`Read a resource by URI from a connected MCP server`).argument(`<uri>`,`Resource URI to read`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Server name (required if resource exists on multiple servers)`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await M(t,async({clientManager:n})=>{let r=n.getAllClients();if(t.server){let r=n.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Reading ${e} from ${t.server}...`);let i=await r.readResource(e);if(t.json)console.log(JSON.stringify(i,null,2));else for(let e of i.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2));return}let i=await Promise.all(r.map(async t=>{try{let n=(await t.listResources()).some(t=>t.uri===e);return{serverName:t.serverName,hasResource:n,error:null}}catch(e){return{serverName:t.serverName,hasResource:!1,error:e}}})),a=[];for(let{serverName:e,hasResource:t,error:n}of i)n?console.error(`Failed to list resources from ${e}: ${$(n)}`):t&&a.push(e);if(a.length===0)throw Error(`Resource "${e}" not found on any connected server`);if(a.length>1)throw Error(`Resource "${e}" found on multiple servers: ${a.join(`, `)}. Use --server to disambiguate`);let o=a[0],s=n.getClient(o);if(!s)throw Error(`Internal error: Server "${o}" not connected`);t.json||console.error(`Reading ${e} from ${o}...`);let c=await s.readResource(e);if(t.json)console.log(JSON.stringify(c,null,2));else for(let e of c.contents)`text`in e?console.log(e.text):console.log(JSON.stringify(e,null,2))})}catch(e){console.error(`Error executing read-resource: ${$(e)}`),process.exit(1)}});function Ot(e){return e instanceof Error?e.message:String(e)}function kt(e){console.log(`Stopped mcp-proxy server '${e.serverId}'.`),console.log(`Endpoint: http://${e.host}:${e.port}`),console.log(`Result: ${e.message}`)}const At=new A(`stop`).description(`Stop a running HTTP mcp-proxy server`).option(`--id <id>`,`Target server ID from the runtime registry`).option(`--host <host>`,`Target runtime host`).option(`--port <port>`,`Target runtime port`,e=>Number.parseInt(e,10)).option(`-c, --config <path>`,`Reserved for future config-based targeting support`).option(`--token <token>`,`Override the persisted shutdown token`).option(`--force`,`Skip server ID verification against the /health response`,!1).option(`-j, --json`,`Output as JSON`,!1).option(`--timeout <ms>`,`Maximum time to wait for shutdown completion`,e=>Number.parseInt(e,10),5e3).action(async e=>{try{e.config&&console.error(`Warning: --config is not used yet; runtime resolution uses the persisted registry.`);let t=await v().createStopServerService().stop({serverId:e.id,host:e.host,port:e.port,token:e.token,force:e.force,timeoutMs:e.timeout});if(e.json){console.log(JSON.stringify(t,null,2));return}kt(t)}catch(t){let n=`Error executing stop: ${Ot(t)}`;e.json?console.log(JSON.stringify({ok:!1,error:n},null,2)):console.error(n),process.exit(1)}});function jt(e){return e instanceof Error?e.message:String(e)}const Mt=new A(`use-tool`).description(`Execute an MCP tool with arguments`).argument(`<toolName>`,`Tool name to execute`).option(`-c, --config <path>`,`Path to MCP server configuration file (repeatable; later files override earlier ones)`,t).option(`-s, --server <name>`,`Server name (required if tool exists on multiple servers)`).option(`-a, --args <json>`,`Tool arguments as JSON string`,`{}`).option(`-t, --timeout <ms>`,`Request timeout in milliseconds for tool execution (default: 60000)`,Number.parseInt).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{let n={};try{n=JSON.parse(t.args)}catch{console.error(`Error: Invalid JSON in --args`),process.exit(1)}await M(t,async({container:r,config:i,clientManager:a})=>{let o=a.getAllClients();if(t.server){let r=a.getClient(t.server);if(!r)throw Error(`Server "${t.server}" not found`);t.json||console.error(`Executing ${e} on ${t.server}...`);let i=t.timeout?{timeout:t.timeout}:void 0,o=await r.callTool(e,n,i);if(t.json)console.log(JSON.stringify(o,null,2));else{if(console.log(`
|
|
142
142
|
Result:`),o.content)for(let e of o.content)e.type===`text`?console.log(e.text):console.log(JSON.stringify(e,null,2));o.isError&&(console.error(`
|
|
143
143
|
⚠️ Tool execution returned an error`),process.exit(1))}return}let s=await Promise.all(o.map(async t=>{try{let n=(await t.listTools()).some(t=>t.name===e);return{serverName:t.serverName,hasTool:n,error:null}}catch(e){return{serverName:t.serverName,hasTool:!1,error:e}}})),c=[];for(let{serverName:e,hasTool:n,error:r}of s)r?t.json||console.error(`Failed to list tools from ${e}:`,r):n&&c.push(e);if(c.length===0){let n=i.skills?.paths||[];if(n.length>0)try{let i=process.env.PROJECT_PATH||process.cwd(),a=r.createSkillService(i,n),o=e.startsWith(`skill__`)?e.slice(7):e,s=await a.getSkill(o);if(s){let e={content:[{type:`text`,text:s.content}]};t.json?console.log(JSON.stringify(e,null,2)):(console.log(`
|
|
144
144
|
Skill content:`),console.log(s.content));return}}catch(n){t.json||console.error(`Failed to lookup skill "${e}":`,n)}throw Error(`Tool or skill "${e}" not found on any connected server or configured skill paths`)}if(c.length>1)throw Error(`Tool "${e}" found on multiple servers: ${c.join(`, `)}`);let l=c[0],u=a.getClient(l);if(!u)throw Error(`Internal error: Server "${l}" not connected`);t.json||console.error(`Executing ${e} on ${l}...`);let d=t.timeout?{timeout:t.timeout}:void 0,f=await u.callTool(e,n,d);if(t.json)console.log(JSON.stringify(f,null,2));else{if(console.log(`
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src-Cs1NjdyA.cjs");exports.CALLBACK_BIND_WAIT_MS=e.X,exports.CALLBACK_POLL_INTERVAL_MS=e.Z,exports.CALLBACK_PORT_SPAN=e.Q,exports.CALLBACK_TIMEOUT_MS=e.$,exports.CallbackRendezvous=e.ct,exports.ConfigFetcherService=e.R,exports.DEFAULT_CALLBACK_PATH=e.et,exports.DEFAULT_CALLBACK_PORT=e.tt,exports.DEFAULT_HTTP_RUNTIME_TIMEOUT_MS=e.g,exports.DefinitionsCacheService=e.j,exports.DescribeToolsTool=e.m,exports.FileTokenStore=e.G,exports.HttpTransportHandler=e.S,exports.McpClientManagerService=e.E,exports.McpOAuthProvider=e.W,exports.MemoryTokenStore=e.K,exports.OAuthCallbackServer=e.nt,exports.OutputGuardService=e.O,exports.RESERVATION_STALE_MS=e.lt,exports.RuntimeStateService=e.T,exports.SearchListToolsTool=e.p,exports.SkillService=e.w,exports.StdioHttpTransportHandler=e.u,exports.StdioTransportHandler=e.d,exports.StopServerService=e.C,exports.TRANSPORT_MODE=e.t,exports.UseToolTool=e.f,exports.acquireSharedCallbackServer=e.rt,exports.cleanupStaleRegistries=e.M,exports.closeSharedCallbackServer=e.it,exports.collectConfigPath=e.F,exports.createHttpTransportHandler=e.i,exports.createOAuthProvider=e.B,exports.createProxyContainer=e.a,exports.createProxyIoCContainer=e.o,exports.createProxyLogger=e.A,exports.createServer=e.n,exports.createSessionServer=e.r,exports.createStdioHttpTransportHandler=e.s,exports.createStdioTransportHandler=e.c,exports.findConfigFile=e.P,exports.findHealthyExistingRuntime=e._,exports.generateServerId=e.N,exports.getDefaultRendezvousRoot=e.ut,exports.getDefaultTokenStoreDir=e.q,exports.getSharedCallbackServer=e.at,exports.initializeSharedServices=e.l,exports.isAuthError=e.D,exports.parseMcpConfig=e.z,exports.prestartHttpRuntime=e.y,exports.probeRuntimeHealth=e.b,exports.readAuthEntryForUrl=e.J,exports.releaseSharedCallbackServer=e.ot,exports.resolveAuthScheme=e.V,exports.resolveBearerToken=e.H,exports.resolveCallbackPort=e.U,exports.resolveOutputGuardOptions=e.k,exports.resolveWorkspaceRoot=e.dt,exports.toConfigPaths=e.I,exports.toConfigSources=e.L,exports.withTokenStoreLock=e.Y,exports.workspaceCallbackPort=e.st;
|
package/dist/index.d.cts
CHANGED
|
@@ -1212,7 +1212,7 @@ interface CreateOAuthProviderOptions {
|
|
|
1212
1212
|
* @param options - Server identity, configuration and injected collaborators
|
|
1213
1213
|
* @returns A provider ready to hand to an SDK transport
|
|
1214
1214
|
*/
|
|
1215
|
-
export declare function createOAuthProvider(options: CreateOAuthProviderOptions): McpOAuthProvider | undefined
|
|
1215
|
+
export declare function createOAuthProvider(options: CreateOAuthProviderOptions): Promise<McpOAuthProvider | undefined>;
|
|
1216
1216
|
/**
|
|
1217
1217
|
* Port the loopback listener must bind for this server.
|
|
1218
1218
|
*
|
|
@@ -1233,7 +1233,7 @@ export declare function createOAuthProvider(options: CreateOAuthProviderOptions)
|
|
|
1233
1233
|
* @param workspaceRoot - Checkout the port belongs to
|
|
1234
1234
|
* @returns The port to bind
|
|
1235
1235
|
*/
|
|
1236
|
-
export declare function resolveCallbackPort(config: UrlServerConfig, workspaceRoot?: string): number
|
|
1236
|
+
export declare function resolveCallbackPort(config: UrlServerConfig, workspaceRoot?: string): Promise<number>;
|
|
1237
1237
|
//#endregion
|
|
1238
1238
|
//#region src/services/ConfigFetcherService.d.ts
|
|
1239
1239
|
/**
|
|
@@ -1377,7 +1377,7 @@ export declare function toConfigSources(paths: string[]): ConfigSource[];
|
|
|
1377
1377
|
* - Environment variable configuration pattern
|
|
1378
1378
|
*
|
|
1379
1379
|
* CODING STANDARDS:
|
|
1380
|
-
* - Use
|
|
1380
|
+
* - Use asynchronous filesystem operations for config discovery
|
|
1381
1381
|
* - Check PROJECT_PATH environment variable first
|
|
1382
1382
|
* - Fall back to current working directory
|
|
1383
1383
|
* - Support both .yaml and .json extensions
|
|
@@ -1394,7 +1394,7 @@ export declare function toConfigSources(paths: string[]): ConfigSource[];
|
|
|
1394
1394
|
*
|
|
1395
1395
|
* @returns Absolute path to config file, or null if not found
|
|
1396
1396
|
*/
|
|
1397
|
-
export declare function findConfigFile(): string | null
|
|
1397
|
+
export declare function findConfigFile(): Promise<string | null>;
|
|
1398
1398
|
//#endregion
|
|
1399
1399
|
//#region src/utils/generateServerId.d.ts
|
|
1400
1400
|
/**
|
|
@@ -1617,7 +1617,7 @@ export declare function cleanupStaleRegistries(): Promise<void>;
|
|
|
1617
1617
|
* @param startPath - Where to begin the walk
|
|
1618
1618
|
* @returns The workspace root, or the working directory when no marker is found
|
|
1619
1619
|
*/
|
|
1620
|
-
export declare function resolveWorkspaceRoot(startPath?: string): string
|
|
1620
|
+
export declare function resolveWorkspaceRoot(startPath?: string): Promise<string>;
|
|
1621
1621
|
//#endregion
|
|
1622
1622
|
//#region src/commands/http-runtime.d.ts
|
|
1623
1623
|
export declare const DEFAULT_HTTP_RUNTIME_TIMEOUT_MS = 120000;
|
|
@@ -2886,7 +2886,7 @@ interface SharedServices {
|
|
|
2886
2886
|
}
|
|
2887
2887
|
interface ProxyContainer {
|
|
2888
2888
|
createConfigFetcherService(options: ConfigFetcherOptions): ConfigFetcherService;
|
|
2889
|
-
createClientManagerService(outputGuardOptions?: OutputGuardOptions, authOptions?: McpClientManagerAuthOptions, outputSchemaValidation?: OutputSchemaValidationOptions, clientCapabilities?: ClientCapabilities): McpClientManagerService
|
|
2889
|
+
createClientManagerService(outputGuardOptions?: OutputGuardOptions, authOptions?: McpClientManagerAuthOptions, outputSchemaValidation?: OutputSchemaValidationOptions, clientCapabilities?: ClientCapabilities): Promise<McpClientManagerService>;
|
|
2890
2890
|
createRuntimeStateService(runtimeDir?: string): RuntimeStateService;
|
|
2891
2891
|
createStopServerService(runtimeStateService?: RuntimeStateService): StopServerService;
|
|
2892
2892
|
createSkillService(cwd: string, skillPaths: string[], options?: {
|
package/dist/index.d.mts
CHANGED
|
@@ -1212,7 +1212,7 @@ interface CreateOAuthProviderOptions {
|
|
|
1212
1212
|
* @param options - Server identity, configuration and injected collaborators
|
|
1213
1213
|
* @returns A provider ready to hand to an SDK transport
|
|
1214
1214
|
*/
|
|
1215
|
-
export declare function createOAuthProvider(options: CreateOAuthProviderOptions): McpOAuthProvider | undefined
|
|
1215
|
+
export declare function createOAuthProvider(options: CreateOAuthProviderOptions): Promise<McpOAuthProvider | undefined>;
|
|
1216
1216
|
/**
|
|
1217
1217
|
* Port the loopback listener must bind for this server.
|
|
1218
1218
|
*
|
|
@@ -1233,7 +1233,7 @@ export declare function createOAuthProvider(options: CreateOAuthProviderOptions)
|
|
|
1233
1233
|
* @param workspaceRoot - Checkout the port belongs to
|
|
1234
1234
|
* @returns The port to bind
|
|
1235
1235
|
*/
|
|
1236
|
-
export declare function resolveCallbackPort(config: UrlServerConfig, workspaceRoot?: string): number
|
|
1236
|
+
export declare function resolveCallbackPort(config: UrlServerConfig, workspaceRoot?: string): Promise<number>;
|
|
1237
1237
|
//#endregion
|
|
1238
1238
|
//#region src/services/ConfigFetcherService.d.ts
|
|
1239
1239
|
/**
|
|
@@ -1377,7 +1377,7 @@ export declare function toConfigSources(paths: string[]): ConfigSource[];
|
|
|
1377
1377
|
* - Environment variable configuration pattern
|
|
1378
1378
|
*
|
|
1379
1379
|
* CODING STANDARDS:
|
|
1380
|
-
* - Use
|
|
1380
|
+
* - Use asynchronous filesystem operations for config discovery
|
|
1381
1381
|
* - Check PROJECT_PATH environment variable first
|
|
1382
1382
|
* - Fall back to current working directory
|
|
1383
1383
|
* - Support both .yaml and .json extensions
|
|
@@ -1394,7 +1394,7 @@ export declare function toConfigSources(paths: string[]): ConfigSource[];
|
|
|
1394
1394
|
*
|
|
1395
1395
|
* @returns Absolute path to config file, or null if not found
|
|
1396
1396
|
*/
|
|
1397
|
-
export declare function findConfigFile(): string | null
|
|
1397
|
+
export declare function findConfigFile(): Promise<string | null>;
|
|
1398
1398
|
//#endregion
|
|
1399
1399
|
//#region src/utils/generateServerId.d.ts
|
|
1400
1400
|
/**
|
|
@@ -1617,7 +1617,7 @@ export declare function cleanupStaleRegistries(): Promise<void>;
|
|
|
1617
1617
|
* @param startPath - Where to begin the walk
|
|
1618
1618
|
* @returns The workspace root, or the working directory when no marker is found
|
|
1619
1619
|
*/
|
|
1620
|
-
export declare function resolveWorkspaceRoot(startPath?: string): string
|
|
1620
|
+
export declare function resolveWorkspaceRoot(startPath?: string): Promise<string>;
|
|
1621
1621
|
//#endregion
|
|
1622
1622
|
//#region src/commands/http-runtime.d.ts
|
|
1623
1623
|
export declare const DEFAULT_HTTP_RUNTIME_TIMEOUT_MS = 120000;
|
|
@@ -2886,7 +2886,7 @@ interface SharedServices {
|
|
|
2886
2886
|
}
|
|
2887
2887
|
interface ProxyContainer {
|
|
2888
2888
|
createConfigFetcherService(options: ConfigFetcherOptions): ConfigFetcherService;
|
|
2889
|
-
createClientManagerService(outputGuardOptions?: OutputGuardOptions, authOptions?: McpClientManagerAuthOptions, outputSchemaValidation?: OutputSchemaValidationOptions, clientCapabilities?: ClientCapabilities): McpClientManagerService
|
|
2889
|
+
createClientManagerService(outputGuardOptions?: OutputGuardOptions, authOptions?: McpClientManagerAuthOptions, outputSchemaValidation?: OutputSchemaValidationOptions, clientCapabilities?: ClientCapabilities): Promise<McpClientManagerService>;
|
|
2890
2890
|
createRuntimeStateService(runtimeDir?: string): RuntimeStateService;
|
|
2891
2891
|
createStopServerService(runtimeStateService?: RuntimeStateService): StopServerService;
|
|
2892
2892
|
createSkillService(cwd: string, skillPaths: string[], options?: {
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{X as CALLBACK_BIND_WAIT_MS,Z as CALLBACK_POLL_INTERVAL_MS,Q as CALLBACK_PORT_SPAN,$ as CALLBACK_TIMEOUT_MS,ct as CallbackRendezvous,R as ConfigFetcherService,et as DEFAULT_CALLBACK_PATH,tt as DEFAULT_CALLBACK_PORT,g as DEFAULT_HTTP_RUNTIME_TIMEOUT_MS,j as DefinitionsCacheService,m as DescribeToolsTool,G as FileTokenStore,S as HttpTransportHandler,E as McpClientManagerService,W as McpOAuthProvider,K as MemoryTokenStore,nt as OAuthCallbackServer,O as OutputGuardService,lt as RESERVATION_STALE_MS,T as RuntimeStateService,p as SearchListToolsTool,w as SkillService,u as StdioHttpTransportHandler,d as StdioTransportHandler,C as StopServerService,t as TRANSPORT_MODE,f as UseToolTool,rt as acquireSharedCallbackServer,M as cleanupStaleRegistries,it as closeSharedCallbackServer,F as collectConfigPath,i as createHttpTransportHandler,B as createOAuthProvider,a as createProxyContainer,o as createProxyIoCContainer,A as createProxyLogger,n as createServer,r as createSessionServer,s as createStdioHttpTransportHandler,c as createStdioTransportHandler,P as findConfigFile,_ as findHealthyExistingRuntime,N as generateServerId,ut as getDefaultRendezvousRoot,q as getDefaultTokenStoreDir,at as getSharedCallbackServer,l as initializeSharedServices,D as isAuthError,z as parseMcpConfig,y as prestartHttpRuntime,b as probeRuntimeHealth,J as readAuthEntryForUrl,ot as releaseSharedCallbackServer,V as resolveAuthScheme,H as resolveBearerToken,U as resolveCallbackPort,k as resolveOutputGuardOptions,dt as resolveWorkspaceRoot,I as toConfigPaths,L as toConfigSources,Y as withTokenStoreLock,st as workspaceCallbackPort}from"./src-
|
|
1
|
+
export{X as CALLBACK_BIND_WAIT_MS,Z as CALLBACK_POLL_INTERVAL_MS,Q as CALLBACK_PORT_SPAN,$ as CALLBACK_TIMEOUT_MS,ct as CallbackRendezvous,R as ConfigFetcherService,et as DEFAULT_CALLBACK_PATH,tt as DEFAULT_CALLBACK_PORT,g as DEFAULT_HTTP_RUNTIME_TIMEOUT_MS,j as DefinitionsCacheService,m as DescribeToolsTool,G as FileTokenStore,S as HttpTransportHandler,E as McpClientManagerService,W as McpOAuthProvider,K as MemoryTokenStore,nt as OAuthCallbackServer,O as OutputGuardService,lt as RESERVATION_STALE_MS,T as RuntimeStateService,p as SearchListToolsTool,w as SkillService,u as StdioHttpTransportHandler,d as StdioTransportHandler,C as StopServerService,t as TRANSPORT_MODE,f as UseToolTool,rt as acquireSharedCallbackServer,M as cleanupStaleRegistries,it as closeSharedCallbackServer,F as collectConfigPath,i as createHttpTransportHandler,B as createOAuthProvider,a as createProxyContainer,o as createProxyIoCContainer,A as createProxyLogger,n as createServer,r as createSessionServer,s as createStdioHttpTransportHandler,c as createStdioTransportHandler,P as findConfigFile,_ as findHealthyExistingRuntime,N as generateServerId,ut as getDefaultRendezvousRoot,q as getDefaultTokenStoreDir,at as getSharedCallbackServer,l as initializeSharedServices,D as isAuthError,z as parseMcpConfig,y as prestartHttpRuntime,b as probeRuntimeHealth,J as readAuthEntryForUrl,ot as releaseSharedCallbackServer,V as resolveAuthScheme,H as resolveBearerToken,U as resolveCallbackPort,k as resolveOutputGuardOptions,dt as resolveWorkspaceRoot,I as toConfigPaths,L as toConfigSources,Y as withTokenStoreLock,st as workspaceCallbackPort}from"./src-B7q2gdrL.mjs";
|