// @kodax-ai/kodax — bundled distribution. See docs/ADR.md ADR-022 + ADR-024.
import{a as s}from"./chunk-V4WSBIXB.js";import S from"fs/promises";import O from"path";import{getEncoding as se}from"js-tiktoken";var E=null;function ie(){return E||(E=se("cl100k_base")),E}s(ie,"getEncoder");function v(n){return n?ie().encode(n).length:0}s(v,"countTextTokens");function ae(n){let e=0;for(let t of n)if(e+=4,typeof t.content=="string")e+=v(t.content);else for(let r of t.content)r.type==="text"?e+=v(r.text):r.type==="tool_use"?(e+=v(r.name),e+=v(JSON.stringify(r.input))):r.type==="tool_result"?(e+=4,e+=typeof r.content=="string"?v(r.content):r.content.reduce((o,i)=>o+(i.type==="text"?v(i.text):1500),0)):r.type==="thinking"?e+=v(r.thinking):r.type==="image"&&(e+=1500);return e}s(ae,"estimateTokens");function le(n){return v(n)}s(le,"countTokens");var pe=["read","edit","bash:test","bash:read-only","bash:mutating","bash:network","subagent"];var Zt=new Set(pe);import{homedir as $e}from"node:os";import{join as G}from"node:path";var je=".kodax",Fe="KODAX_HOME",N;function H(){if(N)return N;let n=process.env[Fe];return n&&n.length>0?n:G($e(),je)}s(H,"getAgentConfigHome");function b(...n){return G(H(),...n)}s(b,"getAgentConfigPath");function Q(n){return encodeURIComponent(n)}s(Q,"safeIdComponent");function _(){return b("mcp")}s(_,"defaultMcpCacheDir");function h(n,e,t){return`mcp:${Q(n)}:${e}:${Q(t)}`}s(h,"createMcpCapabilityId");function x(n){let e=n.match(/^mcp:([^:]+):(tool|resource|prompt):(.+)$/);if(!e?.[1]||!e[2]||!e[3])throw new Error(`Invalid MCP capability id: ${n}`);return{serverId:decodeURIComponent(e[1]),kind:e[2],name:decodeURIComponent(e[3])}}s(x,"parseMcpCapabilityId");function M(n,e){let t=typeof n?.description=="string"?n.description.trim():"",r=typeof n?.title=="string"?n.title.trim():"";return t||r||e}s(M,"summarizeMcpCatalogEntry");function A(n,e,t){if(n==="resource"||n==="prompt")return"read";let r=e.toLowerCase();return t?.destructive===!0||t?.destructiveHint===!0?"write":t?.openWorld===!0||t?.openWorldHint===!0?"network":t?.exec===!0||t?.execHint===!0||r.includes("exec")?"exec":r.includes("delete")||r.includes("remove")||r.includes("write")||r.includes("update")||r.includes("create")?"write":"read"}s(A,"deriveMcpCapabilityRisk");function ot(n){return[n.id,n.serverId,n.kind,n.name,n.title,n.summary,...n.tags??[]].filter(e=>typeof e=="string"&&e.trim().length>0).join(`
`).toLowerCase()}s(ot,"buildCatalogSearchText");function P(n,e,t={}){let r=e.trim().toLowerCase(),o=Math.max(1,Math.floor(t.limit??10));return n.filter(i=>!t.kind||i.kind===t.kind).map(i=>({item:i,haystack:ot(i)})).filter(({haystack:i})=>r.length===0||i.includes(r)).slice(0,o).map(({item:i})=>i)}s(P,"searchMcpCatalog");function D(n,e){let t=O.join(n,"catalog");return{catalogDir:t,indexPath:O.join(t,`${e}.index.json`),itemsPath:O.join(t,`${e}.items.json`)}}s(D,"getMcpCachePaths");async function Y(n,e){let{catalogDir:t,indexPath:r,itemsPath:o}=D(n,e.serverId);await S.mkdir(t,{recursive:!0}),await S.writeFile(r,JSON.stringify({serverId:e.serverId,updatedAt:e.updatedAt,items:e.items},null,2),"utf8"),await S.writeFile(o,JSON.stringify({serverId:e.serverId,updatedAt:e.updatedAt,descriptors:e.descriptors},null,2),"utf8")}s(Y,"writeMcpServerCatalog");async function $(n,e){let{indexPath:t,itemsPath:r}=D(n,e);try{let[o,i]=await Promise.all([S.readFile(t,"utf8"),S.readFile(r,"utf8")]),a=JSON.parse(o),l=JSON.parse(i);return{serverId:e,updatedAt:l.updatedAt??a.updatedAt??new Date(0).toISOString(),items:a.items??[],descriptors:l.descriptors??[]}}catch{return}}s($,"readMcpServerCatalog");import{spawn as st}from"child_process";function it(n){return`Content-Length: ${Buffer.byteLength(n,"utf8")}\r
\r
${n}`}s(it,"createContentLengthFrame");function at(n){let e,t=Buffer.alloc(0),r,o=n.framing??"content-length";function i(){if(r)for(;t.length>0;){if(o==="content-length"){let u=t.indexOf(`\r
\r
`);if(u<0)return;let c=t.subarray(0,u).toString("utf8").match(/Content-Length:\s*(\d+)/i);if(!c?.[1]){t=Buffer.alloc(0),r.onError(new Error("Malformed Content-Length header from MCP server."));return}let p=Number(c[1]),m=u+4+p;if(t.length<m)return;let T=t.subarray(u+4,m).toString("utf8");t=t.subarray(m),r.onMessage(T);continue}let a=t.indexOf(10);if(a<0)return;let l=t.subarray(0,a).toString("utf8").replace(/\r$/,"").trim();t=t.subarray(a+1),l.startsWith("{")&&r.onMessage(l)}}return s(i,"drainBuffer"),{get connected(){return!!e},get detectedFraming(){return o},async open(a){r=a,t=Buffer.alloc(0);let l=st(n.command,n.args??[],{cwd:n.cwd,env:{...globalThis.process.env,...n.env??{}},stdio:"pipe",windowsHide:!0});e=l,l.stdin.on("error",()=>{}),l.stdout.on("data",u=>{t=Buffer.concat([t,u]),i()}),l.stderr.on("data",u=>{let d=u.toString("utf8").trim();d&&a.onError(new Error(d))}),l.on("error",u=>{e=void 0,a.onError(u),a.onClose(`Process error: ${u.message}`)}),l.on("exit",(u,d)=>{e=void 0,a.onClose(`Process exited (${u??"signal"}${d?`:${d}`:""}).`)})},async send(a){if(!e?.stdin.writable)throw new Error("Stdio transport is not writable.");o==="ndjson"?e.stdin.write(a+`
`,"utf8"):e.stdin.write(it(a),"utf8")},switchFraming(a){o=a,t=Buffer.alloc(0)},async close(){t=Buffer.alloc(0),e&&(e.removeAllListeners(),e.stdout.removeAllListeners(),e.stderr.removeAllListeners(),e.kill(),e=void 0)}}}s(at,"createStdioTransport");function j(n,e,t){let r=e+n,o="",i=[];for(;;){let a=r.indexOf(`
`);if(a<0)break;let l=r.slice(0,a).replace(/\r$/,"");if(r=r.slice(a+1),l===""){i.length>0&&t({event:o||"message",data:i.join(`
`)}),o="",i.length=0;continue}l.startsWith(":")||(l.startsWith("event:")?o=l.slice(6).trim():l.startsWith("data:")&&i.push(l.slice(5).trimStart()))}return i.length>0||o?(o?`event:${o}
`:"")+i.map(l=>`data:${l}
`).join("")+r:r}s(j,"parseSseChunks");function lt(n){let e,t,r,o=!1;function i(d){try{return new URL(d,n.url).href}catch{return d}}s(i,"resolveEndpointUrl");let a,l=new Promise(d=>{a=d});async function u(d){let c=d.body;if(!c){r?.onError(new Error("SSE response has no body."));return}let p=c.getReader(),m=new TextDecoder,T="";try{for(;;){let{done:y,value:re}=await p.read();if(y)break;let oe=m.decode(re,{stream:!0});T=j(oe,T,w=>{if(w.event==="endpoint"){t=i(w.data.trim()),a?.();return}w.event==="message"&&r?.onMessage(w.data)})}}catch(y){y.name!=="AbortError"&&r?.onError(y instanceof Error?y:new Error(String(y)))}o=!1,r?.onClose("SSE stream ended.")}return s(u,"readSseStream"),{get connected(){return o},async open(d){r=d,e=new AbortController;let c=await fetch(n.url,{method:"GET",headers:{Accept:"text/event-stream",...n.headers??{}},signal:e.signal});if(!c.ok)throw new Error(`SSE connection failed: ${c.status} ${c.statusText}`);o=!0,u(c).catch(m=>{r?.onError(m instanceof Error?m:new Error(String(m)))});let p=new Promise((m,T)=>{setTimeout(()=>T(new Error("SSE server did not send an endpoint event within 10 s.")),1e4)});await Promise.race([l,p])},async send(d){if(!t||!o)throw new Error("SSE transport is not connected.");let c=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json",...n.headers??{}},body:d,signal:e?.signal});if(!c.ok)throw new Error(`SSE POST failed: ${c.status} ${c.statusText}`)},async close(){o=!1,t=void 0,e?.abort(),e=void 0}}}s(lt,"createSseTransport");function dt(n){let e,t,r=!1;async function o(){if(e)try{let i=await fetch(n.url,{method:"GET",headers:{Accept:"text/event-stream",...n.headers??{}},signal:e.signal});if(i.status===405||!i.ok||!i.body)return;let a=i.body.getReader(),l=new TextDecoder,u="";for(;;){let{done:d,value:c}=await a.read();if(d)break;u=j(l.decode(c,{stream:!0}),u,p=>{p.event==="message"&&t?.onMessage(p.data)})}}catch(i){i.name!=="AbortError"&&t?.onError(i instanceof Error?i:new Error(String(i)))}}return s(o,"openNotificationStream"),{get connected(){return r},async open(i){t=i,e=new AbortController,r=!0,o().catch(()=>{})},async send(i){if(!r)throw new Error("Streamable HTTP transport is not connected.");let a=await fetch(n.url,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/event-stream",...n.headers??{}},body:i,signal:e?.signal});if(!a.ok)throw new Error(`HTTP POST failed: ${a.status} ${a.statusText}`);if((a.headers.get("content-type")??"").includes("text/event-stream")&&a.body){let d=a.body.getReader(),c=new TextDecoder,p="";for(;;){let{done:m,value:T}=await d.read();if(m)break;p=j(c.decode(T,{stream:!0}),p,y=>{y.event==="message"&&t?.onMessage(y.data)})}return}let u=await a.text();u.trim()&&t?.onMessage(u)},async close(){r=!1,e?.abort(),e=void 0}}}s(dt,"createStreamableHttpTransport");function F(n,e={}){let t=n.type??"stdio";switch(t){case"stdio":{if(!n.command)throw new Error('MCP stdio transport requires a "command" field.');return at({command:n.command,args:n.args,cwd:n.cwd,env:n.env,framing:e.stdioFraming})}case"sse":{if(!n.url)throw new Error('MCP SSE transport requires a "url" field.');return lt({url:n.url,headers:n.headers})}case"streamable-http":{if(!n.url)throw new Error('MCP streamable-http transport requires a "url" field.');return dt({url:n.url,headers:n.headers})}default:throw new Error(`Unknown MCP transport type: ${t}`)}}s(F,"createMcpTransport");import I from"fs/promises";import ut from"path";function z(){return b("mcp-tokens")}s(z,"getTokenDir");function J(n){return ut.join(z(),`${n}.json`)}s(J,"getTokenPath");async function ct(n){try{let e=await I.readFile(J(n),"utf-8");return JSON.parse(e)}catch{return null}}s(ct,"loadToken");async function ft(n,e){await I.mkdir(z(),{recursive:!0,mode:448});let t=J(n);await I.writeFile(t,JSON.stringify(e,null,2),"utf-8"),process.platform!=="win32"&&await I.chmod(t,384)}s(ft,"saveToken");function mt(n){return n.expiresAt?Date.now()>=n.expiresAt-6e4:!1}s(mt,"isTokenExpired");async function pt(n,e){if(!e.refreshToken)throw new Error("No refresh token available. Re-authorization required.");let t=new URLSearchParams({grant_type:"refresh_token",client_id:n.clientId,refresh_token:e.refreshToken}),r=await fetch(n.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:t.toString()});if(!r.ok){let i=await r.text();throw new Error(`OAuth token refresh failed (${r.status}): ${i}`)}let o=await gt(r,"OAuth token refresh");return yt(o)}s(pt,"refreshToken");async function gt(n,e){let t;try{t=await n.json()}catch(r){throw new Error(`Failed to parse ${e} response as JSON: ${r instanceof Error?r.message:String(r)}`)}if(typeof t!="object"||t===null||Array.isArray(t))throw new Error(`${e} response is not a JSON object`);return t}s(gt,"safeParseJsonResponse");function yt(n){let e=typeof n.access_token=="string"?n.access_token:"";if(!e)throw new Error("No access_token in OAuth response");let t=typeof n.expires_in=="number"?n.expires_in:void 0;return{accessToken:e,refreshToken:typeof n.refresh_token=="string"?n.refresh_token:void 0,expiresAt:t?Date.now()+t*1e3:void 0,tokenType:typeof n.token_type=="string"?n.token_type:"Bearer",scope:typeof n.scope=="string"?n.scope:void 0}}s(yt,"parseTokenResponse");async function Z(n,e){let t=await ct(n);if(t&&!mt(t))return t;if(t?.refreshToken)try{let r=await pt(e,t);return await ft(n,r),r}catch(r){let o=r instanceof Error?r.message:String(r);process.stderr.write(`[kodax:mcp:oauth] Token refresh failed for ${n}: ${o}
`)}return null}s(Z,"getValidToken");function g(n){if(!(!n||Array.isArray(n)||typeof n!="object"))return n}s(g,"asRecord");function f(n){return typeof n=="string"&&n.trim().length>0?n.trim():void 0}s(f,"readString");function B(n){if(!Array.isArray(n))return;let e=n.map(t=>f(t)).filter(t=>t!==void 0);return e.length>0?e:void 0}s(B,"toStringArray");function ee(n){return typeof n=="boolean"?n:void 0}s(ee,"readBoolean");function C(n){if(n!=null){if(typeof n=="string")return n.trim()||void 0;if(typeof n=="number"||typeof n=="boolean")return String(n);try{return JSON.stringify(n,null,2)}catch{return}}}s(C,"stringifyStructuredValue");function te(n){if(typeof n=="string")return n.trim()||void 0;if(Array.isArray(n)){let t=n.map(r=>{let o=g(r);return o?f(o.text)??f(o.content)??f(o.uri)??C(o):C(r)}).filter(r=>r!==void 0&&r.length>0);return t.length>0?t.join(`

`):void 0}let e=g(n);return e?f(e.text)??f(e.content)??C(e):C(n)}s(te,"flattenMcpContent");function X(n){return JSON.stringify(n)}s(X,"jsonRpcString");function ht(n,e,t){let r=f(e.name)??"unnamed_tool",o=g(e.annotations),i=M(e,`MCP tool ${r}`);return{id:h(n,"tool",r),serverId:n,kind:"tool",name:r,title:f(e.title),summary:i,tags:B(e.tags),risk:A("tool",r,o),annotations:o,inputSchema:e.inputSchema??e.input_schema,outputSchema:e.outputSchema??e.output_schema,cachedAt:t}}s(ht,"buildToolDescriptor");function Tt(n,e,t){let r=f(e.uri)??f(e.name)??"resource",o=g(e.annotations),i=M(e,`MCP resource ${r}`);return{id:h(n,"resource",r),serverId:n,kind:"resource",name:r,title:f(e.title),summary:i,tags:B(e.tags),risk:A("resource",r,o),annotations:o,uri:r,mimeType:f(e.mimeType)??f(e.mime_type),cachedAt:t}}s(Tt,"buildResourceDescriptor");function vt(n,e,t){let r=f(e.name)??"prompt",o=g(e.annotations),i=M(e,`MCP prompt ${r}`);return{id:h(n,"prompt",r),serverId:n,kind:"prompt",name:r,title:f(e.title),summary:i,tags:B(e.tags),risk:A("prompt",r,o),annotations:o,promptArgsSchema:e.arguments??e.argsSchema??e.args_schema,cachedAt:t}}s(vt,"buildPromptDescriptor");function bt(n){let{inputSchema:e,outputSchema:t,promptArgsSchema:r,uri:o,mimeType:i,...a}=n;return a}s(bt,"toCatalogItem");function xt(n,e){let t=g(n);return t?{entries:Array.isArray(t[e])?t[e].map(o=>g(o)).filter(o=>o!==void 0):[],nextCursor:f(t.nextCursor)??f(t.next_cursor)}:{entries:[]}}s(xt,"extractListEntries");var St=3e4,Rt=6e4;function kt(n){return n.startupTimeoutMs??(parseInt(process.env.MCP_TIMEOUT??"",10)||St)}s(kt,"getStartupTimeoutMs");function wt(n){return n.requestTimeoutMs??(parseInt(process.env.MCP_REQUEST_TIMEOUT??"",10)||Rt)}s(wt,"getRequestTimeoutMs");var R=class{static{s(this,"McpServerRuntime")}serverId;config;cacheDir;transport;pending=new Map;nextRequestId=0;initialized=!1;connectPromise;catalog;diagnostics;constructor(e,t,r){this.serverId=e,this.config=t,this.cacheDir=r,this.diagnostics={serverId:e,connect:t.connect??"lazy",status:(t.connect??"lazy")==="disabled"?"disabled":"idle",dirty:!0,tools:0,resources:0,prompts:0}}getDiagnostics(){return{...this.diagnostics}}async prewarmIfNeeded(){(this.config.connect??"lazy")==="prewarm"&&await this.refreshCatalog(!0)}async getCachedCatalog(){return this.catalog||(this.catalog=await $(this.cacheDir,this.serverId),this.catalog&&this.applyCatalogSnapshot(this.catalog)),this.catalog}async getCatalog(e=!1){if(this.catalog||(this.catalog=await $(this.cacheDir,this.serverId),this.catalog&&this.applyCatalogSnapshot(this.catalog)),e||this.diagnostics.dirty||!this.catalog)try{await this.refreshCatalog(e)}catch(t){if(!this.catalog)throw t}return this.catalog??{serverId:this.serverId,items:[],descriptors:[],updatedAt:new Date(0).toISOString()}}async describeCapability(e){return(await this.getCatalog()).descriptors.find(r=>r.id===e)}async callTool(e,t){await this.connect();let r=await this.request("tools/call",{name:e,arguments:t}),o=g(r);return{content:te(o?.content),structuredContent:o?.structuredContent??o?.structured_content,metadata:{serverId:this.serverId,isError:ee(o?.isError)??ee(o?.is_error)??!1,raw:o}}}async readResource(e,t){await this.connect();let r=await this.request("resources/read",{uri:e,...t}),o=g(r),i=Array.isArray(o?.contents)?o.contents:[];return{content:te(i),structuredContent:i,metadata:{serverId:this.serverId,raw:o}}}async getPrompt(e,t){return await this.connect(),this.request("prompts/get",{name:e,arguments:t})}async refreshCatalog(e=!1){if((this.config.connect??"lazy")==="disabled"){this.diagnostics.status="disabled",this.diagnostics.dirty=!1;return}e&&await this.dispose();try{await this.connect();let t=new Date().toISOString(),r=await this.listDescriptors("tools/list","tools",t),o=await this.listDescriptors("resources/list","resources",t),i=await this.listDescriptors("prompts/list","prompts",t),a=[...r,...o,...i],l={serverId:this.serverId,descriptors:a,items:a.map(bt),updatedAt:t};this.catalog=l,this.applyCatalogSnapshot(l),await Y(this.cacheDir,l)}catch(t){let r=t instanceof Error?t.message:String(t);throw this.diagnostics.status="error",this.diagnostics.lastError=r,this.diagnostics.dirty=!0,t}}async dispose(){this.connectPromise=void 0,await this.resetTransport()}async resetTransport(){for(let[e,t]of this.pending)clearTimeout(t.timeout),t.reject(new Error(`MCP server "${this.serverId}" disposed during request ${e}.`)),this.pending.delete(e);this.initialized=!1,this.transport&&(await this.transport.close(),this.transport=void 0),(this.config.connect??"lazy")!=="disabled"&&(this.diagnostics.status="idle",this.diagnostics.dirty=!0)}connect(){return(this.config.connect??"lazy")==="disabled"?Promise.reject(new Error(`MCP server "${this.serverId}" is disabled.`)):this.transport?.connected&&this.initialized?Promise.resolve():(this.connectPromise||(this.connectPromise=this.doConnect().finally(()=>{this.connectPromise=void 0})),this.connectPromise)}async doConnect(){this.diagnostics.status="connecting";let e;if(this.config.auth?.type==="oauth2"){let o=await Z(this.serverId,this.config.auth);o?(this.config.headers?.Authorization&&process.stderr.write(`[kodax:mcp] OAuth token will override user-provided Authorization header for "${this.serverId}"
`),e={Authorization:`${o.tokenType??"Bearer"} ${o.accessToken}`}):process.stderr.write(`[kodax:mcp] OAuth token required for "${this.serverId}" but not available. Connecting without auth.
`)}let r=(this.config.type??"stdio")==="stdio"?["content-length","ndjson"]:[void 0];for(let o of r){await this.resetTransport();let i=e?{...this.config,headers:{...this.config.headers,...e}}:this.config,a=F(i,o?{stdioFraming:o}:{});this.transport=a,await a.open({onMessage:s(l=>this.handleMessage(l),"onMessage"),onError:s(l=>{this.diagnostics.lastError=l.message},"onError"),onClose:s(l=>{this.failPending(`MCP server "${this.serverId}" closed: ${l}`),this.transport=void 0,this.initialized=!1,this.diagnostics.status="error",this.diagnostics.lastError=l,this.diagnostics.dirty=!0},"onClose")});try{let l=kt(this.config),u=o==="content-length"?Math.min(l,1e4):l,d=await this.request("initialize",{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"KodaX",version:"0.7"}},u);await this.notify("notifications/initialized",{});let c=g(d);this.initialized=!0,this.diagnostics.status="ready",this.diagnostics.lastError=void 0,this.diagnostics.dirty=this.diagnostics.dirty||c?.capabilities!==void 0;return}catch(l){if(o===r[r.length-1])throw l}}}async listDescriptors(e,t,r){let o=[],i;for(;;){let a;try{a=await this.request(e,i?{cursor:i}:{})}catch(d){if(o.length>0)break;if((d instanceof Error?d.message:String(d)).toLowerCase().includes("method not found"))return[];throw d}let{entries:l,nextCursor:u}=xt(a,t);for(let d of l){if(t==="tools"){o.push(ht(this.serverId,d,r));continue}if(t==="resources"){o.push(Tt(this.serverId,d,r));continue}o.push(vt(this.serverId,d,r))}if(!u)break;i=u}return o}async request(e,t,r=wt(this.config)){if(!this.transport?.connected)throw new Error(`MCP server "${this.serverId}" is not connected.`);let o=++this.nextRequestId,i=X({jsonrpc:"2.0",id:o,method:e,params:t});return new Promise((a,l)=>{let u=setTimeout(()=>{this.pending.delete(o),l(new Error(`MCP request timed out for ${this.serverId}:${e}`))},r);u.unref?.(),this.pending.set(o,{resolve:a,reject:l,timeout:u}),this.transport.send(i).catch(d=>{clearTimeout(u),this.pending.delete(o),l(d instanceof Error?d:new Error(String(d)))})})}async notify(e,t){this.transport?.connected&&await this.transport.send(X({jsonrpc:"2.0",method:e,params:t})).catch(()=>{})}handleMessage(e){let t;try{t=JSON.parse(e)}catch{this.diagnostics.status="error",this.diagnostics.lastError=`Malformed MCP JSON payload from "${this.serverId}".`;return}let r=f(t.method),o=typeof t.id=="number"?t.id:void 0;if(o!==void 0&&!r){let a=this.pending.get(o);if(!a)return;clearTimeout(a.timeout),this.pending.delete(o);let l=g(t.error);if(l?.message){a.reject(new Error(l.message));return}a.resolve(t.result);return}if(!r)return;r.endsWith("/list_changed")&&(this.diagnostics.dirty=!0);let i=t.id;i!=null&&this.transport?.send(X({jsonrpc:"2.0",id:i,error:{code:-32601,message:`Method not supported by client: ${r}`}})).catch(()=>{})}failPending(e){for(let[t,r]of this.pending)clearTimeout(r.timeout),r.reject(new Error(e)),this.pending.delete(t)}applyCatalogSnapshot(e){this.diagnostics.cachedAt=e.updatedAt,this.diagnostics.tools=e.items.filter(t=>t.kind==="tool").length,this.diagnostics.resources=e.items.filter(t=>t.kind==="resource").length,this.diagnostics.prompts=e.items.filter(t=>t.kind==="prompt").length,this.diagnostics.dirty=!1,this.diagnostics.status!=="disabled"&&(this.diagnostics.status=this.transport?.connected?"ready":"idle")}};function Mt(n){return Object.entries(n??{}).filter(([,e])=>(e.connect??"lazy")!=="disabled")}s(Mt,"enabledServerEntries");var L=class{static{s(this,"McpCapabilityProvider")}id="mcp";kinds=["tool","resource","prompt"];runtimes=new Map;cacheDir;constructor(e,t={}){this.cacheDir=t.cacheDir??_();for(let[r,o]of Mt(e))this.runtimes.set(r,new R(r,o,this.cacheDir))}hasActiveServers(){return this.runtimes.size>0}async prewarm(){await Promise.allSettled(Array.from(this.runtimes.values()).map(e=>e.prewarmIfNeeded()))}async search(e,t={}){let r=await this.collectCatalogItems(t.server);return P(r,e,{kind:t.kind,limit:t.limit})}async describe(e){let{serverId:t}=x(e);return this.requireRuntime(t).describeCapability(e)}async execute(e,t){let{serverId:r,kind:o,name:i}=x(e);if(o!=="tool")throw new Error(`Capability ${e} is not an MCP tool.`);let l=await this.requireRuntime(r).callTool(i,t);return{kind:"tool",content:l.content,structuredContent:l.structuredContent,artifacts:[{kind:"provider",label:e,value:e}],metadata:{providerId:this.id,capabilityId:e,serverId:r,...l.metadata??{}}}}async read(e,t={}){let{serverId:r,kind:o,name:i}=x(e);if(o!=="resource")throw new Error(`Capability ${e} is not an MCP resource.`);let l=await this.requireRuntime(r).readResource(i,t);return{kind:"resource",content:l.content,structuredContent:l.structuredContent,artifacts:[{kind:"provider",label:e,value:e}],metadata:{providerId:this.id,capabilityId:e,serverId:r,...l.metadata??{}}}}async getPrompt(e,t={}){let{serverId:r,kind:o,name:i}=x(e);if(o!=="prompt")throw new Error(`Capability ${e} is not an MCP prompt.`);return this.requireRuntime(r).getPrompt(i,t)}async getPromptContext(){if(!this.hasActiveServers())return;let e=this.listServerDiagnostics(),t=["## MCP Capability Provider","Use `mcp_describe` to inspect input schemas, then `mcp_call` to invoke. Use `mcp_read_resource` for resources.","When a built-in tool fails or is unavailable, check whether an MCP tool below can accomplish the same goal.",""];for(let r of e){let o=[`### ${r.serverId}`,`status=${r.status}`];r.lastError&&o.push(`warning=${r.lastError}`),t.push(o.join(" | "));let i=this.runtimes.get(r.serverId),a=i?await i.getCachedCatalog():void 0,l=10;if(a&&a.items.length>0){let u=a.items.slice(0,l);for(let c of u)t.push(`- \`${c.id}\` (${c.kind}) \u2014 ${c.summary}`);let d=a.items.length-u.length;d>0&&t.push(`- +${d} more (use \`mcp_search\` to discover)`)}else r.cachedAt&&t.push(`- ${r.tools} tools / ${r.resources} resources / ${r.prompts} prompts (use \`mcp_search\` to discover)`);t.push("")}return t.join(`
`)}getDiagnostics(){if(!this.hasActiveServers())return;let e=this.listServerDiagnostics();return{cacheDir:this.cacheDir,serverCount:e.length,servers:e,toolCount:e.reduce((t,r)=>t+r.tools,0),resourceCount:e.reduce((t,r)=>t+r.resources,0),promptCount:e.reduce((t,r)=>t+r.prompts,0)}}async refresh(){for(let e of this.runtimes.values())await e.refreshCatalog()}async dispose(){for(let e of this.runtimes.values())await e.dispose()}async collectCatalogItems(e){let t=e?[this.requireRuntime(e)]:Array.from(this.runtimes.values()),r=[],o;for(let i of t)try{let a=await i.getCatalog();r.push(...a.items)}catch(a){if(e)throw a;o||(o=a instanceof Error?a:new Error(String(a)))}if(r.length===0&&o)throw o;return r}listServerDiagnostics(){return Array.from(this.runtimes.values()).map(e=>e.getDiagnostics())}requireRuntime(e){let t=this.runtimes.get(e);if(!t)throw new Error(`Unknown MCP server: ${e}`);return t}};import At from"node:fs/promises";import ne from"node:path";var k="demo",It="echo_tool",Ct="memory://guide",Et="draft_prompt",Ot=String.raw`const TOOL_NAME = 'echo_tool';
const RESOURCE_URI = 'memory://guide';
const PROMPT_NAME = 'draft_prompt';
let buffer = Buffer.alloc(0);

function writeMessage(payload) {
  const body = Buffer.from(JSON.stringify(payload), 'utf8');
  process.stdout.write('Content-Length: ' + body.length + '\r\n\r\n');
  process.stdout.write(body);
}

function handleRequest(message) {
  const id = message.id;
  const method = message.method;
  const params = message.params || {};
  if (method === 'initialize') {
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        protocolVersion: '2024-11-05',
        capabilities: {
          tools: {},
          resources: {},
          prompts: {},
        },
        serverInfo: {
          name: 'kodax-mcp-test-server',
          version: '1.0.0',
        },
      },
    });
    return;
  }
  if (method === 'tools/list') {
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        tools: [{
          name: TOOL_NAME,
          title: 'Echo Tool',
          description: 'Echo text back from the MCP test server.',
          inputSchema: {
            type: 'object',
            properties: {
              text: { type: 'string' },
              mode: { type: 'string' },
            },
            required: ['text'],
          },
          annotations: {
            destructive: false,
          },
        }],
      },
    });
    return;
  }
  if (method === 'resources/list') {
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        resources: [{
          uri: RESOURCE_URI,
          title: 'Guide Resource',
          description: 'Provides guide text.',
          mimeType: 'text/plain',
        }],
      },
    });
    return;
  }
  if (method === 'prompts/list') {
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        prompts: [{
          name: PROMPT_NAME,
          title: 'Draft Prompt',
          description: 'A simple prompt from the MCP test server.',
        }],
      },
    });
    return;
  }
  if (method === 'tools/call') {
    const args = params.arguments || params.args || {};
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        content: [{
          type: 'text',
          text: 'echo:' + String(args.text || ''),
        }],
        structuredContent: {
          echo: args.text || '',
          mode: args.mode || null,
        },
      },
    });
    return;
  }
  if (method === 'resources/read') {
    const uri = params.uri || params.name || RESOURCE_URI;
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        contents: [{
          uri,
          mimeType: 'text/plain',
          text: 'resource:' + String(uri),
        }],
      },
    });
    return;
  }
  if (method === 'prompts/get') {
    const args = params.arguments || params.args || {};
    const topic = args.topic || 'none';
    writeMessage({
      jsonrpc: '2.0',
      id,
      result: {
        description: 'Prompt result for ' + String(params.name || PROMPT_NAME),
        messages: [{
          role: 'user',
          content: {
            type: 'text',
            text: 'prompt:' + String(params.name || PROMPT_NAME) + ':' + String(topic),
          },
        }],
      },
    });
    return;
  }

  writeMessage({
    jsonrpc: '2.0',
    id,
    error: {
      code: -32601,
      message: 'Method not found: ' + String(method),
    },
  });
}

function handleFrame(raw) {
  let message;
  try {
    message = JSON.parse(raw);
  } catch (error) {
    process.stderr.write('bad json: ' + String(error) + '\n');
    return;
  }
  if (message.id !== undefined) {
    handleRequest(message);
  }
}

process.stdin.on('data', (chunk) => {
  buffer = Buffer.concat([buffer, chunk]);
  while (true) {
    const headerEnd = buffer.indexOf('\r\n\r\n');
    if (headerEnd < 0) {
      return;
    }
    const header = buffer.subarray(0, headerEnd).toString('utf8');
    const match = header.match(/Content-Length:\s*(\d+)/i);
    if (!match) {
      process.stderr.write('missing content-length\n');
      buffer = Buffer.alloc(0);
      return;
    }
    const length = Number(match[1]);
    const frameEnd = headerEnd + 4 + length;
    if (buffer.length < frameEnd) {
      return;
    }
    const body = buffer.subarray(headerEnd + 4, frameEnd).toString('utf8');
    buffer = buffer.subarray(frameEnd);
    handleFrame(body);
  }
});

process.on('SIGTERM', () => process.exit(0));
process.on('SIGINT', () => process.exit(0));
`;async function _t(n){let e=ne.join(n,"mcp-test-server.cjs"),t=ne.join(n,"mcp-cache");return await At.writeFile(e,Ot,"utf8"),{cacheDir:t,scriptPath:e,serverId:k,toolId:h(k,"tool",It),resourceId:h(k,"resource",Ct),promptId:h(k,"prompt",Et),servers:{[k]:{type:"stdio",command:process.execPath,args:[e],connect:"prewarm",startupTimeoutMs:5e3,requestTimeoutMs:5e3}}}}s(_t,"createMcpTestServerFixture");export{ae as a,le as b,b as c,_ as d,h as e,x as f,P as g,D as h,F as i,R as j,L as k,_t as l};
