@agimon-ai/mcp-proxy 0.10.8 → 0.10.9
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
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const e=require(`./src-
|
|
2
|
+
const e=require(`./src-d-zwLzEG.cjs`);let t=require(`node:fs`),n=require(`node:fs/promises`),r=require(`js-yaml`);r=e.O(r,1);let i=require(`node:crypto`),a=require(`node:path`);a=e.O(a,1);let o=require(`@agimon-ai/foundation-process-registry`),s=require(`node:child_process`),c=require(`liquidjs`),l=require(`commander`),u=require(`node:url`),d=require(`@agimon-ai/foundation-port-registry`);const f=[`pnpm-workspace.yaml`,`nx.json`,`.git`],p=`localhost`;function m(e=process.env.PROJECT_PATH||process.cwd()){let n=a.default.resolve(e);for(;;){for(let e of f)if((0,t.existsSync)(a.default.join(n,e)))return n;let e=a.default.dirname(n);if(e===n)return process.cwd();n=e}}async function h(e){let t=(await new o.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:e,serviceName:`mcp-proxy-http`}))[0];if(!t?.host||!t?.port)return null;let n=t.metadata;return{host:t.host,port:t.port,serverId:n?.serverId??`unknown`}}async function g(e,t){try{return(await fetch(`http://${e}:${t}/health`)).ok}catch{return!1}}function _(){let e=(0,u.fileURLToPath)(require(`url`).pathToFileURL(__filename).href),n=a.default.dirname(e),r=[a.default.resolve(n,`cli.mjs`),a.default.resolve(n,`..`,`dist`,`cli.mjs`),a.default.resolve(n,`..`,`..`,`dist`,`cli.mjs`)],i=[a.default.resolve(n,`..`,`cli.ts`),a.default.resolve(n,`..`,`..`,`src`,`cli.ts`)];for(let e of r)if((0,t.existsSync)(e))return{command:process.execPath,args:[e]};for(let e of i)if((0,t.existsSync)(e))return{command:process.execPath,args:[`--import`,`tsx`,e]};throw Error(`Unable to locate mcp-proxy CLI entrypoint`)}function v(e){if(!e)return 12e4;let t=Number.parseInt(e,10);if(!Number.isInteger(t)||t<=0)throw Error(`Invalid timeout value: ${e}`);return t}async function y(e,t){let r=Date.now()+t;for(;Date.now()<r;){try{await(0,n.access)(e);return}catch{}await new Promise(e=>setTimeout(e,250))}throw Error(`Timed out waiting for runtime state file: ${e}`)}async function b(t,n){let r=new e.b,i=Date.now()+n;for(;Date.now()<i;){let e=await r.read(t);if(e){let t=`http://${e.host}:${e.port}/health`;try{let n=await fetch(t);if(n.ok){let t=await n.json().catch(()=>null);if(!t||t.transport===`http`)return{host:e.host,port:e.port}}}catch{}}await new Promise(e=>setTimeout(e,250))}throw Error(`Timed out waiting for HTTP runtime '${t}' to become healthy`)}function x(e,t,n){let{command:r,args:i}=_(),a=(0,s.spawn)(r,[...i,...e],{detached:!0,cwd:n,stdio:`ignore`,env:t});return a.unref(),a}async function ee(t,n,r,i){let a=await t.list(),o=r||p,s=a.find(e=>!!(n&&e.serverId===n||i!==void 0&&e.host===o&&e.port===i));if(!s)return;let c=new e.v(t);try{await c.stop({serverId:s.serverId,force:!0})}catch{await t.remove(s.serverId)}}async function S(t){let n=t.id||e.w(),r=v(t.timeoutMs),i=t.registryPath||t.registryDir,s=m(),c=await h(s);if(c&&await g(c.host,c.port))return{host:c.host,port:c.port,serverId:c.serverId,workspaceRoot:s,reusedExistingRuntime:!0};let l=t.port??c?.port;await ee(new e.b,t.id,t.host,l);let u={...process.env,...i?{PORT_REGISTRY_PATH:i,PROCESS_REGISTRY_PATH:(0,o.resolveSiblingRegistryPath)(i,`processes.json`)}:{}},d=x([`mcp-serve`,`--type`,`http`,`--id`,n,`--host`,t.host||p,...l===void 0?[]:[`--port`,String(l)],...t.config?[`--config`,t.config]:[],...t.cache===!1?[`--no-cache`]:[],...t.definitionsCache?[`--definitions-cache`,t.definitionsCache]:[],...t.clearDefinitionsCache?[`--clear-definitions-cache`]:[],`--proxy-mode`,t.proxyMode],u,s),f=new Promise((e,t)=>{d.once(`exit`,(e,n)=>{t(Error(`Background runtime exited before becoming healthy (code=${e??`null`}, signal=${n??`null`})`))})}),_=a.default.join(e.b.getDefaultRuntimeDir(),`${n}.runtime.json`);try{await Promise.race([y(_,r),f]);let{host:e,port:t}=await Promise.race([b(n,r),f]);return{host:e,port:t,serverId:n,workspaceRoot:s,reusedExistingRuntime:!1}}catch(e){throw Error(`Failed to prestart HTTP runtime '${n}': ${e instanceof Error?e.message:String(e)}`,{cause:e})}}function te(e){process.stdout.write(`mcp-proxy HTTP runtime ready at http://${e.host}:${e.port} (${e.serverId})\n`),process.stdout.write(`runtimeId=${e.serverId}\n`),process.stdout.write(`runtimeUrl=http://${e.host}:${e.port}\n`),process.stdout.write(`workspaceRoot=${e.workspaceRoot}\n`)}function C(e){return e instanceof Error?e.message:String(e)}async function ne(e,t){try{return(await fetch(`http://${e}:${t}/health`,{signal:AbortSignal.timeout(3e3)})).ok}catch{return!1}}async function re(e,t,n,r,i){let a=t.proxy?.host??`localhost`,o=t.proxy?.port,s=`http://${a}:${o}/mcp`;await ne(a,o)||(r.json||console.error(`Starting HTTP proxy server in background...`),await S({host:a,port:o,config:n,cache:r.useCache!==!1,clearDefinitionsCache:!1,proxyMode:`flat`}));let c=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}: ${C(e)}`)}try{return await i({container:e,configFilePath:n,config:t,clientManager:c})}finally{await c.disconnectAll()}}async function ie(e,t,n,r,i){let a=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}: ${C(t)}`)}})),a.getAllClients().length===0)throw Error(`No MCP servers connected`);try{return await i({container:e,configFilePath:n,config:t,clientManager:a})}finally{await a.disconnectAll()}}async function w(t,n){let r=e.o(),i=t.config||e.T();if(!i)throw Error(`No config file found. Use --config or create mcp-config.yaml`);let a=await r.createConfigFetcherService({configFilePath:i,useCache:t.useCache}).fetchConfiguration();return a.proxy?.port?await re(r,a,i,t,n):await ie(r,a,i,t,n)}function ae(e){return e instanceof Error?e.message:String(e)}const oe=new l.Command(`describe-tools`).description(`Describe specific MCP tools`).argument(`<toolNames...>`,`Tool names to describe`).option(`-c, --config <path>`,`Path to MCP server configuration file`).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await w(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);continue}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:
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{C as e,D as t,T as n,b as r,d as i,f as a,m as o,n as s,o as c,p as l,r as u,t as d,u as f,v as p,w as m}from"./src-
|
|
2
|
+
import{C as e,D as t,T as n,b as r,d as i,f as a,m as o,n as s,o as c,p as l,r as u,t as d,u as f,v as p,w as m}from"./src-COQJ9SvW.mjs";import{constants as h,existsSync as g,readFileSync as _}from"node:fs";import{access as v,writeFile as y}from"node:fs/promises";import b from"js-yaml";import{randomUUID as ee}from"node:crypto";import x,{dirname as S,join as te,resolve as C}from"node:path";import{ProcessRegistryService as ne,createProcessLease as re,resolveSiblingRegistryPath as ie}from"@agimon-ai/foundation-process-registry";import{spawn as ae}from"node:child_process";import{Liquid as oe}from"liquidjs";import{Command as w}from"commander";import{fileURLToPath as se}from"node:url";import{DEFAULT_PORT_RANGE as T,PortRegistryService as ce}from"@agimon-ai/foundation-port-registry";const le=[`pnpm-workspace.yaml`,`nx.json`,`.git`],E=`localhost`;function D(e=process.env.PROJECT_PATH||process.cwd()){let t=x.resolve(e);for(;;){for(let e of le)if(g(x.join(t,e)))return t;let e=x.dirname(t);if(e===t)return process.cwd();t=e}}async function ue(e){let t=(await new ne(process.env.PROCESS_REGISTRY_PATH).listProcesses({repositoryPath:e,serviceName:`mcp-proxy-http`}))[0];if(!t?.host||!t?.port)return null;let n=t.metadata;return{host:t.host,port:t.port,serverId:n?.serverId??`unknown`}}async function de(e,t){try{return(await fetch(`http://${e}:${t}/health`)).ok}catch{return!1}}function fe(){let e=se(import.meta.url),t=x.dirname(e),n=[x.resolve(t,`cli.mjs`),x.resolve(t,`..`,`dist`,`cli.mjs`),x.resolve(t,`..`,`..`,`dist`,`cli.mjs`)],r=[x.resolve(t,`..`,`cli.ts`),x.resolve(t,`..`,`..`,`src`,`cli.ts`)];for(let e of n)if(g(e))return{command:process.execPath,args:[e]};for(let e of r)if(g(e))return{command:process.execPath,args:[`--import`,`tsx`,e]};throw Error(`Unable to locate mcp-proxy CLI entrypoint`)}function pe(e){if(!e)return 12e4;let t=Number.parseInt(e,10);if(!Number.isInteger(t)||t<=0)throw Error(`Invalid timeout value: ${e}`);return t}async function me(e,t){let n=Date.now()+t;for(;Date.now()<n;){try{await v(e);return}catch{}await new Promise(e=>setTimeout(e,250))}throw Error(`Timed out waiting for runtime state file: ${e}`)}async function he(e,t){let n=new r,i=Date.now()+t;for(;Date.now()<i;){let t=await n.read(e);if(t){let e=`http://${t.host}:${t.port}/health`;try{let n=await fetch(e);if(n.ok){let e=await n.json().catch(()=>null);if(!e||e.transport===`http`)return{host:t.host,port:t.port}}}catch{}}await new Promise(e=>setTimeout(e,250))}throw Error(`Timed out waiting for HTTP runtime '${e}' to become healthy`)}function ge(e,t,n){let{command:r,args:i}=fe(),a=ae(r,[...i,...e],{detached:!0,cwd:n,stdio:`ignore`,env:t});return a.unref(),a}async function _e(e,t,n,r){let i=await e.list(),a=n||E,o=i.find(e=>!!(t&&e.serverId===t||r!==void 0&&e.host===a&&e.port===r));if(!o)return;let s=new p(e);try{await s.stop({serverId:o.serverId,force:!0})}catch{await e.remove(o.serverId)}}async function O(e){let t=e.id||m(),n=pe(e.timeoutMs),i=e.registryPath||e.registryDir,a=D(),o=await ue(a);if(o&&await de(o.host,o.port))return{host:o.host,port:o.port,serverId:o.serverId,workspaceRoot:a,reusedExistingRuntime:!0};let s=e.port??o?.port;await _e(new r,e.id,e.host,s);let c={...process.env,...i?{PORT_REGISTRY_PATH:i,PROCESS_REGISTRY_PATH:ie(i,`processes.json`)}:{}},l=ge([`mcp-serve`,`--type`,`http`,`--id`,t,`--host`,e.host||E,...s===void 0?[]:[`--port`,String(s)],...e.config?[`--config`,e.config]:[],...e.cache===!1?[`--no-cache`]:[],...e.definitionsCache?[`--definitions-cache`,e.definitionsCache]:[],...e.clearDefinitionsCache?[`--clear-definitions-cache`]:[],`--proxy-mode`,e.proxyMode],c,a),u=new Promise((e,t)=>{l.once(`exit`,(e,n)=>{t(Error(`Background runtime exited before becoming healthy (code=${e??`null`}, signal=${n??`null`})`))})}),d=x.join(r.getDefaultRuntimeDir(),`${t}.runtime.json`);try{await Promise.race([me(d,n),u]);let{host:e,port:r}=await Promise.race([he(t,n),u]);return{host:e,port:r,serverId:t,workspaceRoot:a,reusedExistingRuntime:!1}}catch(e){throw Error(`Failed to prestart HTTP runtime '${t}': ${e instanceof Error?e.message:String(e)}`,{cause:e})}}function ve(e){process.stdout.write(`mcp-proxy HTTP runtime ready at http://${e.host}:${e.port} (${e.serverId})\n`),process.stdout.write(`runtimeId=${e.serverId}\n`),process.stdout.write(`runtimeUrl=http://${e.host}:${e.port}\n`),process.stdout.write(`workspaceRoot=${e.workspaceRoot}\n`)}function k(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 O({host:a,port:o,config:n,cache:r.useCache!==!1,clearDefinitionsCache:!1,proxyMode:`flat`}));let c=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}: ${k(e)}`)}try{return await i({container:e,configFilePath:n,config:t,clientManager:c})}finally{await c.disconnectAll()}}async function xe(e,t,n,r,i){let a=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}: ${k(t)}`)}})),a.getAllClients().length===0)throw Error(`No MCP servers connected`);try{return await i({container:e,configFilePath:n,config:t,clientManager:a})}finally{await a.disconnectAll()}}async function A(e,t){let r=c(),i=e.config||n();if(!i)throw Error(`No config file found. Use --config or create mcp-config.yaml`);let a=await r.createConfigFetcherService({configFilePath:i,useCache:e.useCache}).fetchConfiguration();return a.proxy?.port?await be(r,a,i,e,t):await xe(r,a,i,e,t)}function Se(e){return e instanceof Error?e.message:String(e)}const Ce=new w(`describe-tools`).description(`Describe specific MCP tools`).argument(`<toolNames...>`,`Tool names to describe`).option(`-c, --config <path>`,`Path to MCP server configuration file`).option(`-s, --server <name>`,`Filter by server name`).option(`-j, --json`,`Output as JSON`,!1).action(async(e,t)=>{try{await A(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);continue}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:
|
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-d-zwLzEG.cjs`);exports.ConfigFetcherService=e.E,exports.DefinitionsCacheService=e.C,exports.DescribeToolsTool=e._,exports.HttpTransportHandler=e.m,exports.McpClientManagerService=e.x,exports.RuntimeStateService=e.b,exports.SearchListToolsTool=e.g,exports.SkillService=e.y,exports.SseTransportHandler=e.p,exports.StdioHttpTransportHandler=e.d,exports.StdioTransportHandler=e.f,exports.StopServerService=e.v,exports.TRANSPORT_MODE=e.t,exports.UseToolTool=e.h,exports.createHttpTransportHandler=e.i,exports.createProxyContainer=e.a,exports.createProxyLogger=e.S,exports.createServer=e.n,exports.createSessionServer=e.r,exports.createSseTransportHandler=e.s,exports.createStdioHttpTransportHandler=e.c,exports.createStdioTransportHandler=e.l,exports.findConfigFile=e.T,exports.generateServerId=e.w,exports.initializeSharedServices=e.u;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,E as t,S as n,T as r,_ as i,a,b as o,c as s,d as c,f as l,g as u,h as d,i as f,l as p,m,n as h,p as g,r as _,s as v,t as y,u as b,v as x,w as S,x as C,y as w}from"./src-
|
|
1
|
+
import{C as e,E as t,S as n,T as r,_ as i,a,b as o,c as s,d as c,f as l,g as u,h as d,i as f,l as p,m,n as h,p as g,r as _,s as v,t as y,u as b,v as x,w as S,x as C,y as w}from"./src-COQJ9SvW.mjs";export{t as ConfigFetcherService,e as DefinitionsCacheService,i as DescribeToolsTool,m as HttpTransportHandler,C as McpClientManagerService,o as RuntimeStateService,u as SearchListToolsTool,w as SkillService,g as SseTransportHandler,c as StdioHttpTransportHandler,l as StdioTransportHandler,x as StopServerService,y as TRANSPORT_MODE,d as UseToolTool,f as createHttpTransportHandler,a as createProxyContainer,n as createProxyLogger,h as createServer,_ as createSessionServer,v as createSseTransportHandler,s as createStdioHttpTransportHandler,p as createStdioTransportHandler,r as findConfigFile,S as generateServerId,b as initializeSharedServices};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as e}from"node:fs";import{access as t,mkdir as n,readFile as r,readdir as i,rm as a,stat as o,unlink as s,watch as c,writeFile as l}from"node:fs/promises";import u from"js-yaml";import{z as d}from"zod";import{createHash as f,randomBytes as p,randomUUID as m}from"node:crypto";import{homedir as h,tmpdir as g}from"node:os";import{dirname as _,isAbsolute as v,join as y,resolve as b}from"node:path";import{createNodeTelemetry as ee}from"@agimon-ai/log-sink-mcp";import{Client as x}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as te}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as ne}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as re}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{createProcessLease as ie}from"@agimon-ai/foundation-process-registry";import{spawn as ae}from"node:child_process";import{Liquid as oe}from"liquidjs";import{coerceArgs as se,formatZodError as ce,jsonSchemaToZod as le}from"@agimon-ai/foundation-validator";import{once as ue}from"node:events";import{createServer as de}from"node:http";import{promisify as fe}from"node:util";import{getRequestListener as pe}from"@hono/node-server";import{StreamableHTTPServerTransport as me}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as he,ElicitRequestSchema as ge,GetPromptRequestSchema as _e,ListPromptsRequestSchema as ve,ListResourcesRequestSchema as ye,ListToolsRequestSchema as be,ReadResourceRequestSchema as xe,isInitializeRequest as Se}from"@modelcontextprotocol/sdk/types.js";import{Hono as Ce}from"hono";import{SSEServerTransport as we}from"@modelcontextprotocol/sdk/server/sse.js";import{StdioServerTransport as Te}from"@modelcontextprotocol/sdk/server/stdio.js";import{Server as Ee}from"@modelcontextprotocol/sdk/server/index.js";var S=`0.10.7`;function C(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(console.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}function w(e){if(typeof e==`string`)return C(e);if(Array.isArray(e))return e.map(e=>w(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=w(r);return t}return e}const De=[/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\./,/^224\./,/^240\./,/^localhost$/i,/^.*\.localhost$/i,/^\[::\]/,/^\[::1\]/,/^\[0:0:0:0:0:0:0:1\]/,/^\[0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:1\]/i,/^\[fe80:/i,/^\[fc00:/i,/^\[fd00:/i,/^\[::ffff:127\./i,/^\[::ffff:7f[0-9a-f]{2}:/i,/^\[::ffff:10\./i,/^\[::ffff:a[0-9a-f]{2}:/i,/^\[::ffff:172\.(1[6-9]|2\d|3[01])\./i,/^\[::ffff:ac1[0-9a-f]:/i,/^\[::ffff:192\.168\./i,/^\[::ffff:c0a8:/i,/^\[::ffff:169\.254\./i,/^\[::ffff:a9fe:/i,/^\[::ffff:0\./i,/^\[::127\./i,/^\[::7f[0-9a-f]{2}:/i,/^\[::10\./i,/^\[::a[0-9a-f]{2}:/i,/^\[::192\.168\./i,/^\[::c0a8:/i];function Oe(e,t){let n=t?.allowPrivateIPs??!1,r=t?.enforceHttps??!0,i;try{i=new URL(e)}catch{throw Error(`Invalid URL format: ${e}`)}let a=i.protocol.replace(`:`,``);if(r&&a!==`https`)throw Error(`HTTPS is required for security. URL uses '${a}://'. Set security.enforceHttps: false to allow HTTP.`);if(a!==`http`&&a!==`https`)throw Error(`Invalid URL protocol '${a}://'. Only http:// and https:// are allowed.`);if(!n){let e=i.hostname.toLowerCase();if(De.some(t=>t.test(e)))throw Error(`Private IP addresses and localhost are blocked for security (${e}). Set security.allowPrivateIPs: true to allow internal networks.`)}}function ke(e){let t=C(e.url);if(Oe(t,e.security),e.validation){if(e.validation.url&&!new RegExp(e.validation.url).test(t))throw Error(`Remote config URL "${t}" does not match validation pattern: ${e.validation.url}`);if(e.validation.headers&&Object.keys(e.validation.headers).length>0){if(!e.headers){let t=Object.keys(e.validation.headers);throw Error(`Remote config is missing required headers: ${t.join(`, `)}`)}for(let[t,n]of Object.entries(e.validation.headers)){if(!(t in e.headers))throw Error(`Remote config is missing required header: ${t}`);let r=C(e.headers[t]);if(!new RegExp(n).test(r))throw Error(`Remote config header "${t}" value "${r}" does not match validation pattern: ${n}`)}}}}const Ae=d.object({name:d.string(),description:d.string(),folder:d.string().optional()}),je=d.object({skill:Ae.optional()}),T=d.object({instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),je).optional()}).optional(),Me=d.object({command:d.string(),args:d.array(d.string()).optional(),env:d.record(d.string(),d.string()).optional(),disabled:d.boolean().optional(),instruction:d.string().optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),config:T}),Ne=d.object({url:d.string().url(),headers:d.record(d.string(),d.string()).optional(),type:d.enum([`http`,`sse`]).optional(),disabled:d.boolean().optional(),instruction:d.string().optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),config:T}),Pe=d.union([Me,Ne]),Fe=d.object({url:d.string().optional(),headers:d.record(d.string(),d.string()).optional()}).optional(),Ie=d.object({allowPrivateIPs:d.boolean().optional(),enforceHttps:d.boolean().optional()}).optional(),Le=d.object({url:d.string(),headers:d.record(d.string(),d.string()).optional(),validation:Fe,security:Ie,mergeStrategy:d.enum([`local-priority`,`remote-priority`,`merge-deep`]).optional()}),E=d.object({paths:d.array(d.string())}),D=d.object({type:d.enum([`stdio`,`http`,`sse`,`stdio-http`]).optional(),port:d.number().int().positive().optional(),host:d.string().optional(),keepAlive:d.boolean().optional()}).optional(),Re=d.object({id:d.string().optional(),proxy:D,mcpServers:d.record(d.string(),Pe),remoteConfigs:d.array(Le).optional(),skills:E.optional()}),ze=d.object({command:d.string(),args:d.array(d.string()).optional(),env:d.record(d.string(),d.string()).optional()}),Be=d.object({url:d.string().url(),headers:d.record(d.string(),d.string()).optional()}),Ve=d.object({url:d.string().url(),headers:d.record(d.string(),d.string()).optional()}),He=d.object({name:d.string(),description:d.string(),folder:d.string().optional()}),O=d.object({skill:He.optional()}),Ue=d.discriminatedUnion(`transport`,[d.object({name:d.string(),instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),O).optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),transport:d.literal(`stdio`),config:ze}),d.object({name:d.string(),instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),O).optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),transport:d.literal(`http`),config:Be}),d.object({name:d.string(),instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),O).optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),transport:d.literal(`sse`),config:Ve})]),We=d.object({id:d.string().optional(),proxy:D,mcpServers:d.record(d.string(),Ue),skills:E.optional()});function Ge(e){let t={};for(let[n,r]of Object.entries(e.mcpServers))if(!(`disabled`in r&&r.disabled===!0)){if(`command`in r){let e=r,i=C(e.command),a=e.args?.map(e=>C(e)),o=e.env?w(e.env):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:`stdio`,config:{command:i,args:a,env:o}}}else if(`url`in r){let e=r,i=e.type===`sse`?`sse`:`http`,a=C(e.url),o=e.headers?w(e.headers):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:i,config:{url:a,headers:o}}}}return{id:e.id,proxy:e.proxy,mcpServers:t,skills:e.skills}}function k(e){let t=Ge(Re.parse(e));return We.parse(t)}var Ke=class{cacheDir;cacheTTL;readEnabled;writeEnabled;logger;constructor(e,t=console){this.cacheDir=y(g(),`mcp-proxy-cache`,`remote-configs`),this.cacheTTL=e?.ttl||3600*1e3,this.readEnabled=e?.readEnabled===void 0?!0:e.readEnabled,this.writeEnabled=e?.writeEnabled===void 0?!0:e.writeEnabled,this.logger=t}generateCacheKey(e){return f(`sha256`).update(e).digest(`hex`)}getCacheFilePath(e){return y(this.cacheDir,`${e}.json`)}async ensureCacheDir(){try{await n(this.cacheDir,{recursive:!0})}catch(e){if(e?.code!==`EEXIST`)throw e}}async get(t){if(!this.readEnabled)return null;try{await this.ensureCacheDir();let n=this.generateCacheKey(t),i=this.getCacheFilePath(n);if(!e(i))return null;let a=await r(i,`utf-8`),o=JSON.parse(a),c=Date.now();if(c>o.expiresAt)return await s(i).catch(()=>{}),null;let l=Math.round((o.expiresAt-c)/1e3);return this.logger.debug(`Remote config cache hit for ${t} (expires in ${l}s)`),o.data}catch(e){return this.logger.warn(`Failed to read remote config cache for ${t}`,e),null}}async set(e,t){if(this.writeEnabled)try{await this.ensureCacheDir();let n=this.generateCacheKey(e),r=this.getCacheFilePath(n),i=Date.now(),a={data:t,timestamp:i,expiresAt:i+this.cacheTTL,url:e};await l(r,JSON.stringify(a,null,2),`utf-8`),this.logger.debug(`Cached remote config for ${e} (TTL: ${Math.round(this.cacheTTL/1e3)}s)`)}catch(t){this.logger.warn(`Failed to write remote config cache for ${e}`,t)}}async clear(t){try{let n=this.generateCacheKey(t),r=this.getCacheFilePath(n);e(r)&&(await s(r),this.logger.info(`Cleared remote config cache for ${t}`))}catch(e){this.logger.warn(`Failed to clear remote config cache for ${t}`,e)}}async clearAll(){try{if(!e(this.cacheDir))return;let t=await i(this.cacheDir),n=t.filter(e=>e.endsWith(`.json`)).map(e=>s(y(this.cacheDir,e)).catch(t=>{this.logger.debug(`Failed to delete remote config cache file ${e}`,t)}));await Promise.all(n),this.logger.info(`Cleared all remote config cache entries (${t.length} files)`)}catch(e){this.logger.warn(`Failed to clear all remote config cache`,e)}}async cleanExpired(){try{if(!e(this.cacheDir))return;let t=Date.now(),n=(await i(this.cacheDir)).filter(e=>e.endsWith(`.json`)),a=(await Promise.all(n.map(async e=>{let n=y(this.cacheDir,e);try{let e=await r(n,`utf-8`);return t>JSON.parse(e).expiresAt?(await s(n),!0):!1}catch(e){return await s(n).catch(()=>{this.logger.debug(`Failed to delete corrupt cache file ${n}`,e)}),this.logger.warn(`Removed unreadable remote config cache file ${n}`,e),!0}}))).filter(Boolean).length;a>0&&this.logger.info(`Cleaned up ${a} expired remote config cache entries`)}catch(e){this.logger.warn(`Failed to clean expired remote config cache`,e)}}async getStats(){try{if(!e(this.cacheDir))return{totalEntries:0,totalSize:0};let t=(await i(this.cacheDir)).filter(e=>e.endsWith(`.json`)),n=(await Promise.all(t.map(async e=>{let t=y(this.cacheDir,e);try{let e=await r(t,`utf-8`);return Buffer.byteLength(e,`utf-8`)}catch{return 0}}))).reduce((e,t)=>e+t,0);return{totalEntries:t.length,totalSize:n}}catch(e){return this.logger.warn(`Failed to get remote config cache stats`,e),{totalEntries:0,totalSize:0}}}isReadEnabled(){return this.readEnabled}isWriteEnabled(){return this.writeEnabled}setReadEnabled(e){this.readEnabled=e}setWriteEnabled(e){this.writeEnabled=e}},qe=class{configFilePath;cacheTtlMs;cachedConfig=null;lastFetchTime=0;remoteConfigCache;logger;constructor(e,t=console){this.configFilePath=e.configFilePath,this.cacheTtlMs=e.cacheTtlMs||6e4,this.logger=t;let n=e.useCache===void 0?!0:e.useCache;if(this.remoteConfigCache=new Ke({ttl:e.remoteCacheTtlMs||3600*1e3,readEnabled:n,writeEnabled:!0},t),!this.configFilePath)throw Error(`configFilePath must be provided`)}async fetchConfiguration(e=!1){let t=Date.now();if(!e&&this.cachedConfig&&t-this.lastFetchTime<this.cacheTtlMs)return this.cachedConfig;let n=await this.loadRawConfigFromFile(),r=n.remoteConfigs||[],i=await this.parseConfig(n),a=r.map(async e=>{try{return ke(e),{config:await this.loadFromUrl(e),mergeStrategy:e.mergeStrategy||`local-priority`,url:e.url}}catch(t){return this.logger.warn(`Failed to fetch remote config from ${e.url}`,t),null}}),o=await Promise.all(a);for(let e of o)e!==null&&(i=this.mergeConfigurations(i,e.config,e.mergeStrategy));if(!i.mcpServers||typeof i.mcpServers!=`object`)throw Error(`Invalid MCP configuration: missing or invalid mcpServers`);return this.cachedConfig=i,this.lastFetchTime=t,i}async loadRawConfigFromFile(){if(!this.configFilePath)throw Error(`No config file path provided`);if(!e(this.configFilePath))throw Error(`Config file not found: ${this.configFilePath}`);try{let e=await r(this.configFilePath,`utf-8`),t;return t=this.configFilePath.endsWith(`.yaml`)||this.configFilePath.endsWith(`.yml`)?u.load(e):JSON.parse(e),t}catch(e){throw e instanceof Error?Error(`Failed to load config file: ${e.message}`):Error(`Failed to load config file: Unknown error`)}}async parseConfig(e){try{let{remoteConfigs:t,...n}=e;return k(n)}catch(e){throw e instanceof Error?Error(`Failed to parse config: ${e.message}`):Error(`Failed to parse config: Unknown error`)}}async loadFromUrl(e){try{let t=this.interpolateEnvVars(e.url),n=await this.remoteConfigCache.get(t);if(n)return n;let r=e.headers?Object.fromEntries(Object.entries(e.headers).map(([e,t])=>[e,this.interpolateEnvVars(t)])):{},i=await fetch(t,{headers:r,signal:AbortSignal.timeout(3e4)});if(!i.ok)throw Error(`Failed to fetch remote config: ${i.status} ${i.statusText}`);let a=k(await i.json());return await this.remoteConfigCache.set(t,a),a}catch(t){throw t instanceof Error?Error(`Failed to fetch remote config from ${e.url}: ${t.message}`,{cause:t}):Error(`Failed to fetch remote config from ${e.url}: Unknown error`)}}interpolateEnvVars(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(this.logger.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}mergeConfigurations(e,t,n){switch(n){case`local-priority`:return{id:e.id??t.id,mcpServers:{...t.mcpServers,...e.mcpServers},skills:e.skills??t.skills};case`remote-priority`:return{id:t.id??e.id,mcpServers:{...e.mcpServers,...t.mcpServers},skills:t.skills??e.skills};case`merge-deep`:{let n={...t.mcpServers};for(let[t,r]of Object.entries(e.mcpServers))if(n[t]){let e=n[t],i={...e.config,...r.config},a=`env`in e.config?e.config.env:void 0,o=`env`in r.config?r.config.env:void 0;(a||o)&&(i.env={...a||{},...o||{}});let s=`headers`in e.config?e.config.headers:void 0,c=`headers`in r.config?r.config.headers:void 0;(s||c)&&(i.headers={...s||{},...c||{}}),n[t]={...e,...r,config:i}}else n[t]=r;return{id:e.id??t.id,mcpServers:n,skills:e.skills??t.skills}}default:throw Error(`Unknown merge strategy: ${n}`)}}clearCache(){this.cachedConfig=null,this.lastFetchTime=0}isCacheValid(){let e=Date.now();return this.cachedConfig!==null&&e-this.lastFetchTime<this.cacheTtlMs}};const Je=`[skill-detection]`;function Ye(){let t=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],n=process.env.PROJECT_PATH;if(n)for(let r of t){let t=b(n,r);if(e(t))return t}let r=process.cwd();for(let n=0;n<=3;n++){for(let n of t){let t=y(r,n);if(e(t))return t}let n=_(r);if(n===r)break;r=n}return null}function Xe(e=6){let t=``,n=e;for(;n>0;){let e=p(n);for(let r=0;r<e.length&&n>0;r++){let i=e[r];i>247||(t+=`23456789abcdefghjkmnpqrstuvwxyz`[i%31],n--)}}return t}function Ze(e){let t=e.trimStart();if(!t.startsWith(`---`))return{frontMatter:null,content:e};let n=t.indexOf(`
|
|
1
|
+
import{existsSync as e}from"node:fs";import{access as t,mkdir as n,readFile as r,readdir as i,rm as a,stat as o,unlink as s,watch as c,writeFile as l}from"node:fs/promises";import u from"js-yaml";import{z as d}from"zod";import{createHash as f,randomBytes as p,randomUUID as m}from"node:crypto";import{homedir as h,tmpdir as g}from"node:os";import{dirname as _,isAbsolute as v,join as y,resolve as b}from"node:path";import{createNodeTelemetry as ee}from"@agimon-ai/log-sink-mcp";import{Client as x}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as te}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as ne}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as re}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{createProcessLease as ie}from"@agimon-ai/foundation-process-registry";import{spawn as ae}from"node:child_process";import{Liquid as oe}from"liquidjs";import{coerceArgs as se,formatZodError as ce,jsonSchemaToZod as le}from"@agimon-ai/foundation-validator";import{once as ue}from"node:events";import{createServer as de}from"node:http";import{promisify as fe}from"node:util";import{getRequestListener as pe}from"@hono/node-server";import{StreamableHTTPServerTransport as me}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as he,ElicitRequestSchema as ge,GetPromptRequestSchema as _e,ListPromptsRequestSchema as ve,ListResourcesRequestSchema as ye,ListToolsRequestSchema as be,ReadResourceRequestSchema as xe,isInitializeRequest as Se}from"@modelcontextprotocol/sdk/types.js";import{Hono as Ce}from"hono";import{SSEServerTransport as we}from"@modelcontextprotocol/sdk/server/sse.js";import{StdioServerTransport as Te}from"@modelcontextprotocol/sdk/server/stdio.js";import{Server as Ee}from"@modelcontextprotocol/sdk/server/index.js";var S=`0.10.8`;function C(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(console.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}function w(e){if(typeof e==`string`)return C(e);if(Array.isArray(e))return e.map(e=>w(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=w(r);return t}return e}const De=[/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\./,/^224\./,/^240\./,/^localhost$/i,/^.*\.localhost$/i,/^\[::\]/,/^\[::1\]/,/^\[0:0:0:0:0:0:0:1\]/,/^\[0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:1\]/i,/^\[fe80:/i,/^\[fc00:/i,/^\[fd00:/i,/^\[::ffff:127\./i,/^\[::ffff:7f[0-9a-f]{2}:/i,/^\[::ffff:10\./i,/^\[::ffff:a[0-9a-f]{2}:/i,/^\[::ffff:172\.(1[6-9]|2\d|3[01])\./i,/^\[::ffff:ac1[0-9a-f]:/i,/^\[::ffff:192\.168\./i,/^\[::ffff:c0a8:/i,/^\[::ffff:169\.254\./i,/^\[::ffff:a9fe:/i,/^\[::ffff:0\./i,/^\[::127\./i,/^\[::7f[0-9a-f]{2}:/i,/^\[::10\./i,/^\[::a[0-9a-f]{2}:/i,/^\[::192\.168\./i,/^\[::c0a8:/i];function Oe(e,t){let n=t?.allowPrivateIPs??!1,r=t?.enforceHttps??!0,i;try{i=new URL(e)}catch{throw Error(`Invalid URL format: ${e}`)}let a=i.protocol.replace(`:`,``);if(r&&a!==`https`)throw Error(`HTTPS is required for security. URL uses '${a}://'. Set security.enforceHttps: false to allow HTTP.`);if(a!==`http`&&a!==`https`)throw Error(`Invalid URL protocol '${a}://'. Only http:// and https:// are allowed.`);if(!n){let e=i.hostname.toLowerCase();if(De.some(t=>t.test(e)))throw Error(`Private IP addresses and localhost are blocked for security (${e}). Set security.allowPrivateIPs: true to allow internal networks.`)}}function ke(e){let t=C(e.url);if(Oe(t,e.security),e.validation){if(e.validation.url&&!new RegExp(e.validation.url).test(t))throw Error(`Remote config URL "${t}" does not match validation pattern: ${e.validation.url}`);if(e.validation.headers&&Object.keys(e.validation.headers).length>0){if(!e.headers){let t=Object.keys(e.validation.headers);throw Error(`Remote config is missing required headers: ${t.join(`, `)}`)}for(let[t,n]of Object.entries(e.validation.headers)){if(!(t in e.headers))throw Error(`Remote config is missing required header: ${t}`);let r=C(e.headers[t]);if(!new RegExp(n).test(r))throw Error(`Remote config header "${t}" value "${r}" does not match validation pattern: ${n}`)}}}}const Ae=d.object({name:d.string(),description:d.string(),folder:d.string().optional()}),je=d.object({skill:Ae.optional()}),T=d.object({instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),je).optional()}).optional(),Me=d.object({command:d.string(),args:d.array(d.string()).optional(),env:d.record(d.string(),d.string()).optional(),disabled:d.boolean().optional(),instruction:d.string().optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),config:T}),Ne=d.object({url:d.string().url(),headers:d.record(d.string(),d.string()).optional(),type:d.enum([`http`,`sse`]).optional(),disabled:d.boolean().optional(),instruction:d.string().optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),config:T}),Pe=d.union([Me,Ne]),Fe=d.object({url:d.string().optional(),headers:d.record(d.string(),d.string()).optional()}).optional(),Ie=d.object({allowPrivateIPs:d.boolean().optional(),enforceHttps:d.boolean().optional()}).optional(),Le=d.object({url:d.string(),headers:d.record(d.string(),d.string()).optional(),validation:Fe,security:Ie,mergeStrategy:d.enum([`local-priority`,`remote-priority`,`merge-deep`]).optional()}),E=d.object({paths:d.array(d.string())}),D=d.object({type:d.enum([`stdio`,`http`,`sse`,`stdio-http`]).optional(),port:d.number().int().positive().optional(),host:d.string().optional(),keepAlive:d.boolean().optional()}).optional(),Re=d.object({id:d.string().optional(),proxy:D,mcpServers:d.record(d.string(),Pe),remoteConfigs:d.array(Le).optional(),skills:E.optional()}),ze=d.object({command:d.string(),args:d.array(d.string()).optional(),env:d.record(d.string(),d.string()).optional()}),Be=d.object({url:d.string().url(),headers:d.record(d.string(),d.string()).optional()}),Ve=d.object({url:d.string().url(),headers:d.record(d.string(),d.string()).optional()}),He=d.object({name:d.string(),description:d.string(),folder:d.string().optional()}),O=d.object({skill:He.optional()}),Ue=d.discriminatedUnion(`transport`,[d.object({name:d.string(),instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),O).optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),transport:d.literal(`stdio`),config:ze}),d.object({name:d.string(),instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),O).optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),transport:d.literal(`http`),config:Be}),d.object({name:d.string(),instruction:d.string().optional(),toolBlacklist:d.array(d.string()).optional(),omitToolDescription:d.boolean().optional(),prompts:d.record(d.string(),O).optional(),timeout:d.number().positive().optional(),requestTimeout:d.number().positive().optional(),transport:d.literal(`sse`),config:Ve})]),We=d.object({id:d.string().optional(),proxy:D,mcpServers:d.record(d.string(),Ue),skills:E.optional()});function Ge(e){let t={};for(let[n,r]of Object.entries(e.mcpServers))if(!(`disabled`in r&&r.disabled===!0)){if(`command`in r){let e=r,i=C(e.command),a=e.args?.map(e=>C(e)),o=e.env?w(e.env):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:`stdio`,config:{command:i,args:a,env:o}}}else if(`url`in r){let e=r,i=e.type===`sse`?`sse`:`http`,a=C(e.url),o=e.headers?w(e.headers):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:i,config:{url:a,headers:o}}}}return{id:e.id,proxy:e.proxy,mcpServers:t,skills:e.skills}}function k(e){let t=Ge(Re.parse(e));return We.parse(t)}var Ke=class{cacheDir;cacheTTL;readEnabled;writeEnabled;logger;constructor(e,t=console){this.cacheDir=y(g(),`mcp-proxy-cache`,`remote-configs`),this.cacheTTL=e?.ttl||3600*1e3,this.readEnabled=e?.readEnabled===void 0?!0:e.readEnabled,this.writeEnabled=e?.writeEnabled===void 0?!0:e.writeEnabled,this.logger=t}generateCacheKey(e){return f(`sha256`).update(e).digest(`hex`)}getCacheFilePath(e){return y(this.cacheDir,`${e}.json`)}async ensureCacheDir(){try{await n(this.cacheDir,{recursive:!0})}catch(e){if(e?.code!==`EEXIST`)throw e}}async get(t){if(!this.readEnabled)return null;try{await this.ensureCacheDir();let n=this.generateCacheKey(t),i=this.getCacheFilePath(n);if(!e(i))return null;let a=await r(i,`utf-8`),o=JSON.parse(a),c=Date.now();if(c>o.expiresAt)return await s(i).catch(()=>{}),null;let l=Math.round((o.expiresAt-c)/1e3);return this.logger.debug(`Remote config cache hit for ${t} (expires in ${l}s)`),o.data}catch(e){return this.logger.warn(`Failed to read remote config cache for ${t}`,e),null}}async set(e,t){if(this.writeEnabled)try{await this.ensureCacheDir();let n=this.generateCacheKey(e),r=this.getCacheFilePath(n),i=Date.now(),a={data:t,timestamp:i,expiresAt:i+this.cacheTTL,url:e};await l(r,JSON.stringify(a,null,2),`utf-8`),this.logger.debug(`Cached remote config for ${e} (TTL: ${Math.round(this.cacheTTL/1e3)}s)`)}catch(t){this.logger.warn(`Failed to write remote config cache for ${e}`,t)}}async clear(t){try{let n=this.generateCacheKey(t),r=this.getCacheFilePath(n);e(r)&&(await s(r),this.logger.info(`Cleared remote config cache for ${t}`))}catch(e){this.logger.warn(`Failed to clear remote config cache for ${t}`,e)}}async clearAll(){try{if(!e(this.cacheDir))return;let t=await i(this.cacheDir),n=t.filter(e=>e.endsWith(`.json`)).map(e=>s(y(this.cacheDir,e)).catch(t=>{this.logger.debug(`Failed to delete remote config cache file ${e}`,t)}));await Promise.all(n),this.logger.info(`Cleared all remote config cache entries (${t.length} files)`)}catch(e){this.logger.warn(`Failed to clear all remote config cache`,e)}}async cleanExpired(){try{if(!e(this.cacheDir))return;let t=Date.now(),n=(await i(this.cacheDir)).filter(e=>e.endsWith(`.json`)),a=(await Promise.all(n.map(async e=>{let n=y(this.cacheDir,e);try{let e=await r(n,`utf-8`);return t>JSON.parse(e).expiresAt?(await s(n),!0):!1}catch(e){return await s(n).catch(()=>{this.logger.debug(`Failed to delete corrupt cache file ${n}`,e)}),this.logger.warn(`Removed unreadable remote config cache file ${n}`,e),!0}}))).filter(Boolean).length;a>0&&this.logger.info(`Cleaned up ${a} expired remote config cache entries`)}catch(e){this.logger.warn(`Failed to clean expired remote config cache`,e)}}async getStats(){try{if(!e(this.cacheDir))return{totalEntries:0,totalSize:0};let t=(await i(this.cacheDir)).filter(e=>e.endsWith(`.json`)),n=(await Promise.all(t.map(async e=>{let t=y(this.cacheDir,e);try{let e=await r(t,`utf-8`);return Buffer.byteLength(e,`utf-8`)}catch{return 0}}))).reduce((e,t)=>e+t,0);return{totalEntries:t.length,totalSize:n}}catch(e){return this.logger.warn(`Failed to get remote config cache stats`,e),{totalEntries:0,totalSize:0}}}isReadEnabled(){return this.readEnabled}isWriteEnabled(){return this.writeEnabled}setReadEnabled(e){this.readEnabled=e}setWriteEnabled(e){this.writeEnabled=e}},qe=class{configFilePath;cacheTtlMs;cachedConfig=null;lastFetchTime=0;remoteConfigCache;logger;constructor(e,t=console){this.configFilePath=e.configFilePath,this.cacheTtlMs=e.cacheTtlMs||6e4,this.logger=t;let n=e.useCache===void 0?!0:e.useCache;if(this.remoteConfigCache=new Ke({ttl:e.remoteCacheTtlMs||3600*1e3,readEnabled:n,writeEnabled:!0},t),!this.configFilePath)throw Error(`configFilePath must be provided`)}async fetchConfiguration(e=!1){let t=Date.now();if(!e&&this.cachedConfig&&t-this.lastFetchTime<this.cacheTtlMs)return this.cachedConfig;let n=await this.loadRawConfigFromFile(),r=n.remoteConfigs||[],i=await this.parseConfig(n),a=r.map(async e=>{try{return ke(e),{config:await this.loadFromUrl(e),mergeStrategy:e.mergeStrategy||`local-priority`,url:e.url}}catch(t){return this.logger.warn(`Failed to fetch remote config from ${e.url}`,t),null}}),o=await Promise.all(a);for(let e of o)e!==null&&(i=this.mergeConfigurations(i,e.config,e.mergeStrategy));if(!i.mcpServers||typeof i.mcpServers!=`object`)throw Error(`Invalid MCP configuration: missing or invalid mcpServers`);return this.cachedConfig=i,this.lastFetchTime=t,i}async loadRawConfigFromFile(){if(!this.configFilePath)throw Error(`No config file path provided`);if(!e(this.configFilePath))throw Error(`Config file not found: ${this.configFilePath}`);try{let e=await r(this.configFilePath,`utf-8`),t;return t=this.configFilePath.endsWith(`.yaml`)||this.configFilePath.endsWith(`.yml`)?u.load(e):JSON.parse(e),t}catch(e){throw e instanceof Error?Error(`Failed to load config file: ${e.message}`):Error(`Failed to load config file: Unknown error`)}}async parseConfig(e){try{let{remoteConfigs:t,...n}=e;return k(n)}catch(e){throw e instanceof Error?Error(`Failed to parse config: ${e.message}`):Error(`Failed to parse config: Unknown error`)}}async loadFromUrl(e){try{let t=this.interpolateEnvVars(e.url),n=await this.remoteConfigCache.get(t);if(n)return n;let r=e.headers?Object.fromEntries(Object.entries(e.headers).map(([e,t])=>[e,this.interpolateEnvVars(t)])):{},i=await fetch(t,{headers:r,signal:AbortSignal.timeout(3e4)});if(!i.ok)throw Error(`Failed to fetch remote config: ${i.status} ${i.statusText}`);let a=k(await i.json());return await this.remoteConfigCache.set(t,a),a}catch(t){throw t instanceof Error?Error(`Failed to fetch remote config from ${e.url}: ${t.message}`,{cause:t}):Error(`Failed to fetch remote config from ${e.url}: Unknown error`)}}interpolateEnvVars(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(this.logger.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}mergeConfigurations(e,t,n){switch(n){case`local-priority`:return{id:e.id??t.id,mcpServers:{...t.mcpServers,...e.mcpServers},skills:e.skills??t.skills};case`remote-priority`:return{id:t.id??e.id,mcpServers:{...e.mcpServers,...t.mcpServers},skills:t.skills??e.skills};case`merge-deep`:{let n={...t.mcpServers};for(let[t,r]of Object.entries(e.mcpServers))if(n[t]){let e=n[t],i={...e.config,...r.config},a=`env`in e.config?e.config.env:void 0,o=`env`in r.config?r.config.env:void 0;(a||o)&&(i.env={...a||{},...o||{}});let s=`headers`in e.config?e.config.headers:void 0,c=`headers`in r.config?r.config.headers:void 0;(s||c)&&(i.headers={...s||{},...c||{}}),n[t]={...e,...r,config:i}}else n[t]=r;return{id:e.id??t.id,mcpServers:n,skills:e.skills??t.skills}}default:throw Error(`Unknown merge strategy: ${n}`)}}clearCache(){this.cachedConfig=null,this.lastFetchTime=0}isCacheValid(){let e=Date.now();return this.cachedConfig!==null&&e-this.lastFetchTime<this.cacheTtlMs}};const Je=`[skill-detection]`;function Ye(){let t=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],n=process.env.PROJECT_PATH;if(n)for(let r of t){let t=b(n,r);if(e(t))return t}let r=process.cwd();for(let n=0;n<=3;n++){for(let n of t){let t=y(r,n);if(e(t))return t}let n=_(r);if(n===r)break;r=n}return null}function Xe(e=6){let t=``,n=e;for(;n>0;){let e=p(n);for(let r=0;r<e.length&&n>0;r++){let i=e[r];i>247||(t+=`23456789abcdefghjkmnpqrstuvwxyz`[i%31],n--)}}return t}function Ze(e){let t=e.trimStart();if(!t.startsWith(`---`))return{frontMatter:null,content:e};let n=t.indexOf(`
|
|
2
2
|
---`,3);if(n===-1)return{frontMatter:null,content:e};let r=t.slice(4,n).trim();if(!r)return{frontMatter:null,content:e};let i={},a=r.split(`
|
|
3
3
|
`),o=null,s=[],c=null,l=0,u=()=>{o&&s.length>0&&(c===`literal`?i[o]=s.join(`
|
|
4
4
|
`).trimEnd():c===`folded`?i[o]=s.join(` `).trim():i[o]=s.join(``).trim()),o=null,s=[],c=null,l=0};for(let e=0;e<a.length;e++){let t=a[e],n=t.trim(),r=t.indexOf(`:`);if(r!==-1&&!t.startsWith(` `)&&!t.startsWith(` `)){u();let n=t.slice(0,r).trim(),s=t.slice(r+1).trim();if(s===`|`||s===`|-`){if(o=n,c=`literal`,e+1<a.length){let t=a[e+1].match(/^(\s+)/);l=t?t[1].length:2}}else if(s===`>`||s===`>-`){if(o=n,c=`folded`,e+1<a.length){let t=a[e+1].match(/^(\s+)/);l=t?t[1].length:2}}else (s.startsWith(`"`)&&s.endsWith(`"`)||s.startsWith(`'`)&&s.endsWith(`'`))&&(s=s.slice(1,-1)),n&&s&&(i[n]=s)}else if(c&&o){let e=t.match(/^(\s*)/)?.[1].length||0;if(n===``)s.push(``);else if(e>=l){let e=t.slice(l);s.push(e)}else u()}}return u(),{frontMatter:i,content:t.slice(n+4).trimStart()}}function Qe(e){return e!==null&&typeof e.name==`string`&&e.name.length>0&&typeof e.description==`string`&&e.description.length>0}function $e(e){let{frontMatter:t,content:n}=Ze(e);return t&&Qe(t)?{skill:{name:t.name,description:t.description},content:n}:null}function A(e){let t=e.indexOf(`__`);return t>0?{serverName:e.substring(0,t),actualToolName:e.substring(t+2)}:{actualToolName:e}}function et(e){return e.endsWith(`.yaml`)||e.endsWith(`.yml`)}function j(e){return e instanceof Error?e.message:String(e)}function tt(e){let t=b(e),n=t.length>=2&&t[1]===`:`&&(t[0]>=`A`&&t[0]<=`Z`||t[0]>=`a`&&t[0]<=`z`)?`${t[0].toLowerCase()}${t.slice(1)}`:t,r=``,i=!1;for(let e of n){if(e>=`a`&&e<=`z`||e>=`A`&&e<=`Z`||e>=`0`&&e<=`9`||e===`.`||e===`_`||e===`-`){r+=e,i=!1;continue}i||=(r+=`_`,!0)}let a=0,o=r.length;for(;a<o&&r[a]===`_`;)a+=1;for(;o>a&&r[o-1]===`_`;)--o;return r.slice(a,o)}function M(e){return{...e,failures:[...e.failures??[]],skills:(e.skills??[]).map(e=>({...e})),servers:Object.fromEntries(Object.entries(e.servers).map(([e,t])=>[e,{...t,tools:(t.tools??[]).map(e=>({...e})),resources:(t.resources??[]).map(e=>({...e})),prompts:(t.prompts??[]).map(e=>({...e,arguments:e.arguments?.map(e=>({...e}))})),promptSkills:(t.promptSkills??[]).map(e=>({...e,skill:{...e.skill}}))}]))}}var N=class{clientManager;skillService;cacheData;liveDefinitionsPromise=null;mergedDefinitionsPromise=null;logger;constructor(e,t,n,r=console){this.clientManager=e,this.skillService=t,this.cacheData=n?.cacheData,this.logger=r}static async readFromFile(e){let t=await r(e,`utf-8`),n=et(e)?u.load(t):JSON.parse(t);if(!n||typeof n!=`object`)throw Error(`Definitions cache must be an object`);let i=n;if(i.version!==1||!i.servers)throw Error(`Definitions cache is missing required fields`);return{...i,failures:Array.isArray(i.failures)?i.failures:[],skills:Array.isArray(i.skills)?i.skills:[],servers:Object.fromEntries(Object.entries(i.servers).map(([e,t])=>[e,{...t,tools:Array.isArray(t.tools)?t.tools:[],resources:Array.isArray(t.resources)?t.resources:[],prompts:Array.isArray(t.prompts)?t.prompts:[],promptSkills:Array.isArray(t.promptSkills)?t.promptSkills:[]}]))}}static async writeToFile(e,t){let r=et(e)?u.dump(t,{noRefs:!0}):JSON.stringify(t,null,2);await n(_(e),{recursive:!0}),await l(e,r,`utf-8`)}static getDefaultCachePath(e){let t=tt(e);return y(h(),`.aicode-toolkit`,`${t}.definitions-cache.json`)}static generateConfigHash(e){return f(`sha256`).update(JSON.stringify(e)).digest(`hex`)}static isCacheValid(e,t){return!(t.configHash&&e.configHash&&e.configHash!==t.configHash||t.oneMcpVersion&&e.oneMcpVersion&&e.oneMcpVersion!==t.oneMcpVersion)}static async clearFile(e){await a(e,{force:!0})}clearLiveCache(){this.liveDefinitionsPromise=null,this.mergedDefinitionsPromise=null}setCacheData(e){this.cacheData=e,this.mergedDefinitionsPromise=null}async collectForCache(e){let t=await this.collectLiveDefinitions(e);return this.setCacheData(t),this.liveDefinitionsPromise=Promise.resolve(M(t)),M(t)}async getDefinitions(){return this.mergedDefinitionsPromise||=(async()=>{let e=this.clientManager.getAllClients();if(!this.cacheData)return this.getLiveDefinitions();let t=e.map(e=>e.serverName).filter(e=>!this.cacheData?.servers[e]);if(t.length===0)return M(this.cacheData);let n=await this.getLiveDefinitions(),r=M(this.cacheData);for(let e of t){let t=n.servers[e];t&&(r.servers[e]=t)}let i=new Map;for(let e of[...r.failures,...n.failures])i.set(e.serverName,e.error);return r.failures=Array.from(i.entries()).map(([e,t])=>({serverName:e,error:t})),r.skills.length===0&&n.skills.length>0&&(r.skills=n.skills.map(e=>({...e}))),r})(),this.mergedDefinitionsPromise}async getServerDefinitions(){let e=await this.getDefinitions(),t=this.clientManager.getKnownServerNames();return t.length===0?Object.values(e.servers):t.map(t=>e.servers[t]).filter(e=>e!==void 0)}async getServersForTool(e){return(await this.getServerDefinitions()).filter(t=>t.tools.some(t=>t.name===e)).map(e=>e.serverName)}async getToolSchema(e,t){return(await this.getDefinitions()).servers[e]?.tools.find(e=>e.name===t)?.inputSchema}async getServersForResource(e){return(await this.getServerDefinitions()).filter(t=>t.resources.some(t=>t.uri===e)).map(e=>e.serverName)}async getPromptSkillByName(e){let t=await this.getDefinitions();for(let[n,r]of Object.entries(t.servers))for(let t of r.promptSkills)if(t.skill.name===e)return{serverName:n,promptName:t.promptName,skill:t.skill,autoDetected:t.autoDetected}}async getCachedFileSkills(){return(await this.getDefinitions()).skills.map(e=>({...e}))}async getLiveDefinitions(){return this.liveDefinitionsPromise||=this.collectLiveDefinitions(),this.liveDefinitionsPromise}async collectLiveDefinitions(e){let t=this.clientManager.getAllClients(),n=[],r={},i=await Promise.all(t.map(async e=>{try{let t=await e.listTools(),n=await this.listResourcesSafe(e),r=await this.listPromptsSafe(e),i=new Set(e.toolBlacklist||[]),a=t.filter(e=>!i.has(e.name)),o=await this.collectPromptSkillsForClient(e,r);return{serverName:e.serverName,serverInstruction:e.serverInstruction,omitToolDescription:e.omitToolDescription,toolBlacklist:e.toolBlacklist,tools:a.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,_meta:e._meta})),resources:n,prompts:r,promptSkills:o}}catch(t){return n.push({serverName:e.serverName,error:j(t)}),null}}));for(let e of i)e&&(r[e.serverName]=e);return{version:1,oneMcpVersion:e?.oneMcpVersion,generatedAt:new Date().toISOString(),configPath:e?.configPath,configHash:e?.configHash,serverId:e?.serverId,servers:r,skills:await this.collectFileSkills(),failures:n}}async collectFileSkills(){return this.skillService?(await this.skillService.getSkills()).map(e=>this.toCachedFileSkill(e)):[]}toCachedFileSkill(e){return{name:e.name,description:e.description,location:e.location,basePath:e.basePath}}async listPromptsSafe(e){try{return(await e.listPrompts()).map(e=>({name:e.name,description:e.description,arguments:e.arguments?.map(e=>({...e}))}))}catch(t){return this.logger.warn(`${Je} Failed to list prompts from ${e.serverName}: ${j(t)}`),[]}}async listResourcesSafe(e){try{return(await e.listResources()).map(e=>({uri:e.uri,name:e.name,description:e.description,mimeType:e.mimeType}))}catch(t){return this.logger.warn(`[capability-discovery] Failed to list resources from ${e.serverName}: ${j(t)}`),[]}}async collectPromptSkillsForClient(e,t){let n=new Set(e.prompts?Object.keys(e.prompts):[]),r=[];if(e.prompts)for(let[t,n]of Object.entries(e.prompts))n.skill&&r.push({promptName:t,skill:{...n.skill}});let i=t.filter(e=>!n.has(e.name)).slice(0,50),a=await Promise.all(i.map(async t=>{try{let n=$e((await e.getPrompt(t.name)).messages?.map(e=>{let t=e.content;return typeof t==`string`?t:t&&typeof t==`object`&&`text`in t?String(t.text):``}).join(`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`),l=require(`node:fs/promises`),u=require(`js-yaml`);u=s(u);let d=require(`zod`),f=require(`node:crypto`),p=require(`node:os`),m=require(`node:path`),ee=require(`@agimon-ai/log-sink-mcp`),h=require(`@modelcontextprotocol/sdk/client/index.js`),te=require(`@modelcontextprotocol/sdk/client/sse.js`),ne=require(`@modelcontextprotocol/sdk/client/stdio.js`),re=require(`@modelcontextprotocol/sdk/client/streamableHttp.js`),ie=require(`@agimon-ai/foundation-process-registry`),ae=require(`node:child_process`),oe=require(`liquidjs`),g=require(`@agimon-ai/foundation-validator`),se=require(`node:events`),ce=require(`node:http`),le=require(`node:util`),ue=require(`@hono/node-server`),de=require(`@modelcontextprotocol/sdk/server/streamableHttp.js`),_=require(`@modelcontextprotocol/sdk/types.js`),fe=require(`hono`),pe=require(`@modelcontextprotocol/sdk/server/sse.js`),me=require(`@modelcontextprotocol/sdk/server/stdio.js`),v=require(`@modelcontextprotocol/sdk/server/index.js`);var y=`0.10.7`;function b(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(console.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}function x(e){if(typeof e==`string`)return b(e);if(Array.isArray(e))return e.map(e=>x(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=x(r);return t}return e}const he=[/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\./,/^224\./,/^240\./,/^localhost$/i,/^.*\.localhost$/i,/^\[::\]/,/^\[::1\]/,/^\[0:0:0:0:0:0:0:1\]/,/^\[0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:1\]/i,/^\[fe80:/i,/^\[fc00:/i,/^\[fd00:/i,/^\[::ffff:127\./i,/^\[::ffff:7f[0-9a-f]{2}:/i,/^\[::ffff:10\./i,/^\[::ffff:a[0-9a-f]{2}:/i,/^\[::ffff:172\.(1[6-9]|2\d|3[01])\./i,/^\[::ffff:ac1[0-9a-f]:/i,/^\[::ffff:192\.168\./i,/^\[::ffff:c0a8:/i,/^\[::ffff:169\.254\./i,/^\[::ffff:a9fe:/i,/^\[::ffff:0\./i,/^\[::127\./i,/^\[::7f[0-9a-f]{2}:/i,/^\[::10\./i,/^\[::a[0-9a-f]{2}:/i,/^\[::192\.168\./i,/^\[::c0a8:/i];function ge(e,t){let n=t?.allowPrivateIPs??!1,r=t?.enforceHttps??!0,i;try{i=new URL(e)}catch{throw Error(`Invalid URL format: ${e}`)}let a=i.protocol.replace(`:`,``);if(r&&a!==`https`)throw Error(`HTTPS is required for security. URL uses '${a}://'. Set security.enforceHttps: false to allow HTTP.`);if(a!==`http`&&a!==`https`)throw Error(`Invalid URL protocol '${a}://'. Only http:// and https:// are allowed.`);if(!n){let e=i.hostname.toLowerCase();if(he.some(t=>t.test(e)))throw Error(`Private IP addresses and localhost are blocked for security (${e}). Set security.allowPrivateIPs: true to allow internal networks.`)}}function _e(e){let t=b(e.url);if(ge(t,e.security),e.validation){if(e.validation.url&&!new RegExp(e.validation.url).test(t))throw Error(`Remote config URL "${t}" does not match validation pattern: ${e.validation.url}`);if(e.validation.headers&&Object.keys(e.validation.headers).length>0){if(!e.headers){let t=Object.keys(e.validation.headers);throw Error(`Remote config is missing required headers: ${t.join(`, `)}`)}for(let[t,n]of Object.entries(e.validation.headers)){if(!(t in e.headers))throw Error(`Remote config is missing required header: ${t}`);let r=b(e.headers[t]);if(!new RegExp(n).test(r))throw Error(`Remote config header "${t}" value "${r}" does not match validation pattern: ${n}`)}}}}const ve=d.z.object({name:d.z.string(),description:d.z.string(),folder:d.z.string().optional()}),ye=d.z.object({skill:ve.optional()}),be=d.z.object({instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),ye).optional()}).optional(),xe=d.z.object({command:d.z.string(),args:d.z.array(d.z.string()).optional(),env:d.z.record(d.z.string(),d.z.string()).optional(),disabled:d.z.boolean().optional(),instruction:d.z.string().optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),config:be}),Se=d.z.object({url:d.z.string().url(),headers:d.z.record(d.z.string(),d.z.string()).optional(),type:d.z.enum([`http`,`sse`]).optional(),disabled:d.z.boolean().optional(),instruction:d.z.string().optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),config:be}),Ce=d.z.union([xe,Se]),we=d.z.object({url:d.z.string().optional(),headers:d.z.record(d.z.string(),d.z.string()).optional()}).optional(),Te=d.z.object({allowPrivateIPs:d.z.boolean().optional(),enforceHttps:d.z.boolean().optional()}).optional(),Ee=d.z.object({url:d.z.string(),headers:d.z.record(d.z.string(),d.z.string()).optional(),validation:we,security:Te,mergeStrategy:d.z.enum([`local-priority`,`remote-priority`,`merge-deep`]).optional()}),De=d.z.object({paths:d.z.array(d.z.string())}),Oe=d.z.object({type:d.z.enum([`stdio`,`http`,`sse`,`stdio-http`]).optional(),port:d.z.number().int().positive().optional(),host:d.z.string().optional(),keepAlive:d.z.boolean().optional()}).optional(),ke=d.z.object({id:d.z.string().optional(),proxy:Oe,mcpServers:d.z.record(d.z.string(),Ce),remoteConfigs:d.z.array(Ee).optional(),skills:De.optional()}),Ae=d.z.object({command:d.z.string(),args:d.z.array(d.z.string()).optional(),env:d.z.record(d.z.string(),d.z.string()).optional()}),je=d.z.object({url:d.z.string().url(),headers:d.z.record(d.z.string(),d.z.string()).optional()}),Me=d.z.object({url:d.z.string().url(),headers:d.z.record(d.z.string(),d.z.string()).optional()}),Ne=d.z.object({name:d.z.string(),description:d.z.string(),folder:d.z.string().optional()}),S=d.z.object({skill:Ne.optional()}),Pe=d.z.discriminatedUnion(`transport`,[d.z.object({name:d.z.string(),instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),S).optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),transport:d.z.literal(`stdio`),config:Ae}),d.z.object({name:d.z.string(),instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),S).optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),transport:d.z.literal(`http`),config:je}),d.z.object({name:d.z.string(),instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),S).optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),transport:d.z.literal(`sse`),config:Me})]),Fe=d.z.object({id:d.z.string().optional(),proxy:Oe,mcpServers:d.z.record(d.z.string(),Pe),skills:De.optional()});function Ie(e){let t={};for(let[n,r]of Object.entries(e.mcpServers))if(!(`disabled`in r&&r.disabled===!0)){if(`command`in r){let e=r,i=b(e.command),a=e.args?.map(e=>b(e)),o=e.env?x(e.env):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:`stdio`,config:{command:i,args:a,env:o}}}else if(`url`in r){let e=r,i=e.type===`sse`?`sse`:`http`,a=b(e.url),o=e.headers?x(e.headers):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:i,config:{url:a,headers:o}}}}return{id:e.id,proxy:e.proxy,mcpServers:t,skills:e.skills}}function Le(e){let t=Ie(ke.parse(e));return Fe.parse(t)}var Re=class{cacheDir;cacheTTL;readEnabled;writeEnabled;logger;constructor(e,t=console){this.cacheDir=(0,m.join)((0,p.tmpdir)(),`mcp-proxy-cache`,`remote-configs`),this.cacheTTL=e?.ttl||3600*1e3,this.readEnabled=e?.readEnabled===void 0?!0:e.readEnabled,this.writeEnabled=e?.writeEnabled===void 0?!0:e.writeEnabled,this.logger=t}generateCacheKey(e){return(0,f.createHash)(`sha256`).update(e).digest(`hex`)}getCacheFilePath(e){return(0,m.join)(this.cacheDir,`${e}.json`)}async ensureCacheDir(){try{await(0,l.mkdir)(this.cacheDir,{recursive:!0})}catch(e){if(e?.code!==`EEXIST`)throw e}}async get(e){if(!this.readEnabled)return null;try{await this.ensureCacheDir();let t=this.generateCacheKey(e),n=this.getCacheFilePath(t);if(!(0,c.existsSync)(n))return null;let r=await(0,l.readFile)(n,`utf-8`),i=JSON.parse(r),a=Date.now();if(a>i.expiresAt)return await(0,l.unlink)(n).catch(()=>{}),null;let o=Math.round((i.expiresAt-a)/1e3);return this.logger.debug(`Remote config cache hit for ${e} (expires in ${o}s)`),i.data}catch(t){return this.logger.warn(`Failed to read remote config cache for ${e}`,t),null}}async set(e,t){if(this.writeEnabled)try{await this.ensureCacheDir();let n=this.generateCacheKey(e),r=this.getCacheFilePath(n),i=Date.now(),a={data:t,timestamp:i,expiresAt:i+this.cacheTTL,url:e};await(0,l.writeFile)(r,JSON.stringify(a,null,2),`utf-8`),this.logger.debug(`Cached remote config for ${e} (TTL: ${Math.round(this.cacheTTL/1e3)}s)`)}catch(t){this.logger.warn(`Failed to write remote config cache for ${e}`,t)}}async clear(e){try{let t=this.generateCacheKey(e),n=this.getCacheFilePath(t);(0,c.existsSync)(n)&&(await(0,l.unlink)(n),this.logger.info(`Cleared remote config cache for ${e}`))}catch(t){this.logger.warn(`Failed to clear remote config cache for ${e}`,t)}}async clearAll(){try{if(!(0,c.existsSync)(this.cacheDir))return;let e=await(0,l.readdir)(this.cacheDir),t=e.filter(e=>e.endsWith(`.json`)).map(e=>(0,l.unlink)((0,m.join)(this.cacheDir,e)).catch(t=>{this.logger.debug(`Failed to delete remote config cache file ${e}`,t)}));await Promise.all(t),this.logger.info(`Cleared all remote config cache entries (${e.length} files)`)}catch(e){this.logger.warn(`Failed to clear all remote config cache`,e)}}async cleanExpired(){try{if(!(0,c.existsSync)(this.cacheDir))return;let e=Date.now(),t=(await(0,l.readdir)(this.cacheDir)).filter(e=>e.endsWith(`.json`)),n=(await Promise.all(t.map(async t=>{let n=(0,m.join)(this.cacheDir,t);try{let t=await(0,l.readFile)(n,`utf-8`);return e>JSON.parse(t).expiresAt?(await(0,l.unlink)(n),!0):!1}catch(e){return await(0,l.unlink)(n).catch(()=>{this.logger.debug(`Failed to delete corrupt cache file ${n}`,e)}),this.logger.warn(`Removed unreadable remote config cache file ${n}`,e),!0}}))).filter(Boolean).length;n>0&&this.logger.info(`Cleaned up ${n} expired remote config cache entries`)}catch(e){this.logger.warn(`Failed to clean expired remote config cache`,e)}}async getStats(){try{if(!(0,c.existsSync)(this.cacheDir))return{totalEntries:0,totalSize:0};let e=(await(0,l.readdir)(this.cacheDir)).filter(e=>e.endsWith(`.json`)),t=(await Promise.all(e.map(async e=>{let t=(0,m.join)(this.cacheDir,e);try{let e=await(0,l.readFile)(t,`utf-8`);return Buffer.byteLength(e,`utf-8`)}catch{return 0}}))).reduce((e,t)=>e+t,0);return{totalEntries:e.length,totalSize:t}}catch(e){return this.logger.warn(`Failed to get remote config cache stats`,e),{totalEntries:0,totalSize:0}}}isReadEnabled(){return this.readEnabled}isWriteEnabled(){return this.writeEnabled}setReadEnabled(e){this.readEnabled=e}setWriteEnabled(e){this.writeEnabled=e}},ze=class{configFilePath;cacheTtlMs;cachedConfig=null;lastFetchTime=0;remoteConfigCache;logger;constructor(e,t=console){this.configFilePath=e.configFilePath,this.cacheTtlMs=e.cacheTtlMs||6e4,this.logger=t;let n=e.useCache===void 0?!0:e.useCache;if(this.remoteConfigCache=new Re({ttl:e.remoteCacheTtlMs||3600*1e3,readEnabled:n,writeEnabled:!0},t),!this.configFilePath)throw Error(`configFilePath must be provided`)}async fetchConfiguration(e=!1){let t=Date.now();if(!e&&this.cachedConfig&&t-this.lastFetchTime<this.cacheTtlMs)return this.cachedConfig;let n=await this.loadRawConfigFromFile(),r=n.remoteConfigs||[],i=await this.parseConfig(n),a=r.map(async e=>{try{return _e(e),{config:await this.loadFromUrl(e),mergeStrategy:e.mergeStrategy||`local-priority`,url:e.url}}catch(t){return this.logger.warn(`Failed to fetch remote config from ${e.url}`,t),null}}),o=await Promise.all(a);for(let e of o)e!==null&&(i=this.mergeConfigurations(i,e.config,e.mergeStrategy));if(!i.mcpServers||typeof i.mcpServers!=`object`)throw Error(`Invalid MCP configuration: missing or invalid mcpServers`);return this.cachedConfig=i,this.lastFetchTime=t,i}async loadRawConfigFromFile(){if(!this.configFilePath)throw Error(`No config file path provided`);if(!(0,c.existsSync)(this.configFilePath))throw Error(`Config file not found: ${this.configFilePath}`);try{let e=await(0,l.readFile)(this.configFilePath,`utf-8`),t;return t=this.configFilePath.endsWith(`.yaml`)||this.configFilePath.endsWith(`.yml`)?u.default.load(e):JSON.parse(e),t}catch(e){throw e instanceof Error?Error(`Failed to load config file: ${e.message}`):Error(`Failed to load config file: Unknown error`)}}async parseConfig(e){try{let{remoteConfigs:t,...n}=e;return Le(n)}catch(e){throw e instanceof Error?Error(`Failed to parse config: ${e.message}`):Error(`Failed to parse config: Unknown error`)}}async loadFromUrl(e){try{let t=this.interpolateEnvVars(e.url),n=await this.remoteConfigCache.get(t);if(n)return n;let r=e.headers?Object.fromEntries(Object.entries(e.headers).map(([e,t])=>[e,this.interpolateEnvVars(t)])):{},i=await fetch(t,{headers:r,signal:AbortSignal.timeout(3e4)});if(!i.ok)throw Error(`Failed to fetch remote config: ${i.status} ${i.statusText}`);let a=Le(await i.json());return await this.remoteConfigCache.set(t,a),a}catch(t){throw t instanceof Error?Error(`Failed to fetch remote config from ${e.url}: ${t.message}`,{cause:t}):Error(`Failed to fetch remote config from ${e.url}: Unknown error`)}}interpolateEnvVars(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(this.logger.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}mergeConfigurations(e,t,n){switch(n){case`local-priority`:return{id:e.id??t.id,mcpServers:{...t.mcpServers,...e.mcpServers},skills:e.skills??t.skills};case`remote-priority`:return{id:t.id??e.id,mcpServers:{...e.mcpServers,...t.mcpServers},skills:t.skills??e.skills};case`merge-deep`:{let n={...t.mcpServers};for(let[t,r]of Object.entries(e.mcpServers))if(n[t]){let e=n[t],i={...e.config,...r.config},a=`env`in e.config?e.config.env:void 0,o=`env`in r.config?r.config.env:void 0;(a||o)&&(i.env={...a||{},...o||{}});let s=`headers`in e.config?e.config.headers:void 0,c=`headers`in r.config?r.config.headers:void 0;(s||c)&&(i.headers={...s||{},...c||{}}),n[t]={...e,...r,config:i}}else n[t]=r;return{id:e.id??t.id,mcpServers:n,skills:e.skills??t.skills}}default:throw Error(`Unknown merge strategy: ${n}`)}}clearCache(){this.cachedConfig=null,this.lastFetchTime=0}isCacheValid(){let e=Date.now();return this.cachedConfig!==null&&e-this.lastFetchTime<this.cacheTtlMs}};const Be=`[skill-detection]`;function Ve(){let e=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],t=process.env.PROJECT_PATH;if(t)for(let n of e){let e=(0,m.resolve)(t,n);if((0,c.existsSync)(e))return e}let n=process.cwd();for(let t=0;t<=3;t++){for(let t of e){let e=(0,m.join)(n,t);if((0,c.existsSync)(e))return e}let t=(0,m.dirname)(n);if(t===n)break;n=t}return null}function He(e=6){let t=``,n=e;for(;n>0;){let e=(0,f.randomBytes)(n);for(let r=0;r<e.length&&n>0;r++){let i=e[r];i>247||(t+=`23456789abcdefghjkmnpqrstuvwxyz`[i%31],n--)}}return t}function Ue(e){let t=e.trimStart();if(!t.startsWith(`---`))return{frontMatter:null,content:e};let n=t.indexOf(`
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`),l=require(`node:fs/promises`),u=require(`js-yaml`);u=s(u,1);let d=require(`zod`),f=require(`node:crypto`),p=require(`node:os`),m=require(`node:path`),ee=require(`@agimon-ai/log-sink-mcp`),h=require(`@modelcontextprotocol/sdk/client/index.js`),te=require(`@modelcontextprotocol/sdk/client/sse.js`),ne=require(`@modelcontextprotocol/sdk/client/stdio.js`),re=require(`@modelcontextprotocol/sdk/client/streamableHttp.js`),ie=require(`@agimon-ai/foundation-process-registry`),ae=require(`node:child_process`),oe=require(`liquidjs`),g=require(`@agimon-ai/foundation-validator`),se=require(`node:events`),ce=require(`node:http`),le=require(`node:util`),ue=require(`@hono/node-server`),de=require(`@modelcontextprotocol/sdk/server/streamableHttp.js`),_=require(`@modelcontextprotocol/sdk/types.js`),fe=require(`hono`),pe=require(`@modelcontextprotocol/sdk/server/sse.js`),me=require(`@modelcontextprotocol/sdk/server/stdio.js`),v=require(`@modelcontextprotocol/sdk/server/index.js`);var y=`0.10.8`;function b(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(console.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}function x(e){if(typeof e==`string`)return b(e);if(Array.isArray(e))return e.map(e=>x(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=x(r);return t}return e}const he=[/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\./,/^224\./,/^240\./,/^localhost$/i,/^.*\.localhost$/i,/^\[::\]/,/^\[::1\]/,/^\[0:0:0:0:0:0:0:1\]/,/^\[0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:0{1,4}:1\]/i,/^\[fe80:/i,/^\[fc00:/i,/^\[fd00:/i,/^\[::ffff:127\./i,/^\[::ffff:7f[0-9a-f]{2}:/i,/^\[::ffff:10\./i,/^\[::ffff:a[0-9a-f]{2}:/i,/^\[::ffff:172\.(1[6-9]|2\d|3[01])\./i,/^\[::ffff:ac1[0-9a-f]:/i,/^\[::ffff:192\.168\./i,/^\[::ffff:c0a8:/i,/^\[::ffff:169\.254\./i,/^\[::ffff:a9fe:/i,/^\[::ffff:0\./i,/^\[::127\./i,/^\[::7f[0-9a-f]{2}:/i,/^\[::10\./i,/^\[::a[0-9a-f]{2}:/i,/^\[::192\.168\./i,/^\[::c0a8:/i];function ge(e,t){let n=t?.allowPrivateIPs??!1,r=t?.enforceHttps??!0,i;try{i=new URL(e)}catch{throw Error(`Invalid URL format: ${e}`)}let a=i.protocol.replace(`:`,``);if(r&&a!==`https`)throw Error(`HTTPS is required for security. URL uses '${a}://'. Set security.enforceHttps: false to allow HTTP.`);if(a!==`http`&&a!==`https`)throw Error(`Invalid URL protocol '${a}://'. Only http:// and https:// are allowed.`);if(!n){let e=i.hostname.toLowerCase();if(he.some(t=>t.test(e)))throw Error(`Private IP addresses and localhost are blocked for security (${e}). Set security.allowPrivateIPs: true to allow internal networks.`)}}function _e(e){let t=b(e.url);if(ge(t,e.security),e.validation){if(e.validation.url&&!new RegExp(e.validation.url).test(t))throw Error(`Remote config URL "${t}" does not match validation pattern: ${e.validation.url}`);if(e.validation.headers&&Object.keys(e.validation.headers).length>0){if(!e.headers){let t=Object.keys(e.validation.headers);throw Error(`Remote config is missing required headers: ${t.join(`, `)}`)}for(let[t,n]of Object.entries(e.validation.headers)){if(!(t in e.headers))throw Error(`Remote config is missing required header: ${t}`);let r=b(e.headers[t]);if(!new RegExp(n).test(r))throw Error(`Remote config header "${t}" value "${r}" does not match validation pattern: ${n}`)}}}}const ve=d.z.object({name:d.z.string(),description:d.z.string(),folder:d.z.string().optional()}),ye=d.z.object({skill:ve.optional()}),be=d.z.object({instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),ye).optional()}).optional(),xe=d.z.object({command:d.z.string(),args:d.z.array(d.z.string()).optional(),env:d.z.record(d.z.string(),d.z.string()).optional(),disabled:d.z.boolean().optional(),instruction:d.z.string().optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),config:be}),Se=d.z.object({url:d.z.string().url(),headers:d.z.record(d.z.string(),d.z.string()).optional(),type:d.z.enum([`http`,`sse`]).optional(),disabled:d.z.boolean().optional(),instruction:d.z.string().optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),config:be}),Ce=d.z.union([xe,Se]),we=d.z.object({url:d.z.string().optional(),headers:d.z.record(d.z.string(),d.z.string()).optional()}).optional(),Te=d.z.object({allowPrivateIPs:d.z.boolean().optional(),enforceHttps:d.z.boolean().optional()}).optional(),Ee=d.z.object({url:d.z.string(),headers:d.z.record(d.z.string(),d.z.string()).optional(),validation:we,security:Te,mergeStrategy:d.z.enum([`local-priority`,`remote-priority`,`merge-deep`]).optional()}),De=d.z.object({paths:d.z.array(d.z.string())}),Oe=d.z.object({type:d.z.enum([`stdio`,`http`,`sse`,`stdio-http`]).optional(),port:d.z.number().int().positive().optional(),host:d.z.string().optional(),keepAlive:d.z.boolean().optional()}).optional(),ke=d.z.object({id:d.z.string().optional(),proxy:Oe,mcpServers:d.z.record(d.z.string(),Ce),remoteConfigs:d.z.array(Ee).optional(),skills:De.optional()}),Ae=d.z.object({command:d.z.string(),args:d.z.array(d.z.string()).optional(),env:d.z.record(d.z.string(),d.z.string()).optional()}),je=d.z.object({url:d.z.string().url(),headers:d.z.record(d.z.string(),d.z.string()).optional()}),Me=d.z.object({url:d.z.string().url(),headers:d.z.record(d.z.string(),d.z.string()).optional()}),Ne=d.z.object({name:d.z.string(),description:d.z.string(),folder:d.z.string().optional()}),S=d.z.object({skill:Ne.optional()}),Pe=d.z.discriminatedUnion(`transport`,[d.z.object({name:d.z.string(),instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),S).optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),transport:d.z.literal(`stdio`),config:Ae}),d.z.object({name:d.z.string(),instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),S).optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),transport:d.z.literal(`http`),config:je}),d.z.object({name:d.z.string(),instruction:d.z.string().optional(),toolBlacklist:d.z.array(d.z.string()).optional(),omitToolDescription:d.z.boolean().optional(),prompts:d.z.record(d.z.string(),S).optional(),timeout:d.z.number().positive().optional(),requestTimeout:d.z.number().positive().optional(),transport:d.z.literal(`sse`),config:Me})]),Fe=d.z.object({id:d.z.string().optional(),proxy:Oe,mcpServers:d.z.record(d.z.string(),Pe),skills:De.optional()});function Ie(e){let t={};for(let[n,r]of Object.entries(e.mcpServers))if(!(`disabled`in r&&r.disabled===!0)){if(`command`in r){let e=r,i=b(e.command),a=e.args?.map(e=>b(e)),o=e.env?x(e.env):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:`stdio`,config:{command:i,args:a,env:o}}}else if(`url`in r){let e=r,i=e.type===`sse`?`sse`:`http`,a=b(e.url),o=e.headers?x(e.headers):void 0;t[n]={name:n,instruction:e.instruction||e.config?.instruction,toolBlacklist:e.config?.toolBlacklist,omitToolDescription:e.config?.omitToolDescription,prompts:e.config?.prompts,timeout:e.timeout,requestTimeout:e.requestTimeout,transport:i,config:{url:a,headers:o}}}}return{id:e.id,proxy:e.proxy,mcpServers:t,skills:e.skills}}function Le(e){let t=Ie(ke.parse(e));return Fe.parse(t)}var Re=class{cacheDir;cacheTTL;readEnabled;writeEnabled;logger;constructor(e,t=console){this.cacheDir=(0,m.join)((0,p.tmpdir)(),`mcp-proxy-cache`,`remote-configs`),this.cacheTTL=e?.ttl||3600*1e3,this.readEnabled=e?.readEnabled===void 0?!0:e.readEnabled,this.writeEnabled=e?.writeEnabled===void 0?!0:e.writeEnabled,this.logger=t}generateCacheKey(e){return(0,f.createHash)(`sha256`).update(e).digest(`hex`)}getCacheFilePath(e){return(0,m.join)(this.cacheDir,`${e}.json`)}async ensureCacheDir(){try{await(0,l.mkdir)(this.cacheDir,{recursive:!0})}catch(e){if(e?.code!==`EEXIST`)throw e}}async get(e){if(!this.readEnabled)return null;try{await this.ensureCacheDir();let t=this.generateCacheKey(e),n=this.getCacheFilePath(t);if(!(0,c.existsSync)(n))return null;let r=await(0,l.readFile)(n,`utf-8`),i=JSON.parse(r),a=Date.now();if(a>i.expiresAt)return await(0,l.unlink)(n).catch(()=>{}),null;let o=Math.round((i.expiresAt-a)/1e3);return this.logger.debug(`Remote config cache hit for ${e} (expires in ${o}s)`),i.data}catch(t){return this.logger.warn(`Failed to read remote config cache for ${e}`,t),null}}async set(e,t){if(this.writeEnabled)try{await this.ensureCacheDir();let n=this.generateCacheKey(e),r=this.getCacheFilePath(n),i=Date.now(),a={data:t,timestamp:i,expiresAt:i+this.cacheTTL,url:e};await(0,l.writeFile)(r,JSON.stringify(a,null,2),`utf-8`),this.logger.debug(`Cached remote config for ${e} (TTL: ${Math.round(this.cacheTTL/1e3)}s)`)}catch(t){this.logger.warn(`Failed to write remote config cache for ${e}`,t)}}async clear(e){try{let t=this.generateCacheKey(e),n=this.getCacheFilePath(t);(0,c.existsSync)(n)&&(await(0,l.unlink)(n),this.logger.info(`Cleared remote config cache for ${e}`))}catch(t){this.logger.warn(`Failed to clear remote config cache for ${e}`,t)}}async clearAll(){try{if(!(0,c.existsSync)(this.cacheDir))return;let e=await(0,l.readdir)(this.cacheDir),t=e.filter(e=>e.endsWith(`.json`)).map(e=>(0,l.unlink)((0,m.join)(this.cacheDir,e)).catch(t=>{this.logger.debug(`Failed to delete remote config cache file ${e}`,t)}));await Promise.all(t),this.logger.info(`Cleared all remote config cache entries (${e.length} files)`)}catch(e){this.logger.warn(`Failed to clear all remote config cache`,e)}}async cleanExpired(){try{if(!(0,c.existsSync)(this.cacheDir))return;let e=Date.now(),t=(await(0,l.readdir)(this.cacheDir)).filter(e=>e.endsWith(`.json`)),n=(await Promise.all(t.map(async t=>{let n=(0,m.join)(this.cacheDir,t);try{let t=await(0,l.readFile)(n,`utf-8`);return e>JSON.parse(t).expiresAt?(await(0,l.unlink)(n),!0):!1}catch(e){return await(0,l.unlink)(n).catch(()=>{this.logger.debug(`Failed to delete corrupt cache file ${n}`,e)}),this.logger.warn(`Removed unreadable remote config cache file ${n}`,e),!0}}))).filter(Boolean).length;n>0&&this.logger.info(`Cleaned up ${n} expired remote config cache entries`)}catch(e){this.logger.warn(`Failed to clean expired remote config cache`,e)}}async getStats(){try{if(!(0,c.existsSync)(this.cacheDir))return{totalEntries:0,totalSize:0};let e=(await(0,l.readdir)(this.cacheDir)).filter(e=>e.endsWith(`.json`)),t=(await Promise.all(e.map(async e=>{let t=(0,m.join)(this.cacheDir,e);try{let e=await(0,l.readFile)(t,`utf-8`);return Buffer.byteLength(e,`utf-8`)}catch{return 0}}))).reduce((e,t)=>e+t,0);return{totalEntries:e.length,totalSize:t}}catch(e){return this.logger.warn(`Failed to get remote config cache stats`,e),{totalEntries:0,totalSize:0}}}isReadEnabled(){return this.readEnabled}isWriteEnabled(){return this.writeEnabled}setReadEnabled(e){this.readEnabled=e}setWriteEnabled(e){this.writeEnabled=e}},ze=class{configFilePath;cacheTtlMs;cachedConfig=null;lastFetchTime=0;remoteConfigCache;logger;constructor(e,t=console){this.configFilePath=e.configFilePath,this.cacheTtlMs=e.cacheTtlMs||6e4,this.logger=t;let n=e.useCache===void 0?!0:e.useCache;if(this.remoteConfigCache=new Re({ttl:e.remoteCacheTtlMs||3600*1e3,readEnabled:n,writeEnabled:!0},t),!this.configFilePath)throw Error(`configFilePath must be provided`)}async fetchConfiguration(e=!1){let t=Date.now();if(!e&&this.cachedConfig&&t-this.lastFetchTime<this.cacheTtlMs)return this.cachedConfig;let n=await this.loadRawConfigFromFile(),r=n.remoteConfigs||[],i=await this.parseConfig(n),a=r.map(async e=>{try{return _e(e),{config:await this.loadFromUrl(e),mergeStrategy:e.mergeStrategy||`local-priority`,url:e.url}}catch(t){return this.logger.warn(`Failed to fetch remote config from ${e.url}`,t),null}}),o=await Promise.all(a);for(let e of o)e!==null&&(i=this.mergeConfigurations(i,e.config,e.mergeStrategy));if(!i.mcpServers||typeof i.mcpServers!=`object`)throw Error(`Invalid MCP configuration: missing or invalid mcpServers`);return this.cachedConfig=i,this.lastFetchTime=t,i}async loadRawConfigFromFile(){if(!this.configFilePath)throw Error(`No config file path provided`);if(!(0,c.existsSync)(this.configFilePath))throw Error(`Config file not found: ${this.configFilePath}`);try{let e=await(0,l.readFile)(this.configFilePath,`utf-8`),t;return t=this.configFilePath.endsWith(`.yaml`)||this.configFilePath.endsWith(`.yml`)?u.default.load(e):JSON.parse(e),t}catch(e){throw e instanceof Error?Error(`Failed to load config file: ${e.message}`):Error(`Failed to load config file: Unknown error`)}}async parseConfig(e){try{let{remoteConfigs:t,...n}=e;return Le(n)}catch(e){throw e instanceof Error?Error(`Failed to parse config: ${e.message}`):Error(`Failed to parse config: Unknown error`)}}async loadFromUrl(e){try{let t=this.interpolateEnvVars(e.url),n=await this.remoteConfigCache.get(t);if(n)return n;let r=e.headers?Object.fromEntries(Object.entries(e.headers).map(([e,t])=>[e,this.interpolateEnvVars(t)])):{},i=await fetch(t,{headers:r,signal:AbortSignal.timeout(3e4)});if(!i.ok)throw Error(`Failed to fetch remote config: ${i.status} ${i.statusText}`);let a=Le(await i.json());return await this.remoteConfigCache.set(t,a),a}catch(t){throw t instanceof Error?Error(`Failed to fetch remote config from ${e.url}: ${t.message}`,{cause:t}):Error(`Failed to fetch remote config from ${e.url}: Unknown error`)}}interpolateEnvVars(e){return e.replace(/\$\{([^}]+)\}/g,(e,t)=>{let n=process.env[t];return n===void 0?(this.logger.warn(`Environment variable ${t} is not defined, keeping placeholder`),`\${${t}}`):n})}mergeConfigurations(e,t,n){switch(n){case`local-priority`:return{id:e.id??t.id,mcpServers:{...t.mcpServers,...e.mcpServers},skills:e.skills??t.skills};case`remote-priority`:return{id:t.id??e.id,mcpServers:{...e.mcpServers,...t.mcpServers},skills:t.skills??e.skills};case`merge-deep`:{let n={...t.mcpServers};for(let[t,r]of Object.entries(e.mcpServers))if(n[t]){let e=n[t],i={...e.config,...r.config},a=`env`in e.config?e.config.env:void 0,o=`env`in r.config?r.config.env:void 0;(a||o)&&(i.env={...a||{},...o||{}});let s=`headers`in e.config?e.config.headers:void 0,c=`headers`in r.config?r.config.headers:void 0;(s||c)&&(i.headers={...s||{},...c||{}}),n[t]={...e,...r,config:i}}else n[t]=r;return{id:e.id??t.id,mcpServers:n,skills:e.skills??t.skills}}default:throw Error(`Unknown merge strategy: ${n}`)}}clearCache(){this.cachedConfig=null,this.lastFetchTime=0}isCacheValid(){let e=Date.now();return this.cachedConfig!==null&&e-this.lastFetchTime<this.cacheTtlMs}};const Be=`[skill-detection]`;function Ve(){let e=[`mcp-config.yaml`,`mcp-config.yml`,`mcp-config.json`],t=process.env.PROJECT_PATH;if(t)for(let n of e){let e=(0,m.resolve)(t,n);if((0,c.existsSync)(e))return e}let n=process.cwd();for(let t=0;t<=3;t++){for(let t of e){let e=(0,m.join)(n,t);if((0,c.existsSync)(e))return e}let t=(0,m.dirname)(n);if(t===n)break;n=t}return null}function He(e=6){let t=``,n=e;for(;n>0;){let e=(0,f.randomBytes)(n);for(let r=0;r<e.length&&n>0;r++){let i=e[r];i>247||(t+=`23456789abcdefghjkmnpqrstuvwxyz`[i%31],n--)}}return t}function Ue(e){let t=e.trimStart();if(!t.startsWith(`---`))return{frontMatter:null,content:e};let n=t.indexOf(`
|
|
2
2
|
---`,3);if(n===-1)return{frontMatter:null,content:e};let r=t.slice(4,n).trim();if(!r)return{frontMatter:null,content:e};let i={},a=r.split(`
|
|
3
3
|
`),o=null,s=[],c=null,l=0,u=()=>{o&&s.length>0&&(c===`literal`?i[o]=s.join(`
|
|
4
4
|
`).trimEnd():c===`folded`?i[o]=s.join(` `).trim():i[o]=s.join(``).trim()),o=null,s=[],c=null,l=0};for(let e=0;e<a.length;e++){let t=a[e],n=t.trim(),r=t.indexOf(`:`);if(r!==-1&&!t.startsWith(` `)&&!t.startsWith(` `)){u();let n=t.slice(0,r).trim(),s=t.slice(r+1).trim();if(s===`|`||s===`|-`){if(o=n,c=`literal`,e+1<a.length){let t=a[e+1].match(/^(\s+)/);l=t?t[1].length:2}}else if(s===`>`||s===`>-`){if(o=n,c=`folded`,e+1<a.length){let t=a[e+1].match(/^(\s+)/);l=t?t[1].length:2}}else (s.startsWith(`"`)&&s.endsWith(`"`)||s.startsWith(`'`)&&s.endsWith(`'`))&&(s=s.slice(1,-1)),n&&s&&(i[n]=s)}else if(c&&o){let e=t.match(/^(\s*)/)?.[1].length||0;if(n===``)s.push(``);else if(e>=l){let e=t.slice(l);s.push(e)}else u()}}return u(),{frontMatter:i,content:t.slice(n+4).trimStart()}}function We(e){return e!==null&&typeof e.name==`string`&&e.name.length>0&&typeof e.description==`string`&&e.description.length>0}function Ge(e){let{frontMatter:t,content:n}=Ue(e);return t&&We(t)?{skill:{name:t.name,description:t.description},content:n}:null}function C(e){let t=e.indexOf(`__`);return t>0?{serverName:e.substring(0,t),actualToolName:e.substring(t+2)}:{actualToolName:e}}function Ke(e){return e.endsWith(`.yaml`)||e.endsWith(`.yml`)}function w(e){return e instanceof Error?e.message:String(e)}function qe(e){let t=(0,m.resolve)(e),n=t.length>=2&&t[1]===`:`&&(t[0]>=`A`&&t[0]<=`Z`||t[0]>=`a`&&t[0]<=`z`)?`${t[0].toLowerCase()}${t.slice(1)}`:t,r=``,i=!1;for(let e of n){if(e>=`a`&&e<=`z`||e>=`A`&&e<=`Z`||e>=`0`&&e<=`9`||e===`.`||e===`_`||e===`-`){r+=e,i=!1;continue}i||=(r+=`_`,!0)}let a=0,o=r.length;for(;a<o&&r[a]===`_`;)a+=1;for(;o>a&&r[o-1]===`_`;)--o;return r.slice(a,o)}function T(e){return{...e,failures:[...e.failures??[]],skills:(e.skills??[]).map(e=>({...e})),servers:Object.fromEntries(Object.entries(e.servers).map(([e,t])=>[e,{...t,tools:(t.tools??[]).map(e=>({...e})),resources:(t.resources??[]).map(e=>({...e})),prompts:(t.prompts??[]).map(e=>({...e,arguments:e.arguments?.map(e=>({...e}))})),promptSkills:(t.promptSkills??[]).map(e=>({...e,skill:{...e.skill}}))}]))}}var E=class{clientManager;skillService;cacheData;liveDefinitionsPromise=null;mergedDefinitionsPromise=null;logger;constructor(e,t,n,r=console){this.clientManager=e,this.skillService=t,this.cacheData=n?.cacheData,this.logger=r}static async readFromFile(e){let t=await(0,l.readFile)(e,`utf-8`),n=Ke(e)?u.default.load(t):JSON.parse(t);if(!n||typeof n!=`object`)throw Error(`Definitions cache must be an object`);let r=n;if(r.version!==1||!r.servers)throw Error(`Definitions cache is missing required fields`);return{...r,failures:Array.isArray(r.failures)?r.failures:[],skills:Array.isArray(r.skills)?r.skills:[],servers:Object.fromEntries(Object.entries(r.servers).map(([e,t])=>[e,{...t,tools:Array.isArray(t.tools)?t.tools:[],resources:Array.isArray(t.resources)?t.resources:[],prompts:Array.isArray(t.prompts)?t.prompts:[],promptSkills:Array.isArray(t.promptSkills)?t.promptSkills:[]}]))}}static async writeToFile(e,t){let n=Ke(e)?u.default.dump(t,{noRefs:!0}):JSON.stringify(t,null,2);await(0,l.mkdir)((0,m.dirname)(e),{recursive:!0}),await(0,l.writeFile)(e,n,`utf-8`)}static getDefaultCachePath(e){let t=qe(e);return(0,m.join)((0,p.homedir)(),`.aicode-toolkit`,`${t}.definitions-cache.json`)}static generateConfigHash(e){return(0,f.createHash)(`sha256`).update(JSON.stringify(e)).digest(`hex`)}static isCacheValid(e,t){return!(t.configHash&&e.configHash&&e.configHash!==t.configHash||t.oneMcpVersion&&e.oneMcpVersion&&e.oneMcpVersion!==t.oneMcpVersion)}static async clearFile(e){await(0,l.rm)(e,{force:!0})}clearLiveCache(){this.liveDefinitionsPromise=null,this.mergedDefinitionsPromise=null}setCacheData(e){this.cacheData=e,this.mergedDefinitionsPromise=null}async collectForCache(e){let t=await this.collectLiveDefinitions(e);return this.setCacheData(t),this.liveDefinitionsPromise=Promise.resolve(T(t)),T(t)}async getDefinitions(){return this.mergedDefinitionsPromise||=(async()=>{let e=this.clientManager.getAllClients();if(!this.cacheData)return this.getLiveDefinitions();let t=e.map(e=>e.serverName).filter(e=>!this.cacheData?.servers[e]);if(t.length===0)return T(this.cacheData);let n=await this.getLiveDefinitions(),r=T(this.cacheData);for(let e of t){let t=n.servers[e];t&&(r.servers[e]=t)}let i=new Map;for(let e of[...r.failures,...n.failures])i.set(e.serverName,e.error);return r.failures=Array.from(i.entries()).map(([e,t])=>({serverName:e,error:t})),r.skills.length===0&&n.skills.length>0&&(r.skills=n.skills.map(e=>({...e}))),r})(),this.mergedDefinitionsPromise}async getServerDefinitions(){let e=await this.getDefinitions(),t=this.clientManager.getKnownServerNames();return t.length===0?Object.values(e.servers):t.map(t=>e.servers[t]).filter(e=>e!==void 0)}async getServersForTool(e){return(await this.getServerDefinitions()).filter(t=>t.tools.some(t=>t.name===e)).map(e=>e.serverName)}async getToolSchema(e,t){return(await this.getDefinitions()).servers[e]?.tools.find(e=>e.name===t)?.inputSchema}async getServersForResource(e){return(await this.getServerDefinitions()).filter(t=>t.resources.some(t=>t.uri===e)).map(e=>e.serverName)}async getPromptSkillByName(e){let t=await this.getDefinitions();for(let[n,r]of Object.entries(t.servers))for(let t of r.promptSkills)if(t.skill.name===e)return{serverName:n,promptName:t.promptName,skill:t.skill,autoDetected:t.autoDetected}}async getCachedFileSkills(){return(await this.getDefinitions()).skills.map(e=>({...e}))}async getLiveDefinitions(){return this.liveDefinitionsPromise||=this.collectLiveDefinitions(),this.liveDefinitionsPromise}async collectLiveDefinitions(e){let t=this.clientManager.getAllClients(),n=[],r={},i=await Promise.all(t.map(async e=>{try{let t=await e.listTools(),n=await this.listResourcesSafe(e),r=await this.listPromptsSafe(e),i=new Set(e.toolBlacklist||[]),a=t.filter(e=>!i.has(e.name)),o=await this.collectPromptSkillsForClient(e,r);return{serverName:e.serverName,serverInstruction:e.serverInstruction,omitToolDescription:e.omitToolDescription,toolBlacklist:e.toolBlacklist,tools:a.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema,_meta:e._meta})),resources:n,prompts:r,promptSkills:o}}catch(t){return n.push({serverName:e.serverName,error:w(t)}),null}}));for(let e of i)e&&(r[e.serverName]=e);return{version:1,oneMcpVersion:e?.oneMcpVersion,generatedAt:new Date().toISOString(),configPath:e?.configPath,configHash:e?.configHash,serverId:e?.serverId,servers:r,skills:await this.collectFileSkills(),failures:n}}async collectFileSkills(){return this.skillService?(await this.skillService.getSkills()).map(e=>this.toCachedFileSkill(e)):[]}toCachedFileSkill(e){return{name:e.name,description:e.description,location:e.location,basePath:e.basePath}}async listPromptsSafe(e){try{return(await e.listPrompts()).map(e=>({name:e.name,description:e.description,arguments:e.arguments?.map(e=>({...e}))}))}catch(t){return this.logger.warn(`${Be} Failed to list prompts from ${e.serverName}: ${w(t)}`),[]}}async listResourcesSafe(e){try{return(await e.listResources()).map(e=>({uri:e.uri,name:e.name,description:e.description,mimeType:e.mimeType}))}catch(t){return this.logger.warn(`[capability-discovery] Failed to list resources from ${e.serverName}: ${w(t)}`),[]}}async collectPromptSkillsForClient(e,t){let n=new Set(e.prompts?Object.keys(e.prompts):[]),r=[];if(e.prompts)for(let[t,n]of Object.entries(e.prompts))n.skill&&r.push({promptName:t,skill:{...n.skill}});let i=t.filter(e=>!n.has(e.name)).slice(0,50),a=await Promise.all(i.map(async t=>{try{let n=Ge((await e.getPrompt(t.name)).messages?.map(e=>{let t=e.content;return typeof t==`string`?t:t&&typeof t==`object`&&`text`in t?String(t.text):``}).join(`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/mcp-proxy",
|
|
3
3
|
"description": "MCP proxy server package",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.9",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -22,24 +22,24 @@
|
|
|
22
22
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
23
23
|
"chalk": "5.6.2",
|
|
24
24
|
"commander": "14.0.3",
|
|
25
|
-
"@hono/node-server": "
|
|
26
|
-
"hono": "4.12.
|
|
25
|
+
"@hono/node-server": "2.0.1",
|
|
26
|
+
"hono": "4.12.16",
|
|
27
27
|
"gray-matter": "4.0.3",
|
|
28
28
|
"js-yaml": "4.1.1",
|
|
29
|
-
"liquidjs": "10.25.
|
|
30
|
-
"zod": "4.
|
|
31
|
-
"@agimon-ai/foundation-process-registry": "0.8.
|
|
32
|
-
"@agimon-ai/log-sink-mcp": "0.8.
|
|
33
|
-
"@agimon-ai/foundation-
|
|
34
|
-
"@agimon-ai/foundation-
|
|
29
|
+
"liquidjs": "10.25.7",
|
|
30
|
+
"zod": "4.4.1",
|
|
31
|
+
"@agimon-ai/foundation-process-registry": "0.8.4",
|
|
32
|
+
"@agimon-ai/log-sink-mcp": "0.8.4",
|
|
33
|
+
"@agimon-ai/foundation-validator": "0.5.4",
|
|
34
|
+
"@agimon-ai/foundation-port-registry": "0.8.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/js-yaml": "4.0.9",
|
|
38
38
|
"@types/node": "25.6.0",
|
|
39
|
-
"tsdown": "0.21.
|
|
40
|
-
"typescript": "6.0.
|
|
39
|
+
"tsdown": "0.21.10",
|
|
40
|
+
"typescript": "6.0.3",
|
|
41
41
|
"unplugin-raw": "0.7.0",
|
|
42
|
-
"vitest": "4.1.
|
|
42
|
+
"vitest": "4.1.5"
|
|
43
43
|
},
|
|
44
44
|
"type": "module",
|
|
45
45
|
"publishConfig": {
|