emceepee 0.3.5 → 0.3.6
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/emceepee-http.js +5 -5
- package/dist/emceepee.js +3 -3
- package/package.json +1 -1
package/dist/emceepee-http.js
CHANGED
|
@@ -55,14 +55,14 @@ data:
|
|
|
55
55
|
`;if(W)$+=`id: ${W}
|
|
56
56
|
`;return $+=`data: ${JSON.stringify(Y)}
|
|
57
57
|
|
|
58
|
-
`,Q.enqueue(X.encode($)),!0}catch{return!1}}handleUnsupportedRequest(){return new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32000,message:"Method not allowed."},id:null}),{status:405,headers:{Allow:"GET, POST, DELETE","Content-Type":"application/json"}})}async handlePostRequest(Q,X){try{let Y=Q.headers.get("accept");if(!Y?.includes("application/json")||!Y.includes("text/event-stream"))return this.createJsonErrorResponse(406,-32000,"Not Acceptable: Client must accept both application/json and text/event-stream");let W=Q.headers.get("content-type");if(!W||!W.includes("application/json"))return this.createJsonErrorResponse(415,-32000,"Unsupported Media Type: Content-Type must be application/json");let $={headers:Object.fromEntries(Q.headers.entries())},J;if(X?.parsedBody!==void 0)J=X.parsedBody;else try{J=await Q.json()}catch{return this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON")}let G;try{if(Array.isArray(J))G=J.map((O)=>X6.parse(O));else G=[X6.parse(J)]}catch{return this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON-RPC message")}let H=G.some(F5);if(H){if(this._initialized&&this.sessionId!==void 0)return this.createJsonErrorResponse(400,-32600,"Invalid Request: Server already initialized");if(G.length>1)return this.createJsonErrorResponse(400,-32600,"Invalid Request: Only one initialization request is allowed");if(this.sessionId=this.sessionIdGenerator?.(),this._initialized=!0,this.sessionId&&this._onsessioninitialized)await Promise.resolve(this._onsessioninitialized(this.sessionId))}if(!H){let O=this.validateSession(Q);if(O)return O;let U=this.validateProtocolVersion(Q);if(U)return U}if(!G.some(p1)){for(let O of G)this.onmessage?.(O,{authInfo:X?.authInfo,requestInfo:$});return new Response(null,{status:202})}let z=crypto.randomUUID(),K=G.find((O)=>F5(O)),V=K?K.params.protocolVersion:Q.headers.get("mcp-protocol-version")??y3;if(this._enableJsonResponse)return new Promise((O)=>{this._streamMapping.set(z,{resolveJson:O,cleanup:()=>{this._streamMapping.delete(z)}});for(let U of G)if(p1(U))this._requestToStreamMapping.set(U.id,z);for(let U of G)this.onmessage?.(U,{authInfo:X?.authInfo,requestInfo:$})});let A=new TextEncoder,F,L=new ReadableStream({start:(O)=>{F=O},cancel:()=>{this._streamMapping.delete(z)}}),D={"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"};if(this.sessionId!==void 0)D["mcp-session-id"]=this.sessionId;for(let O of G)if(p1(O))this._streamMapping.set(z,{controller:F,encoder:A,cleanup:()=>{this._streamMapping.delete(z);try{F.close()}catch{}}}),this._requestToStreamMapping.set(O.id,z);await this.writePrimingEvent(F,A,z,V);for(let O of G){let U,w;if(p1(O)&&this._eventStore&&V>="2025-11-25")U=()=>{this.closeSSEStream(O.id)},w=()=>{this.closeStandaloneSSEStream()};this.onmessage?.(O,{authInfo:X?.authInfo,requestInfo:$,closeSSEStream:U,closeStandaloneSSEStream:w})}return new Response(L,{status:200,headers:D})}catch(Y){return this.onerror?.(Y),this.createJsonErrorResponse(400,-32700,"Parse error",{data:String(Y)})}}async handleDeleteRequest(Q){let X=this.validateSession(Q);if(X)return X;let Y=this.validateProtocolVersion(Q);if(Y)return Y;return await Promise.resolve(this._onsessionclosed?.(this.sessionId)),await this.close(),new Response(null,{status:200})}validateSession(Q){if(this.sessionIdGenerator===void 0)return;if(!this._initialized)return this.createJsonErrorResponse(400,-32000,"Bad Request: Server not initialized");let X=Q.headers.get("mcp-session-id");if(!X)return this.createJsonErrorResponse(400,-32000,"Bad Request: Mcp-Session-Id header is required");if(X!==this.sessionId)return this.createJsonErrorResponse(404,-32001,"Session not found");return}validateProtocolVersion(Q){let X=Q.headers.get("mcp-protocol-version");if(X!==null&&!Q9.includes(X))return this.createJsonErrorResponse(400,-32000,`Bad Request: Unsupported protocol version: ${X} (supported versions: ${Q9.join(", ")})`);return}async close(){this._streamMapping.forEach(({cleanup:Q})=>{Q()}),this._streamMapping.clear(),this._requestResponseMap.clear(),this.onclose?.()}closeSSEStream(Q){let X=this._requestToStreamMapping.get(Q);if(!X)return;let Y=this._streamMapping.get(X);if(Y)Y.cleanup()}closeStandaloneSSEStream(){let Q=this._streamMapping.get(this._standaloneSseStreamId);if(Q)Q.cleanup()}async send(Q,X){let Y=X?.relatedRequestId;if(P1(Q)||p9(Q))Y=Q.id;if(Y===void 0){if(P1(Q)||p9(Q))throw Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");let J;if(this._eventStore)J=await this._eventStore.storeEvent(this._standaloneSseStreamId,Q);let G=this._streamMapping.get(this._standaloneSseStreamId);if(G===void 0)return;if(G.controller&&G.encoder)this.writeSSEEvent(G.controller,G.encoder,Q,J);return}let W=this._requestToStreamMapping.get(Y);if(!W)throw Error(`No connection established for request ID: ${String(Y)}`);let $=this._streamMapping.get(W);if(!this._enableJsonResponse&&$?.controller&&$?.encoder){let J;if(this._eventStore)J=await this._eventStore.storeEvent(W,Q);this.writeSSEEvent($.controller,$.encoder,Q,J)}if(P1(Q)||p9(Q)){this._requestResponseMap.set(Y,Q);let J=Array.from(this._requestToStreamMapping.entries()).filter(([H,B])=>B===W).map(([H])=>H);if(J.every((H)=>this._requestResponseMap.has(H))){if(!$)throw Error(`No connection established for request ID: ${String(Y)}`);if(this._enableJsonResponse&&$.resolveJson){let H={"Content-Type":"application/json"};if(this.sessionId!==void 0)H["mcp-session-id"]=this.sessionId;let B=J.map((z)=>this._requestResponseMap.get(z));if(B.length===1)$.resolveJson(new Response(JSON.stringify(B[0]),{status:200,headers:H}));else $.resolveJson(new Response(JSON.stringify(B),{status:200,headers:H}))}else $.cleanup();for(let H of J)this._requestResponseMap.delete(H),this._requestToStreamMapping.delete(H)}}}}class lJ{constructor(Q={}){this._requestContext=new WeakMap,this._webStandardTransport=new uJ(Q),this._requestListener=hJ(async(X)=>{let Y=this._requestContext.get(X);return this._webStandardTransport.handleRequest(X,{authInfo:Y?.authInfo,parsedBody:Y?.parsedBody})})}get sessionId(){return this._webStandardTransport.sessionId}set onclose(Q){this._webStandardTransport.onclose=Q}get onclose(){return this._webStandardTransport.onclose}set onerror(Q){this._webStandardTransport.onerror=Q}get onerror(){return this._webStandardTransport.onerror}set onmessage(Q){this._webStandardTransport.onmessage=Q}get onmessage(){return this._webStandardTransport.onmessage}async start(){return this._webStandardTransport.start()}async close(){return this._webStandardTransport.close()}async send(Q,X){return this._webStandardTransport.send(Q,X)}async handleRequest(Q,X,Y){let W=Q.auth;await hJ(async(J)=>{return this._webStandardTransport.handleRequest(J,{authInfo:W,parsedBody:Y})})(Q,X)}closeSSEStream(Q){this._webStandardTransport.closeSSEStream(Q)}closeStandaloneSSEStream(){this._webStandardTransport.closeStandaloneSSEStream()}}import{createServer as Wu}from"http";import{readFileSync as $u}from"fs";import SY from"node:crypto";var IU="0123456789ABCDEFGHJKMNPQRSTVWXYZ",IY=32;var Mg=16,TU=10,SU=281474976710655;var q9;(function(Q){Q.Base32IncorrectEncoding="B32_ENC_INVALID",Q.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",Q.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",Q.EncodeTimeNegative="ENC_TIME_NEG",Q.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",Q.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",Q.PRNGDetectFailure="PRNG_DETECT",Q.ULIDInvalid="ULID_INVALID",Q.Unexpected="UNEXPECTED",Q.UUIDInvalid="UUID_INVALID"})(q9||(q9={}));class j8 extends Error{constructor(Q,X){super(`${X} (${Q})`);this.name="ULIDError",this.code=Q}}function bg(Q){let X=Math.floor(Q()*IY)%IY;return IU.charAt(X)}function Pg(Q){let X=Zg(),Y=X&&(X.crypto||X.msCrypto)||(typeof SY<"u"?SY:null);if(typeof Y?.getRandomValues==="function")return()=>{let W=new Uint8Array(1);return Y.getRandomValues(W),W[0]/256};else if(typeof Y?.randomBytes==="function")return()=>Y.randomBytes(1).readUInt8()/256;else if(SY?.randomBytes)return()=>SY.randomBytes(1).readUInt8()/256;throw new j8(q9.PRNGDetectFailure,"Failed to find a reliable PRNG")}function Zg(){if(Sg())return self;if(typeof window<"u")return window;if(typeof global<"u")return global;if(typeof globalThis<"u")return globalThis;return null}function Rg(Q,X){let Y="";for(;Q>0;Q--)Y=bg(X)+Y;return Y}function Eg(Q,X=TU){if(isNaN(Q))throw new j8(q9.EncodeTimeValueMalformed,`Time must be a number: ${Q}`);else if(Q>SU)throw new j8(q9.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${SU}: ${Q}`);else if(Q<0)throw new j8(q9.EncodeTimeNegative,`Time must be positive: ${Q}`);else if(Number.isInteger(Q)===!1)throw new j8(q9.EncodeTimeValueMalformed,`Time must be an integer: ${Q}`);let Y,W="";for(let $=X;$>0;$--)Y=Q%IY,W=IU.charAt(Y)+W,Q=(Q-Y)/IY;return W}function Sg(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function r0(Q,X){let Y=X||Pg(),W=!Q||isNaN(Q)?Date.now():Q;return Eg(W,TU)+Rg(Mg,Y)}function mJ(Q){return Q.type==="http"}function cJ(Q){return Q.type==="stdio"}class pJ{configs=new Map;logger;constructor(Q={}){this.logger=Q.logger}addConfig(Q,X,Y){let W=this.configs.has(Q);return this.configs.set(Q,{name:Q,type:"http",url:X,addedAt:new Date,addedBy:Y}),this.logger?.info(W?"server_config_updated":"server_config_added",{server:Q,type:"http",url:X,addedBy:Y}),!W}addStdioConfig(Q,X,Y,W,$){let J=this.configs.has(Q);return this.configs.set(Q,{name:Q,type:"stdio",command:X,args:Y,env:W?.env,cwd:W?.cwd,restartConfig:W?.restartConfig,addedAt:new Date,addedBy:$}),this.logger?.info(J?"server_config_updated":"server_config_added",{server:Q,type:"stdio",command:X,args:Y,addedBy:$}),!J}getConfig(Q){return this.configs.get(Q)}listConfigs(){return Array.from(this.configs.values())}removeConfig(Q){let X=this.configs.delete(Q);if(X)this.logger?.info("server_config_removed",{server:Q});return X}hasConfig(Q){return this.configs.has(Q)}get size(){return this.configs.size}clear(){this.configs.clear(),this.logger?.info("server_configs_cleared",{})}}var Ig={maxEvents:1000,retentionMs:1800000,cleanupIntervalMs:300000};class dJ{events=[];config;logger;lastDeliveredId=null;waiters=[];cleanupIntervalHandle=null;constructor(Q={},X){this.config={...Ig,...Q},this.logger=X,this.startCleanupInterval()}addEvent(Q,X,Y){let W=r0(),$={id:W,type:Q,server:X,data:Y,createdAt:new Date,sentViaSSE:!1};this.events.push($);while(this.events.length>this.config.maxEvents)this.events.shift();return this.logger?.debug("event_added",{id:W,type:Q,server:X}),this.wakeWaiters($),W}hasNewEvents(){if(this.lastDeliveredId===null)return this.events.length>0;let Q=this.events.findIndex((X)=>X.id===this.lastDeliveredId);if(Q===-1)return this.events.length>0;return Q<this.events.length-1}getNewEvents(){if(this.events.length===0)return[];let Q=0;if(this.lastDeliveredId!==null){let Y=this.events.findIndex((W)=>W.id===this.lastDeliveredId);if(Y!==-1)Q=Y+1}let X=this.events.slice(Q);if(X.length>0){let Y=X[X.length-1];if(Y)this.lastDeliveredId=Y.id}return X}getEventsAfter(Q){if(Q===null)return[...this.events];let X=this.events.findIndex((Y)=>Y.id===Q);if(X===-1)return[...this.events];return this.events.slice(X+1)}markSent(Q){let X=this.events.find((Y)=>Y.id===Q);if(X)X.sentViaSSE=!0}waitForActivity(Q){return new Promise((X)=>{let Y=setTimeout(()=>{let W=this.waiters.findIndex(($)=>$.timeoutHandle===Y);if(W!==-1)this.waiters.splice(W,1);X(null)},Q);this.waiters.push({resolve:X,timeoutHandle:Y})})}wakeWaiters(Q){let X=this.waiters;this.waiters=[];for(let Y of X)clearTimeout(Y.timeoutHandle),Y.resolve(Q)}startCleanupInterval(){this.cleanupIntervalHandle=setInterval(()=>{this.runCleanup()},this.config.cleanupIntervalMs)}runCleanup(){let Q=Date.now()-this.config.retentionMs,X=0;while(this.events.length>0){let Y=this.events[0];if(Y&&Y.createdAt.getTime()<Q)this.events.shift(),X++;else break}if(X>0)this.logger?.debug("events_cleaned",{removed:X,remaining:this.events.length})}shutdown(){if(this.cleanupIntervalHandle)clearInterval(this.cleanupIntervalHandle),this.cleanupIntervalHandle=null;for(let Q of this.waiters)clearTimeout(Q.timeoutHandle),Q.resolve(null);this.waiters=[]}}var Tg={defaultTtlMs:600000,completedRetentionMs:300000,cleanupIntervalMs:60000};class iJ{tasks=new Map;eventSystem;config;cleanupIntervalHandle=null;constructor(Q,X={}){this.eventSystem=Q,this.config={...Tg,...X},this.startCleanupInterval()}createTask(Q,X,Y,W){let $=r0(),J=new Date,G={taskId:$,server:Q,toolName:X,args:Y,status:"working",createdAt:J,lastUpdatedAt:J,ttl:W??this.config.defaultTtlMs};return this.tasks.set($,G),this.eventSystem.addEvent("task_created",Q,{taskId:$,toolName:X,args:Y}),G}completeTask(Q,X){let Y=this.tasks.get(Q);if(Y?.status!=="working")return;Y.status="completed",Y.result=X,Y.lastUpdatedAt=new Date,this.scheduleTaskCleanup(Y),this.eventSystem.addEvent("task_completed",Y.server,{taskId:Q,toolName:Y.toolName,result:X})}failTask(Q,X){let Y=this.tasks.get(Q);if(Y?.status!=="working")return;Y.status="failed",Y.error=X,Y.lastUpdatedAt=new Date,this.scheduleTaskCleanup(Y),this.eventSystem.addEvent("task_failed",Y.server,{taskId:Q,toolName:Y.toolName,error:X})}cancelTask(Q){let X=this.tasks.get(Q);if(X?.status!=="working")return!1;return X.status="cancelled",X.lastUpdatedAt=new Date,this.scheduleTaskCleanup(X),this.eventSystem.addEvent("task_cancelled",X.server,{taskId:Q,toolName:X.toolName}),!0}getTask(Q){let X=this.tasks.get(Q);if(!X)return;let{_cleanupTimeoutHandle:Y,...W}=X;return W}getTasksForServer(Q){return Array.from(this.tasks.values()).filter((X)=>X.server===Q).map((X)=>({taskId:X.taskId,server:X.server,toolName:X.toolName,args:X.args,status:X.status,result:X.result,error:X.error,createdAt:X.createdAt,lastUpdatedAt:X.lastUpdatedAt,ttl:X.ttl}))}getAllTasks(Q=!1){let X=["completed","failed","cancelled","expired"];return Array.from(this.tasks.values()).filter((Y)=>Q||!X.includes(Y.status)).map((Y)=>({taskId:Y.taskId,server:Y.server,toolName:Y.toolName,args:Y.args,status:Y.status,result:Y.result,error:Y.error,createdAt:Y.createdAt,lastUpdatedAt:Y.lastUpdatedAt,ttl:Y.ttl}))}getWorkingTasksForServer(Q){return Array.from(this.tasks.values()).filter((X)=>X.server===Q&&X.status==="working").map((X)=>({taskId:X.taskId,toolName:X.toolName,status:X.status}))}scheduleTaskCleanup(Q){if(Q._cleanupTimeoutHandle)clearTimeout(Q._cleanupTimeoutHandle);Q._cleanupTimeoutHandle=setTimeout(()=>{this.tasks.delete(Q.taskId)},this.config.completedRetentionMs)}startCleanupInterval(){this.cleanupIntervalHandle=setInterval(()=>{this.runCleanup()},this.config.cleanupIntervalMs)}runCleanup(){let Q=Date.now();for(let X of this.tasks.values()){if(X.status!=="working")continue;if(Q-X.createdAt.getTime()>=X.ttl)X.status="expired",X.error=`Task expired after ${String(X.ttl)}ms TTL`,X.lastUpdatedAt=new Date,this.eventSystem.addEvent("task_expired",X.server,{taskId:X.taskId,toolName:X.toolName,ttl:X.ttl}),this.scheduleTaskCleanup(X)}}shutdown(){if(this.cleanupIntervalHandle)clearInterval(this.cleanupIntervalHandle),this.cleanupIntervalHandle=null;for(let Q of this.tasks.values())if(Q._cleanupTimeoutHandle)clearTimeout(Q._cleanupTimeoutHandle)}}var Cg={maxNotificationsPerServer:100,maxLogsPerServer:500};class nJ{buffers=new Map;eventSystem;config;constructor(Q,X={}){this.eventSystem=Q,this.config={...Cg,...X}}addNotification(Q){let X=this.getOrCreateBuffers(Q.server);if(X.notifications.length>=this.config.maxNotificationsPerServer)X.notifications.shift();X.notifications.push(Q),this.eventSystem.addEvent("notification",Q.server,{method:Q.method,params:Q.params,timestamp:Q.timestamp.toISOString()})}addLog(Q){let X=this.getOrCreateBuffers(Q.server);if(X.logs.length>=this.config.maxLogsPerServer)X.logs.shift();X.logs.push(Q)}getAndClearNotifications(){let Q=[];for(let X of this.buffers.values())Q.push(...X.notifications),X.notifications=[];return Q}getAndClearLogs(){let Q=[];for(let X of this.buffers.values())Q.push(...X.logs),X.logs=[];return Q}getNotificationsForServer(Q){let X=this.buffers.get(Q);return X?[...X.notifications]:[]}getLogsForServer(Q){let X=this.buffers.get(Q);return X?[...X.logs]:[]}getNotificationCount(){let Q=0;for(let X of this.buffers.values())Q+=X.notifications.length;return Q}getLogCount(){let Q=0;for(let X of this.buffers.values())Q+=X.logs.length;return Q}clearServer(Q){this.buffers.delete(Q)}getOrCreateBuffers(Q){let X=this.buffers.get(Q);if(!X)X={notifications:[],logs:[]},this.buffers.set(Q,X);return X}}var kg={defaultTimeoutMs:600000};class oJ{samplingRequests=new Map;elicitationRequests=new Map;eventSystem;config;constructor(Q,X={}){this.eventSystem=Q,this.config={...kg,...X}}addSamplingRequest(Q,X,Y,W){let $=r0(),J=setTimeout(()=>{let H=this.samplingRequests.get($);if(H)this.samplingRequests.delete($),this.eventSystem.addEvent("sampling_expired",Q,{requestId:$,reason:`Timed out after ${String(this.config.defaultTimeoutMs)}ms`}),H.reject(Error(`Sampling request timed out after ${String(this.config.defaultTimeoutMs)}ms`))},this.config.defaultTimeoutMs),G={requestId:$,server:Q,timestamp:new Date,params:X,resolve:Y,reject:W,timeoutHandle:J};return this.samplingRequests.set($,G),this.eventSystem.addEvent("sampling_request",Q,{requestId:$,params:X}),$}addElicitationRequest(Q,X,Y,W){let $=r0(),J=setTimeout(()=>{let H=this.elicitationRequests.get($);if(H)this.elicitationRequests.delete($),this.eventSystem.addEvent("elicitation_expired",Q,{requestId:$,reason:`Timed out after ${String(this.config.defaultTimeoutMs)}ms`}),H.reject(Error(`Elicitation request timed out after ${String(this.config.defaultTimeoutMs)}ms`))},this.config.defaultTimeoutMs),G={requestId:$,server:Q,timestamp:new Date,params:X,resolve:Y,reject:W,timeoutHandle:J};return this.elicitationRequests.set($,G),this.eventSystem.addEvent("elicitation_request",Q,{requestId:$,params:X}),$}respondToSampling(Q,X){let Y=this.samplingRequests.get(Q);if(!Y)throw Error(`Sampling request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.samplingRequests.delete(Q),Y.resolve(X)}cancelSampling(Q,X="User cancelled"){let Y=this.samplingRequests.get(Q);if(!Y)throw Error(`Sampling request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.samplingRequests.delete(Q),this.eventSystem.addEvent("sampling_expired",Y.server,{requestId:Q,reason:X}),Y.reject(Error(X))}respondToElicitation(Q,X){let Y=this.elicitationRequests.get(Q);if(!Y)throw Error(`Elicitation request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.elicitationRequests.delete(Q),Y.resolve(X)}cancelElicitation(Q,X="User cancelled"){let Y=this.elicitationRequests.get(Q);if(!Y)throw Error(`Elicitation request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.elicitationRequests.delete(Q),this.eventSystem.addEvent("elicitation_expired",Y.server,{requestId:Q,reason:X}),Y.reject(Error(X))}getPendingSamplingRequests(){return Array.from(this.samplingRequests.values()).map((Q)=>({requestId:Q.requestId,server:Q.server,timestamp:Q.timestamp,params:Q.params}))}getPendingElicitationRequests(){return Array.from(this.elicitationRequests.values()).map((Q)=>({requestId:Q.requestId,server:Q.server,timestamp:Q.timestamp,params:Q.params}))}getRequestsForServer(Q){return{sampling:this.getPendingSamplingRequests().filter((X)=>X.server===Q),elicitation:this.getPendingElicitationRequests().filter((X)=>X.server===Q)}}hasPendingRequests(){return this.samplingRequests.size>0||this.elicitationRequests.size>0}rejectRequestsForServer(Q,X){for(let[Y,W]of this.samplingRequests)if(W.server===Q)clearTimeout(W.timeoutHandle),this.samplingRequests.delete(Y),this.eventSystem.addEvent("sampling_expired",Q,{requestId:Y,reason:X}),W.reject(Error(X));for(let[Y,W]of this.elicitationRequests)if(W.server===Q)clearTimeout(W.timeoutHandle),this.elicitationRequests.delete(Y),this.eventSystem.addEvent("elicitation_expired",Q,{requestId:Y,reason:X}),W.reject(Error(X))}shutdown(){for(let Q of this.samplingRequests.values())clearTimeout(Q.timeoutHandle),Q.reject(Error("PendingRequestsManager shutting down"));this.samplingRequests.clear();for(let Q of this.elicitationRequests.values())clearTimeout(Q.timeoutHandle),Q.reject(Error("PendingRequestsManager shutting down"));this.elicitationRequests.clear()}}var vg={maxActiveTimers:100,maxDurationMs:86400000,retentionMs:300000};class rJ{timers=new Map;expiredBuffer=[];eventSystem;config;constructor(Q,X={}){this.eventSystem=Q,this.config={...vg,...X}}createTimer(Q,X,Y=!1){if(this.getActiveTimers().length>=this.config.maxActiveTimers)throw Error(`Maximum active timers (${String(this.config.maxActiveTimers)}) exceeded`);if(Q<=0)throw Error("Duration must be positive");if(Q>this.config.maxDurationMs)throw Error(`Duration exceeds maximum (${String(this.config.maxDurationMs)}ms)`);let $=r0(),J=new Date,G=new Date(J.getTime()+Q),H={id:$,durationMs:Q,message:X,createdAt:J,expiresAt:G,status:"active",interval:Y,fireCount:0};if(Y)H._intervalHandle=setInterval(()=>{this.fireIntervalTimer($)},Q);else H._timeoutHandle=setTimeout(()=>{this.expireTimer($)},Q);return this.timers.set($,H),this.toPublicTimer(H)}getTimer(Q){let X=this.timers.get(Q);if(!X)return;return this.toPublicTimer(X)}deleteTimer(Q){let X=this.timers.get(Q);if(!X)return;if(X._timeoutHandle)clearTimeout(X._timeoutHandle),X._timeoutHandle=void 0;if(X._intervalHandle)clearInterval(X._intervalHandle),X._intervalHandle=void 0;return X.status="deleted",this.scheduleCleanup(X),this.toPublicTimer(X)}getAllTimers(Q=!1){let X=Array.from(this.timers.values());return(Q?X:X.filter((W)=>W.status==="active")).map((W)=>this.toPublicTimer(W))}getActiveTimers(){return Array.from(this.timers.values()).filter((Q)=>Q.status==="active").map((Q)=>this.toPublicTimer(Q))}getAndClearExpired(){let Q=[...this.expiredBuffer];return this.expiredBuffer.length=0,Q}hasExpired(){return this.expiredBuffer.length>0}shutdown(){for(let Q of this.timers.values()){if(Q._timeoutHandle)clearTimeout(Q._timeoutHandle);if(Q._intervalHandle)clearInterval(Q._intervalHandle)}this.timers.clear(),this.expiredBuffer.length=0}expireTimer(Q){let X=this.timers.get(Q);if(!X?.status||X.status!=="active")return;X.status="expired",X._timeoutHandle=void 0,X.fireCount++,this.expiredBuffer.push({id:X.id,message:X.message,expiredAt:new Date().toISOString()}),this.eventSystem.addEvent("timer_expired","emceepee",{timerId:X.id,message:X.message}),this.scheduleCleanup(X)}fireIntervalTimer(Q){let X=this.timers.get(Q);if(!X?.status||X.status!=="active")return;X.fireCount++,X.expiresAt=new Date(Date.now()+X.durationMs),this.expiredBuffer.push({id:X.id,message:X.message,expiredAt:new Date().toISOString()}),this.eventSystem.addEvent("timer_expired","emceepee",{timerId:X.id,message:X.message,fireCount:X.fireCount,interval:!0})}scheduleCleanup(Q){setTimeout(()=>{this.timers.delete(Q.id)},this.config.retentionMs)}toPublicTimer(Q){return{id:Q.id,durationMs:Q.durationMs,message:Q.message,createdAt:Q.createdAt,expiresAt:Q.expiresAt,status:Q.status,interval:Q.interval,fireCount:Q.fireCount}}}class tJ{sessionId;createdAt;lastActivityAt;backendConnections=new Map;eventSystem;taskManager;pendingRequests;bufferManager;timerManager;logger;constructor(Q,X={},Y){this.sessionId=Q,this.createdAt=new Date,this.lastActivityAt=new Date,this.logger=Y,this.eventSystem=new dJ(X.eventSystemConfig,Y),this.taskManager=new iJ(this.eventSystem,X.taskConfig),this.pendingRequests=new oJ(this.eventSystem,X.requestConfig),this.bufferManager=new nJ(this.eventSystem,X.bufferConfig),this.timerManager=new rJ(this.eventSystem,X.timerConfig)}touch(){this.lastActivityAt=new Date}getConnection(Q){return this.backendConnections.get(Q)}isConnectedTo(Q){return this.backendConnections.get(Q)?.status==="connected"}listConnectedServers(){return Array.from(this.backendConnections.entries()).filter(([,Q])=>Q.status==="connected").map(([Q])=>Q)}listConnections(){return Array.from(this.backendConnections.entries()).map(([Q,X])=>({name:Q,status:X.status,connectedAt:X.connectedAt,lastError:X.lastError}))}setConnectionStatus(Q,X,Y){let W=this.backendConnections.get(Q);if(W){if(W.status=X,X==="connected")W.connectedAt=new Date,W.lastError=void 0;else if(X==="error"&&Y)W.lastError=Y}}addConnection(Q,X){this.backendConnections.set(Q,{client:X,status:"connecting"})}removeConnection(Q){return this.backendConnections.delete(Q)}async cleanup(){this.logger?.info("session_cleanup_start",{sessionId:this.sessionId}),this.pendingRequests.shutdown(),this.taskManager.shutdown(),this.timerManager.shutdown(),this.eventSystem.shutdown();for(let[Q,X]of this.backendConnections)try{await X.client.disconnect(),this.logger?.debug("session_backend_disconnected",{sessionId:this.sessionId,server:Q})}catch(Y){this.logger?.debug("session_backend_disconnect_error",{sessionId:this.sessionId,server:Q,error:Y instanceof Error?Y.message:String(Y)})}this.backendConnections.clear(),this.logger?.info("session_cleanup_complete",{sessionId:this.sessionId})}}class aJ{constructor(Q){this._client=Q}async*callToolStream(Q,X=b6,Y){let W=this._client,$={...Y,task:Y?.task??(W.isToolTask(Q.name)?{}:void 0)},J=W.requestStream({method:"tools/call",params:Q},X,$),G=W.getToolOutputValidator(Q.name);for await(let H of J){if(H.type==="result"&&G){let B=H.result;if(!B.structuredContent&&!B.isError){yield{type:"error",error:new I(k.InvalidRequest,`Tool ${Q.name} has an output schema but did not return structured content`)};return}if(B.structuredContent)try{let z=G(B.structuredContent);if(!z.valid){yield{type:"error",error:new I(k.InvalidParams,`Structured content does not match the tool's output schema: ${z.errorMessage}`)};return}}catch(z){if(z instanceof I){yield{type:"error",error:z};return}yield{type:"error",error:new I(k.InvalidParams,`Failed to validate structured content: ${z instanceof Error?z.message:String(z)}`)};return}}yield H}}async getTask(Q,X){return this._client.getTask({taskId:Q},X)}async getTaskResult(Q,X,Y){return this._client.getTaskResult({taskId:Q},X,Y)}async listTasks(Q,X){return this._client.listTasks(Q?{cursor:Q}:void 0,X)}async cancelTask(Q,X){return this._client.cancelTask({taskId:Q},X)}requestStream(Q,X,Y){return this._client.requestStream(Q,X,Y)}}function TY(Q,X){if(!Q||X===null||typeof X!=="object")return;if(Q.type==="object"&&Q.properties&&typeof Q.properties==="object"){let Y=X,W=Q.properties;for(let $ of Object.keys(W)){let J=W[$];if(Y[$]===void 0&&Object.prototype.hasOwnProperty.call(J,"default"))Y[$]=J.default;if(Y[$]!==void 0)TY(J,Y[$])}}if(Array.isArray(Q.anyOf)){for(let Y of Q.anyOf)if(typeof Y!=="boolean")TY(Y,X)}if(Array.isArray(Q.oneOf)){for(let Y of Q.oneOf)if(typeof Y!=="boolean")TY(Y,X)}}function _g(Q){if(!Q)return{supportsFormMode:!1,supportsUrlMode:!1};let X=Q.form!==void 0,Y=Q.url!==void 0;return{supportsFormMode:X||!X&&!Y,supportsUrlMode:Y}}class N8 extends G4{constructor(Q,X){super(X);if(this._clientInfo=Q,this._cachedToolOutputValidators=new Map,this._cachedKnownTaskTools=new Set,this._cachedRequiredTaskTools=new Set,this._listChangedDebounceTimers=new Map,this._capabilities=X?.capabilities??{},this._jsonSchemaValidator=X?.jsonSchemaValidator??new s4,X?.listChanged)this._pendingListChangedConfig=X.listChanged}_setupListChangedHandlers(Q){if(Q.tools&&this._serverCapabilities?.tools?.listChanged)this._setupListChangedHandler("tools",W9,Q.tools,async()=>{return(await this.listTools()).tools});if(Q.prompts&&this._serverCapabilities?.prompts?.listChanged)this._setupListChangedHandler("prompts",Y9,Q.prompts,async()=>{return(await this.listPrompts()).prompts});if(Q.resources&&this._serverCapabilities?.resources?.listChanged)this._setupListChangedHandler("resources",X9,Q.resources,async()=>{return(await this.listResources()).resources})}get experimental(){if(!this._experimental)this._experimental={tasks:new aJ(this)};return this._experimental}registerCapabilities(Q){if(this.transport)throw Error("Cannot register capabilities after connecting to transport");this._capabilities=JX(this._capabilities,Q)}setRequestHandler(Q,X){let W=c1(Q)?.method;if(!W)throw Error("Schema is missing a method literal");let $;if(e0(W)){let G=W;$=G._zod?.def?.value??G.value}else{let G=W;$=G._def?.value??G.value}if(typeof $!=="string")throw Error("Schema method literal must be a string");let J=$;if(J==="elicitation/create"){let G=async(H,B)=>{let z=c0(J9,H);if(!z.success){let U=z.error instanceof Error?z.error.message:String(z.error);throw new I(k.InvalidParams,`Invalid elicitation request: ${U}`)}let{params:K}=z.data;K.mode=K.mode??"form";let{supportsFormMode:V,supportsUrlMode:A}=_g(this._capabilities.elicitation);if(K.mode==="form"&&!V)throw new I(k.InvalidParams,"Client does not support form-mode elicitation requests");if(K.mode==="url"&&!A)throw new I(k.InvalidParams,"Client does not support URL-mode elicitation requests");let F=await Promise.resolve(X(H,B));if(K.task){let U=c0(W6,F);if(!U.success){let w=U.error instanceof Error?U.error.message:String(U.error);throw new I(k.InvalidParams,`Invalid task creation result: ${w}`)}return U.data}let L=c0(n9,F);if(!L.success){let U=L.error instanceof Error?L.error.message:String(L.error);throw new I(k.InvalidParams,`Invalid elicitation result: ${U}`)}let D=L.data,O=K.mode==="form"?K.requestedSchema:void 0;if(K.mode==="form"&&D.action==="accept"&&D.content&&O){if(this._capabilities.elicitation?.form?.applyDefaults)try{TY(O,D.content)}catch{}}return D};return super.setRequestHandler(Q,G)}if(J==="sampling/createMessage"){let G=async(H,B)=>{let z=c0($9,H);if(!z.success){let F=z.error instanceof Error?z.error.message:String(z.error);throw new I(k.InvalidParams,`Invalid sampling request: ${F}`)}let{params:K}=z.data,V=await Promise.resolve(X(H,B));if(K.task){let F=c0(W6,V);if(!F.success){let L=F.error instanceof Error?F.error.message:String(F.error);throw new I(k.InvalidParams,`Invalid task creation result: ${L}`)}return F.data}let A=c0($4,V);if(!A.success){let F=A.error instanceof Error?A.error.message:String(A.error);throw new I(k.InvalidParams,`Invalid sampling result: ${F}`)}return A.data};return super.setRequestHandler(Q,G)}return super.setRequestHandler(Q,X)}assertCapability(Q,X){if(!this._serverCapabilities?.[Q])throw Error(`Server does not support ${Q} (required for ${X})`)}async connect(Q,X){if(await super.connect(Q),Q.sessionId!==void 0)return;try{let Y=await this.request({method:"initialize",params:{protocolVersion:w6,capabilities:this._capabilities,clientInfo:this._clientInfo}},D5,X);if(Y===void 0)throw Error(`Server sent invalid initialize result: ${Y}`);if(!Q9.includes(Y.protocolVersion))throw Error(`Server's protocol version is not supported: ${Y.protocolVersion}`);if(this._serverCapabilities=Y.capabilities,this._serverVersion=Y.serverInfo,Q.setProtocolVersion)Q.setProtocolVersion(Y.protocolVersion);if(this._instructions=Y.instructions,await this.notification({method:"notifications/initialized"}),this._pendingListChangedConfig)this._setupListChangedHandlers(this._pendingListChangedConfig),this._pendingListChangedConfig=void 0}catch(Y){throw this.close(),Y}}getServerCapabilities(){return this._serverCapabilities}getServerVersion(){return this._serverVersion}getInstructions(){return this._instructions}assertCapabilityForMethod(Q){switch(Q){case"logging/setLevel":if(!this._serverCapabilities?.logging)throw Error(`Server does not support logging (required for ${Q})`);break;case"prompts/get":case"prompts/list":if(!this._serverCapabilities?.prompts)throw Error(`Server does not support prompts (required for ${Q})`);break;case"resources/list":case"resources/templates/list":case"resources/read":case"resources/subscribe":case"resources/unsubscribe":if(!this._serverCapabilities?.resources)throw Error(`Server does not support resources (required for ${Q})`);if(Q==="resources/subscribe"&&!this._serverCapabilities.resources.subscribe)throw Error(`Server does not support resource subscriptions (required for ${Q})`);break;case"tools/call":case"tools/list":if(!this._serverCapabilities?.tools)throw Error(`Server does not support tools (required for ${Q})`);break;case"completion/complete":if(!this._serverCapabilities?.completions)throw Error(`Server does not support completions (required for ${Q})`);break;case"initialize":break;case"ping":break}}assertNotificationCapability(Q){switch(Q){case"notifications/roots/list_changed":if(!this._capabilities.roots?.listChanged)throw Error(`Client does not support roots list changed notifications (required for ${Q})`);break;case"notifications/initialized":break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(Q){if(!this._capabilities)return;switch(Q){case"sampling/createMessage":if(!this._capabilities.sampling)throw Error(`Client does not support sampling capability (required for ${Q})`);break;case"elicitation/create":if(!this._capabilities.elicitation)throw Error(`Client does not support elicitation capability (required for ${Q})`);break;case"roots/list":if(!this._capabilities.roots)throw Error(`Client does not support roots capability (required for ${Q})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw Error(`Client does not support tasks capability (required for ${Q})`);break;case"ping":break}}assertTaskCapability(Q){bY(this._serverCapabilities?.tasks?.requests,Q,"Server")}assertTaskHandlerCapability(Q){if(!this._capabilities)return;PY(this._capabilities.tasks?.requests,Q,"Client")}async ping(Q){return this.request({method:"ping"},Y6,Q)}async complete(Q,X){return this.request({method:"completion/complete",params:Q},I5,X)}async setLoggingLevel(Q,X){return this.request({method:"logging/setLevel",params:{level:Q}},Y6,X)}async getPrompt(Q,X){return this.request({method:"prompts/get",params:Q},Z5,X)}async listPrompts(Q,X){return this.request({method:"prompts/list",params:Q},q5,X)}async listResources(Q,X){return this.request({method:"resources/list",params:Q},O5,X)}async listResourceTemplates(Q,X){return this.request({method:"resources/templates/list",params:Q},U5,X)}async readResource(Q,X){return this.request({method:"resources/read",params:Q},N5,X)}async subscribeResource(Q,X){return this.request({method:"resources/subscribe",params:Q},Y6,X)}async unsubscribeResource(Q,X){return this.request({method:"resources/unsubscribe",params:Q},Y6,X)}async callTool(Q,X=b6,Y){if(this.isToolTaskRequired(Q.name))throw new I(k.InvalidRequest,`Tool "${Q.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);let W=await this.request({method:"tools/call",params:Q},X,Y),$=this.getToolOutputValidator(Q.name);if($){if(!W.structuredContent&&!W.isError)throw new I(k.InvalidRequest,`Tool ${Q.name} has an output schema but did not return structured content`);if(W.structuredContent)try{let J=$(W.structuredContent);if(!J.valid)throw new I(k.InvalidParams,`Structured content does not match the tool's output schema: ${J.errorMessage}`)}catch(J){if(J instanceof I)throw J;throw new I(k.InvalidParams,`Failed to validate structured content: ${J instanceof Error?J.message:String(J)}`)}}return W}isToolTask(Q){if(!this._serverCapabilities?.tasks?.requests?.tools?.call)return!1;return this._cachedKnownTaskTools.has(Q)}isToolTaskRequired(Q){return this._cachedRequiredTaskTools.has(Q)}cacheToolMetadata(Q){this._cachedToolOutputValidators.clear(),this._cachedKnownTaskTools.clear(),this._cachedRequiredTaskTools.clear();for(let X of Q){if(X.outputSchema){let W=this._jsonSchemaValidator.getValidator(X.outputSchema);this._cachedToolOutputValidators.set(X.name,W)}let Y=X.execution?.taskSupport;if(Y==="required"||Y==="optional")this._cachedKnownTaskTools.add(X.name);if(Y==="required")this._cachedRequiredTaskTools.add(X.name)}}getToolOutputValidator(Q){return this._cachedToolOutputValidators.get(Q)}async listTools(Q,X){let Y=await this.request({method:"tools/list",params:Q},R5,X);return this.cacheToolMetadata(Y.tools),Y}_setupListChangedHandler(Q,X,Y,W){let $=a3.safeParse(Y);if(!$.success)throw Error(`Invalid ${Q} listChanged options: ${$.error.message}`);if(typeof Y.onChanged!=="function")throw Error(`Invalid ${Q} listChanged options: onChanged must be a function`);let{autoRefresh:J,debounceMs:G}=$.data,{onChanged:H}=Y,B=async()=>{if(!J){H(null,null);return}try{let K=await W();H(null,K)}catch(K){let V=K instanceof Error?K:Error(String(K));H(V,null)}},z=()=>{if(G){let K=this._listChangedDebounceTimers.get(Q);if(K)clearTimeout(K);let V=setTimeout(B,G);this._listChangedDebounceTimers.set(Q,V)}else B()};this.setNotificationHandler(X,z)}async sendRootsListChanged(){return this.notification({method:"notifications/roots/list_changed"})}}function CY(Q){if(!Q)return{};if(Q instanceof Headers)return Object.fromEntries(Q.entries());if(Array.isArray(Q))return Object.fromEntries(Q);return{...Q}}function CU(Q=fetch,X){if(!X)return Q;return async(Y,W)=>{let $={...X,...W,headers:W?.headers?{...CY(X.headers),...CY(W.headers)}:X.headers};return Q(Y,$)}}var sJ;sJ=globalThis.crypto?.webcrypto??globalThis.crypto??import("node:crypto").then((Q)=>Q.webcrypto);async function xg(Q){return(await sJ).getRandomValues(new Uint8Array(Q))}async function yg(Q){let Y=Math.pow(2,8)-Math.pow(2,8)%66,W="";while(W.length<Q){let $=await xg(Q-W.length);for(let J of $)if(J<Y)W+="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"[J%66]}return W}async function fg(Q){return await yg(Q)}async function gg(Q){let X=await(await sJ).subtle.digest("SHA-256",new TextEncoder().encode(Q));return btoa(String.fromCharCode(...new Uint8Array(X))).replace(/\//g,"_").replace(/\+/g,"-").replace(/=/g,"")}async function eJ(Q){if(!Q)Q=43;if(Q<43||Q>128)throw`Expected a length between 43 and 128. Received ${Q}.`;let X=await fg(Q),Y=await gg(X);return{code_verifier:X,code_challenge:Y}}var h0=P3().superRefine((Q,X)=>{if(!URL.canParse(Q))return X.addIssue({code:x3.custom,message:"URL must be parseable",fatal:!0}),KQ}).refine((Q)=>{let X=new URL(Q);return X.protocol!=="javascript:"&&X.protocol!=="data:"&&X.protocol!=="vbscript:"},{message:"URL cannot use javascript:, data:, or vbscript: scheme"}),vU=C0({resource:j().url(),authorization_servers:E(h0).optional(),jwks_uri:j().url().optional(),scopes_supported:E(j()).optional(),bearer_methods_supported:E(j()).optional(),resource_signing_alg_values_supported:E(j()).optional(),resource_name:j().optional(),resource_documentation:j().optional(),resource_policy_uri:j().url().optional(),resource_tos_uri:j().url().optional(),tls_client_certificate_bound_access_tokens:B0().optional(),authorization_details_types_supported:E(j()).optional(),dpop_signing_alg_values_supported:E(j()).optional(),dpop_bound_access_tokens_required:B0().optional()}),QG=C0({issuer:j(),authorization_endpoint:h0,token_endpoint:h0,registration_endpoint:h0.optional(),scopes_supported:E(j()).optional(),response_types_supported:E(j()),response_modes_supported:E(j()).optional(),grant_types_supported:E(j()).optional(),token_endpoint_auth_methods_supported:E(j()).optional(),token_endpoint_auth_signing_alg_values_supported:E(j()).optional(),service_documentation:h0.optional(),revocation_endpoint:h0.optional(),revocation_endpoint_auth_methods_supported:E(j()).optional(),revocation_endpoint_auth_signing_alg_values_supported:E(j()).optional(),introspection_endpoint:j().optional(),introspection_endpoint_auth_methods_supported:E(j()).optional(),introspection_endpoint_auth_signing_alg_values_supported:E(j()).optional(),code_challenge_methods_supported:E(j()).optional(),client_id_metadata_document_supported:B0().optional()}),hg=C0({issuer:j(),authorization_endpoint:h0,token_endpoint:h0,userinfo_endpoint:h0.optional(),jwks_uri:h0,registration_endpoint:h0.optional(),scopes_supported:E(j()).optional(),response_types_supported:E(j()),response_modes_supported:E(j()).optional(),grant_types_supported:E(j()).optional(),acr_values_supported:E(j()).optional(),subject_types_supported:E(j()),id_token_signing_alg_values_supported:E(j()),id_token_encryption_alg_values_supported:E(j()).optional(),id_token_encryption_enc_values_supported:E(j()).optional(),userinfo_signing_alg_values_supported:E(j()).optional(),userinfo_encryption_alg_values_supported:E(j()).optional(),userinfo_encryption_enc_values_supported:E(j()).optional(),request_object_signing_alg_values_supported:E(j()).optional(),request_object_encryption_alg_values_supported:E(j()).optional(),request_object_encryption_enc_values_supported:E(j()).optional(),token_endpoint_auth_methods_supported:E(j()).optional(),token_endpoint_auth_signing_alg_values_supported:E(j()).optional(),display_values_supported:E(j()).optional(),claim_types_supported:E(j()).optional(),claims_supported:E(j()).optional(),service_documentation:j().optional(),claims_locales_supported:E(j()).optional(),ui_locales_supported:E(j()).optional(),claims_parameter_supported:B0().optional(),request_parameter_supported:B0().optional(),request_uri_parameter_supported:B0().optional(),require_request_uri_registration:B0().optional(),op_policy_uri:h0.optional(),op_tos_uri:h0.optional(),client_id_metadata_document_supported:B0().optional()}),_U=T({...hg.shape,...QG.pick({code_challenge_methods_supported:!0}).shape}),xU=T({access_token:j(),id_token:j().optional(),token_type:j(),expires_in:vQ.number().optional(),scope:j().optional(),refresh_token:j().optional()}).strip(),yU=T({error:j(),error_description:j().optional(),error_uri:j().optional()}),kU=h0.optional().or(x("").transform(()=>{return})),ug=T({redirect_uris:E(h0),token_endpoint_auth_method:j().optional(),grant_types:E(j()).optional(),response_types:E(j()).optional(),client_name:j().optional(),client_uri:h0.optional(),logo_uri:kU,scope:j().optional(),contacts:E(j()).optional(),tos_uri:kU,policy_uri:j().optional(),jwks_uri:h0.optional(),jwks:R3().optional(),software_id:j().optional(),software_version:j().optional(),software_statement:j().optional()}).strip(),lg=T({client_id:j(),client_secret:j().optional(),client_id_issued_at:J0().optional(),client_secret_expires_at:J0().optional()}).strip(),fU=ug.merge(lg),cr=T({error:j(),error_description:j().optional()}).strip(),pr=T({token:j(),token_type_hint:j().optional()}).strip();function gU(Q){let X=typeof Q==="string"?new URL(Q):new URL(Q.href);return X.hash="",X}function hU({requestedResource:Q,configuredResource:X}){let Y=typeof Q==="string"?new URL(Q):new URL(Q.href),W=typeof X==="string"?new URL(X):new URL(X.href);if(Y.origin!==W.origin)return!1;if(Y.pathname.length<W.pathname.length)return!1;let $=Y.pathname.endsWith("/")?Y.pathname:Y.pathname+"/",J=W.pathname.endsWith("/")?W.pathname:W.pathname+"/";return $.startsWith(J)}class S0 extends Error{constructor(Q,X){super(Q);this.errorUri=X,this.name=this.constructor.name}toResponseObject(){let Q={error:this.errorCode,error_description:this.message};if(this.errorUri)Q.error_uri=this.errorUri;return Q}get errorCode(){return this.constructor.errorCode}}class kY extends S0{}kY.errorCode="invalid_request";class q8 extends S0{}q8.errorCode="invalid_client";class w8 extends S0{}w8.errorCode="invalid_grant";class M8 extends S0{}M8.errorCode="unauthorized_client";class vY extends S0{}vY.errorCode="unsupported_grant_type";class _Y extends S0{}_Y.errorCode="invalid_scope";class xY extends S0{}xY.errorCode="access_denied";class h6 extends S0{}h6.errorCode="server_error";class yY extends S0{}yY.errorCode="temporarily_unavailable";class fY extends S0{}fY.errorCode="unsupported_response_type";class gY extends S0{}gY.errorCode="unsupported_token_type";class hY extends S0{}hY.errorCode="invalid_token";class uY extends S0{}uY.errorCode="method_not_allowed";class lY extends S0{}lY.errorCode="too_many_requests";class b8 extends S0{}b8.errorCode="invalid_client_metadata";class mY extends S0{}mY.errorCode="insufficient_scope";class cY extends S0{}cY.errorCode="invalid_target";var uU={[kY.errorCode]:kY,[q8.errorCode]:q8,[w8.errorCode]:w8,[M8.errorCode]:M8,[vY.errorCode]:vY,[_Y.errorCode]:_Y,[xY.errorCode]:xY,[h6.errorCode]:h6,[yY.errorCode]:yY,[fY.errorCode]:fY,[gY.errorCode]:gY,[hY.errorCode]:hY,[uY.errorCode]:uY,[lY.errorCode]:lY,[b8.errorCode]:b8,[mY.errorCode]:mY,[cY.errorCode]:cY};class u6 extends Error{constructor(Q){super(Q??"Unauthorized")}}function mg(Q){return["client_secret_basic","client_secret_post","none"].includes(Q)}var XG="code",YG="S256";function cg(Q,X){let Y=Q.client_secret!==void 0;if(X.length===0)return Y?"client_secret_post":"none";if("token_endpoint_auth_method"in Q&&Q.token_endpoint_auth_method&&mg(Q.token_endpoint_auth_method)&&X.includes(Q.token_endpoint_auth_method))return Q.token_endpoint_auth_method;if(Y&&X.includes("client_secret_basic"))return"client_secret_basic";if(Y&&X.includes("client_secret_post"))return"client_secret_post";if(X.includes("none"))return"none";return Y?"client_secret_post":"none"}function pg(Q,X,Y,W){let{client_id:$,client_secret:J}=X;switch(Q){case"client_secret_basic":dg($,J,Y);return;case"client_secret_post":ig($,J,W);return;case"none":ng($,W);return;default:throw Error(`Unsupported client authentication method: ${Q}`)}}function dg(Q,X,Y){if(!X)throw Error("client_secret_basic authentication requires a client_secret");let W=btoa(`${Q}:${X}`);Y.set("Authorization",`Basic ${W}`)}function ig(Q,X,Y){if(Y.set("client_id",Q),X)Y.set("client_secret",X)}function ng(Q,X){X.set("client_id",Q)}async function mU(Q){let X=Q instanceof Response?Q.status:void 0,Y=Q instanceof Response?await Q.text():Q;try{let W=yU.parse(JSON.parse(Y)),{error:$,error_description:J,error_uri:G}=W;return new(uU[$]||h6)(J||"",G)}catch(W){let $=`${X?`HTTP ${X}: `:""}Invalid OAuth error response: ${W}. Raw body: ${Y}`;return new h6($)}}async function YQ(Q,X){try{return await WG(Q,X)}catch(Y){if(Y instanceof q8||Y instanceof M8)return await Q.invalidateCredentials?.("all"),await WG(Q,X);else if(Y instanceof w8)return await Q.invalidateCredentials?.("tokens"),await WG(Q,X);throw Y}}async function WG(Q,{serverUrl:X,authorizationCode:Y,scope:W,resourceMetadataUrl:$,fetchFn:J}){let G,H;try{if(G=await tg(X,{resourceMetadataUrl:$},J),G.authorization_servers&&G.authorization_servers.length>0)H=G.authorization_servers[0]}catch{}if(!H)H=new URL("/",X);let B=await rg(X,Q,G),z=await Xh(H,{fetchFn:J}),K=await Promise.resolve(Q.clientInformation());if(!K){if(Y!==void 0)throw Error("Existing OAuth client information is required when exchanging an authorization code");let O=z?.client_id_metadata_document_supported===!0,U=Q.clientMetadataUrl;if(U&&!og(U))throw new b8(`clientMetadataUrl must be a valid HTTPS URL with a non-root pathname, got: ${U}`);if(O&&U)K={client_id:U},await Q.saveClientInformation?.(K);else{if(!Q.saveClientInformation)throw Error("OAuth client information must be saveable for dynamic registration");let M=await Gh(H,{metadata:z,clientMetadata:Q.clientMetadata,fetchFn:J});await Q.saveClientInformation(M),K=M}}let V=!Q.redirectUrl;if(Y!==void 0||V){let O=await Jh(Q,H,{metadata:z,resource:B,authorizationCode:Y,fetchFn:J});return await Q.saveTokens(O),"AUTHORIZED"}let A=await Q.tokens();if(A?.refresh_token)try{let O=await $h(H,{metadata:z,clientInformation:K,refreshToken:A.refresh_token,resource:B,addClientAuthentication:Q.addClientAuthentication,fetchFn:J});return await Q.saveTokens(O),"AUTHORIZED"}catch(O){if(!(O instanceof S0)||O instanceof h6);else throw O}let F=Q.state?await Q.state():void 0,{authorizationUrl:L,codeVerifier:D}=await Yh(H,{metadata:z,clientInformation:K,state:F,redirectUrl:Q.redirectUrl,scope:W||G?.scopes_supported?.join(" ")||Q.clientMetadata.scope,resource:B});return await Q.saveCodeVerifier(D),await Q.redirectToAuthorization(L),"REDIRECT"}function og(Q){if(!Q)return!1;try{let X=new URL(Q);return X.protocol==="https:"&&X.pathname!=="/"}catch{return!1}}async function rg(Q,X,Y){let W=gU(Q);if(X.validateResourceURL)return await X.validateResourceURL(W,Y?.resource);if(!Y)return;if(!hU({requestedResource:W,configuredResource:Y.resource}))throw Error(`Protected resource ${Y.resource} does not match expected ${W} (or origin)`);return new URL(Y.resource)}function JG(Q){let X=Q.headers.get("WWW-Authenticate");if(!X)return{};let[Y,W]=X.split(" ");if(Y.toLowerCase()!=="bearer"||!W)return{};let $=$G(Q,"resource_metadata")||void 0,J;if($)try{J=new URL($)}catch{}let G=$G(Q,"scope")||void 0,H=$G(Q,"error")||void 0;return{resourceMetadataUrl:J,scope:G,error:H}}function $G(Q,X){let Y=Q.headers.get("WWW-Authenticate");if(!Y)return null;let W=new RegExp(`${X}=(?:"([^"]+)"|([^\\s,]+))`),$=Y.match(W);if($)return $[1]||$[2];return null}async function tg(Q,X,Y=fetch){let W=await eg(Q,"oauth-protected-resource",Y,{protocolVersion:X?.protocolVersion,metadataUrl:X?.resourceMetadataUrl});if(!W||W.status===404)throw await W?.body?.cancel(),Error("Resource server does not implement OAuth 2.0 Protected Resource Metadata.");if(!W.ok)throw await W.body?.cancel(),Error(`HTTP ${W.status} trying to load well-known OAuth protected resource metadata.`);return vU.parse(await W.json())}async function GG(Q,X,Y=fetch){try{return await Y(Q,{headers:X})}catch(W){if(W instanceof TypeError)if(X)return GG(Q,void 0,Y);else return;throw W}}function ag(Q,X="",Y={}){if(X.endsWith("/"))X=X.slice(0,-1);return Y.prependPathname?`${X}/.well-known/${Q}`:`/.well-known/${Q}${X}`}async function lU(Q,X,Y=fetch){return await GG(Q,{"MCP-Protocol-Version":X},Y)}function sg(Q,X){return!Q||Q.status>=400&&Q.status<500&&X!=="/"}async function eg(Q,X,Y,W){let $=new URL(Q),J=W?.protocolVersion??w6,G;if(W?.metadataUrl)G=new URL(W.metadataUrl);else{let B=ag(X,$.pathname);G=new URL(B,W?.metadataServerUrl??$),G.search=$.search}let H=await lU(G,J,Y);if(!W?.metadataUrl&&sg(H,$.pathname)){let B=new URL(`/.well-known/${X}`,$);H=await lU(B,J,Y)}return H}function Qh(Q){let X=typeof Q==="string"?new URL(Q):Q,Y=X.pathname!=="/",W=[];if(!Y)return W.push({url:new URL("/.well-known/oauth-authorization-server",X.origin),type:"oauth"}),W.push({url:new URL("/.well-known/openid-configuration",X.origin),type:"oidc"}),W;let $=X.pathname;if($.endsWith("/"))$=$.slice(0,-1);return W.push({url:new URL(`/.well-known/oauth-authorization-server${$}`,X.origin),type:"oauth"}),W.push({url:new URL(`/.well-known/openid-configuration${$}`,X.origin),type:"oidc"}),W.push({url:new URL(`${$}/.well-known/openid-configuration`,X.origin),type:"oidc"}),W}async function Xh(Q,{fetchFn:X=fetch,protocolVersion:Y=w6}={}){let W={"MCP-Protocol-Version":Y,Accept:"application/json"},$=Qh(Q);for(let{url:J,type:G}of $){let H=await GG(J,W,X);if(!H)continue;if(!H.ok){if(await H.body?.cancel(),H.status>=400&&H.status<500)continue;throw Error(`HTTP ${H.status} trying to load ${G==="oauth"?"OAuth":"OpenID provider"} metadata from ${J}`)}if(G==="oauth")return QG.parse(await H.json());else return _U.parse(await H.json())}return}async function Yh(Q,{metadata:X,clientInformation:Y,redirectUrl:W,scope:$,state:J,resource:G}){let H;if(X){if(H=new URL(X.authorization_endpoint),!X.response_types_supported.includes(XG))throw Error(`Incompatible auth server: does not support response type ${XG}`);if(X.code_challenge_methods_supported&&!X.code_challenge_methods_supported.includes(YG))throw Error(`Incompatible auth server: does not support code challenge method ${YG}`)}else H=new URL("/authorize",Q);let B=await eJ(),z=B.code_verifier,K=B.code_challenge;if(H.searchParams.set("response_type",XG),H.searchParams.set("client_id",Y.client_id),H.searchParams.set("code_challenge",K),H.searchParams.set("code_challenge_method",YG),H.searchParams.set("redirect_uri",String(W)),J)H.searchParams.set("state",J);if($)H.searchParams.set("scope",$);if($?.includes("offline_access"))H.searchParams.append("prompt","consent");if(G)H.searchParams.set("resource",G.href);return{authorizationUrl:H,codeVerifier:z}}function Wh(Q,X,Y){return new URLSearchParams({grant_type:"authorization_code",code:Q,code_verifier:X,redirect_uri:String(Y)})}async function cU(Q,{metadata:X,tokenRequestParams:Y,clientInformation:W,addClientAuthentication:$,resource:J,fetchFn:G}){let H=X?.token_endpoint?new URL(X.token_endpoint):new URL("/token",Q),B=new Headers({"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"});if(J)Y.set("resource",J.href);if($)await $(B,Y,H,X);else if(W){let K=X?.token_endpoint_auth_methods_supported??[],V=cg(W,K);pg(V,W,B,Y)}let z=await(G??fetch)(H,{method:"POST",headers:B,body:Y});if(!z.ok)throw await mU(z);return xU.parse(await z.json())}async function $h(Q,{metadata:X,clientInformation:Y,refreshToken:W,resource:$,addClientAuthentication:J,fetchFn:G}){let H=new URLSearchParams({grant_type:"refresh_token",refresh_token:W}),B=await cU(Q,{metadata:X,tokenRequestParams:H,clientInformation:Y,addClientAuthentication:J,resource:$,fetchFn:G});return{refresh_token:W,...B}}async function Jh(Q,X,{metadata:Y,resource:W,authorizationCode:$,fetchFn:J}={}){let G=Q.clientMetadata.scope,H;if(Q.prepareTokenRequest)H=await Q.prepareTokenRequest(G);if(!H){if(!$)throw Error("Either provider.prepareTokenRequest() or authorizationCode is required");if(!Q.redirectUrl)throw Error("redirectUrl is required for authorization_code flow");let z=await Q.codeVerifier();H=Wh($,z,Q.redirectUrl)}let B=await Q.clientInformation();return cU(X,{metadata:Y,tokenRequestParams:H,clientInformation:B??void 0,addClientAuthentication:Q.addClientAuthentication,resource:W,fetchFn:J})}async function Gh(Q,{metadata:X,clientMetadata:Y,fetchFn:W}){let $;if(X){if(!X.registration_endpoint)throw Error("Incompatible auth server: does not support dynamic client registration");$=new URL(X.registration_endpoint)}else $=new URL("/register",Q);let J=await(W??fetch)($,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Y)});if(!J.ok)throw await mU(J);return fU.parse(await J.json())}class BG extends Error{constructor(Q,X){super(Q),this.name="ParseError",this.type=X.type,this.field=X.field,this.value=X.value,this.line=X.line}}function HG(Q){}function pU(Q){if(typeof Q=="function")throw TypeError("`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?");let{onEvent:X=HG,onError:Y=HG,onRetry:W=HG,onComment:$}=Q,J="",G=!0,H,B="",z="";function K(D){let O=G?D.replace(/^\xEF\xBB\xBF/,""):D,[U,w]=Hh(`${J}${O}`);for(let M of U)V(M);J=w,G=!1}function V(D){if(D===""){F();return}if(D.startsWith(":")){$&&$(D.slice(D.startsWith(": ")?2:1));return}let O=D.indexOf(":");if(O!==-1){let U=D.slice(0,O),w=D[O+1]===" "?2:1,M=D.slice(O+w);A(U,M,D);return}A(D,"",D)}function A(D,O,U){switch(D){case"event":z=O;break;case"data":B=`${B}${O}
|
|
58
|
+
`,Q.enqueue(X.encode($)),!0}catch{return!1}}handleUnsupportedRequest(){return new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32000,message:"Method not allowed."},id:null}),{status:405,headers:{Allow:"GET, POST, DELETE","Content-Type":"application/json"}})}async handlePostRequest(Q,X){try{let Y=Q.headers.get("accept");if(!Y?.includes("application/json")||!Y.includes("text/event-stream"))return this.createJsonErrorResponse(406,-32000,"Not Acceptable: Client must accept both application/json and text/event-stream");let W=Q.headers.get("content-type");if(!W||!W.includes("application/json"))return this.createJsonErrorResponse(415,-32000,"Unsupported Media Type: Content-Type must be application/json");let $={headers:Object.fromEntries(Q.headers.entries())},J;if(X?.parsedBody!==void 0)J=X.parsedBody;else try{J=await Q.json()}catch{return this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON")}let G;try{if(Array.isArray(J))G=J.map((O)=>X6.parse(O));else G=[X6.parse(J)]}catch{return this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON-RPC message")}let H=G.some(F5);if(H){if(this._initialized&&this.sessionId!==void 0)return this.createJsonErrorResponse(400,-32600,"Invalid Request: Server already initialized");if(G.length>1)return this.createJsonErrorResponse(400,-32600,"Invalid Request: Only one initialization request is allowed");if(this.sessionId=this.sessionIdGenerator?.(),this._initialized=!0,this.sessionId&&this._onsessioninitialized)await Promise.resolve(this._onsessioninitialized(this.sessionId))}if(!H){let O=this.validateSession(Q);if(O)return O;let U=this.validateProtocolVersion(Q);if(U)return U}if(!G.some(p1)){for(let O of G)this.onmessage?.(O,{authInfo:X?.authInfo,requestInfo:$});return new Response(null,{status:202})}let z=crypto.randomUUID(),K=G.find((O)=>F5(O)),V=K?K.params.protocolVersion:Q.headers.get("mcp-protocol-version")??y3;if(this._enableJsonResponse)return new Promise((O)=>{this._streamMapping.set(z,{resolveJson:O,cleanup:()=>{this._streamMapping.delete(z)}});for(let U of G)if(p1(U))this._requestToStreamMapping.set(U.id,z);for(let U of G)this.onmessage?.(U,{authInfo:X?.authInfo,requestInfo:$})});let A=new TextEncoder,F,L=new ReadableStream({start:(O)=>{F=O},cancel:()=>{this._streamMapping.delete(z)}}),D={"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"};if(this.sessionId!==void 0)D["mcp-session-id"]=this.sessionId;for(let O of G)if(p1(O))this._streamMapping.set(z,{controller:F,encoder:A,cleanup:()=>{this._streamMapping.delete(z);try{F.close()}catch{}}}),this._requestToStreamMapping.set(O.id,z);await this.writePrimingEvent(F,A,z,V);for(let O of G){let U,w;if(p1(O)&&this._eventStore&&V>="2025-11-25")U=()=>{this.closeSSEStream(O.id)},w=()=>{this.closeStandaloneSSEStream()};this.onmessage?.(O,{authInfo:X?.authInfo,requestInfo:$,closeSSEStream:U,closeStandaloneSSEStream:w})}return new Response(L,{status:200,headers:D})}catch(Y){return this.onerror?.(Y),this.createJsonErrorResponse(400,-32700,"Parse error",{data:String(Y)})}}async handleDeleteRequest(Q){let X=this.validateSession(Q);if(X)return X;let Y=this.validateProtocolVersion(Q);if(Y)return Y;return await Promise.resolve(this._onsessionclosed?.(this.sessionId)),await this.close(),new Response(null,{status:200})}validateSession(Q){if(this.sessionIdGenerator===void 0)return;if(!this._initialized)return this.createJsonErrorResponse(400,-32000,"Bad Request: Server not initialized");let X=Q.headers.get("mcp-session-id");if(!X)return this.createJsonErrorResponse(400,-32000,"Bad Request: Mcp-Session-Id header is required");if(X!==this.sessionId)return this.createJsonErrorResponse(404,-32001,"Session not found");return}validateProtocolVersion(Q){let X=Q.headers.get("mcp-protocol-version");if(X!==null&&!Q9.includes(X))return this.createJsonErrorResponse(400,-32000,`Bad Request: Unsupported protocol version: ${X} (supported versions: ${Q9.join(", ")})`);return}async close(){this._streamMapping.forEach(({cleanup:Q})=>{Q()}),this._streamMapping.clear(),this._requestResponseMap.clear(),this.onclose?.()}closeSSEStream(Q){let X=this._requestToStreamMapping.get(Q);if(!X)return;let Y=this._streamMapping.get(X);if(Y)Y.cleanup()}closeStandaloneSSEStream(){let Q=this._streamMapping.get(this._standaloneSseStreamId);if(Q)Q.cleanup()}async send(Q,X){let Y=X?.relatedRequestId;if(P1(Q)||p9(Q))Y=Q.id;if(Y===void 0){if(P1(Q)||p9(Q))throw Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");let J;if(this._eventStore)J=await this._eventStore.storeEvent(this._standaloneSseStreamId,Q);let G=this._streamMapping.get(this._standaloneSseStreamId);if(G===void 0)return;if(G.controller&&G.encoder)this.writeSSEEvent(G.controller,G.encoder,Q,J);return}let W=this._requestToStreamMapping.get(Y);if(!W)throw Error(`No connection established for request ID: ${String(Y)}`);let $=this._streamMapping.get(W);if(!this._enableJsonResponse&&$?.controller&&$?.encoder){let J;if(this._eventStore)J=await this._eventStore.storeEvent(W,Q);this.writeSSEEvent($.controller,$.encoder,Q,J)}if(P1(Q)||p9(Q)){this._requestResponseMap.set(Y,Q);let J=Array.from(this._requestToStreamMapping.entries()).filter(([H,B])=>B===W).map(([H])=>H);if(J.every((H)=>this._requestResponseMap.has(H))){if(!$)throw Error(`No connection established for request ID: ${String(Y)}`);if(this._enableJsonResponse&&$.resolveJson){let H={"Content-Type":"application/json"};if(this.sessionId!==void 0)H["mcp-session-id"]=this.sessionId;let B=J.map((z)=>this._requestResponseMap.get(z));if(B.length===1)$.resolveJson(new Response(JSON.stringify(B[0]),{status:200,headers:H}));else $.resolveJson(new Response(JSON.stringify(B),{status:200,headers:H}))}else $.cleanup();for(let H of J)this._requestResponseMap.delete(H),this._requestToStreamMapping.delete(H)}}}}class lJ{constructor(Q={}){this._requestContext=new WeakMap,this._webStandardTransport=new uJ(Q),this._requestListener=hJ(async(X)=>{let Y=this._requestContext.get(X);return this._webStandardTransport.handleRequest(X,{authInfo:Y?.authInfo,parsedBody:Y?.parsedBody})})}get sessionId(){return this._webStandardTransport.sessionId}set onclose(Q){this._webStandardTransport.onclose=Q}get onclose(){return this._webStandardTransport.onclose}set onerror(Q){this._webStandardTransport.onerror=Q}get onerror(){return this._webStandardTransport.onerror}set onmessage(Q){this._webStandardTransport.onmessage=Q}get onmessage(){return this._webStandardTransport.onmessage}async start(){return this._webStandardTransport.start()}async close(){return this._webStandardTransport.close()}async send(Q,X){return this._webStandardTransport.send(Q,X)}async handleRequest(Q,X,Y){let W=Q.auth;await hJ(async(J)=>{return this._webStandardTransport.handleRequest(J,{authInfo:W,parsedBody:Y})})(Q,X)}closeSSEStream(Q){this._webStandardTransport.closeSSEStream(Q)}closeStandaloneSSEStream(){this._webStandardTransport.closeStandaloneSSEStream()}}import{createServer as Wu}from"http";import{readFileSync as $u}from"fs";import SY from"node:crypto";var IU="0123456789ABCDEFGHJKMNPQRSTVWXYZ",IY=32;var Mg=16,TU=10,SU=281474976710655;var q9;(function(Q){Q.Base32IncorrectEncoding="B32_ENC_INVALID",Q.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",Q.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",Q.EncodeTimeNegative="ENC_TIME_NEG",Q.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",Q.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",Q.PRNGDetectFailure="PRNG_DETECT",Q.ULIDInvalid="ULID_INVALID",Q.Unexpected="UNEXPECTED",Q.UUIDInvalid="UUID_INVALID"})(q9||(q9={}));class j8 extends Error{constructor(Q,X){super(`${X} (${Q})`);this.name="ULIDError",this.code=Q}}function bg(Q){let X=Math.floor(Q()*IY)%IY;return IU.charAt(X)}function Pg(Q){let X=Zg(),Y=X&&(X.crypto||X.msCrypto)||(typeof SY<"u"?SY:null);if(typeof Y?.getRandomValues==="function")return()=>{let W=new Uint8Array(1);return Y.getRandomValues(W),W[0]/256};else if(typeof Y?.randomBytes==="function")return()=>Y.randomBytes(1).readUInt8()/256;else if(SY?.randomBytes)return()=>SY.randomBytes(1).readUInt8()/256;throw new j8(q9.PRNGDetectFailure,"Failed to find a reliable PRNG")}function Zg(){if(Sg())return self;if(typeof window<"u")return window;if(typeof global<"u")return global;if(typeof globalThis<"u")return globalThis;return null}function Rg(Q,X){let Y="";for(;Q>0;Q--)Y=bg(X)+Y;return Y}function Eg(Q,X=TU){if(isNaN(Q))throw new j8(q9.EncodeTimeValueMalformed,`Time must be a number: ${Q}`);else if(Q>SU)throw new j8(q9.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${SU}: ${Q}`);else if(Q<0)throw new j8(q9.EncodeTimeNegative,`Time must be positive: ${Q}`);else if(Number.isInteger(Q)===!1)throw new j8(q9.EncodeTimeValueMalformed,`Time must be an integer: ${Q}`);let Y,W="";for(let $=X;$>0;$--)Y=Q%IY,W=IU.charAt(Y)+W,Q=(Q-Y)/IY;return W}function Sg(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function r0(Q,X){let Y=X||Pg(),W=!Q||isNaN(Q)?Date.now():Q;return Eg(W,TU)+Rg(Mg,Y)}function mJ(Q){return Q.type==="http"}function cJ(Q){return Q.type==="stdio"}class pJ{configs=new Map;logger;constructor(Q={}){this.logger=Q.logger}addConfig(Q,X,Y,W){let $=this.configs.has(Q);return this.configs.set(Q,{name:Q,type:"http",url:X,headers:Y?.headers,addedAt:new Date,addedBy:W}),this.logger?.info($?"server_config_updated":"server_config_added",{server:Q,type:"http",url:X,hasHeaders:Y?.headers!==void 0,addedBy:W}),!$}addStdioConfig(Q,X,Y,W,$){let J=this.configs.has(Q);return this.configs.set(Q,{name:Q,type:"stdio",command:X,args:Y,env:W?.env,cwd:W?.cwd,restartConfig:W?.restartConfig,addedAt:new Date,addedBy:$}),this.logger?.info(J?"server_config_updated":"server_config_added",{server:Q,type:"stdio",command:X,args:Y,addedBy:$}),!J}getConfig(Q){return this.configs.get(Q)}listConfigs(){return Array.from(this.configs.values())}removeConfig(Q){let X=this.configs.delete(Q);if(X)this.logger?.info("server_config_removed",{server:Q});return X}hasConfig(Q){return this.configs.has(Q)}get size(){return this.configs.size}clear(){this.configs.clear(),this.logger?.info("server_configs_cleared",{})}}var Ig={maxEvents:1000,retentionMs:1800000,cleanupIntervalMs:300000};class dJ{events=[];config;logger;lastDeliveredId=null;waiters=[];cleanupIntervalHandle=null;constructor(Q={},X){this.config={...Ig,...Q},this.logger=X,this.startCleanupInterval()}addEvent(Q,X,Y){let W=r0(),$={id:W,type:Q,server:X,data:Y,createdAt:new Date,sentViaSSE:!1};this.events.push($);while(this.events.length>this.config.maxEvents)this.events.shift();return this.logger?.debug("event_added",{id:W,type:Q,server:X}),this.wakeWaiters($),W}hasNewEvents(){if(this.lastDeliveredId===null)return this.events.length>0;let Q=this.events.findIndex((X)=>X.id===this.lastDeliveredId);if(Q===-1)return this.events.length>0;return Q<this.events.length-1}getNewEvents(){if(this.events.length===0)return[];let Q=0;if(this.lastDeliveredId!==null){let Y=this.events.findIndex((W)=>W.id===this.lastDeliveredId);if(Y!==-1)Q=Y+1}let X=this.events.slice(Q);if(X.length>0){let Y=X[X.length-1];if(Y)this.lastDeliveredId=Y.id}return X}getEventsAfter(Q){if(Q===null)return[...this.events];let X=this.events.findIndex((Y)=>Y.id===Q);if(X===-1)return[...this.events];return this.events.slice(X+1)}markSent(Q){let X=this.events.find((Y)=>Y.id===Q);if(X)X.sentViaSSE=!0}waitForActivity(Q){return new Promise((X)=>{let Y=setTimeout(()=>{let W=this.waiters.findIndex(($)=>$.timeoutHandle===Y);if(W!==-1)this.waiters.splice(W,1);X(null)},Q);this.waiters.push({resolve:X,timeoutHandle:Y})})}wakeWaiters(Q){let X=this.waiters;this.waiters=[];for(let Y of X)clearTimeout(Y.timeoutHandle),Y.resolve(Q)}startCleanupInterval(){this.cleanupIntervalHandle=setInterval(()=>{this.runCleanup()},this.config.cleanupIntervalMs)}runCleanup(){let Q=Date.now()-this.config.retentionMs,X=0;while(this.events.length>0){let Y=this.events[0];if(Y&&Y.createdAt.getTime()<Q)this.events.shift(),X++;else break}if(X>0)this.logger?.debug("events_cleaned",{removed:X,remaining:this.events.length})}shutdown(){if(this.cleanupIntervalHandle)clearInterval(this.cleanupIntervalHandle),this.cleanupIntervalHandle=null;for(let Q of this.waiters)clearTimeout(Q.timeoutHandle),Q.resolve(null);this.waiters=[]}}var Tg={defaultTtlMs:600000,completedRetentionMs:300000,cleanupIntervalMs:60000};class iJ{tasks=new Map;eventSystem;config;cleanupIntervalHandle=null;constructor(Q,X={}){this.eventSystem=Q,this.config={...Tg,...X},this.startCleanupInterval()}createTask(Q,X,Y,W){let $=r0(),J=new Date,G={taskId:$,server:Q,toolName:X,args:Y,status:"working",createdAt:J,lastUpdatedAt:J,ttl:W??this.config.defaultTtlMs};return this.tasks.set($,G),this.eventSystem.addEvent("task_created",Q,{taskId:$,toolName:X,args:Y}),G}completeTask(Q,X){let Y=this.tasks.get(Q);if(Y?.status!=="working")return;Y.status="completed",Y.result=X,Y.lastUpdatedAt=new Date,this.scheduleTaskCleanup(Y),this.eventSystem.addEvent("task_completed",Y.server,{taskId:Q,toolName:Y.toolName,result:X})}failTask(Q,X){let Y=this.tasks.get(Q);if(Y?.status!=="working")return;Y.status="failed",Y.error=X,Y.lastUpdatedAt=new Date,this.scheduleTaskCleanup(Y),this.eventSystem.addEvent("task_failed",Y.server,{taskId:Q,toolName:Y.toolName,error:X})}cancelTask(Q){let X=this.tasks.get(Q);if(X?.status!=="working")return!1;return X.status="cancelled",X.lastUpdatedAt=new Date,this.scheduleTaskCleanup(X),this.eventSystem.addEvent("task_cancelled",X.server,{taskId:Q,toolName:X.toolName}),!0}getTask(Q){let X=this.tasks.get(Q);if(!X)return;let{_cleanupTimeoutHandle:Y,...W}=X;return W}getTasksForServer(Q){return Array.from(this.tasks.values()).filter((X)=>X.server===Q).map((X)=>({taskId:X.taskId,server:X.server,toolName:X.toolName,args:X.args,status:X.status,result:X.result,error:X.error,createdAt:X.createdAt,lastUpdatedAt:X.lastUpdatedAt,ttl:X.ttl}))}getAllTasks(Q=!1){let X=["completed","failed","cancelled","expired"];return Array.from(this.tasks.values()).filter((Y)=>Q||!X.includes(Y.status)).map((Y)=>({taskId:Y.taskId,server:Y.server,toolName:Y.toolName,args:Y.args,status:Y.status,result:Y.result,error:Y.error,createdAt:Y.createdAt,lastUpdatedAt:Y.lastUpdatedAt,ttl:Y.ttl}))}getWorkingTasksForServer(Q){return Array.from(this.tasks.values()).filter((X)=>X.server===Q&&X.status==="working").map((X)=>({taskId:X.taskId,toolName:X.toolName,status:X.status}))}scheduleTaskCleanup(Q){if(Q._cleanupTimeoutHandle)clearTimeout(Q._cleanupTimeoutHandle);Q._cleanupTimeoutHandle=setTimeout(()=>{this.tasks.delete(Q.taskId)},this.config.completedRetentionMs)}startCleanupInterval(){this.cleanupIntervalHandle=setInterval(()=>{this.runCleanup()},this.config.cleanupIntervalMs)}runCleanup(){let Q=Date.now();for(let X of this.tasks.values()){if(X.status!=="working")continue;if(Q-X.createdAt.getTime()>=X.ttl)X.status="expired",X.error=`Task expired after ${String(X.ttl)}ms TTL`,X.lastUpdatedAt=new Date,this.eventSystem.addEvent("task_expired",X.server,{taskId:X.taskId,toolName:X.toolName,ttl:X.ttl}),this.scheduleTaskCleanup(X)}}shutdown(){if(this.cleanupIntervalHandle)clearInterval(this.cleanupIntervalHandle),this.cleanupIntervalHandle=null;for(let Q of this.tasks.values())if(Q._cleanupTimeoutHandle)clearTimeout(Q._cleanupTimeoutHandle)}}var Cg={maxNotificationsPerServer:100,maxLogsPerServer:500};class nJ{buffers=new Map;eventSystem;config;constructor(Q,X={}){this.eventSystem=Q,this.config={...Cg,...X}}addNotification(Q){let X=this.getOrCreateBuffers(Q.server);if(X.notifications.length>=this.config.maxNotificationsPerServer)X.notifications.shift();X.notifications.push(Q),this.eventSystem.addEvent("notification",Q.server,{method:Q.method,params:Q.params,timestamp:Q.timestamp.toISOString()})}addLog(Q){let X=this.getOrCreateBuffers(Q.server);if(X.logs.length>=this.config.maxLogsPerServer)X.logs.shift();X.logs.push(Q)}getAndClearNotifications(){let Q=[];for(let X of this.buffers.values())Q.push(...X.notifications),X.notifications=[];return Q}getAndClearLogs(){let Q=[];for(let X of this.buffers.values())Q.push(...X.logs),X.logs=[];return Q}getNotificationsForServer(Q){let X=this.buffers.get(Q);return X?[...X.notifications]:[]}getLogsForServer(Q){let X=this.buffers.get(Q);return X?[...X.logs]:[]}getNotificationCount(){let Q=0;for(let X of this.buffers.values())Q+=X.notifications.length;return Q}getLogCount(){let Q=0;for(let X of this.buffers.values())Q+=X.logs.length;return Q}clearServer(Q){this.buffers.delete(Q)}getOrCreateBuffers(Q){let X=this.buffers.get(Q);if(!X)X={notifications:[],logs:[]},this.buffers.set(Q,X);return X}}var kg={defaultTimeoutMs:600000};class oJ{samplingRequests=new Map;elicitationRequests=new Map;eventSystem;config;constructor(Q,X={}){this.eventSystem=Q,this.config={...kg,...X}}addSamplingRequest(Q,X,Y,W){let $=r0(),J=setTimeout(()=>{let H=this.samplingRequests.get($);if(H)this.samplingRequests.delete($),this.eventSystem.addEvent("sampling_expired",Q,{requestId:$,reason:`Timed out after ${String(this.config.defaultTimeoutMs)}ms`}),H.reject(Error(`Sampling request timed out after ${String(this.config.defaultTimeoutMs)}ms`))},this.config.defaultTimeoutMs),G={requestId:$,server:Q,timestamp:new Date,params:X,resolve:Y,reject:W,timeoutHandle:J};return this.samplingRequests.set($,G),this.eventSystem.addEvent("sampling_request",Q,{requestId:$,params:X}),$}addElicitationRequest(Q,X,Y,W){let $=r0(),J=setTimeout(()=>{let H=this.elicitationRequests.get($);if(H)this.elicitationRequests.delete($),this.eventSystem.addEvent("elicitation_expired",Q,{requestId:$,reason:`Timed out after ${String(this.config.defaultTimeoutMs)}ms`}),H.reject(Error(`Elicitation request timed out after ${String(this.config.defaultTimeoutMs)}ms`))},this.config.defaultTimeoutMs),G={requestId:$,server:Q,timestamp:new Date,params:X,resolve:Y,reject:W,timeoutHandle:J};return this.elicitationRequests.set($,G),this.eventSystem.addEvent("elicitation_request",Q,{requestId:$,params:X}),$}respondToSampling(Q,X){let Y=this.samplingRequests.get(Q);if(!Y)throw Error(`Sampling request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.samplingRequests.delete(Q),Y.resolve(X)}cancelSampling(Q,X="User cancelled"){let Y=this.samplingRequests.get(Q);if(!Y)throw Error(`Sampling request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.samplingRequests.delete(Q),this.eventSystem.addEvent("sampling_expired",Y.server,{requestId:Q,reason:X}),Y.reject(Error(X))}respondToElicitation(Q,X){let Y=this.elicitationRequests.get(Q);if(!Y)throw Error(`Elicitation request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.elicitationRequests.delete(Q),Y.resolve(X)}cancelElicitation(Q,X="User cancelled"){let Y=this.elicitationRequests.get(Q);if(!Y)throw Error(`Elicitation request '${Q}' not found or already completed`);clearTimeout(Y.timeoutHandle),this.elicitationRequests.delete(Q),this.eventSystem.addEvent("elicitation_expired",Y.server,{requestId:Q,reason:X}),Y.reject(Error(X))}getPendingSamplingRequests(){return Array.from(this.samplingRequests.values()).map((Q)=>({requestId:Q.requestId,server:Q.server,timestamp:Q.timestamp,params:Q.params}))}getPendingElicitationRequests(){return Array.from(this.elicitationRequests.values()).map((Q)=>({requestId:Q.requestId,server:Q.server,timestamp:Q.timestamp,params:Q.params}))}getRequestsForServer(Q){return{sampling:this.getPendingSamplingRequests().filter((X)=>X.server===Q),elicitation:this.getPendingElicitationRequests().filter((X)=>X.server===Q)}}hasPendingRequests(){return this.samplingRequests.size>0||this.elicitationRequests.size>0}rejectRequestsForServer(Q,X){for(let[Y,W]of this.samplingRequests)if(W.server===Q)clearTimeout(W.timeoutHandle),this.samplingRequests.delete(Y),this.eventSystem.addEvent("sampling_expired",Q,{requestId:Y,reason:X}),W.reject(Error(X));for(let[Y,W]of this.elicitationRequests)if(W.server===Q)clearTimeout(W.timeoutHandle),this.elicitationRequests.delete(Y),this.eventSystem.addEvent("elicitation_expired",Q,{requestId:Y,reason:X}),W.reject(Error(X))}shutdown(){for(let Q of this.samplingRequests.values())clearTimeout(Q.timeoutHandle),Q.reject(Error("PendingRequestsManager shutting down"));this.samplingRequests.clear();for(let Q of this.elicitationRequests.values())clearTimeout(Q.timeoutHandle),Q.reject(Error("PendingRequestsManager shutting down"));this.elicitationRequests.clear()}}var vg={maxActiveTimers:100,maxDurationMs:86400000,retentionMs:300000};class rJ{timers=new Map;expiredBuffer=[];eventSystem;config;constructor(Q,X={}){this.eventSystem=Q,this.config={...vg,...X}}createTimer(Q,X,Y=!1){if(this.getActiveTimers().length>=this.config.maxActiveTimers)throw Error(`Maximum active timers (${String(this.config.maxActiveTimers)}) exceeded`);if(Q<=0)throw Error("Duration must be positive");if(Q>this.config.maxDurationMs)throw Error(`Duration exceeds maximum (${String(this.config.maxDurationMs)}ms)`);let $=r0(),J=new Date,G=new Date(J.getTime()+Q),H={id:$,durationMs:Q,message:X,createdAt:J,expiresAt:G,status:"active",interval:Y,fireCount:0};if(Y)H._intervalHandle=setInterval(()=>{this.fireIntervalTimer($)},Q);else H._timeoutHandle=setTimeout(()=>{this.expireTimer($)},Q);return this.timers.set($,H),this.toPublicTimer(H)}getTimer(Q){let X=this.timers.get(Q);if(!X)return;return this.toPublicTimer(X)}deleteTimer(Q){let X=this.timers.get(Q);if(!X)return;if(X._timeoutHandle)clearTimeout(X._timeoutHandle),X._timeoutHandle=void 0;if(X._intervalHandle)clearInterval(X._intervalHandle),X._intervalHandle=void 0;return X.status="deleted",this.scheduleCleanup(X),this.toPublicTimer(X)}getAllTimers(Q=!1){let X=Array.from(this.timers.values());return(Q?X:X.filter((W)=>W.status==="active")).map((W)=>this.toPublicTimer(W))}getActiveTimers(){return Array.from(this.timers.values()).filter((Q)=>Q.status==="active").map((Q)=>this.toPublicTimer(Q))}getAndClearExpired(){let Q=[...this.expiredBuffer];return this.expiredBuffer.length=0,Q}hasExpired(){return this.expiredBuffer.length>0}shutdown(){for(let Q of this.timers.values()){if(Q._timeoutHandle)clearTimeout(Q._timeoutHandle);if(Q._intervalHandle)clearInterval(Q._intervalHandle)}this.timers.clear(),this.expiredBuffer.length=0}expireTimer(Q){let X=this.timers.get(Q);if(!X?.status||X.status!=="active")return;X.status="expired",X._timeoutHandle=void 0,X.fireCount++,this.expiredBuffer.push({id:X.id,message:X.message,expiredAt:new Date().toISOString()}),this.eventSystem.addEvent("timer_expired","emceepee",{timerId:X.id,message:X.message}),this.scheduleCleanup(X)}fireIntervalTimer(Q){let X=this.timers.get(Q);if(!X?.status||X.status!=="active")return;X.fireCount++,X.expiresAt=new Date(Date.now()+X.durationMs),this.expiredBuffer.push({id:X.id,message:X.message,expiredAt:new Date().toISOString()}),this.eventSystem.addEvent("timer_expired","emceepee",{timerId:X.id,message:X.message,fireCount:X.fireCount,interval:!0})}scheduleCleanup(Q){setTimeout(()=>{this.timers.delete(Q.id)},this.config.retentionMs)}toPublicTimer(Q){return{id:Q.id,durationMs:Q.durationMs,message:Q.message,createdAt:Q.createdAt,expiresAt:Q.expiresAt,status:Q.status,interval:Q.interval,fireCount:Q.fireCount}}}class tJ{sessionId;createdAt;lastActivityAt;backendConnections=new Map;eventSystem;taskManager;pendingRequests;bufferManager;timerManager;logger;constructor(Q,X={},Y){this.sessionId=Q,this.createdAt=new Date,this.lastActivityAt=new Date,this.logger=Y,this.eventSystem=new dJ(X.eventSystemConfig,Y),this.taskManager=new iJ(this.eventSystem,X.taskConfig),this.pendingRequests=new oJ(this.eventSystem,X.requestConfig),this.bufferManager=new nJ(this.eventSystem,X.bufferConfig),this.timerManager=new rJ(this.eventSystem,X.timerConfig)}touch(){this.lastActivityAt=new Date}getConnection(Q){return this.backendConnections.get(Q)}isConnectedTo(Q){return this.backendConnections.get(Q)?.status==="connected"}listConnectedServers(){return Array.from(this.backendConnections.entries()).filter(([,Q])=>Q.status==="connected").map(([Q])=>Q)}listConnections(){return Array.from(this.backendConnections.entries()).map(([Q,X])=>({name:Q,status:X.status,connectedAt:X.connectedAt,lastError:X.lastError}))}setConnectionStatus(Q,X,Y){let W=this.backendConnections.get(Q);if(W){if(W.status=X,X==="connected")W.connectedAt=new Date,W.lastError=void 0;else if(X==="error"&&Y)W.lastError=Y}}addConnection(Q,X){this.backendConnections.set(Q,{client:X,status:"connecting"})}removeConnection(Q){return this.backendConnections.delete(Q)}async cleanup(){this.logger?.info("session_cleanup_start",{sessionId:this.sessionId}),this.pendingRequests.shutdown(),this.taskManager.shutdown(),this.timerManager.shutdown(),this.eventSystem.shutdown();for(let[Q,X]of this.backendConnections)try{await X.client.disconnect(),this.logger?.debug("session_backend_disconnected",{sessionId:this.sessionId,server:Q})}catch(Y){this.logger?.debug("session_backend_disconnect_error",{sessionId:this.sessionId,server:Q,error:Y instanceof Error?Y.message:String(Y)})}this.backendConnections.clear(),this.logger?.info("session_cleanup_complete",{sessionId:this.sessionId})}}class aJ{constructor(Q){this._client=Q}async*callToolStream(Q,X=b6,Y){let W=this._client,$={...Y,task:Y?.task??(W.isToolTask(Q.name)?{}:void 0)},J=W.requestStream({method:"tools/call",params:Q},X,$),G=W.getToolOutputValidator(Q.name);for await(let H of J){if(H.type==="result"&&G){let B=H.result;if(!B.structuredContent&&!B.isError){yield{type:"error",error:new I(k.InvalidRequest,`Tool ${Q.name} has an output schema but did not return structured content`)};return}if(B.structuredContent)try{let z=G(B.structuredContent);if(!z.valid){yield{type:"error",error:new I(k.InvalidParams,`Structured content does not match the tool's output schema: ${z.errorMessage}`)};return}}catch(z){if(z instanceof I){yield{type:"error",error:z};return}yield{type:"error",error:new I(k.InvalidParams,`Failed to validate structured content: ${z instanceof Error?z.message:String(z)}`)};return}}yield H}}async getTask(Q,X){return this._client.getTask({taskId:Q},X)}async getTaskResult(Q,X,Y){return this._client.getTaskResult({taskId:Q},X,Y)}async listTasks(Q,X){return this._client.listTasks(Q?{cursor:Q}:void 0,X)}async cancelTask(Q,X){return this._client.cancelTask({taskId:Q},X)}requestStream(Q,X,Y){return this._client.requestStream(Q,X,Y)}}function TY(Q,X){if(!Q||X===null||typeof X!=="object")return;if(Q.type==="object"&&Q.properties&&typeof Q.properties==="object"){let Y=X,W=Q.properties;for(let $ of Object.keys(W)){let J=W[$];if(Y[$]===void 0&&Object.prototype.hasOwnProperty.call(J,"default"))Y[$]=J.default;if(Y[$]!==void 0)TY(J,Y[$])}}if(Array.isArray(Q.anyOf)){for(let Y of Q.anyOf)if(typeof Y!=="boolean")TY(Y,X)}if(Array.isArray(Q.oneOf)){for(let Y of Q.oneOf)if(typeof Y!=="boolean")TY(Y,X)}}function _g(Q){if(!Q)return{supportsFormMode:!1,supportsUrlMode:!1};let X=Q.form!==void 0,Y=Q.url!==void 0;return{supportsFormMode:X||!X&&!Y,supportsUrlMode:Y}}class N8 extends G4{constructor(Q,X){super(X);if(this._clientInfo=Q,this._cachedToolOutputValidators=new Map,this._cachedKnownTaskTools=new Set,this._cachedRequiredTaskTools=new Set,this._listChangedDebounceTimers=new Map,this._capabilities=X?.capabilities??{},this._jsonSchemaValidator=X?.jsonSchemaValidator??new s4,X?.listChanged)this._pendingListChangedConfig=X.listChanged}_setupListChangedHandlers(Q){if(Q.tools&&this._serverCapabilities?.tools?.listChanged)this._setupListChangedHandler("tools",W9,Q.tools,async()=>{return(await this.listTools()).tools});if(Q.prompts&&this._serverCapabilities?.prompts?.listChanged)this._setupListChangedHandler("prompts",Y9,Q.prompts,async()=>{return(await this.listPrompts()).prompts});if(Q.resources&&this._serverCapabilities?.resources?.listChanged)this._setupListChangedHandler("resources",X9,Q.resources,async()=>{return(await this.listResources()).resources})}get experimental(){if(!this._experimental)this._experimental={tasks:new aJ(this)};return this._experimental}registerCapabilities(Q){if(this.transport)throw Error("Cannot register capabilities after connecting to transport");this._capabilities=JX(this._capabilities,Q)}setRequestHandler(Q,X){let W=c1(Q)?.method;if(!W)throw Error("Schema is missing a method literal");let $;if(e0(W)){let G=W;$=G._zod?.def?.value??G.value}else{let G=W;$=G._def?.value??G.value}if(typeof $!=="string")throw Error("Schema method literal must be a string");let J=$;if(J==="elicitation/create"){let G=async(H,B)=>{let z=c0(J9,H);if(!z.success){let U=z.error instanceof Error?z.error.message:String(z.error);throw new I(k.InvalidParams,`Invalid elicitation request: ${U}`)}let{params:K}=z.data;K.mode=K.mode??"form";let{supportsFormMode:V,supportsUrlMode:A}=_g(this._capabilities.elicitation);if(K.mode==="form"&&!V)throw new I(k.InvalidParams,"Client does not support form-mode elicitation requests");if(K.mode==="url"&&!A)throw new I(k.InvalidParams,"Client does not support URL-mode elicitation requests");let F=await Promise.resolve(X(H,B));if(K.task){let U=c0(W6,F);if(!U.success){let w=U.error instanceof Error?U.error.message:String(U.error);throw new I(k.InvalidParams,`Invalid task creation result: ${w}`)}return U.data}let L=c0(n9,F);if(!L.success){let U=L.error instanceof Error?L.error.message:String(L.error);throw new I(k.InvalidParams,`Invalid elicitation result: ${U}`)}let D=L.data,O=K.mode==="form"?K.requestedSchema:void 0;if(K.mode==="form"&&D.action==="accept"&&D.content&&O){if(this._capabilities.elicitation?.form?.applyDefaults)try{TY(O,D.content)}catch{}}return D};return super.setRequestHandler(Q,G)}if(J==="sampling/createMessage"){let G=async(H,B)=>{let z=c0($9,H);if(!z.success){let F=z.error instanceof Error?z.error.message:String(z.error);throw new I(k.InvalidParams,`Invalid sampling request: ${F}`)}let{params:K}=z.data,V=await Promise.resolve(X(H,B));if(K.task){let F=c0(W6,V);if(!F.success){let L=F.error instanceof Error?F.error.message:String(F.error);throw new I(k.InvalidParams,`Invalid task creation result: ${L}`)}return F.data}let A=c0($4,V);if(!A.success){let F=A.error instanceof Error?A.error.message:String(A.error);throw new I(k.InvalidParams,`Invalid sampling result: ${F}`)}return A.data};return super.setRequestHandler(Q,G)}return super.setRequestHandler(Q,X)}assertCapability(Q,X){if(!this._serverCapabilities?.[Q])throw Error(`Server does not support ${Q} (required for ${X})`)}async connect(Q,X){if(await super.connect(Q),Q.sessionId!==void 0)return;try{let Y=await this.request({method:"initialize",params:{protocolVersion:w6,capabilities:this._capabilities,clientInfo:this._clientInfo}},D5,X);if(Y===void 0)throw Error(`Server sent invalid initialize result: ${Y}`);if(!Q9.includes(Y.protocolVersion))throw Error(`Server's protocol version is not supported: ${Y.protocolVersion}`);if(this._serverCapabilities=Y.capabilities,this._serverVersion=Y.serverInfo,Q.setProtocolVersion)Q.setProtocolVersion(Y.protocolVersion);if(this._instructions=Y.instructions,await this.notification({method:"notifications/initialized"}),this._pendingListChangedConfig)this._setupListChangedHandlers(this._pendingListChangedConfig),this._pendingListChangedConfig=void 0}catch(Y){throw this.close(),Y}}getServerCapabilities(){return this._serverCapabilities}getServerVersion(){return this._serverVersion}getInstructions(){return this._instructions}assertCapabilityForMethod(Q){switch(Q){case"logging/setLevel":if(!this._serverCapabilities?.logging)throw Error(`Server does not support logging (required for ${Q})`);break;case"prompts/get":case"prompts/list":if(!this._serverCapabilities?.prompts)throw Error(`Server does not support prompts (required for ${Q})`);break;case"resources/list":case"resources/templates/list":case"resources/read":case"resources/subscribe":case"resources/unsubscribe":if(!this._serverCapabilities?.resources)throw Error(`Server does not support resources (required for ${Q})`);if(Q==="resources/subscribe"&&!this._serverCapabilities.resources.subscribe)throw Error(`Server does not support resource subscriptions (required for ${Q})`);break;case"tools/call":case"tools/list":if(!this._serverCapabilities?.tools)throw Error(`Server does not support tools (required for ${Q})`);break;case"completion/complete":if(!this._serverCapabilities?.completions)throw Error(`Server does not support completions (required for ${Q})`);break;case"initialize":break;case"ping":break}}assertNotificationCapability(Q){switch(Q){case"notifications/roots/list_changed":if(!this._capabilities.roots?.listChanged)throw Error(`Client does not support roots list changed notifications (required for ${Q})`);break;case"notifications/initialized":break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(Q){if(!this._capabilities)return;switch(Q){case"sampling/createMessage":if(!this._capabilities.sampling)throw Error(`Client does not support sampling capability (required for ${Q})`);break;case"elicitation/create":if(!this._capabilities.elicitation)throw Error(`Client does not support elicitation capability (required for ${Q})`);break;case"roots/list":if(!this._capabilities.roots)throw Error(`Client does not support roots capability (required for ${Q})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw Error(`Client does not support tasks capability (required for ${Q})`);break;case"ping":break}}assertTaskCapability(Q){bY(this._serverCapabilities?.tasks?.requests,Q,"Server")}assertTaskHandlerCapability(Q){if(!this._capabilities)return;PY(this._capabilities.tasks?.requests,Q,"Client")}async ping(Q){return this.request({method:"ping"},Y6,Q)}async complete(Q,X){return this.request({method:"completion/complete",params:Q},I5,X)}async setLoggingLevel(Q,X){return this.request({method:"logging/setLevel",params:{level:Q}},Y6,X)}async getPrompt(Q,X){return this.request({method:"prompts/get",params:Q},Z5,X)}async listPrompts(Q,X){return this.request({method:"prompts/list",params:Q},q5,X)}async listResources(Q,X){return this.request({method:"resources/list",params:Q},O5,X)}async listResourceTemplates(Q,X){return this.request({method:"resources/templates/list",params:Q},U5,X)}async readResource(Q,X){return this.request({method:"resources/read",params:Q},N5,X)}async subscribeResource(Q,X){return this.request({method:"resources/subscribe",params:Q},Y6,X)}async unsubscribeResource(Q,X){return this.request({method:"resources/unsubscribe",params:Q},Y6,X)}async callTool(Q,X=b6,Y){if(this.isToolTaskRequired(Q.name))throw new I(k.InvalidRequest,`Tool "${Q.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);let W=await this.request({method:"tools/call",params:Q},X,Y),$=this.getToolOutputValidator(Q.name);if($){if(!W.structuredContent&&!W.isError)throw new I(k.InvalidRequest,`Tool ${Q.name} has an output schema but did not return structured content`);if(W.structuredContent)try{let J=$(W.structuredContent);if(!J.valid)throw new I(k.InvalidParams,`Structured content does not match the tool's output schema: ${J.errorMessage}`)}catch(J){if(J instanceof I)throw J;throw new I(k.InvalidParams,`Failed to validate structured content: ${J instanceof Error?J.message:String(J)}`)}}return W}isToolTask(Q){if(!this._serverCapabilities?.tasks?.requests?.tools?.call)return!1;return this._cachedKnownTaskTools.has(Q)}isToolTaskRequired(Q){return this._cachedRequiredTaskTools.has(Q)}cacheToolMetadata(Q){this._cachedToolOutputValidators.clear(),this._cachedKnownTaskTools.clear(),this._cachedRequiredTaskTools.clear();for(let X of Q){if(X.outputSchema){let W=this._jsonSchemaValidator.getValidator(X.outputSchema);this._cachedToolOutputValidators.set(X.name,W)}let Y=X.execution?.taskSupport;if(Y==="required"||Y==="optional")this._cachedKnownTaskTools.add(X.name);if(Y==="required")this._cachedRequiredTaskTools.add(X.name)}}getToolOutputValidator(Q){return this._cachedToolOutputValidators.get(Q)}async listTools(Q,X){let Y=await this.request({method:"tools/list",params:Q},R5,X);return this.cacheToolMetadata(Y.tools),Y}_setupListChangedHandler(Q,X,Y,W){let $=a3.safeParse(Y);if(!$.success)throw Error(`Invalid ${Q} listChanged options: ${$.error.message}`);if(typeof Y.onChanged!=="function")throw Error(`Invalid ${Q} listChanged options: onChanged must be a function`);let{autoRefresh:J,debounceMs:G}=$.data,{onChanged:H}=Y,B=async()=>{if(!J){H(null,null);return}try{let K=await W();H(null,K)}catch(K){let V=K instanceof Error?K:Error(String(K));H(V,null)}},z=()=>{if(G){let K=this._listChangedDebounceTimers.get(Q);if(K)clearTimeout(K);let V=setTimeout(B,G);this._listChangedDebounceTimers.set(Q,V)}else B()};this.setNotificationHandler(X,z)}async sendRootsListChanged(){return this.notification({method:"notifications/roots/list_changed"})}}function CY(Q){if(!Q)return{};if(Q instanceof Headers)return Object.fromEntries(Q.entries());if(Array.isArray(Q))return Object.fromEntries(Q);return{...Q}}function CU(Q=fetch,X){if(!X)return Q;return async(Y,W)=>{let $={...X,...W,headers:W?.headers?{...CY(X.headers),...CY(W.headers)}:X.headers};return Q(Y,$)}}var sJ;sJ=globalThis.crypto?.webcrypto??globalThis.crypto??import("node:crypto").then((Q)=>Q.webcrypto);async function xg(Q){return(await sJ).getRandomValues(new Uint8Array(Q))}async function yg(Q){let Y=Math.pow(2,8)-Math.pow(2,8)%66,W="";while(W.length<Q){let $=await xg(Q-W.length);for(let J of $)if(J<Y)W+="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"[J%66]}return W}async function fg(Q){return await yg(Q)}async function gg(Q){let X=await(await sJ).subtle.digest("SHA-256",new TextEncoder().encode(Q));return btoa(String.fromCharCode(...new Uint8Array(X))).replace(/\//g,"_").replace(/\+/g,"-").replace(/=/g,"")}async function eJ(Q){if(!Q)Q=43;if(Q<43||Q>128)throw`Expected a length between 43 and 128. Received ${Q}.`;let X=await fg(Q),Y=await gg(X);return{code_verifier:X,code_challenge:Y}}var h0=P3().superRefine((Q,X)=>{if(!URL.canParse(Q))return X.addIssue({code:x3.custom,message:"URL must be parseable",fatal:!0}),KQ}).refine((Q)=>{let X=new URL(Q);return X.protocol!=="javascript:"&&X.protocol!=="data:"&&X.protocol!=="vbscript:"},{message:"URL cannot use javascript:, data:, or vbscript: scheme"}),vU=C0({resource:j().url(),authorization_servers:E(h0).optional(),jwks_uri:j().url().optional(),scopes_supported:E(j()).optional(),bearer_methods_supported:E(j()).optional(),resource_signing_alg_values_supported:E(j()).optional(),resource_name:j().optional(),resource_documentation:j().optional(),resource_policy_uri:j().url().optional(),resource_tos_uri:j().url().optional(),tls_client_certificate_bound_access_tokens:B0().optional(),authorization_details_types_supported:E(j()).optional(),dpop_signing_alg_values_supported:E(j()).optional(),dpop_bound_access_tokens_required:B0().optional()}),QG=C0({issuer:j(),authorization_endpoint:h0,token_endpoint:h0,registration_endpoint:h0.optional(),scopes_supported:E(j()).optional(),response_types_supported:E(j()),response_modes_supported:E(j()).optional(),grant_types_supported:E(j()).optional(),token_endpoint_auth_methods_supported:E(j()).optional(),token_endpoint_auth_signing_alg_values_supported:E(j()).optional(),service_documentation:h0.optional(),revocation_endpoint:h0.optional(),revocation_endpoint_auth_methods_supported:E(j()).optional(),revocation_endpoint_auth_signing_alg_values_supported:E(j()).optional(),introspection_endpoint:j().optional(),introspection_endpoint_auth_methods_supported:E(j()).optional(),introspection_endpoint_auth_signing_alg_values_supported:E(j()).optional(),code_challenge_methods_supported:E(j()).optional(),client_id_metadata_document_supported:B0().optional()}),hg=C0({issuer:j(),authorization_endpoint:h0,token_endpoint:h0,userinfo_endpoint:h0.optional(),jwks_uri:h0,registration_endpoint:h0.optional(),scopes_supported:E(j()).optional(),response_types_supported:E(j()),response_modes_supported:E(j()).optional(),grant_types_supported:E(j()).optional(),acr_values_supported:E(j()).optional(),subject_types_supported:E(j()),id_token_signing_alg_values_supported:E(j()),id_token_encryption_alg_values_supported:E(j()).optional(),id_token_encryption_enc_values_supported:E(j()).optional(),userinfo_signing_alg_values_supported:E(j()).optional(),userinfo_encryption_alg_values_supported:E(j()).optional(),userinfo_encryption_enc_values_supported:E(j()).optional(),request_object_signing_alg_values_supported:E(j()).optional(),request_object_encryption_alg_values_supported:E(j()).optional(),request_object_encryption_enc_values_supported:E(j()).optional(),token_endpoint_auth_methods_supported:E(j()).optional(),token_endpoint_auth_signing_alg_values_supported:E(j()).optional(),display_values_supported:E(j()).optional(),claim_types_supported:E(j()).optional(),claims_supported:E(j()).optional(),service_documentation:j().optional(),claims_locales_supported:E(j()).optional(),ui_locales_supported:E(j()).optional(),claims_parameter_supported:B0().optional(),request_parameter_supported:B0().optional(),request_uri_parameter_supported:B0().optional(),require_request_uri_registration:B0().optional(),op_policy_uri:h0.optional(),op_tos_uri:h0.optional(),client_id_metadata_document_supported:B0().optional()}),_U=T({...hg.shape,...QG.pick({code_challenge_methods_supported:!0}).shape}),xU=T({access_token:j(),id_token:j().optional(),token_type:j(),expires_in:vQ.number().optional(),scope:j().optional(),refresh_token:j().optional()}).strip(),yU=T({error:j(),error_description:j().optional(),error_uri:j().optional()}),kU=h0.optional().or(x("").transform(()=>{return})),ug=T({redirect_uris:E(h0),token_endpoint_auth_method:j().optional(),grant_types:E(j()).optional(),response_types:E(j()).optional(),client_name:j().optional(),client_uri:h0.optional(),logo_uri:kU,scope:j().optional(),contacts:E(j()).optional(),tos_uri:kU,policy_uri:j().optional(),jwks_uri:h0.optional(),jwks:R3().optional(),software_id:j().optional(),software_version:j().optional(),software_statement:j().optional()}).strip(),lg=T({client_id:j(),client_secret:j().optional(),client_id_issued_at:J0().optional(),client_secret_expires_at:J0().optional()}).strip(),fU=ug.merge(lg),cr=T({error:j(),error_description:j().optional()}).strip(),pr=T({token:j(),token_type_hint:j().optional()}).strip();function gU(Q){let X=typeof Q==="string"?new URL(Q):new URL(Q.href);return X.hash="",X}function hU({requestedResource:Q,configuredResource:X}){let Y=typeof Q==="string"?new URL(Q):new URL(Q.href),W=typeof X==="string"?new URL(X):new URL(X.href);if(Y.origin!==W.origin)return!1;if(Y.pathname.length<W.pathname.length)return!1;let $=Y.pathname.endsWith("/")?Y.pathname:Y.pathname+"/",J=W.pathname.endsWith("/")?W.pathname:W.pathname+"/";return $.startsWith(J)}class S0 extends Error{constructor(Q,X){super(Q);this.errorUri=X,this.name=this.constructor.name}toResponseObject(){let Q={error:this.errorCode,error_description:this.message};if(this.errorUri)Q.error_uri=this.errorUri;return Q}get errorCode(){return this.constructor.errorCode}}class kY extends S0{}kY.errorCode="invalid_request";class q8 extends S0{}q8.errorCode="invalid_client";class w8 extends S0{}w8.errorCode="invalid_grant";class M8 extends S0{}M8.errorCode="unauthorized_client";class vY extends S0{}vY.errorCode="unsupported_grant_type";class _Y extends S0{}_Y.errorCode="invalid_scope";class xY extends S0{}xY.errorCode="access_denied";class h6 extends S0{}h6.errorCode="server_error";class yY extends S0{}yY.errorCode="temporarily_unavailable";class fY extends S0{}fY.errorCode="unsupported_response_type";class gY extends S0{}gY.errorCode="unsupported_token_type";class hY extends S0{}hY.errorCode="invalid_token";class uY extends S0{}uY.errorCode="method_not_allowed";class lY extends S0{}lY.errorCode="too_many_requests";class b8 extends S0{}b8.errorCode="invalid_client_metadata";class mY extends S0{}mY.errorCode="insufficient_scope";class cY extends S0{}cY.errorCode="invalid_target";var uU={[kY.errorCode]:kY,[q8.errorCode]:q8,[w8.errorCode]:w8,[M8.errorCode]:M8,[vY.errorCode]:vY,[_Y.errorCode]:_Y,[xY.errorCode]:xY,[h6.errorCode]:h6,[yY.errorCode]:yY,[fY.errorCode]:fY,[gY.errorCode]:gY,[hY.errorCode]:hY,[uY.errorCode]:uY,[lY.errorCode]:lY,[b8.errorCode]:b8,[mY.errorCode]:mY,[cY.errorCode]:cY};class u6 extends Error{constructor(Q){super(Q??"Unauthorized")}}function mg(Q){return["client_secret_basic","client_secret_post","none"].includes(Q)}var XG="code",YG="S256";function cg(Q,X){let Y=Q.client_secret!==void 0;if(X.length===0)return Y?"client_secret_post":"none";if("token_endpoint_auth_method"in Q&&Q.token_endpoint_auth_method&&mg(Q.token_endpoint_auth_method)&&X.includes(Q.token_endpoint_auth_method))return Q.token_endpoint_auth_method;if(Y&&X.includes("client_secret_basic"))return"client_secret_basic";if(Y&&X.includes("client_secret_post"))return"client_secret_post";if(X.includes("none"))return"none";return Y?"client_secret_post":"none"}function pg(Q,X,Y,W){let{client_id:$,client_secret:J}=X;switch(Q){case"client_secret_basic":dg($,J,Y);return;case"client_secret_post":ig($,J,W);return;case"none":ng($,W);return;default:throw Error(`Unsupported client authentication method: ${Q}`)}}function dg(Q,X,Y){if(!X)throw Error("client_secret_basic authentication requires a client_secret");let W=btoa(`${Q}:${X}`);Y.set("Authorization",`Basic ${W}`)}function ig(Q,X,Y){if(Y.set("client_id",Q),X)Y.set("client_secret",X)}function ng(Q,X){X.set("client_id",Q)}async function mU(Q){let X=Q instanceof Response?Q.status:void 0,Y=Q instanceof Response?await Q.text():Q;try{let W=yU.parse(JSON.parse(Y)),{error:$,error_description:J,error_uri:G}=W;return new(uU[$]||h6)(J||"",G)}catch(W){let $=`${X?`HTTP ${X}: `:""}Invalid OAuth error response: ${W}. Raw body: ${Y}`;return new h6($)}}async function YQ(Q,X){try{return await WG(Q,X)}catch(Y){if(Y instanceof q8||Y instanceof M8)return await Q.invalidateCredentials?.("all"),await WG(Q,X);else if(Y instanceof w8)return await Q.invalidateCredentials?.("tokens"),await WG(Q,X);throw Y}}async function WG(Q,{serverUrl:X,authorizationCode:Y,scope:W,resourceMetadataUrl:$,fetchFn:J}){let G,H;try{if(G=await tg(X,{resourceMetadataUrl:$},J),G.authorization_servers&&G.authorization_servers.length>0)H=G.authorization_servers[0]}catch{}if(!H)H=new URL("/",X);let B=await rg(X,Q,G),z=await Xh(H,{fetchFn:J}),K=await Promise.resolve(Q.clientInformation());if(!K){if(Y!==void 0)throw Error("Existing OAuth client information is required when exchanging an authorization code");let O=z?.client_id_metadata_document_supported===!0,U=Q.clientMetadataUrl;if(U&&!og(U))throw new b8(`clientMetadataUrl must be a valid HTTPS URL with a non-root pathname, got: ${U}`);if(O&&U)K={client_id:U},await Q.saveClientInformation?.(K);else{if(!Q.saveClientInformation)throw Error("OAuth client information must be saveable for dynamic registration");let M=await Gh(H,{metadata:z,clientMetadata:Q.clientMetadata,fetchFn:J});await Q.saveClientInformation(M),K=M}}let V=!Q.redirectUrl;if(Y!==void 0||V){let O=await Jh(Q,H,{metadata:z,resource:B,authorizationCode:Y,fetchFn:J});return await Q.saveTokens(O),"AUTHORIZED"}let A=await Q.tokens();if(A?.refresh_token)try{let O=await $h(H,{metadata:z,clientInformation:K,refreshToken:A.refresh_token,resource:B,addClientAuthentication:Q.addClientAuthentication,fetchFn:J});return await Q.saveTokens(O),"AUTHORIZED"}catch(O){if(!(O instanceof S0)||O instanceof h6);else throw O}let F=Q.state?await Q.state():void 0,{authorizationUrl:L,codeVerifier:D}=await Yh(H,{metadata:z,clientInformation:K,state:F,redirectUrl:Q.redirectUrl,scope:W||G?.scopes_supported?.join(" ")||Q.clientMetadata.scope,resource:B});return await Q.saveCodeVerifier(D),await Q.redirectToAuthorization(L),"REDIRECT"}function og(Q){if(!Q)return!1;try{let X=new URL(Q);return X.protocol==="https:"&&X.pathname!=="/"}catch{return!1}}async function rg(Q,X,Y){let W=gU(Q);if(X.validateResourceURL)return await X.validateResourceURL(W,Y?.resource);if(!Y)return;if(!hU({requestedResource:W,configuredResource:Y.resource}))throw Error(`Protected resource ${Y.resource} does not match expected ${W} (or origin)`);return new URL(Y.resource)}function JG(Q){let X=Q.headers.get("WWW-Authenticate");if(!X)return{};let[Y,W]=X.split(" ");if(Y.toLowerCase()!=="bearer"||!W)return{};let $=$G(Q,"resource_metadata")||void 0,J;if($)try{J=new URL($)}catch{}let G=$G(Q,"scope")||void 0,H=$G(Q,"error")||void 0;return{resourceMetadataUrl:J,scope:G,error:H}}function $G(Q,X){let Y=Q.headers.get("WWW-Authenticate");if(!Y)return null;let W=new RegExp(`${X}=(?:"([^"]+)"|([^\\s,]+))`),$=Y.match(W);if($)return $[1]||$[2];return null}async function tg(Q,X,Y=fetch){let W=await eg(Q,"oauth-protected-resource",Y,{protocolVersion:X?.protocolVersion,metadataUrl:X?.resourceMetadataUrl});if(!W||W.status===404)throw await W?.body?.cancel(),Error("Resource server does not implement OAuth 2.0 Protected Resource Metadata.");if(!W.ok)throw await W.body?.cancel(),Error(`HTTP ${W.status} trying to load well-known OAuth protected resource metadata.`);return vU.parse(await W.json())}async function GG(Q,X,Y=fetch){try{return await Y(Q,{headers:X})}catch(W){if(W instanceof TypeError)if(X)return GG(Q,void 0,Y);else return;throw W}}function ag(Q,X="",Y={}){if(X.endsWith("/"))X=X.slice(0,-1);return Y.prependPathname?`${X}/.well-known/${Q}`:`/.well-known/${Q}${X}`}async function lU(Q,X,Y=fetch){return await GG(Q,{"MCP-Protocol-Version":X},Y)}function sg(Q,X){return!Q||Q.status>=400&&Q.status<500&&X!=="/"}async function eg(Q,X,Y,W){let $=new URL(Q),J=W?.protocolVersion??w6,G;if(W?.metadataUrl)G=new URL(W.metadataUrl);else{let B=ag(X,$.pathname);G=new URL(B,W?.metadataServerUrl??$),G.search=$.search}let H=await lU(G,J,Y);if(!W?.metadataUrl&&sg(H,$.pathname)){let B=new URL(`/.well-known/${X}`,$);H=await lU(B,J,Y)}return H}function Qh(Q){let X=typeof Q==="string"?new URL(Q):Q,Y=X.pathname!=="/",W=[];if(!Y)return W.push({url:new URL("/.well-known/oauth-authorization-server",X.origin),type:"oauth"}),W.push({url:new URL("/.well-known/openid-configuration",X.origin),type:"oidc"}),W;let $=X.pathname;if($.endsWith("/"))$=$.slice(0,-1);return W.push({url:new URL(`/.well-known/oauth-authorization-server${$}`,X.origin),type:"oauth"}),W.push({url:new URL(`/.well-known/openid-configuration${$}`,X.origin),type:"oidc"}),W.push({url:new URL(`${$}/.well-known/openid-configuration`,X.origin),type:"oidc"}),W}async function Xh(Q,{fetchFn:X=fetch,protocolVersion:Y=w6}={}){let W={"MCP-Protocol-Version":Y,Accept:"application/json"},$=Qh(Q);for(let{url:J,type:G}of $){let H=await GG(J,W,X);if(!H)continue;if(!H.ok){if(await H.body?.cancel(),H.status>=400&&H.status<500)continue;throw Error(`HTTP ${H.status} trying to load ${G==="oauth"?"OAuth":"OpenID provider"} metadata from ${J}`)}if(G==="oauth")return QG.parse(await H.json());else return _U.parse(await H.json())}return}async function Yh(Q,{metadata:X,clientInformation:Y,redirectUrl:W,scope:$,state:J,resource:G}){let H;if(X){if(H=new URL(X.authorization_endpoint),!X.response_types_supported.includes(XG))throw Error(`Incompatible auth server: does not support response type ${XG}`);if(X.code_challenge_methods_supported&&!X.code_challenge_methods_supported.includes(YG))throw Error(`Incompatible auth server: does not support code challenge method ${YG}`)}else H=new URL("/authorize",Q);let B=await eJ(),z=B.code_verifier,K=B.code_challenge;if(H.searchParams.set("response_type",XG),H.searchParams.set("client_id",Y.client_id),H.searchParams.set("code_challenge",K),H.searchParams.set("code_challenge_method",YG),H.searchParams.set("redirect_uri",String(W)),J)H.searchParams.set("state",J);if($)H.searchParams.set("scope",$);if($?.includes("offline_access"))H.searchParams.append("prompt","consent");if(G)H.searchParams.set("resource",G.href);return{authorizationUrl:H,codeVerifier:z}}function Wh(Q,X,Y){return new URLSearchParams({grant_type:"authorization_code",code:Q,code_verifier:X,redirect_uri:String(Y)})}async function cU(Q,{metadata:X,tokenRequestParams:Y,clientInformation:W,addClientAuthentication:$,resource:J,fetchFn:G}){let H=X?.token_endpoint?new URL(X.token_endpoint):new URL("/token",Q),B=new Headers({"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"});if(J)Y.set("resource",J.href);if($)await $(B,Y,H,X);else if(W){let K=X?.token_endpoint_auth_methods_supported??[],V=cg(W,K);pg(V,W,B,Y)}let z=await(G??fetch)(H,{method:"POST",headers:B,body:Y});if(!z.ok)throw await mU(z);return xU.parse(await z.json())}async function $h(Q,{metadata:X,clientInformation:Y,refreshToken:W,resource:$,addClientAuthentication:J,fetchFn:G}){let H=new URLSearchParams({grant_type:"refresh_token",refresh_token:W}),B=await cU(Q,{metadata:X,tokenRequestParams:H,clientInformation:Y,addClientAuthentication:J,resource:$,fetchFn:G});return{refresh_token:W,...B}}async function Jh(Q,X,{metadata:Y,resource:W,authorizationCode:$,fetchFn:J}={}){let G=Q.clientMetadata.scope,H;if(Q.prepareTokenRequest)H=await Q.prepareTokenRequest(G);if(!H){if(!$)throw Error("Either provider.prepareTokenRequest() or authorizationCode is required");if(!Q.redirectUrl)throw Error("redirectUrl is required for authorization_code flow");let z=await Q.codeVerifier();H=Wh($,z,Q.redirectUrl)}let B=await Q.clientInformation();return cU(X,{metadata:Y,tokenRequestParams:H,clientInformation:B??void 0,addClientAuthentication:Q.addClientAuthentication,resource:W,fetchFn:J})}async function Gh(Q,{metadata:X,clientMetadata:Y,fetchFn:W}){let $;if(X){if(!X.registration_endpoint)throw Error("Incompatible auth server: does not support dynamic client registration");$=new URL(X.registration_endpoint)}else $=new URL("/register",Q);let J=await(W??fetch)($,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Y)});if(!J.ok)throw await mU(J);return fU.parse(await J.json())}class BG extends Error{constructor(Q,X){super(Q),this.name="ParseError",this.type=X.type,this.field=X.field,this.value=X.value,this.line=X.line}}function HG(Q){}function pU(Q){if(typeof Q=="function")throw TypeError("`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?");let{onEvent:X=HG,onError:Y=HG,onRetry:W=HG,onComment:$}=Q,J="",G=!0,H,B="",z="";function K(D){let O=G?D.replace(/^\xEF\xBB\xBF/,""):D,[U,w]=Hh(`${J}${O}`);for(let M of U)V(M);J=w,G=!1}function V(D){if(D===""){F();return}if(D.startsWith(":")){$&&$(D.slice(D.startsWith(": ")?2:1));return}let O=D.indexOf(":");if(O!==-1){let U=D.slice(0,O),w=D[O+1]===" "?2:1,M=D.slice(O+w);A(U,M,D);return}A(D,"",D)}function A(D,O,U){switch(D){case"event":z=O;break;case"data":B=`${B}${O}
|
|
59
59
|
`;break;case"id":H=O.includes("\x00")?void 0:O;break;case"retry":/^\d+$/.test(O)?W(parseInt(O,10)):Y(new BG(`Invalid \`retry\` value: "${O}"`,{type:"invalid-retry",value:O,line:U}));break;default:Y(new BG(`Unknown field "${D.length>20?`${D.slice(0,20)}…`:D}"`,{type:"unknown-field",field:D,value:O,line:U}));break}}function F(){B.length>0&&X({id:H,event:z||void 0,data:B.endsWith(`
|
|
60
60
|
`)?B.slice(0,-1):B}),H=void 0,B="",z=""}function L(D={}){J&&D.consume&&V(J),G=!0,H=void 0,B="",z="",J=""}return{feed:K,reset:L}}function Hh(Q){let X=[],Y="",W=0;for(;W<Q.length;){let $=Q.indexOf("\r",W),J=Q.indexOf(`
|
|
61
61
|
`,W),G=-1;if($!==-1&&J!==-1?G=Math.min($,J):$!==-1?$===Q.length-1?G=-1:G=$:J!==-1&&(G=J),G===-1){Y=Q.slice(W);break}else{let H=Q.slice(W,G);X.push(H),W=G+1,Q[W-1]==="\r"&&Q[W]===`
|
|
62
|
-
`&&W++}}return[X,Y]}class zG extends TransformStream{constructor({onError:Q,onRetry:X,onComment:Y}={}){let W;super({start($){W=pU({onEvent:(J)=>{$.enqueue(J)},onError(J){Q==="terminate"?$.error(J):typeof Q=="function"&&Q(J)},onRetry:X,onComment:Y})},transform($){W.feed($)}})}}var Bh={initialReconnectionDelay:1000,maxReconnectionDelay:30000,reconnectionDelayGrowFactor:1.5,maxRetries:2};class w9 extends Error{constructor(Q,X){super(`Streamable HTTP error: ${X}`);this.code=Q}}class pY{constructor(Q,X){this._hasCompletedAuthFlow=!1,this._url=Q,this._resourceMetadataUrl=void 0,this._scope=void 0,this._requestInit=X?.requestInit,this._authProvider=X?.authProvider,this._fetch=X?.fetch,this._fetchWithInit=CU(X?.fetch,X?.requestInit),this._sessionId=X?.sessionId,this._reconnectionOptions=X?.reconnectionOptions??Bh}async _authThenStart(){if(!this._authProvider)throw new u6("No auth provider");let Q;try{Q=await YQ(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})}catch(X){throw this.onerror?.(X),X}if(Q!=="AUTHORIZED")throw new u6;return await this._startOrAuthSse({resumptionToken:void 0})}async _commonHeaders(){let Q={};if(this._authProvider){let Y=await this._authProvider.tokens();if(Y)Q.Authorization=`Bearer ${Y.access_token}`}if(this._sessionId)Q["mcp-session-id"]=this._sessionId;if(this._protocolVersion)Q["mcp-protocol-version"]=this._protocolVersion;let X=CY(this._requestInit?.headers);return new Headers({...Q,...X})}async _startOrAuthSse(Q){let{resumptionToken:X}=Q;try{let Y=await this._commonHeaders();if(Y.set("Accept","text/event-stream"),X)Y.set("last-event-id",X);let W=await(this._fetch??fetch)(this._url,{method:"GET",headers:Y,signal:this._abortController?.signal});if(!W.ok){if(await W.body?.cancel(),W.status===401&&this._authProvider)return await this._authThenStart();if(W.status===405)return;throw new w9(W.status,`Failed to open SSE stream: ${W.statusText}`)}this._handleSseStream(W.body,Q,!0)}catch(Y){throw this.onerror?.(Y),Y}}_getNextReconnectionDelay(Q){if(this._serverRetryMs!==void 0)return this._serverRetryMs;let X=this._reconnectionOptions.initialReconnectionDelay,Y=this._reconnectionOptions.reconnectionDelayGrowFactor,W=this._reconnectionOptions.maxReconnectionDelay;return Math.min(X*Math.pow(Y,Q),W)}_scheduleReconnection(Q,X=0){let Y=this._reconnectionOptions.maxRetries;if(X>=Y){this.onerror?.(Error(`Maximum reconnection attempts (${Y}) exceeded.`));return}let W=this._getNextReconnectionDelay(X);this._reconnectionTimeout=setTimeout(()=>{this._startOrAuthSse(Q).catch(($)=>{this.onerror?.(Error(`Failed to reconnect SSE stream: ${$ instanceof Error?$.message:String($)}`)),this._scheduleReconnection(Q,X+1)})},W)}_handleSseStream(Q,X,Y){if(!Q)return;let{onresumptiontoken:W,replayMessageId:$}=X,J,G=!1,H=!1;(async()=>{try{let z=Q.pipeThrough(new TextDecoderStream).pipeThrough(new zG({onRetry:(A)=>{this._serverRetryMs=A}})).getReader();while(!0){let{value:A,done:F}=await z.read();if(F)break;if(A.id)J=A.id,G=!0,W?.(A.id);if(!A.data)continue;if(!A.event||A.event==="message")try{let L=X6.parse(JSON.parse(A.data));if(P1(L)){if(H=!0,$!==void 0)L.id=$}this.onmessage?.(L)}catch(L){this.onerror?.(L)}}if((Y||G)&&!H&&this._abortController&&!this._abortController.signal.aborted)this._scheduleReconnection({resumptionToken:J,onresumptiontoken:W,replayMessageId:$},0)}catch(z){if(this.onerror?.(Error(`SSE stream disconnected: ${z}`)),(Y||G)&&!H&&this._abortController&&!this._abortController.signal.aborted)try{this._scheduleReconnection({resumptionToken:J,onresumptiontoken:W,replayMessageId:$},0)}catch(A){this.onerror?.(Error(`Failed to reconnect: ${A instanceof Error?A.message:String(A)}`))}}})()}async start(){if(this._abortController)throw Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");this._abortController=new AbortController}async finishAuth(Q){if(!this._authProvider)throw new u6("No auth provider");if(await YQ(this._authProvider,{serverUrl:this._url,authorizationCode:Q,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new u6("Failed to authorize")}async close(){if(this._reconnectionTimeout)clearTimeout(this._reconnectionTimeout),this._reconnectionTimeout=void 0;this._abortController?.abort(),this.onclose?.()}async send(Q,X){try{let{resumptionToken:Y,onresumptiontoken:W}=X||{};if(Y){this._startOrAuthSse({resumptionToken:Y,replayMessageId:p1(Q)?Q.id:void 0}).catch((V)=>this.onerror?.(V));return}let $=await this._commonHeaders();$.set("content-type","application/json"),$.set("accept","application/json, text/event-stream");let J={...this._requestInit,method:"POST",headers:$,body:JSON.stringify(Q),signal:this._abortController?.signal},G=await(this._fetch??fetch)(this._url,J),H=G.headers.get("mcp-session-id");if(H)this._sessionId=H;if(!G.ok){let V=await G.text().catch(()=>null);if(G.status===401&&this._authProvider){if(this._hasCompletedAuthFlow)throw new w9(401,"Server returned 401 after successful authentication");let{resourceMetadataUrl:A,scope:F}=JG(G);if(this._resourceMetadataUrl=A,this._scope=F,await YQ(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new u6;return this._hasCompletedAuthFlow=!0,this.send(Q)}if(G.status===403&&this._authProvider){let{resourceMetadataUrl:A,scope:F,error:L}=JG(G);if(L==="insufficient_scope"){let D=G.headers.get("WWW-Authenticate");if(this._lastUpscopingHeader===D)throw new w9(403,"Server returned 403 after trying upscoping");if(F)this._scope=F;if(A)this._resourceMetadataUrl=A;if(this._lastUpscopingHeader=D??void 0,await YQ(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetch})!=="AUTHORIZED")throw new u6;return this.send(Q)}}throw new w9(G.status,`Error POSTing to endpoint: ${V}`)}if(this._hasCompletedAuthFlow=!1,this._lastUpscopingHeader=void 0,G.status===202){if(await G.body?.cancel(),p3(Q))this._startOrAuthSse({resumptionToken:void 0}).catch((V)=>this.onerror?.(V));return}let z=(Array.isArray(Q)?Q:[Q]).filter((V)=>("method"in V)&&("id"in V)&&V.id!==void 0).length>0,K=G.headers.get("content-type");if(z)if(K?.includes("text/event-stream"))this._handleSseStream(G.body,{onresumptiontoken:W},!1);else if(K?.includes("application/json")){let V=await G.json(),A=Array.isArray(V)?V.map((F)=>X6.parse(F)):[X6.parse(V)];for(let F of A)this.onmessage?.(F)}else throw await G.body?.cancel(),new w9(-1,`Unexpected content type: ${K}`);else await G.body?.cancel()}catch(Y){throw this.onerror?.(Y),Y}}get sessionId(){return this._sessionId}async terminateSession(){if(!this._sessionId)return;try{let Q=await this._commonHeaders(),X={...this._requestInit,method:"DELETE",headers:Q,signal:this._abortController?.signal},Y=await(this._fetch??fetch)(this._url,X);if(await Y.body?.cancel(),!Y.ok&&Y.status!==405)throw new w9(Y.status,`Failed to terminate session: ${Y.statusText}`);this._sessionId=void 0}catch(Q){throw this.onerror?.(Q),Q}}setProtocolVersion(Q){this._protocolVersion=Q}get protocolVersion(){return this._protocolVersion}async resumeStream(Q,X){await this._startOrAuthSse({resumptionToken:Q,onresumptiontoken:X?.onresumptiontoken})}}var zh=1000,Kh=180000,Vh=2,Ah=0.1,dU=120000,Fh=0.1,Dh=60000,Lh=3;class KG{name;url;onStatusChange;onNotification;onLog;onSamplingRequest;onElicitationRequest;onReconnecting;onReconnected;onHealthDegraded;onHealthRestored;client=null;transport=null;status="disconnected";errorMessage;capabilities;isClosing=!1;reconnectAttempt=0;reconnectTimeoutHandle=null;nextRetryMs=0;isReconnecting=!1;healthCheckIntervalHandle=null;consecutiveHealthFailures=0;healthStatus="healthy";constructor(Q){this.name=Q.name,this.url=Q.url,this.onStatusChange=Q.onStatusChange,this.onNotification=Q.onNotification,this.onLog=Q.onLog,this.onSamplingRequest=Q.onSamplingRequest,this.onElicitationRequest=Q.onElicitationRequest,this.onReconnecting=Q.onReconnecting,this.onReconnected=Q.onReconnected,this.onHealthDegraded=Q.onHealthDegraded,this.onHealthRestored=Q.onHealthRestored}getTransportType(){return"http"}getUrl(){return this.url}getInfo(){let Q={name:this.name,url:this.url,status:this.status};if(this.errorMessage!==void 0)Q.error=this.errorMessage;if(this.capabilities!==void 0)Q.capabilities=this.capabilities;return Q}getName(){return this.name}getStatus(){return this.status}isConnected(){return this.status==="connected"}getReconnectionState(){if(this.status!=="reconnecting")return null;return{attempt:this.reconnectAttempt,nextRetryMs:this.nextRetryMs}}getHealthStatus(){return this.healthStatus}getConsecutiveHealthFailures(){return this.consecutiveHealthFailures}async connect(){if(this.status==="connected"||this.status==="connecting")return;this.setStatus("connecting");try{this.transport=new pY(new URL(this.url)),this.client=new N8({name:"emceepee",version:"0.1.0"},{capabilities:{sampling:{},elicitation:{form:{}}}}),this.setupNotificationHandler(),this.transport.onclose=()=>{if(!this.isClosing)this.handleUnexpectedDisconnect()},this.transport.onerror=(X)=>{if((X.name==="AbortError"||X.message.includes("AbortError"))&&(this.isClosing||this.status==="disconnected"))return;this.errorMessage=X.message,this.handleUnexpectedDisconnect()},await this.client.connect(this.transport);let Q=this.client.getServerCapabilities();this.capabilities={tools:Q?.tools!==void 0,resources:Q?.resources!==void 0,prompts:Q?.prompts!==void 0,resourceTemplates:Q?.resources!==void 0,resourceSubscriptions:Q?.resources?.subscribe===!0},this.setStatus("connected"),this.startHealthChecks()}catch(Q){let X=Q instanceof Error?Q.message:String(Q);throw this.setStatus("error",X),Q}}async disconnect(){if(this.isClosing=!0,this.stopHealthChecks(),this.cancelReconnection(),this.transport)try{await this.transport.close()}catch{}this.client=null,this.transport=null,this.isClosing=!1,this.setStatus("disconnected")}async forceReconnect(){if(this.stopHealthChecks(),this.cancelReconnection(),this.transport){this.isClosing=!0;try{await this.transport.close()}catch{}this.isClosing=!1}this.client=null,this.transport=null,this.reconnectAttempt=0,this.nextRetryMs=0,this.consecutiveHealthFailures=0,this.healthStatus="healthy",await this.connect()}cancelReconnection(){if(this.reconnectTimeoutHandle)clearTimeout(this.reconnectTimeoutHandle),this.reconnectTimeoutHandle=null;this.isReconnecting=!1}async listTools(){let Q=this.getConnectedClient();if(!this.capabilities?.tools)return[];return(await Q.listTools()).tools}async callTool(Q,X={}){return await this.getConnectedClient().callTool({name:Q,arguments:X})}async listResources(){let Q=this.getConnectedClient();if(!this.capabilities?.resources)return[];return(await Q.listResources()).resources}async listResourceTemplates(){let Q=this.getConnectedClient();if(!this.capabilities?.resourceTemplates)return[];return(await Q.listResourceTemplates()).resourceTemplates}async readResource(Q){return await this.getConnectedClient().readResource({uri:Q})}async subscribeResource(Q){let X=this.getConnectedClient();if(!this.capabilities?.resourceSubscriptions)throw Error(`Server '${this.name}' does not support resource subscriptions`);await X.subscribeResource({uri:Q})}async unsubscribeResource(Q){let X=this.getConnectedClient();if(!this.capabilities?.resourceSubscriptions)throw Error(`Server '${this.name}' does not support resource subscriptions`);await X.unsubscribeResource({uri:Q})}supportsResourceSubscriptions(){return this.capabilities?.resourceSubscriptions===!0}async listPrompts(){let Q=this.getConnectedClient();if(!this.capabilities?.prompts)return[];return(await Q.listPrompts()).prompts}async getPrompt(Q,X={}){return await this.getConnectedClient().getPrompt({name:Q,arguments:X})}setupNotificationHandler(){if(!this.client)return;this.client.setNotificationHandler(W9,()=>{this.emitNotification("notifications/tools/list_changed")}),this.client.setNotificationHandler(X9,()=>{this.emitNotification("notifications/resources/list_changed")}),this.client.setNotificationHandler(X4,(Q)=>{this.emitNotification("notifications/resources/updated",Q.params)}),this.client.setNotificationHandler(Y9,()=>{this.emitNotification("notifications/prompts/list_changed")}),this.client.setNotificationHandler(W4,(Q)=>{if(this.onLog)this.onLog({server:this.name,timestamp:new Date,level:Q.params.level,logger:Q.params.logger,data:Q.params.data})}),this.client.setRequestHandler($9,(Q)=>{return new Promise((X,Y)=>{if(this.onSamplingRequest)this.onSamplingRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Sampling not supported: no handler registered"))})}),this.client.setRequestHandler(J9,(Q)=>{return new Promise((X,Y)=>{if(this.onElicitationRequest)this.onElicitationRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Elicitation not supported: no handler registered"))})})}emitNotification(Q,X){if(this.onNotification!==void 0)this.onNotification({server:this.name,timestamp:new Date,method:Q,params:X})}handleUnexpectedDisconnect(){if(this.isReconnecting||this.isClosing)return;this.stopHealthChecks(),this.client=null,this.transport=null,this.isReconnecting=!0,this.reconnectAttempt=0,this.setStatus("reconnecting",this.errorMessage),this.scheduleReconnection()}scheduleReconnection(){if(this.isClosing)return;this.reconnectAttempt++;let Q=this.calculateBackoff(this.reconnectAttempt);if(this.nextRetryMs=Q,this.onReconnecting)this.onReconnecting(this.reconnectAttempt,Q);this.reconnectTimeoutHandle=setTimeout(()=>{this.attemptReconnection()},Q)}async attemptReconnection(){if(this.isClosing)return;try{this.transport=new pY(new URL(this.url)),this.client=new N8({name:"emceepee",version:"0.1.0"},{capabilities:{sampling:{},elicitation:{form:{}}}}),this.setupNotificationHandler(),this.transport.onclose=()=>{if(!this.isClosing)this.handleUnexpectedDisconnect()},this.transport.onerror=(Y)=>{if((Y.name==="AbortError"||Y.message.includes("AbortError"))&&(this.isClosing||this.status==="disconnected"))return;this.errorMessage=Y.message,this.handleUnexpectedDisconnect()},await this.client.connect(this.transport);let Q=this.client.getServerCapabilities();this.capabilities={tools:Q?.tools!==void 0,resources:Q?.resources!==void 0,prompts:Q?.prompts!==void 0,resourceTemplates:Q?.resources!==void 0,resourceSubscriptions:Q?.resources?.subscribe===!0};let X=this.reconnectAttempt;if(this.reconnectAttempt=0,this.nextRetryMs=0,this.isReconnecting=!1,this.consecutiveHealthFailures=0,this.healthStatus="healthy",this.setStatus("connected"),this.onReconnected)this.onReconnected(X);this.startHealthChecks()}catch(Q){this.client=null,this.transport=null,this.errorMessage=Q instanceof Error?Q.message:String(Q),this.scheduleReconnection()}}calculateBackoff(Q){let X=zh*Math.pow(Vh,Q-1),Y=Math.min(X,Kh),W=Y*Ah*(Math.random()*2-1);return Math.round(Y+W)}startHealthChecks(){this.stopHealthChecks();let Q=()=>{let X=dU*Fh*(Math.random()*2-1),Y=Math.round(dU+X);this.healthCheckIntervalHandle=setTimeout(()=>{this.performHealthCheck(),Q()},Y)};Q()}stopHealthChecks(){if(this.healthCheckIntervalHandle)clearTimeout(this.healthCheckIntervalHandle),this.healthCheckIntervalHandle=null}async performHealthCheck(){if(!this.client||!this.isConnected())return;try{let Q=new AbortController,X=setTimeout(()=>{Q.abort()},Dh);try{if(await this.client.listTools(),clearTimeout(X),this.consecutiveHealthFailures>0){let Y=this.healthStatus==="degraded";if(this.consecutiveHealthFailures=0,this.healthStatus="healthy",Y&&this.onHealthRestored)this.onHealthRestored()}}catch(Y){throw clearTimeout(X),Y}}catch(Q){this.consecutiveHealthFailures++;let X=Q instanceof Error?Q.message:String(Q);if(this.consecutiveHealthFailures>=Lh&&this.healthStatus!=="degraded"){if(this.healthStatus="degraded",this.onHealthDegraded)this.onHealthDegraded(this.consecutiveHealthFailures,X)}}}setStatus(Q,X){if(this.status=Q,Q==="error"&&X!==void 0)this.errorMessage=X;else this.errorMessage=void 0;if(this.onStatusChange!==void 0)this.onStatusChange(Q,X)}getConnectedClient(){if(!this.isConnected()||!this.client)throw Error(`Client '${this.name}' is not connected`);return this.client}}var xj=WQ(vj(),1);import iY from"node:process";import{PassThrough as ih}from"node:stream";class qG{append(Q){this._buffer=this._buffer?Buffer.concat([this._buffer,Q]):Q}readMessage(){if(!this._buffer)return null;let Q=this._buffer.indexOf(`
|
|
62
|
+
`&&W++}}return[X,Y]}class zG extends TransformStream{constructor({onError:Q,onRetry:X,onComment:Y}={}){let W;super({start($){W=pU({onEvent:(J)=>{$.enqueue(J)},onError(J){Q==="terminate"?$.error(J):typeof Q=="function"&&Q(J)},onRetry:X,onComment:Y})},transform($){W.feed($)}})}}var Bh={initialReconnectionDelay:1000,maxReconnectionDelay:30000,reconnectionDelayGrowFactor:1.5,maxRetries:2};class w9 extends Error{constructor(Q,X){super(`Streamable HTTP error: ${X}`);this.code=Q}}class pY{constructor(Q,X){this._hasCompletedAuthFlow=!1,this._url=Q,this._resourceMetadataUrl=void 0,this._scope=void 0,this._requestInit=X?.requestInit,this._authProvider=X?.authProvider,this._fetch=X?.fetch,this._fetchWithInit=CU(X?.fetch,X?.requestInit),this._sessionId=X?.sessionId,this._reconnectionOptions=X?.reconnectionOptions??Bh}async _authThenStart(){if(!this._authProvider)throw new u6("No auth provider");let Q;try{Q=await YQ(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})}catch(X){throw this.onerror?.(X),X}if(Q!=="AUTHORIZED")throw new u6;return await this._startOrAuthSse({resumptionToken:void 0})}async _commonHeaders(){let Q={};if(this._authProvider){let Y=await this._authProvider.tokens();if(Y)Q.Authorization=`Bearer ${Y.access_token}`}if(this._sessionId)Q["mcp-session-id"]=this._sessionId;if(this._protocolVersion)Q["mcp-protocol-version"]=this._protocolVersion;let X=CY(this._requestInit?.headers);return new Headers({...Q,...X})}async _startOrAuthSse(Q){let{resumptionToken:X}=Q;try{let Y=await this._commonHeaders();if(Y.set("Accept","text/event-stream"),X)Y.set("last-event-id",X);let W=await(this._fetch??fetch)(this._url,{method:"GET",headers:Y,signal:this._abortController?.signal});if(!W.ok){if(await W.body?.cancel(),W.status===401&&this._authProvider)return await this._authThenStart();if(W.status===405)return;throw new w9(W.status,`Failed to open SSE stream: ${W.statusText}`)}this._handleSseStream(W.body,Q,!0)}catch(Y){throw this.onerror?.(Y),Y}}_getNextReconnectionDelay(Q){if(this._serverRetryMs!==void 0)return this._serverRetryMs;let X=this._reconnectionOptions.initialReconnectionDelay,Y=this._reconnectionOptions.reconnectionDelayGrowFactor,W=this._reconnectionOptions.maxReconnectionDelay;return Math.min(X*Math.pow(Y,Q),W)}_scheduleReconnection(Q,X=0){let Y=this._reconnectionOptions.maxRetries;if(X>=Y){this.onerror?.(Error(`Maximum reconnection attempts (${Y}) exceeded.`));return}let W=this._getNextReconnectionDelay(X);this._reconnectionTimeout=setTimeout(()=>{this._startOrAuthSse(Q).catch(($)=>{this.onerror?.(Error(`Failed to reconnect SSE stream: ${$ instanceof Error?$.message:String($)}`)),this._scheduleReconnection(Q,X+1)})},W)}_handleSseStream(Q,X,Y){if(!Q)return;let{onresumptiontoken:W,replayMessageId:$}=X,J,G=!1,H=!1;(async()=>{try{let z=Q.pipeThrough(new TextDecoderStream).pipeThrough(new zG({onRetry:(A)=>{this._serverRetryMs=A}})).getReader();while(!0){let{value:A,done:F}=await z.read();if(F)break;if(A.id)J=A.id,G=!0,W?.(A.id);if(!A.data)continue;if(!A.event||A.event==="message")try{let L=X6.parse(JSON.parse(A.data));if(P1(L)){if(H=!0,$!==void 0)L.id=$}this.onmessage?.(L)}catch(L){this.onerror?.(L)}}if((Y||G)&&!H&&this._abortController&&!this._abortController.signal.aborted)this._scheduleReconnection({resumptionToken:J,onresumptiontoken:W,replayMessageId:$},0)}catch(z){if(this.onerror?.(Error(`SSE stream disconnected: ${z}`)),(Y||G)&&!H&&this._abortController&&!this._abortController.signal.aborted)try{this._scheduleReconnection({resumptionToken:J,onresumptiontoken:W,replayMessageId:$},0)}catch(A){this.onerror?.(Error(`Failed to reconnect: ${A instanceof Error?A.message:String(A)}`))}}})()}async start(){if(this._abortController)throw Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");this._abortController=new AbortController}async finishAuth(Q){if(!this._authProvider)throw new u6("No auth provider");if(await YQ(this._authProvider,{serverUrl:this._url,authorizationCode:Q,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new u6("Failed to authorize")}async close(){if(this._reconnectionTimeout)clearTimeout(this._reconnectionTimeout),this._reconnectionTimeout=void 0;this._abortController?.abort(),this.onclose?.()}async send(Q,X){try{let{resumptionToken:Y,onresumptiontoken:W}=X||{};if(Y){this._startOrAuthSse({resumptionToken:Y,replayMessageId:p1(Q)?Q.id:void 0}).catch((V)=>this.onerror?.(V));return}let $=await this._commonHeaders();$.set("content-type","application/json"),$.set("accept","application/json, text/event-stream");let J={...this._requestInit,method:"POST",headers:$,body:JSON.stringify(Q),signal:this._abortController?.signal},G=await(this._fetch??fetch)(this._url,J),H=G.headers.get("mcp-session-id");if(H)this._sessionId=H;if(!G.ok){let V=await G.text().catch(()=>null);if(G.status===401&&this._authProvider){if(this._hasCompletedAuthFlow)throw new w9(401,"Server returned 401 after successful authentication");let{resourceMetadataUrl:A,scope:F}=JG(G);if(this._resourceMetadataUrl=A,this._scope=F,await YQ(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!=="AUTHORIZED")throw new u6;return this._hasCompletedAuthFlow=!0,this.send(Q)}if(G.status===403&&this._authProvider){let{resourceMetadataUrl:A,scope:F,error:L}=JG(G);if(L==="insufficient_scope"){let D=G.headers.get("WWW-Authenticate");if(this._lastUpscopingHeader===D)throw new w9(403,"Server returned 403 after trying upscoping");if(F)this._scope=F;if(A)this._resourceMetadataUrl=A;if(this._lastUpscopingHeader=D??void 0,await YQ(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetch})!=="AUTHORIZED")throw new u6;return this.send(Q)}}throw new w9(G.status,`Error POSTing to endpoint: ${V}`)}if(this._hasCompletedAuthFlow=!1,this._lastUpscopingHeader=void 0,G.status===202){if(await G.body?.cancel(),p3(Q))this._startOrAuthSse({resumptionToken:void 0}).catch((V)=>this.onerror?.(V));return}let z=(Array.isArray(Q)?Q:[Q]).filter((V)=>("method"in V)&&("id"in V)&&V.id!==void 0).length>0,K=G.headers.get("content-type");if(z)if(K?.includes("text/event-stream"))this._handleSseStream(G.body,{onresumptiontoken:W},!1);else if(K?.includes("application/json")){let V=await G.json(),A=Array.isArray(V)?V.map((F)=>X6.parse(F)):[X6.parse(V)];for(let F of A)this.onmessage?.(F)}else throw await G.body?.cancel(),new w9(-1,`Unexpected content type: ${K}`);else await G.body?.cancel()}catch(Y){throw this.onerror?.(Y),Y}}get sessionId(){return this._sessionId}async terminateSession(){if(!this._sessionId)return;try{let Q=await this._commonHeaders(),X={...this._requestInit,method:"DELETE",headers:Q,signal:this._abortController?.signal},Y=await(this._fetch??fetch)(this._url,X);if(await Y.body?.cancel(),!Y.ok&&Y.status!==405)throw new w9(Y.status,`Failed to terminate session: ${Y.statusText}`);this._sessionId=void 0}catch(Q){throw this.onerror?.(Q),Q}}setProtocolVersion(Q){this._protocolVersion=Q}get protocolVersion(){return this._protocolVersion}async resumeStream(Q,X){await this._startOrAuthSse({resumptionToken:Q,onresumptiontoken:X?.onresumptiontoken})}}var zh=1000,Kh=180000,Vh=2,Ah=0.1,dU=120000,Fh=0.1,Dh=60000,Lh=3;class KG{name;url;headers;onStatusChange;onNotification;onLog;onSamplingRequest;onElicitationRequest;onReconnecting;onReconnected;onHealthDegraded;onHealthRestored;client=null;transport=null;status="disconnected";errorMessage;capabilities;isClosing=!1;reconnectAttempt=0;reconnectTimeoutHandle=null;nextRetryMs=0;isReconnecting=!1;healthCheckIntervalHandle=null;consecutiveHealthFailures=0;healthStatus="healthy";constructor(Q){this.name=Q.name,this.url=Q.url,this.headers=Q.headers,this.onStatusChange=Q.onStatusChange,this.onNotification=Q.onNotification,this.onLog=Q.onLog,this.onSamplingRequest=Q.onSamplingRequest,this.onElicitationRequest=Q.onElicitationRequest,this.onReconnecting=Q.onReconnecting,this.onReconnected=Q.onReconnected,this.onHealthDegraded=Q.onHealthDegraded,this.onHealthRestored=Q.onHealthRestored}getTransportType(){return"http"}getUrl(){return this.url}getInfo(){let Q={name:this.name,url:this.url,status:this.status};if(this.errorMessage!==void 0)Q.error=this.errorMessage;if(this.capabilities!==void 0)Q.capabilities=this.capabilities;return Q}getName(){return this.name}getStatus(){return this.status}isConnected(){return this.status==="connected"}getReconnectionState(){if(this.status!=="reconnecting")return null;return{attempt:this.reconnectAttempt,nextRetryMs:this.nextRetryMs}}getHealthStatus(){return this.healthStatus}getConsecutiveHealthFailures(){return this.consecutiveHealthFailures}async connect(){if(this.status==="connected"||this.status==="connecting")return;this.setStatus("connecting");try{let Q={};if(this.headers)Q.requestInit={headers:this.headers};this.transport=new pY(new URL(this.url),Q),this.client=new N8({name:"emceepee",version:"0.1.0"},{capabilities:{sampling:{},elicitation:{form:{}}}}),this.setupNotificationHandler(),this.transport.onclose=()=>{if(!this.isClosing)this.handleUnexpectedDisconnect()},this.transport.onerror=(Y)=>{if((Y.name==="AbortError"||Y.message.includes("AbortError"))&&(this.isClosing||this.status==="disconnected"))return;this.errorMessage=Y.message,this.handleUnexpectedDisconnect()},await this.client.connect(this.transport);let X=this.client.getServerCapabilities();this.capabilities={tools:X?.tools!==void 0,resources:X?.resources!==void 0,prompts:X?.prompts!==void 0,resourceTemplates:X?.resources!==void 0,resourceSubscriptions:X?.resources?.subscribe===!0},this.setStatus("connected"),this.startHealthChecks()}catch(Q){let X=Q instanceof Error?Q.message:String(Q);throw this.setStatus("error",X),Q}}async disconnect(){if(this.isClosing=!0,this.stopHealthChecks(),this.cancelReconnection(),this.transport)try{await this.transport.close()}catch{}this.client=null,this.transport=null,this.isClosing=!1,this.setStatus("disconnected")}async forceReconnect(){if(this.stopHealthChecks(),this.cancelReconnection(),this.transport){this.isClosing=!0;try{await this.transport.close()}catch{}this.isClosing=!1}this.client=null,this.transport=null,this.reconnectAttempt=0,this.nextRetryMs=0,this.consecutiveHealthFailures=0,this.healthStatus="healthy",await this.connect()}cancelReconnection(){if(this.reconnectTimeoutHandle)clearTimeout(this.reconnectTimeoutHandle),this.reconnectTimeoutHandle=null;this.isReconnecting=!1}async listTools(){let Q=this.getConnectedClient();if(!this.capabilities?.tools)return[];return(await Q.listTools()).tools}async callTool(Q,X={}){return await this.getConnectedClient().callTool({name:Q,arguments:X})}async listResources(){let Q=this.getConnectedClient();if(!this.capabilities?.resources)return[];return(await Q.listResources()).resources}async listResourceTemplates(){let Q=this.getConnectedClient();if(!this.capabilities?.resourceTemplates)return[];return(await Q.listResourceTemplates()).resourceTemplates}async readResource(Q){return await this.getConnectedClient().readResource({uri:Q})}async subscribeResource(Q){let X=this.getConnectedClient();if(!this.capabilities?.resourceSubscriptions)throw Error(`Server '${this.name}' does not support resource subscriptions`);await X.subscribeResource({uri:Q})}async unsubscribeResource(Q){let X=this.getConnectedClient();if(!this.capabilities?.resourceSubscriptions)throw Error(`Server '${this.name}' does not support resource subscriptions`);await X.unsubscribeResource({uri:Q})}supportsResourceSubscriptions(){return this.capabilities?.resourceSubscriptions===!0}async listPrompts(){let Q=this.getConnectedClient();if(!this.capabilities?.prompts)return[];return(await Q.listPrompts()).prompts}async getPrompt(Q,X={}){return await this.getConnectedClient().getPrompt({name:Q,arguments:X})}setupNotificationHandler(){if(!this.client)return;this.client.setNotificationHandler(W9,()=>{this.emitNotification("notifications/tools/list_changed")}),this.client.setNotificationHandler(X9,()=>{this.emitNotification("notifications/resources/list_changed")}),this.client.setNotificationHandler(X4,(Q)=>{this.emitNotification("notifications/resources/updated",Q.params)}),this.client.setNotificationHandler(Y9,()=>{this.emitNotification("notifications/prompts/list_changed")}),this.client.setNotificationHandler(W4,(Q)=>{if(this.onLog)this.onLog({server:this.name,timestamp:new Date,level:Q.params.level,logger:Q.params.logger,data:Q.params.data})}),this.client.setRequestHandler($9,(Q)=>{return new Promise((X,Y)=>{if(this.onSamplingRequest)this.onSamplingRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Sampling not supported: no handler registered"))})}),this.client.setRequestHandler(J9,(Q)=>{return new Promise((X,Y)=>{if(this.onElicitationRequest)this.onElicitationRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Elicitation not supported: no handler registered"))})})}emitNotification(Q,X){if(this.onNotification!==void 0)this.onNotification({server:this.name,timestamp:new Date,method:Q,params:X})}handleUnexpectedDisconnect(){if(this.isReconnecting||this.isClosing)return;this.stopHealthChecks(),this.client=null,this.transport=null,this.isReconnecting=!0,this.reconnectAttempt=0,this.setStatus("reconnecting",this.errorMessage),this.scheduleReconnection()}scheduleReconnection(){if(this.isClosing)return;this.reconnectAttempt++;let Q=this.calculateBackoff(this.reconnectAttempt);if(this.nextRetryMs=Q,this.onReconnecting)this.onReconnecting(this.reconnectAttempt,Q);this.reconnectTimeoutHandle=setTimeout(()=>{this.attemptReconnection()},Q)}async attemptReconnection(){if(this.isClosing)return;try{let Q={};if(this.headers)Q.requestInit={headers:this.headers};this.transport=new pY(new URL(this.url),Q),this.client=new N8({name:"emceepee",version:"0.1.0"},{capabilities:{sampling:{},elicitation:{form:{}}}}),this.setupNotificationHandler(),this.transport.onclose=()=>{if(!this.isClosing)this.handleUnexpectedDisconnect()},this.transport.onerror=(W)=>{if((W.name==="AbortError"||W.message.includes("AbortError"))&&(this.isClosing||this.status==="disconnected"))return;this.errorMessage=W.message,this.handleUnexpectedDisconnect()},await this.client.connect(this.transport);let X=this.client.getServerCapabilities();this.capabilities={tools:X?.tools!==void 0,resources:X?.resources!==void 0,prompts:X?.prompts!==void 0,resourceTemplates:X?.resources!==void 0,resourceSubscriptions:X?.resources?.subscribe===!0};let Y=this.reconnectAttempt;if(this.reconnectAttempt=0,this.nextRetryMs=0,this.isReconnecting=!1,this.consecutiveHealthFailures=0,this.healthStatus="healthy",this.setStatus("connected"),this.onReconnected)this.onReconnected(Y);this.startHealthChecks()}catch(Q){this.client=null,this.transport=null,this.errorMessage=Q instanceof Error?Q.message:String(Q),this.scheduleReconnection()}}calculateBackoff(Q){let X=zh*Math.pow(Vh,Q-1),Y=Math.min(X,Kh),W=Y*Ah*(Math.random()*2-1);return Math.round(Y+W)}startHealthChecks(){this.stopHealthChecks();let Q=()=>{let X=dU*Fh*(Math.random()*2-1),Y=Math.round(dU+X);this.healthCheckIntervalHandle=setTimeout(()=>{this.performHealthCheck(),Q()},Y)};Q()}stopHealthChecks(){if(this.healthCheckIntervalHandle)clearTimeout(this.healthCheckIntervalHandle),this.healthCheckIntervalHandle=null}async performHealthCheck(){if(!this.client||!this.isConnected())return;try{let Q=new AbortController,X=setTimeout(()=>{Q.abort()},Dh);try{if(await this.client.listTools(),clearTimeout(X),this.consecutiveHealthFailures>0){let Y=this.healthStatus==="degraded";if(this.consecutiveHealthFailures=0,this.healthStatus="healthy",Y&&this.onHealthRestored)this.onHealthRestored()}}catch(Y){throw clearTimeout(X),Y}}catch(Q){this.consecutiveHealthFailures++;let X=Q instanceof Error?Q.message:String(Q);if(this.consecutiveHealthFailures>=Lh&&this.healthStatus!=="degraded"){if(this.healthStatus="degraded",this.onHealthDegraded)this.onHealthDegraded(this.consecutiveHealthFailures,X)}}}setStatus(Q,X){if(this.status=Q,Q==="error"&&X!==void 0)this.errorMessage=X;else this.errorMessage=void 0;if(this.onStatusChange!==void 0)this.onStatusChange(Q,X)}getConnectedClient(){if(!this.isConnected()||!this.client)throw Error(`Client '${this.name}' is not connected`);return this.client}}var xj=WQ(vj(),1);import iY from"node:process";import{PassThrough as ih}from"node:stream";class qG{append(Q){this._buffer=this._buffer?Buffer.concat([this._buffer,Q]):Q}readMessage(){if(!this._buffer)return null;let Q=this._buffer.indexOf(`
|
|
63
63
|
`);if(Q===-1)return null;let X=this._buffer.toString("utf8",0,Q).replace(/\r$/,"");return this._buffer=this._buffer.subarray(Q+1),dh(X)}clear(){this._buffer=void 0}}function dh(Q){return X6.parse(JSON.parse(Q))}function _j(Q){return JSON.stringify(Q)+`
|
|
64
64
|
`}var nh=iY.platform==="win32"?["APPDATA","HOMEDRIVE","HOMEPATH","LOCALAPPDATA","PATH","PROCESSOR_ARCHITECTURE","SYSTEMDRIVE","SYSTEMROOT","TEMP","USERNAME","USERPROFILE","PROGRAMFILES"]:["HOME","LOGNAME","PATH","SHELL","TERM","USER"];function oh(){let Q={};for(let X of nh){let Y=iY.env[X];if(Y===void 0)continue;if(Y.startsWith("()"))continue;Q[X]=Y}return Q}class wG{constructor(Q){if(this._readBuffer=new qG,this._stderrStream=null,this._serverParams=Q,Q.stderr==="pipe"||Q.stderr==="overlapped")this._stderrStream=new ih}async start(){if(this._process)throw Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");return new Promise((Q,X)=>{if(this._process=xj.default(this._serverParams.command,this._serverParams.args??[],{env:{...oh(),...this._serverParams.env},stdio:["pipe","pipe",this._serverParams.stderr??"inherit"],shell:!1,windowsHide:iY.platform==="win32"&&rh(),cwd:this._serverParams.cwd}),this._process.on("error",(Y)=>{X(Y),this.onerror?.(Y)}),this._process.on("spawn",()=>{Q()}),this._process.on("close",(Y)=>{this._process=void 0,this.onclose?.()}),this._process.stdin?.on("error",(Y)=>{this.onerror?.(Y)}),this._process.stdout?.on("data",(Y)=>{this._readBuffer.append(Y),this.processReadBuffer()}),this._process.stdout?.on("error",(Y)=>{this.onerror?.(Y)}),this._stderrStream&&this._process.stderr)this._process.stderr.pipe(this._stderrStream)})}get stderr(){if(this._stderrStream)return this._stderrStream;return this._process?.stderr??null}get pid(){return this._process?.pid??null}processReadBuffer(){while(!0)try{let Q=this._readBuffer.readMessage();if(Q===null)break;this.onmessage?.(Q)}catch(Q){this.onerror?.(Q)}}async close(){if(this._process){let Q=this._process;this._process=void 0;let X=new Promise((Y)=>{Q.once("close",()=>{Y()})});try{Q.stdin?.end()}catch{}if(await Promise.race([X,new Promise((Y)=>setTimeout(Y,2000).unref())]),Q.exitCode===null){try{Q.kill("SIGTERM")}catch{}await Promise.race([X,new Promise((Y)=>setTimeout(Y,2000).unref())])}if(Q.exitCode===null)try{Q.kill("SIGKILL")}catch{}}this._readBuffer.clear()}send(Q){return new Promise((X)=>{if(!this._process?.stdin)throw Error("Not connected");let Y=_j(Q);if(this._process.stdin.write(Y))X();else this._process.stdin.once("drain",X)})}}function rh(){return"type"in iY}var th={enabled:!0,maxAttempts:5,baseDelayMs:1000,maxDelayMs:60000,backoffMultiplier:2};class MG{name;command;args;env;cwd;restartConfig;onStatusChange;onNotification;onLog;onSamplingRequest;onElicitationRequest;onLifecycleEvent;client=null;transport=null;status="disconnected";errorMessage;capabilities;isClosing=!1;restartAttempt=0;restartTimeoutHandle=null;nextRetryMs=0;isRestarting=!1;stderrBuffer=[];maxStderrLines=1000;constructor(Q){this.name=Q.name,this.command=Q.command,this.args=Q.args??[],this.env=Q.env,this.cwd=Q.cwd,this.restartConfig={...th,...Q.restartConfig},this.onStatusChange=Q.onStatusChange,this.onNotification=Q.onNotification,this.onLog=Q.onLog,this.onSamplingRequest=Q.onSamplingRequest,this.onElicitationRequest=Q.onElicitationRequest,this.onLifecycleEvent=Q.onLifecycleEvent}getTransportType(){return"stdio"}getInfo(){let Q={transportType:"stdio",name:this.name,url:`stdio://${this.command}`,status:this.status},X=this.transport._process;if(X?.pid!==void 0)Q.pid=X.pid;if(this.errorMessage!==void 0)Q.error=this.errorMessage;if(this.capabilities!==void 0)Q.capabilities=this.capabilities;return Q}getName(){return this.name}getStatus(){return this.status}isConnected(){return this.status==="connected"}getReconnectionState(){if(this.status!=="reconnecting")return null;return{attempt:this.restartAttempt,nextRetryMs:this.nextRetryMs}}getHealthStatus(){return this.isConnected()?"healthy":"degraded"}getConsecutiveHealthFailures(){return this.isConnected()?0:this.restartAttempt}getCommand(){return this.command}getArgs(){return[...this.args]}getStderrBuffer(){return[...this.stderrBuffer]}async connect(){if(this.status==="connected"||this.status==="connecting")return;this.setStatus("connecting");try{await this.createTransport(),this.emitLifecycleEvent({event:"process_started",timestamp:new Date}),this.setStatus("connected")}catch(Q){let X=Q instanceof Error?Q.message:String(Q);throw this.setStatus("error",X),Q}}async disconnect(){if(this.isClosing=!0,this.cancelReconnection(),this.transport)try{await this.transport.close()}catch{}this.client=null,this.transport=null,this.isClosing=!1,this.setStatus("disconnected"),this.emitLifecycleEvent({event:"process_stopped",timestamp:new Date})}async forceReconnect(){if(this.cancelReconnection(),this.transport){this.isClosing=!0;try{await this.transport.close()}catch{}this.isClosing=!1}this.client=null,this.transport=null,this.restartAttempt=0,this.nextRetryMs=0,await this.connect()}cancelReconnection(){if(this.restartTimeoutHandle)clearTimeout(this.restartTimeoutHandle),this.restartTimeoutHandle=null;this.isRestarting=!1}async listTools(){let Q=this.getConnectedClient();if(!this.capabilities?.tools)return[];return(await Q.listTools()).tools}async callTool(Q,X={}){return await this.getConnectedClient().callTool({name:Q,arguments:X})}async listResources(){let Q=this.getConnectedClient();if(!this.capabilities?.resources)return[];return(await Q.listResources()).resources}async listResourceTemplates(){let Q=this.getConnectedClient();if(!this.capabilities?.resourceTemplates)return[];return(await Q.listResourceTemplates()).resourceTemplates}async readResource(Q){return await this.getConnectedClient().readResource({uri:Q})}async subscribeResource(Q){let X=this.getConnectedClient();if(!this.capabilities?.resourceSubscriptions)throw Error(`Server '${this.name}' does not support resource subscriptions`);await X.subscribeResource({uri:Q})}async unsubscribeResource(Q){let X=this.getConnectedClient();if(!this.capabilities?.resourceSubscriptions)throw Error(`Server '${this.name}' does not support resource subscriptions`);await X.unsubscribeResource({uri:Q})}supportsResourceSubscriptions(){return this.capabilities?.resourceSubscriptions===!0}async listPrompts(){let Q=this.getConnectedClient();if(!this.capabilities?.prompts)return[];return(await Q.listPrompts()).prompts}async getPrompt(Q,X={}){return await this.getConnectedClient().getPrompt({name:Q,arguments:X})}async createTransport(){let Q;if(this.env){Q={};for(let[Y,W]of Object.entries(process.env))if(W!==void 0)Q[Y]=W;Object.assign(Q,this.env)}this.transport=new wG({command:this.command,args:this.args,env:Q,cwd:this.cwd,stderr:"pipe"}),this.client=new N8({name:"emceepee",version:"0.1.0"},{capabilities:{sampling:{},elicitation:{form:{}}}}),this.setupNotificationHandler(),this.transport.onclose=()=>{if(!this.isClosing)this.handleProcessExit()},this.transport.onerror=(Y)=>{if(this.isClosing||this.status==="disconnected")return;this.errorMessage=Y.message,this.handleProcessExit()},await this.client.connect(this.transport),this.setupStderrCapture();let X=this.client.getServerCapabilities();this.capabilities={tools:X?.tools!==void 0,resources:X?.resources!==void 0,prompts:X?.prompts!==void 0,resourceTemplates:X?.resources!==void 0,resourceSubscriptions:X?.resources?.subscribe===!0}}setupStderrCapture(){if(!this.transport)return;let Q=this.transport._process;if(Q?.stderr)Q.stderr.on("data",(X)=>{let Y=X.toString().split(`
|
|
65
|
-
`).filter((W)=>W.length>0);for(let W of Y){if(this.stderrBuffer.push(W),this.stderrBuffer.length>this.maxStderrLines)this.stderrBuffer.shift();if(this.onLog)this.onLog({server:this.name,timestamp:new Date,level:"warning",source:"stderr",data:W})}})}handleProcessExit(Q,X){if(this.isRestarting||this.isClosing)return;if(this.emitLifecycleEvent({event:"process_crashed",timestamp:new Date,exitCode:Q,signal:X}),this.client=null,this.transport=null,this.restartConfig.enabled)this.isRestarting=!0,this.restartAttempt=0,this.setStatus("reconnecting",this.errorMessage),this.scheduleRestart();else this.setStatus("error",`Process exited with code ${Q!==void 0?String(Q):"unknown"}`)}scheduleRestart(){if(this.isClosing)return;if(this.restartAttempt++,this.restartAttempt>this.restartConfig.maxAttempts){this.isRestarting=!1,this.setStatus("error","Max restart attempts exceeded"),this.emitLifecycleEvent({event:"restart_failed",timestamp:new Date,attempt:this.restartAttempt-1,error:"Max restart attempts exceeded"});return}let Q=this.calculateBackoff(this.restartAttempt);this.nextRetryMs=Q,this.emitLifecycleEvent({event:"restarting",timestamp:new Date,attempt:this.restartAttempt,nextRetryMs:Q}),this.restartTimeoutHandle=setTimeout(()=>{this.attemptRestart()},Q)}async attemptRestart(){if(this.isClosing)return;try{await this.createTransport();let Q=this.restartAttempt;this.restartAttempt=0,this.nextRetryMs=0,this.isRestarting=!1,this.setStatus("connected"),this.emitLifecycleEvent({event:"restarted",timestamp:new Date,attempt:Q})}catch(Q){this.client=null,this.transport=null,this.errorMessage=Q instanceof Error?Q.message:String(Q),this.scheduleRestart()}}calculateBackoff(Q){let X=this.restartConfig.baseDelayMs*Math.pow(this.restartConfig.backoffMultiplier,Q-1);return Math.min(X,this.restartConfig.maxDelayMs)}setupNotificationHandler(){if(!this.client)return;this.client.setNotificationHandler(W9,()=>{this.emitNotification("notifications/tools/list_changed")}),this.client.setNotificationHandler(X9,()=>{this.emitNotification("notifications/resources/list_changed")}),this.client.setNotificationHandler(X4,(Q)=>{this.emitNotification("notifications/resources/updated",Q.params)}),this.client.setNotificationHandler(Y9,()=>{this.emitNotification("notifications/prompts/list_changed")}),this.client.setNotificationHandler(W4,(Q)=>{if(this.onLog)this.onLog({server:this.name,timestamp:new Date,level:Q.params.level,logger:Q.params.logger,data:Q.params.data,source:"protocol"})}),this.client.setRequestHandler($9,(Q)=>{return new Promise((X,Y)=>{if(this.onSamplingRequest)this.onSamplingRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Sampling not supported: no handler registered"))})}),this.client.setRequestHandler(J9,(Q)=>{return new Promise((X,Y)=>{if(this.onElicitationRequest)this.onElicitationRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Elicitation not supported: no handler registered"))})})}emitNotification(Q,X){if(this.onNotification!==void 0)this.onNotification({server:this.name,timestamp:new Date,method:Q,params:X})}emitLifecycleEvent(Q){if(this.onLifecycleEvent)this.onLifecycleEvent(Q)}setStatus(Q,X){if(this.status=Q,Q==="error"&&X!==void 0)this.errorMessage=X;else this.errorMessage=void 0;if(this.onStatusChange!==void 0)this.onStatusChange(Q,X)}getConnectedClient(){if(!this.isConnected()||!this.client)throw Error(`Client '${this.name}' is not connected`);return this.client}}var ah={sessionTimeoutMs:86400000,cleanupIntervalMs:300000};class bG{sessions=new Map;serverConfigs;config;logger;cleanupIntervalHandle=null;constructor(Q={}){this.config={...ah,...Q},this.logger=Q.logger;let X={logger:Q.logger};this.serverConfigs=new pJ(X),this.startCleanupInterval()}async createSession(){let Q=r0(),X=new tJ(Q,this.config.sessionStateConfig,this.logger);this.sessions.set(Q,X),this.logger?.info("session_created",{sessionId:Q});let Y=this.serverConfigs.listConfigs();for(let W of Y)try{await this.connectSessionToServer(X,W)}catch($){this.logger?.warn("session_auto_connect_failed",{sessionId:Q,server:W.name,error:$ instanceof Error?$.message:String($)})}return X}getSession(Q){return this.sessions.get(Q)}touchSession(Q){this.sessions.get(Q)?.touch()}async destroySession(Q){let X=this.sessions.get(Q);if(!X)return;this.logger?.info("session_destroying",{sessionId:Q}),await X.cleanup(),this.sessions.delete(Q),this.logger?.info("session_destroyed",{sessionId:Q})}async addServer(Q,X,Y){let W=this.sessions.get(Q);if(!W)throw Error(`Session '${Q}' not found`);let $=this.serverConfigs.addConfig(X,Y,Q),J=this.serverConfigs.getConfig(X);if(!J)throw Error(`Failed to add server config for '${X}'`);let G=await this.connectSessionToServer(W,J);if($){for(let[H,B]of this.sessions)if(H!==Q)B.eventSystem.addEvent("server_added",X,{name:X,url:Y,addedBy:Q})}return G}async addStdioServer(Q,X,Y,W,$){let J=this.sessions.get(Q);if(!J)throw Error(`Session '${Q}' not found`);let G=this.serverConfigs.addStdioConfig(X,Y,W,$,Q),H=this.serverConfigs.getConfig(X);if(!H)throw Error(`Failed to add server config for '${X}'`);let B=await this.connectSessionToServer(J,H);if(G){for(let[z,K]of this.sessions)if(z!==Q)K.eventSystem.addEvent("server_added",X,{name:X,type:"stdio",command:Y,args:W,addedBy:Q})}return B}async removeServer(Q,X){if(this.logger?.debug("removeServer_start",{sessionId:Q,serverName:X}),!this.serverConfigs.removeConfig(X))throw this.logger?.debug("removeServer_not_found",{sessionId:Q,serverName:X}),Error(`Server '${X}' not found`);for(let[W,$]of this.sessions)this.logger?.debug("removeServer_disconnecting_session",{sessionId:W,serverName:X,hasConnection:$.getConnection(X)!==void 0}),await this.disconnectSessionFromServer($,X),$.eventSystem.addEvent("server_removed",X,{name:X,removedBy:Q});this.logger?.debug("removeServer_complete",{sessionId:Q,serverName:X})}listServers(Q){let X=this.sessions.get(Q);return this.serverConfigs.listConfigs().map((W)=>{let $=X?.getConnection(W.name),J;if(mJ(W))J=W.url;else if(cJ(W))J=`stdio://${W.command}`;else J="unknown";let G={name:W.name,url:J,connected:$?.status==="connected",status:$?.status??"not_connected",connectedAt:$?.connectedAt,lastError:$?.lastError};if($?.status==="reconnecting"){let H=$.client.getReconnectionState();if(H)G.reconnectAttempt=H.attempt,G.nextRetryMs=H.nextRetryMs}if($?.status==="connected"){G.healthStatus=$.client.getHealthStatus();let H=$.client.getConsecutiveHealthFailures();if(H>0)G.consecutiveHealthFailures=H}return G})}async reconnectServer(Q,X){let Y=this.sessions.get(Q);if(!Y)throw Error(`Session '${Q}' not found`);let W=this.serverConfigs.getConfig(X);if(!W)throw Error(`Server '${X}' not found`);let $=Y.getConnection(X);if(!$){await this.connectSessionToServer(Y,W);return}this.handleBackendDisconnect(Y,X),await $.client.forceReconnect(),Y.setConnectionStatus(X,"connected"),Y.eventSystem.addEvent("server_reconnected",X,{name:X,attemptsTaken:0,forced:!0}),this.logger?.info("session_server_force_reconnected",{sessionId:Y.sessionId,server:X})}async getOrCreateConnection(Q,X){let Y=this.sessions.get(Q);if(!Y)throw Error(`Session '${Q}' not found`);let W=Y.getConnection(X);if(W?.status==="connected")return W.client;let $=this.serverConfigs.getConfig(X);if(!$)throw Error(`Server '${X}' not found`);return(await this.connectSessionToServer(Y,$)).client}getConnectedClient(Q,X){let Y=this.sessions.get(Q);if(!Y)return;let W=Y.getConnection(X);if(W?.status==="connected")return W.client;return}async connectSessionToServer(Q,X){let Y=Q.backendConnections.get(X.name);if(Y?.status==="connected")return Y;if(Y?.status==="connecting")throw Error(`Already connecting to '${X.name}'`);let W;if(mJ(X))W=this.createHttpClient(Q,X);else if(cJ(X))W=this.createStdioClient(Q,X);else throw Error(`Unknown server config type for '${X.name}'`);Q.addConnection(X.name,W);try{await W.connect(),Q.setConnectionStatus(X.name,"connected"),Q.eventSystem.addEvent("server_connected",X.name,{name:X.name,capabilities:W.getInfo().capabilities}),this.logger?.info("session_server_connected",{sessionId:Q.sessionId,server:X.name});let $=Q.getConnection(X.name);if(!$)throw Error("Connection not found after connect");return $}catch($){let J=$ instanceof Error?$.message:String($);throw Q.setConnectionStatus(X.name,"error",J),this.logger?.warn("session_server_connect_failed",{sessionId:Q.sessionId,server:X.name,error:J}),$}}createHttpClient(Q,X){return new KG({name:X.name,url:X.url,onStatusChange:(Y,W)=>{Q.setConnectionStatus(X.name,Y,W)},onNotification:(Y)=>{Q.bufferManager.addNotification(Y)},onLog:(Y)=>{Q.bufferManager.addLog(Y)},onSamplingRequest:(Y)=>{Q.pendingRequests.addSamplingRequest(Y.server,Y.params,Y.resolve,Y.reject)},onElicitationRequest:(Y)=>{Q.pendingRequests.addElicitationRequest(Y.server,Y.params,Y.resolve,Y.reject)},onReconnecting:(Y,W)=>{if(Y===1)this.handleBackendDisconnect(Q,X.name);Q.eventSystem.addEvent("server_reconnecting",X.name,{name:X.name,attempt:Y,nextRetryMs:W}),this.logger?.debug("session_server_reconnecting",{sessionId:Q.sessionId,server:X.name,attempt:Y,nextRetryMs:W})},onReconnected:(Y)=>{Q.setConnectionStatus(X.name,"connected"),Q.eventSystem.addEvent("server_reconnected",X.name,{name:X.name,attemptsTaken:Y}),this.logger?.info("session_server_reconnected",{sessionId:Q.sessionId,server:X.name,attemptsTaken:Y})},onHealthDegraded:(Y,W)=>{Q.eventSystem.addEvent("server_health_degraded",X.name,{name:X.name,consecutiveFailures:Y,lastError:W}),this.logger?.warn("session_server_health_degraded",{sessionId:Q.sessionId,server:X.name,consecutiveFailures:Y,lastError:W})},onHealthRestored:()=>{Q.eventSystem.addEvent("server_health_restored",X.name,{name:X.name}),this.logger?.info("session_server_health_restored",{sessionId:Q.sessionId,server:X.name})}})}createStdioClient(Q,X){return new MG({name:X.name,command:X.command,args:X.args,env:X.env,cwd:X.cwd,restartConfig:X.restartConfig,onStatusChange:(Y,W)=>{Q.setConnectionStatus(X.name,Y,W)},onNotification:(Y)=>{Q.bufferManager.addNotification(Y)},onLog:(Y)=>{Q.bufferManager.addLog({server:Y.server,timestamp:Y.timestamp,level:Y.level,logger:Y.logger,data:Y.data})},onSamplingRequest:(Y)=>{Q.pendingRequests.addSamplingRequest(Y.server,Y.params,Y.resolve,Y.reject)},onElicitationRequest:(Y)=>{Q.pendingRequests.addElicitationRequest(Y.server,Y.params,Y.resolve,Y.reject)},onLifecycleEvent:(Y)=>{switch(Y.event){case"process_started":this.logger?.info("session_stdio_process_started",{sessionId:Q.sessionId,server:X.name});break;case"process_crashed":this.handleBackendDisconnect(Q,X.name),Q.eventSystem.addEvent("server_process_crashed",X.name,{name:X.name,exitCode:Y.exitCode,signal:Y.signal}),this.logger?.warn("session_stdio_process_crashed",{sessionId:Q.sessionId,server:X.name,exitCode:Y.exitCode,signal:Y.signal});break;case"restarting":Q.eventSystem.addEvent("server_reconnecting",X.name,{name:X.name,attempt:Y.attempt,nextRetryMs:Y.nextRetryMs}),this.logger?.debug("session_stdio_restarting",{sessionId:Q.sessionId,server:X.name,attempt:Y.attempt,nextRetryMs:Y.nextRetryMs});break;case"restarted":Q.setConnectionStatus(X.name,"connected"),Q.eventSystem.addEvent("server_reconnected",X.name,{name:X.name,attemptsTaken:Y.attempt}),this.logger?.info("session_stdio_restarted",{sessionId:Q.sessionId,server:X.name,attemptsTaken:Y.attempt});break;case"restart_failed":Q.setConnectionStatus(X.name,"error",Y.error),Q.eventSystem.addEvent("server_restart_failed",X.name,{name:X.name,error:Y.error}),this.logger?.error("session_stdio_restart_failed",{sessionId:Q.sessionId,server:X.name,error:Y.error});break;case"process_stopped":this.logger?.info("session_stdio_process_stopped",{sessionId:Q.sessionId,server:X.name});break}}})}async disconnectSessionFromServer(Q,X){let Y=Q.getConnection(X);if(!Y){this.logger?.debug("disconnectSessionFromServer_no_connection",{sessionId:Q.sessionId,serverName:X});return}this.logger?.debug("disconnectSessionFromServer_start",{sessionId:Q.sessionId,serverName:X,connectionStatus:Y.status});let W=Q.taskManager.getTasksForServer(X);for(let $ of W)if($.status==="working")Q.taskManager.failTask($.taskId,"Server removed");Q.pendingRequests.rejectRequestsForServer(X,"Server removed");try{this.logger?.debug("disconnectSessionFromServer_calling_disconnect",{sessionId:Q.sessionId,serverName:X}),await Y.client.disconnect(),this.logger?.debug("disconnectSessionFromServer_disconnect_complete",{sessionId:Q.sessionId,serverName:X})}catch($){this.logger?.debug("disconnectSessionFromServer_disconnect_error",{sessionId:Q.sessionId,serverName:X,error:$ instanceof Error?$.message:String($)})}Q.removeConnection(X),this.logger?.debug("disconnectSessionFromServer_complete",{sessionId:Q.sessionId,serverName:X})}handleBackendDisconnect(Q,X){let Y=Q.taskManager.getTasksForServer(X);for(let W of Y)if(W.status==="working")Q.taskManager.failTask(W.taskId,"Server disconnected");Q.pendingRequests.rejectRequestsForServer(X,"Server disconnected"),Q.eventSystem.addEvent("server_disconnected",X,{name:X}),this.logger?.info("session_server_disconnected",{sessionId:Q.sessionId,server:X})}startCleanupInterval(){this.cleanupIntervalHandle=setInterval(()=>{this.runSessionCleanup()},this.config.cleanupIntervalMs)}runSessionCleanup(){let Q=Date.now(),X=[];for(let[Y,W]of this.sessions)if(Q-W.lastActivityAt.getTime()>=this.config.sessionTimeoutMs)X.push(Y);for(let Y of X)this.logger?.info("session_timeout_cleanup",{sessionId:Y}),this.destroySession(Y)}async shutdown(){if(this.logger?.info("session_manager_shutdown_start",{sessionCount:this.sessions.size}),this.cleanupIntervalHandle)clearInterval(this.cleanupIntervalHandle),this.cleanupIntervalHandle=null;for(let Q of Array.from(this.sessions.keys()))await this.destroySession(Q);this.logger?.info("session_manager_shutdown_complete",{})}getServerConfigs(){return this.serverConfigs}listSessionIds(){return Array.from(this.sessions.keys())}get sessionCount(){return this.sessions.size}}var sh={maxEvents:1000,retentionMs:300000};class PG{events=new Map;config;logger;constructor(Q={}){this.config={...sh,...Q},this.logger=Q.logger}storeEvent(Q,X){let Y=r0();return this.events.set(Y,{streamId:Q,message:X,createdAt:Date.now()}),this.logger?.debug("sse_event_stored",{eventId:Y,streamId:Q,messageId:X.id}),this.enforceLimit(),this.cleanupOldEvents(),Promise.resolve(Y)}getStreamIdForEventId(Q){return Promise.resolve(this.events.get(Q)?.streamId)}async replayEventsAfter(Q,{send:X}){this.logger?.debug("sse_replay_requested",{lastEventId:Q,totalEvents:this.events.size});let Y=this.events.get(Q);if(!Y)return this.logger?.debug("sse_replay_event_not_found",{lastEventId:Q}),"";let W=Y.streamId,$=!1,J=0,G=[...this.events.keys()].sort();this.logger?.debug("sse_replay_scanning",{streamId:W,sortedIdsCount:G.length});for(let H of G){if(H===Q){$=!0;continue}if($){let B=this.events.get(H);if(B?.streamId===W)this.logger?.debug("sse_replaying_event",{eventId:H,streamId:W}),await X(H,B.message),J++;else this.logger?.debug("sse_skip_different_stream",{eventId:H,eventStreamId:B?.streamId,targetStreamId:W})}}return this.logger?.debug("sse_replay_complete",{streamId:W,replayedCount:J}),W}enforceLimit(){if(this.events.size<=this.config.maxEvents)return;let X=[...this.events.keys()].sort().slice(0,this.events.size-this.config.maxEvents);for(let Y of X)this.events.delete(Y)}cleanupOldEvents(){let Q=Date.now()-this.config.retentionMs;for(let[X,Y]of this.events)if(Y.createdAt<Q)this.events.delete(X)}getEventCount(){return this.events.size}clear(){this.events.clear()}}function yj(Q){return"url"in Q&&!(("type"in Q)&&Q.type==="stdio")}function fj(Q){return"type"in Q}var gj={debug:0,info:1,warn:2,error:3};function hj(Q="info"){let X=gj[Q],Y=(W,$,J)=>{if(gj[W]<X)return;let G=new Date().toISOString(),H=J?` ${JSON.stringify(J)}`:"";switch(W){case"debug":console.debug(`[${G}] DEBUG ${$}${H}`);break;case"info":console.info(`[${G}] INFO ${$}${H}`);break;case"warn":console.warn(`[${G}] WARN ${$}${H}`);break;case"error":console.error(`[${G}] ERROR ${$}${H}`);break}};return{debug:(W,$)=>{Y("debug",W,$)},info:(W,$)=>{Y("info",W,$)},warn:(W,$)=>{Y("warn",W,$)},error:(W,$)=>{Y("error",W,$)}}}var eh={maxRequestsPerSession:100,maxTotalRequests:1000};class ZG{requests=new Map;sessionRequests=new Map;config;logger;constructor(Q={}){this.config={...eh,...Q},this.logger=Q.logger}startRequest(Q,X,Y,W={}){let $=r0(),J={requestId:$,sessionId:Q,type:X,name:Y,server:W.server,args:W.args,startedAt:new Date,status:"pending"};this.requests.set($,J);let G=this.sessionRequests.get(Q)??[];return G.push($),this.sessionRequests.set(Q,G),this.logger?.debug("request_started",{requestId:$,sessionId:Q,type:X,name:Y,server:W.server}),this.enforceSessionLimit(Q),this.enforceTotalLimit(),$}completeRequest(Q,X){let Y=this.requests.get(Q);if(!Y)return;Y.status="completed",Y.endedAt=new Date,Y.durationMs=Y.endedAt.getTime()-Y.startedAt.getTime(),Y.resultSummary=X,this.logger?.debug("request_completed",{requestId:Q,sessionId:Y.sessionId,type:Y.type,name:Y.name,server:Y.server,durationMs:Y.durationMs})}failRequest(Q,X){let Y=this.requests.get(Q);if(!Y)return;Y.status="failed",Y.endedAt=new Date,Y.durationMs=Y.endedAt.getTime()-Y.startedAt.getTime(),Y.error=X,this.logger?.debug("request_failed",{requestId:Q,sessionId:Y.sessionId,type:Y.type,name:Y.name,server:Y.server,durationMs:Y.durationMs,error:X})}timeoutRequest(Q){let X=this.requests.get(Q);if(!X)return;X.status="timeout",X.endedAt=new Date,X.durationMs=X.endedAt.getTime()-X.startedAt.getTime(),this.logger?.debug("request_timeout",{requestId:Q,sessionId:X.sessionId,type:X.type,name:X.name,server:X.server,durationMs:X.durationMs})}getSessionRequests(Q){return(this.sessionRequests.get(Q)??[]).map((Y)=>this.requests.get(Y)).filter((Y)=>Y!==void 0)}getAllRequests(){return Array.from(this.requests.values())}getRequestsBySession(){let Q=new Map;for(let[X]of this.sessionRequests)Q.set(X,this.getSessionRequests(X));return Q}clearSession(Q){let X=this.sessionRequests.get(Q)??[];for(let Y of X)this.requests.delete(Y);this.sessionRequests.delete(Q)}getStats(){let Q={pending:0,completed:0,failed:0,timeout:0},X={};for(let Y of this.requests.values())Q[Y.status]++,X[Y.type]=(X[Y.type]??0)+1;return{totalRequests:this.requests.size,sessionCount:this.sessionRequests.size,byStatus:Q,byType:X}}enforceSessionLimit(Q){let X=this.sessionRequests.get(Q);if(!X||X.length<=this.config.maxRequestsPerSession)return;let Y=X.length-this.config.maxRequestsPerSession,W=X.splice(0,Y);for(let $ of W)this.requests.delete($)}enforceTotalLimit(){if(this.requests.size<=this.config.maxTotalRequests)return;let Q=Array.from(this.requests.values()).sort((Y,W)=>Y.startedAt.getTime()-W.startedAt.getTime()),X=this.requests.size-this.config.maxTotalRequests;for(let Y=0;Y<X;Y++){let W=Q[Y];if(W){this.requests.delete(W.requestId);let $=this.sessionRequests.get(W.sessionId);if($){let J=$.indexOf(W.requestId);if(J>=0)$.splice(J,1)}}}}}function lj(Q){let X=Q.getRequestsBySession(),Y=Q.getStats(),W=1/0,$=0;for(let G of X.values())for(let H of G){W=Math.min(W,H.startedAt.getTime());let B=H.endedAt?.getTime()??Date.now();$=Math.max($,B)}if(W===1/0)W=Date.now()-60000,$=Date.now();let J=Math.max($-W,1000);return`<!DOCTYPE html>
|
|
65
|
+
`).filter((W)=>W.length>0);for(let W of Y){if(this.stderrBuffer.push(W),this.stderrBuffer.length>this.maxStderrLines)this.stderrBuffer.shift();if(this.onLog)this.onLog({server:this.name,timestamp:new Date,level:"warning",source:"stderr",data:W})}})}handleProcessExit(Q,X){if(this.isRestarting||this.isClosing)return;if(this.emitLifecycleEvent({event:"process_crashed",timestamp:new Date,exitCode:Q,signal:X}),this.client=null,this.transport=null,this.restartConfig.enabled)this.isRestarting=!0,this.restartAttempt=0,this.setStatus("reconnecting",this.errorMessage),this.scheduleRestart();else this.setStatus("error",`Process exited with code ${Q!==void 0?String(Q):"unknown"}`)}scheduleRestart(){if(this.isClosing)return;if(this.restartAttempt++,this.restartAttempt>this.restartConfig.maxAttempts){this.isRestarting=!1,this.setStatus("error","Max restart attempts exceeded"),this.emitLifecycleEvent({event:"restart_failed",timestamp:new Date,attempt:this.restartAttempt-1,error:"Max restart attempts exceeded"});return}let Q=this.calculateBackoff(this.restartAttempt);this.nextRetryMs=Q,this.emitLifecycleEvent({event:"restarting",timestamp:new Date,attempt:this.restartAttempt,nextRetryMs:Q}),this.restartTimeoutHandle=setTimeout(()=>{this.attemptRestart()},Q)}async attemptRestart(){if(this.isClosing)return;try{await this.createTransport();let Q=this.restartAttempt;this.restartAttempt=0,this.nextRetryMs=0,this.isRestarting=!1,this.setStatus("connected"),this.emitLifecycleEvent({event:"restarted",timestamp:new Date,attempt:Q})}catch(Q){this.client=null,this.transport=null,this.errorMessage=Q instanceof Error?Q.message:String(Q),this.scheduleRestart()}}calculateBackoff(Q){let X=this.restartConfig.baseDelayMs*Math.pow(this.restartConfig.backoffMultiplier,Q-1);return Math.min(X,this.restartConfig.maxDelayMs)}setupNotificationHandler(){if(!this.client)return;this.client.setNotificationHandler(W9,()=>{this.emitNotification("notifications/tools/list_changed")}),this.client.setNotificationHandler(X9,()=>{this.emitNotification("notifications/resources/list_changed")}),this.client.setNotificationHandler(X4,(Q)=>{this.emitNotification("notifications/resources/updated",Q.params)}),this.client.setNotificationHandler(Y9,()=>{this.emitNotification("notifications/prompts/list_changed")}),this.client.setNotificationHandler(W4,(Q)=>{if(this.onLog)this.onLog({server:this.name,timestamp:new Date,level:Q.params.level,logger:Q.params.logger,data:Q.params.data,source:"protocol"})}),this.client.setRequestHandler($9,(Q)=>{return new Promise((X,Y)=>{if(this.onSamplingRequest)this.onSamplingRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Sampling not supported: no handler registered"))})}),this.client.setRequestHandler(J9,(Q)=>{return new Promise((X,Y)=>{if(this.onElicitationRequest)this.onElicitationRequest({id:crypto.randomUUID(),server:this.name,timestamp:new Date,params:Q.params,resolve:X,reject:Y});else Y(Error("Elicitation not supported: no handler registered"))})})}emitNotification(Q,X){if(this.onNotification!==void 0)this.onNotification({server:this.name,timestamp:new Date,method:Q,params:X})}emitLifecycleEvent(Q){if(this.onLifecycleEvent)this.onLifecycleEvent(Q)}setStatus(Q,X){if(this.status=Q,Q==="error"&&X!==void 0)this.errorMessage=X;else this.errorMessage=void 0;if(this.onStatusChange!==void 0)this.onStatusChange(Q,X)}getConnectedClient(){if(!this.isConnected()||!this.client)throw Error(`Client '${this.name}' is not connected`);return this.client}}var ah={sessionTimeoutMs:86400000,cleanupIntervalMs:300000};class bG{sessions=new Map;serverConfigs;config;logger;cleanupIntervalHandle=null;constructor(Q={}){this.config={...ah,...Q},this.logger=Q.logger;let X={logger:Q.logger};this.serverConfigs=new pJ(X),this.startCleanupInterval()}async createSession(){let Q=r0(),X=new tJ(Q,this.config.sessionStateConfig,this.logger);this.sessions.set(Q,X),this.logger?.info("session_created",{sessionId:Q});let Y=this.serverConfigs.listConfigs();for(let W of Y)try{await this.connectSessionToServer(X,W)}catch($){this.logger?.warn("session_auto_connect_failed",{sessionId:Q,server:W.name,error:$ instanceof Error?$.message:String($)})}return X}getSession(Q){return this.sessions.get(Q)}touchSession(Q){this.sessions.get(Q)?.touch()}async destroySession(Q){let X=this.sessions.get(Q);if(!X)return;this.logger?.info("session_destroying",{sessionId:Q}),await X.cleanup(),this.sessions.delete(Q),this.logger?.info("session_destroyed",{sessionId:Q})}async addServer(Q,X,Y,W){let $=this.sessions.get(Q);if(!$)throw Error(`Session '${Q}' not found`);let J=this.serverConfigs.addConfig(X,Y,{headers:W?.headers},Q),G=this.serverConfigs.getConfig(X);if(!G)throw Error(`Failed to add server config for '${X}'`);let H=await this.connectSessionToServer($,G);if(J){for(let[B,z]of this.sessions)if(B!==Q)z.eventSystem.addEvent("server_added",X,{name:X,url:Y,addedBy:Q})}return H}async addStdioServer(Q,X,Y,W,$){let J=this.sessions.get(Q);if(!J)throw Error(`Session '${Q}' not found`);let G=this.serverConfigs.addStdioConfig(X,Y,W,$,Q),H=this.serverConfigs.getConfig(X);if(!H)throw Error(`Failed to add server config for '${X}'`);let B=await this.connectSessionToServer(J,H);if(G){for(let[z,K]of this.sessions)if(z!==Q)K.eventSystem.addEvent("server_added",X,{name:X,type:"stdio",command:Y,args:W,addedBy:Q})}return B}async removeServer(Q,X){if(this.logger?.debug("removeServer_start",{sessionId:Q,serverName:X}),!this.serverConfigs.removeConfig(X))throw this.logger?.debug("removeServer_not_found",{sessionId:Q,serverName:X}),Error(`Server '${X}' not found`);for(let[W,$]of this.sessions)this.logger?.debug("removeServer_disconnecting_session",{sessionId:W,serverName:X,hasConnection:$.getConnection(X)!==void 0}),await this.disconnectSessionFromServer($,X),$.eventSystem.addEvent("server_removed",X,{name:X,removedBy:Q});this.logger?.debug("removeServer_complete",{sessionId:Q,serverName:X})}listServers(Q){let X=this.sessions.get(Q);return this.serverConfigs.listConfigs().map((W)=>{let $=X?.getConnection(W.name),J;if(mJ(W))J=W.url;else if(cJ(W))J=`stdio://${W.command}`;else J="unknown";let G={name:W.name,url:J,connected:$?.status==="connected",status:$?.status??"not_connected",connectedAt:$?.connectedAt,lastError:$?.lastError};if($?.status==="reconnecting"){let H=$.client.getReconnectionState();if(H)G.reconnectAttempt=H.attempt,G.nextRetryMs=H.nextRetryMs}if($?.status==="connected"){G.healthStatus=$.client.getHealthStatus();let H=$.client.getConsecutiveHealthFailures();if(H>0)G.consecutiveHealthFailures=H}return G})}async reconnectServer(Q,X){let Y=this.sessions.get(Q);if(!Y)throw Error(`Session '${Q}' not found`);let W=this.serverConfigs.getConfig(X);if(!W)throw Error(`Server '${X}' not found`);let $=Y.getConnection(X);if(!$){await this.connectSessionToServer(Y,W);return}this.handleBackendDisconnect(Y,X),await $.client.forceReconnect(),Y.setConnectionStatus(X,"connected"),Y.eventSystem.addEvent("server_reconnected",X,{name:X,attemptsTaken:0,forced:!0}),this.logger?.info("session_server_force_reconnected",{sessionId:Y.sessionId,server:X})}async getOrCreateConnection(Q,X){let Y=this.sessions.get(Q);if(!Y)throw Error(`Session '${Q}' not found`);let W=Y.getConnection(X);if(W?.status==="connected")return W.client;let $=this.serverConfigs.getConfig(X);if(!$)throw Error(`Server '${X}' not found`);return(await this.connectSessionToServer(Y,$)).client}getConnectedClient(Q,X){let Y=this.sessions.get(Q);if(!Y)return;let W=Y.getConnection(X);if(W?.status==="connected")return W.client;return}async connectSessionToServer(Q,X){let Y=Q.backendConnections.get(X.name);if(Y?.status==="connected")return Y;if(Y?.status==="connecting")throw Error(`Already connecting to '${X.name}'`);let W;if(mJ(X))W=this.createHttpClient(Q,X);else if(cJ(X))W=this.createStdioClient(Q,X);else throw Error(`Unknown server config type for '${X.name}'`);Q.addConnection(X.name,W);try{await W.connect(),Q.setConnectionStatus(X.name,"connected"),Q.eventSystem.addEvent("server_connected",X.name,{name:X.name,capabilities:W.getInfo().capabilities}),this.logger?.info("session_server_connected",{sessionId:Q.sessionId,server:X.name});let $=Q.getConnection(X.name);if(!$)throw Error("Connection not found after connect");return $}catch($){let J=$ instanceof Error?$.message:String($);throw Q.setConnectionStatus(X.name,"error",J),this.logger?.warn("session_server_connect_failed",{sessionId:Q.sessionId,server:X.name,error:J}),$}}createHttpClient(Q,X){return new KG({name:X.name,url:X.url,headers:X.headers,onStatusChange:(Y,W)=>{Q.setConnectionStatus(X.name,Y,W)},onNotification:(Y)=>{Q.bufferManager.addNotification(Y)},onLog:(Y)=>{Q.bufferManager.addLog(Y)},onSamplingRequest:(Y)=>{Q.pendingRequests.addSamplingRequest(Y.server,Y.params,Y.resolve,Y.reject)},onElicitationRequest:(Y)=>{Q.pendingRequests.addElicitationRequest(Y.server,Y.params,Y.resolve,Y.reject)},onReconnecting:(Y,W)=>{if(Y===1)this.handleBackendDisconnect(Q,X.name);Q.eventSystem.addEvent("server_reconnecting",X.name,{name:X.name,attempt:Y,nextRetryMs:W}),this.logger?.debug("session_server_reconnecting",{sessionId:Q.sessionId,server:X.name,attempt:Y,nextRetryMs:W})},onReconnected:(Y)=>{Q.setConnectionStatus(X.name,"connected"),Q.eventSystem.addEvent("server_reconnected",X.name,{name:X.name,attemptsTaken:Y}),this.logger?.info("session_server_reconnected",{sessionId:Q.sessionId,server:X.name,attemptsTaken:Y})},onHealthDegraded:(Y,W)=>{Q.eventSystem.addEvent("server_health_degraded",X.name,{name:X.name,consecutiveFailures:Y,lastError:W}),this.logger?.warn("session_server_health_degraded",{sessionId:Q.sessionId,server:X.name,consecutiveFailures:Y,lastError:W})},onHealthRestored:()=>{Q.eventSystem.addEvent("server_health_restored",X.name,{name:X.name}),this.logger?.info("session_server_health_restored",{sessionId:Q.sessionId,server:X.name})}})}createStdioClient(Q,X){return new MG({name:X.name,command:X.command,args:X.args,env:X.env,cwd:X.cwd,restartConfig:X.restartConfig,onStatusChange:(Y,W)=>{Q.setConnectionStatus(X.name,Y,W)},onNotification:(Y)=>{Q.bufferManager.addNotification(Y)},onLog:(Y)=>{Q.bufferManager.addLog({server:Y.server,timestamp:Y.timestamp,level:Y.level,logger:Y.logger,data:Y.data})},onSamplingRequest:(Y)=>{Q.pendingRequests.addSamplingRequest(Y.server,Y.params,Y.resolve,Y.reject)},onElicitationRequest:(Y)=>{Q.pendingRequests.addElicitationRequest(Y.server,Y.params,Y.resolve,Y.reject)},onLifecycleEvent:(Y)=>{switch(Y.event){case"process_started":this.logger?.info("session_stdio_process_started",{sessionId:Q.sessionId,server:X.name});break;case"process_crashed":this.handleBackendDisconnect(Q,X.name),Q.eventSystem.addEvent("server_process_crashed",X.name,{name:X.name,exitCode:Y.exitCode,signal:Y.signal}),this.logger?.warn("session_stdio_process_crashed",{sessionId:Q.sessionId,server:X.name,exitCode:Y.exitCode,signal:Y.signal});break;case"restarting":Q.eventSystem.addEvent("server_reconnecting",X.name,{name:X.name,attempt:Y.attempt,nextRetryMs:Y.nextRetryMs}),this.logger?.debug("session_stdio_restarting",{sessionId:Q.sessionId,server:X.name,attempt:Y.attempt,nextRetryMs:Y.nextRetryMs});break;case"restarted":Q.setConnectionStatus(X.name,"connected"),Q.eventSystem.addEvent("server_reconnected",X.name,{name:X.name,attemptsTaken:Y.attempt}),this.logger?.info("session_stdio_restarted",{sessionId:Q.sessionId,server:X.name,attemptsTaken:Y.attempt});break;case"restart_failed":Q.setConnectionStatus(X.name,"error",Y.error),Q.eventSystem.addEvent("server_restart_failed",X.name,{name:X.name,error:Y.error}),this.logger?.error("session_stdio_restart_failed",{sessionId:Q.sessionId,server:X.name,error:Y.error});break;case"process_stopped":this.logger?.info("session_stdio_process_stopped",{sessionId:Q.sessionId,server:X.name});break}}})}async disconnectSessionFromServer(Q,X){let Y=Q.getConnection(X);if(!Y){this.logger?.debug("disconnectSessionFromServer_no_connection",{sessionId:Q.sessionId,serverName:X});return}this.logger?.debug("disconnectSessionFromServer_start",{sessionId:Q.sessionId,serverName:X,connectionStatus:Y.status});let W=Q.taskManager.getTasksForServer(X);for(let $ of W)if($.status==="working")Q.taskManager.failTask($.taskId,"Server removed");Q.pendingRequests.rejectRequestsForServer(X,"Server removed");try{this.logger?.debug("disconnectSessionFromServer_calling_disconnect",{sessionId:Q.sessionId,serverName:X}),await Y.client.disconnect(),this.logger?.debug("disconnectSessionFromServer_disconnect_complete",{sessionId:Q.sessionId,serverName:X})}catch($){this.logger?.debug("disconnectSessionFromServer_disconnect_error",{sessionId:Q.sessionId,serverName:X,error:$ instanceof Error?$.message:String($)})}Q.removeConnection(X),this.logger?.debug("disconnectSessionFromServer_complete",{sessionId:Q.sessionId,serverName:X})}handleBackendDisconnect(Q,X){let Y=Q.taskManager.getTasksForServer(X);for(let W of Y)if(W.status==="working")Q.taskManager.failTask(W.taskId,"Server disconnected");Q.pendingRequests.rejectRequestsForServer(X,"Server disconnected"),Q.eventSystem.addEvent("server_disconnected",X,{name:X}),this.logger?.info("session_server_disconnected",{sessionId:Q.sessionId,server:X})}startCleanupInterval(){this.cleanupIntervalHandle=setInterval(()=>{this.runSessionCleanup()},this.config.cleanupIntervalMs)}runSessionCleanup(){let Q=Date.now(),X=[];for(let[Y,W]of this.sessions)if(Q-W.lastActivityAt.getTime()>=this.config.sessionTimeoutMs)X.push(Y);for(let Y of X)this.logger?.info("session_timeout_cleanup",{sessionId:Y}),this.destroySession(Y)}async shutdown(){if(this.logger?.info("session_manager_shutdown_start",{sessionCount:this.sessions.size}),this.cleanupIntervalHandle)clearInterval(this.cleanupIntervalHandle),this.cleanupIntervalHandle=null;for(let Q of Array.from(this.sessions.keys()))await this.destroySession(Q);this.logger?.info("session_manager_shutdown_complete",{})}getServerConfigs(){return this.serverConfigs}listSessionIds(){return Array.from(this.sessions.keys())}get sessionCount(){return this.sessions.size}}var sh={maxEvents:1000,retentionMs:300000};class PG{events=new Map;config;logger;constructor(Q={}){this.config={...sh,...Q},this.logger=Q.logger}storeEvent(Q,X){let Y=r0();return this.events.set(Y,{streamId:Q,message:X,createdAt:Date.now()}),this.logger?.debug("sse_event_stored",{eventId:Y,streamId:Q,messageId:X.id}),this.enforceLimit(),this.cleanupOldEvents(),Promise.resolve(Y)}getStreamIdForEventId(Q){return Promise.resolve(this.events.get(Q)?.streamId)}async replayEventsAfter(Q,{send:X}){this.logger?.debug("sse_replay_requested",{lastEventId:Q,totalEvents:this.events.size});let Y=this.events.get(Q);if(!Y)return this.logger?.debug("sse_replay_event_not_found",{lastEventId:Q}),"";let W=Y.streamId,$=!1,J=0,G=[...this.events.keys()].sort();this.logger?.debug("sse_replay_scanning",{streamId:W,sortedIdsCount:G.length});for(let H of G){if(H===Q){$=!0;continue}if($){let B=this.events.get(H);if(B?.streamId===W)this.logger?.debug("sse_replaying_event",{eventId:H,streamId:W}),await X(H,B.message),J++;else this.logger?.debug("sse_skip_different_stream",{eventId:H,eventStreamId:B?.streamId,targetStreamId:W})}}return this.logger?.debug("sse_replay_complete",{streamId:W,replayedCount:J}),W}enforceLimit(){if(this.events.size<=this.config.maxEvents)return;let X=[...this.events.keys()].sort().slice(0,this.events.size-this.config.maxEvents);for(let Y of X)this.events.delete(Y)}cleanupOldEvents(){let Q=Date.now()-this.config.retentionMs;for(let[X,Y]of this.events)if(Y.createdAt<Q)this.events.delete(X)}getEventCount(){return this.events.size}clear(){this.events.clear()}}function yj(Q){return"url"in Q&&!(("type"in Q)&&Q.type==="stdio")}function fj(Q){return"type"in Q}var gj={debug:0,info:1,warn:2,error:3};function hj(Q="info"){let X=gj[Q],Y=(W,$,J)=>{if(gj[W]<X)return;let G=new Date().toISOString(),H=J?` ${JSON.stringify(J)}`:"";switch(W){case"debug":console.debug(`[${G}] DEBUG ${$}${H}`);break;case"info":console.info(`[${G}] INFO ${$}${H}`);break;case"warn":console.warn(`[${G}] WARN ${$}${H}`);break;case"error":console.error(`[${G}] ERROR ${$}${H}`);break}};return{debug:(W,$)=>{Y("debug",W,$)},info:(W,$)=>{Y("info",W,$)},warn:(W,$)=>{Y("warn",W,$)},error:(W,$)=>{Y("error",W,$)}}}var eh={maxRequestsPerSession:100,maxTotalRequests:1000};class ZG{requests=new Map;sessionRequests=new Map;config;logger;constructor(Q={}){this.config={...eh,...Q},this.logger=Q.logger}startRequest(Q,X,Y,W={}){let $=r0(),J={requestId:$,sessionId:Q,type:X,name:Y,server:W.server,args:W.args,startedAt:new Date,status:"pending"};this.requests.set($,J);let G=this.sessionRequests.get(Q)??[];return G.push($),this.sessionRequests.set(Q,G),this.logger?.debug("request_started",{requestId:$,sessionId:Q,type:X,name:Y,server:W.server}),this.enforceSessionLimit(Q),this.enforceTotalLimit(),$}completeRequest(Q,X){let Y=this.requests.get(Q);if(!Y)return;Y.status="completed",Y.endedAt=new Date,Y.durationMs=Y.endedAt.getTime()-Y.startedAt.getTime(),Y.resultSummary=X,this.logger?.debug("request_completed",{requestId:Q,sessionId:Y.sessionId,type:Y.type,name:Y.name,server:Y.server,durationMs:Y.durationMs})}failRequest(Q,X){let Y=this.requests.get(Q);if(!Y)return;Y.status="failed",Y.endedAt=new Date,Y.durationMs=Y.endedAt.getTime()-Y.startedAt.getTime(),Y.error=X,this.logger?.debug("request_failed",{requestId:Q,sessionId:Y.sessionId,type:Y.type,name:Y.name,server:Y.server,durationMs:Y.durationMs,error:X})}timeoutRequest(Q){let X=this.requests.get(Q);if(!X)return;X.status="timeout",X.endedAt=new Date,X.durationMs=X.endedAt.getTime()-X.startedAt.getTime(),this.logger?.debug("request_timeout",{requestId:Q,sessionId:X.sessionId,type:X.type,name:X.name,server:X.server,durationMs:X.durationMs})}getSessionRequests(Q){return(this.sessionRequests.get(Q)??[]).map((Y)=>this.requests.get(Y)).filter((Y)=>Y!==void 0)}getAllRequests(){return Array.from(this.requests.values())}getRequestsBySession(){let Q=new Map;for(let[X]of this.sessionRequests)Q.set(X,this.getSessionRequests(X));return Q}clearSession(Q){let X=this.sessionRequests.get(Q)??[];for(let Y of X)this.requests.delete(Y);this.sessionRequests.delete(Q)}getStats(){let Q={pending:0,completed:0,failed:0,timeout:0},X={};for(let Y of this.requests.values())Q[Y.status]++,X[Y.type]=(X[Y.type]??0)+1;return{totalRequests:this.requests.size,sessionCount:this.sessionRequests.size,byStatus:Q,byType:X}}enforceSessionLimit(Q){let X=this.sessionRequests.get(Q);if(!X||X.length<=this.config.maxRequestsPerSession)return;let Y=X.length-this.config.maxRequestsPerSession,W=X.splice(0,Y);for(let $ of W)this.requests.delete($)}enforceTotalLimit(){if(this.requests.size<=this.config.maxTotalRequests)return;let Q=Array.from(this.requests.values()).sort((Y,W)=>Y.startedAt.getTime()-W.startedAt.getTime()),X=this.requests.size-this.config.maxTotalRequests;for(let Y=0;Y<X;Y++){let W=Q[Y];if(W){this.requests.delete(W.requestId);let $=this.sessionRequests.get(W.sessionId);if($){let J=$.indexOf(W.requestId);if(J>=0)$.splice(J,1)}}}}}function lj(Q){let X=Q.getRequestsBySession(),Y=Q.getStats(),W=1/0,$=0;for(let G of X.values())for(let H of G){W=Math.min(W,H.startedAt.getTime());let B=H.endedAt?.getTime()??Date.now();$=Math.max($,B)}if(W===1/0)W=Date.now()-60000,$=Date.now();let J=Math.max($-W,1000);return`<!DOCTYPE html>
|
|
66
66
|
<html>
|
|
67
67
|
<head>
|
|
68
68
|
<title>MCP Proxy - Request Waterfall</title>
|
|
@@ -291,6 +291,6 @@ Example: add_server(name: "myserver", url: "http://localhost:3001/mcp")
|
|
|
291
291
|
**Stdio Transport**: Provide \`command\` (and optionally \`args\`) to spawn a local MCP server process.
|
|
292
292
|
Example: add_server(name: "myserver", command: "npx", args: ["some-mcp-server"])
|
|
293
293
|
|
|
294
|
-
Stdio servers support automatic crash recovery with exponential backoff restart.`,inputSchema:{name:v.string().describe("Unique name for this server"),url:v.string().url().optional().describe("HTTP URL of the MCP server endpoint (for HTTP transport)"),command:v.string().optional().describe("Command to spawn (for stdio transport, e.g., 'node', 'npx', 'python')"),args:v.array(v.string()).optional().describe("Arguments for the command (for stdio transport)"),env:v.record(v.string()).optional().describe("Environment variables for the spawned process (stdio only)"),cwd:v.string().optional().describe("Working directory for the spawned process (stdio only)"),restartConfig:v.object({enabled:v.boolean().optional().describe("Enable automatic restart on crash (default: true)"),maxAttempts:v.number().optional().describe("Maximum restart attempts (default: 5)"),baseDelayMs:v.number().optional().describe("Base delay before restart in ms (default: 1000)"),maxDelayMs:v.number().optional().describe("Maximum delay between restarts in ms (default: 60000)"),backoffMultiplier:v.number().optional().describe("Backoff multiplier (default: 2)")}).optional().describe("Restart configuration for stdio servers")}},async({name:$,url:J,
|
|
295
|
-
Capabilities: ${JSON.stringify(D)}`,A)}catch(F){let L=F instanceof Error?F.message:String(F);return h(`Failed to add server: ${L}`)}}),Q.registerTool("remove_server",{description:"Disconnect from a backend MCP server and remove it from the configuration. This disconnects ALL sessions from the server.",inputSchema:{name:v.string().describe("Name of the server to remove")}},async({name:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{return await X.removeServer(G.sessionId,$),E0(`Disconnected from server '${$}'`,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to remove server: ${B}`)}}),Q.registerTool("reconnect_server",{description:"Force reconnection to a backend MCP server. Works on connected, disconnected, or reconnecting servers. Cancels any pending reconnection and immediately attempts a fresh connection.",inputSchema:{name:v.string().describe("Name of the server to reconnect")}},async({name:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{return await X.reconnectServer(G.sessionId,$),E0(`Reconnected to server '${$}'`,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to reconnect: ${B}`)}}),Q.registerTool("list_servers",{description:"List all configured backend MCP servers with their connection status for this session",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=X.listServers(G.sessionId);if(H.length===0)return E0("No servers configured",G);let B=H.map((z)=>{let K={name:z.name,url:z.url,status:z.status,connected:z.connected,connectedAt:z.connectedAt?.toISOString(),lastError:z.lastError};if(z.status==="reconnecting")K.reconnectAttempt=z.reconnectAttempt,K.nextRetryMs=z.nextRetryMs;if(z.status==="connected"){if(K.healthStatus=z.healthStatus,z.consecutiveHealthFailures!==void 0&&z.consecutiveHealthFailures>0)K.consecutiveHealthFailures=z.consecutiveHealthFailures}return K});return I0(B,G)}),Q.registerTool("list_tools",{description:"List tools available from backend servers",inputSchema:{server:v.string().default(".*").describe("Regex pattern to match server names (default: .*)"),tool:v.string().default(".*").describe("Regex pattern to match tool names (default: .*)")}},async({server:$,tool:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{let B=new RegExp($),z=new RegExp(J),K=[];for(let V of H.listConnectedServers()){if(!B.test(V))continue;let A=H.getConnection(V);if(A?.status!=="connected")continue;try{let F=await A.client.listTools();for(let L of F)if(z.test(L.name))K.push({server:V,name:L.name,description:L.description,inputSchema:L.inputSchema})}catch{}}if(K.length===0)return E0("No tools available",H);return I0(K,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to list tools: ${z}`)}}),Q.registerTool("execute_tool",{description:"Execute a tool on a specific backend server",inputSchema:{server:v.string().describe("Name of the backend server"),tool:v.string().describe("Name of the tool to execute"),args:v.record(v.unknown()).optional().describe("Arguments to pass to the tool")}},async({server:$,tool:J,args:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");let z=B.getConnection($);if(z?.status==="reconnecting"){let V=z.client.getReconnectionState(),A=V?` (attempt ${String(V.attempt)}, next retry in ${String(V.nextRetryMs)}ms)`:"";return h(`Server '${$}' is reconnecting${A}. Use reconnect_server to force immediate reconnection or await_activity to wait for reconnection.`)}let K=W.startRequest(B.sessionId,"backend_tool",J,{server:$,args:G});try{let A=await(await X.getOrCreateConnection(B.sessionId,$)).callTool(J,G??{}),F=A.isError?"error":"ok";W.completeRequest(K,F);let L=cj(B);if(L)return{content:[...A.content,{type:"text",text:JSON.stringify(L)}],isError:A.isError};return{content:A.content,isError:A.isError}}catch(V){let A=V instanceof Error?V.message:String(V);return W.failRequest(K,A),h(`Failed to execute tool: ${A}`)}}),Q.registerTool("list_resources",{description:"List resources available from backend servers",inputSchema:{server:v.string().optional().describe("Server name to filter by (omit for all servers)")}},async({server:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{let H=[],B=$?[$]:G.listConnectedServers();for(let z of B){let K=G.getConnection(z);if(K?.status!=="connected")continue;try{let V=await K.client.listResources();for(let A of V)H.push({server:z,uri:A.uri,name:A.name,description:A.description,mimeType:A.mimeType})}catch{}}if(H.length===0)return E0("No resources available",G);return I0(H,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to list resources: ${B}`)}}),Q.registerTool("list_resource_templates",{description:"List resource templates available from backend servers. Templates define parameterized resources that can be read with specific arguments.",inputSchema:{server:v.string().optional().describe("Server name to filter by (omit for all servers)")}},async({server:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{let H=[],B=$?[$]:G.listConnectedServers();for(let z of B){let K=G.getConnection(z);if(K?.status!=="connected")continue;try{let V=await K.client.listResourceTemplates();for(let A of V)H.push({server:z,uriTemplate:A.uriTemplate,name:A.name,description:A.description,mimeType:A.mimeType})}catch{}}if(H.length===0)return E0("No resource templates available",G);return I0(H,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to list resource templates: ${B}`)}}),Q.registerTool("read_resource",{description:"Read a specific resource from a backend server",inputSchema:{server:v.string().describe("Name of the backend server"),uri:v.string().describe("URI of the resource to read")}},async({server:$,uri:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");let B=W.startRequest(H.sessionId,"backend_resource",J,{server:$});try{let V=(await(await X.getOrCreateConnection(H.sessionId,$)).readResource(J)).contents.map((A)=>{if("text"in A&&typeof A.text==="string")return{uri:A.uri,mimeType:A.mimeType,text:A.text};else if("blob"in A&&typeof A.blob==="string")return{uri:A.uri,mimeType:A.mimeType,blob:`[base64 data, ${String(A.blob.length)} chars]`};return A});return W.completeRequest(B,`${String(V.length)} content(s)`),I0({contents:V},H)}catch(z){let K=z instanceof Error?z.message:String(z);return W.failRequest(B,K),h(`Failed to read resource: ${K}`)}}),Q.registerTool("subscribe_resource",{description:"Subscribe to updates for a specific resource. The server will send notifications when the resource changes. Use get_notifications or await_activity to receive updates.",inputSchema:{server:v.string().describe("Name of the backend server"),uri:v.string().describe("URI of the resource to subscribe to")}},async({server:$,uri:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{let B=await X.getOrCreateConnection(H.sessionId,$);if(!B.supportsResourceSubscriptions())return h(`Server '${$}' does not support resource subscriptions`);return await B.subscribeResource(J),E0(`Subscribed to resource '${J}' on server '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to subscribe to resource: ${z}`)}}),Q.registerTool("unsubscribe_resource",{description:"Unsubscribe from updates for a specific resource",inputSchema:{server:v.string().describe("Name of the backend server"),uri:v.string().describe("URI of the resource to unsubscribe from")}},async({server:$,uri:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{let B=await X.getOrCreateConnection(H.sessionId,$);if(!B.supportsResourceSubscriptions())return h(`Server '${$}' does not support resource subscriptions`);return await B.unsubscribeResource(J),E0(`Unsubscribed from resource '${J}' on server '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to unsubscribe from resource: ${z}`)}}),Q.registerTool("list_prompts",{description:"List prompts available from backend servers",inputSchema:{server:v.string().optional().describe("Server name to filter by (omit for all servers)")}},async({server:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{let H=[],B=$?[$]:G.listConnectedServers();for(let z of B){let K=G.getConnection(z);if(K?.status!=="connected")continue;try{let V=await K.client.listPrompts();for(let A of V)H.push({server:z,name:A.name,description:A.description,arguments:A.arguments})}catch{}}if(H.length===0)return E0("No prompts available",G);return I0(H,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to list prompts: ${B}`)}}),Q.registerTool("get_prompt",{description:"Get a specific prompt from a backend server",inputSchema:{server:v.string().describe("Name of the backend server"),name:v.string().describe("Name of the prompt to get"),arguments:v.record(v.string()).optional().describe("Arguments to pass to the prompt")}},async({server:$,name:J,arguments:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");try{let K=await(await X.getOrCreateConnection(B.sessionId,$)).getPrompt(J,G??{});return I0(K,B)}catch(z){let K=z instanceof Error?z.message:String(z);return h(`Failed to get prompt: ${K}`)}}),Q.registerTool("get_notifications",{description:"Get and clear buffered notifications from backend servers for this session",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.bufferManager.getAndClearNotifications();if(H.length===0)return E0("No notifications",G);let B=H.map((z)=>({server:z.server,method:z.method,timestamp:z.timestamp.toISOString(),params:z.params}));return I0(B,G)}),Q.registerTool("get_logs",{description:"Get and clear buffered log messages from backend servers for this session",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.bufferManager.getAndClearLogs();if(H.length===0)return E0("No log messages",G);let B=H.map((z)=>({server:z.server,level:z.level,logger:z.logger,timestamp:z.timestamp.toISOString(),data:z.data}));return I0(B,G)}),Q.registerTool("get_sampling_requests",{description:"Get pending sampling requests from backend servers that need LLM responses. These are requests from MCP servers asking for LLM completions. URGENT: Backend servers are blocked waiting for these responses. You MUST respond promptly using respond_to_sampling.",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.pendingRequests.getPendingSamplingRequests();if(H.length===0)return E0("No pending sampling requests",G);let B=H.map((z)=>({requestId:z.requestId,server:z.server,timestamp:z.timestamp.toISOString(),maxTokens:z.params.maxTokens,systemPrompt:z.params.systemPrompt,temperature:z.params.temperature,messages:z.params.messages,modelPreferences:z.params.modelPreferences,tools:z.params.tools?.map((K)=>({name:K.name,description:K.description}))}));return I0(B,G)}),Q.registerTool("respond_to_sampling",{description:"Respond to a pending sampling request with an LLM result",inputSchema:{request_id:v.string().describe("The ID of the sampling request to respond to"),role:v.enum(["user","assistant"]).describe("The role of the message"),content:v.string().describe("The text content of the response"),model:v.string().describe("The model that generated the response"),stop_reason:v.enum(["endTurn","maxTokens","stopSequence","toolUse"]).optional().describe("Why the model stopped generating")}},({request_id:$,role:J,content:G,model:H,stop_reason:B},z)=>{let K=H0(X,z,Y);if(!K)return h("Session not found");try{return K.pendingRequests.respondToSampling($,{role:J,content:{type:"text",text:G},model:H,stopReason:B}),E0(`Responded to sampling request '${$}'`,K)}catch(V){let A=V instanceof Error?V.message:String(V);return h(`Failed to respond: ${A}`)}}),Q.registerTool("cancel_sampling_request",{description:"Cancel a pending sampling request without responding. Use this when you want to ignore a request or if it seems to be part of a loop.",inputSchema:{request_id:v.string().describe("The ID of the sampling request to cancel"),reason:v.string().default("User cancelled").describe("Optional reason for cancellation")}},({request_id:$,reason:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{return H.pendingRequests.cancelSampling($,J),E0(`Cancelled sampling request '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to cancel: ${z}`)}}),Q.registerTool("get_elicitations",{description:"Get pending elicitation requests from backend servers that need user input. These are requests from MCP servers asking for form data or user confirmation. URGENT: Backend servers are blocked waiting for user responses. You MUST respond promptly using respond_to_elicitation or the request may time out.",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.pendingRequests.getPendingElicitationRequests();if(H.length===0)return E0("No pending elicitation requests",G);let B=H.map((z)=>({requestId:z.requestId,server:z.server,timestamp:z.timestamp.toISOString(),mode:"mode"in z.params?z.params.mode:"form",message:z.params.message,requestedSchema:"requestedSchema"in z.params?z.params.requestedSchema:void 0,elicitationId:"elicitationId"in z.params?z.params.elicitationId:void 0,url:"url"in z.params?z.params.url:void 0}));return I0(B,G)}),Q.registerTool("respond_to_elicitation",{description:"Respond to a pending elicitation request with user input",inputSchema:{request_id:v.string().describe("The ID of the elicitation request to respond to"),action:v.enum(["accept","decline","cancel"]).describe("The user's action: accept (with content), decline, or cancel"),content:v.record(v.union([v.string(),v.number(),v.boolean(),v.array(v.string())])).optional().describe("The form field values (required if action is 'accept' for form mode)")}},({request_id:$,action:J,content:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");try{return B.pendingRequests.respondToElicitation($,{action:J,content:G}),E0(`Responded to elicitation request '${$}' with action '${J}'`,B)}catch(z){let K=z instanceof Error?z.message:String(z);return h(`Failed to respond: ${K}`)}}),Q.registerTool("cancel_elicitation_request",{description:"Cancel a pending elicitation request without responding.",inputSchema:{request_id:v.string().describe("The ID of the elicitation request to cancel"),reason:v.string().default("User cancelled").describe("Optional reason for cancellation")}},({request_id:$,reason:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{return H.pendingRequests.cancelElicitation($,J),E0(`Cancelled elicitation request '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to cancel: ${z}`)}}),Q.registerTool("await_activity",{description:"Wait for activity (events, pending requests) or timeout. Use this to poll for changes efficiently instead of repeatedly calling get_* tools. IMPORTANT: If pending_client.sampling or pending_client.elicitation counts are non-zero, you MUST respond promptly - backend servers are blocked waiting.",inputSchema:{timeout_ms:v.number().min(100).max(900000).default(30000).describe("Maximum time to wait in milliseconds (100-900000, default: 30000)"),last_event_id:v.string().optional().describe("Only return events after this ID (for pagination/continuation)")}},async({timeout_ms:$,last_event_id:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");let B=J?H.eventSystem.getEventsAfter(J):H.eventSystem.getNewEvents();if(B.length>0)return I0({triggered_by:"existing_events",events:B.map((K)=>({id:K.id,type:K.type,server:K.server,createdAt:K.createdAt.toISOString(),data:K.data})),pending_server:{tasks:H.taskManager.getAllTasks().map((K)=>({taskId:K.taskId,server:K.server,toolName:K.toolName,status:K.status}))},pending_client:{sampling:H.pendingRequests.getPendingSamplingRequests().length,elicitation:H.pendingRequests.getPendingElicitationRequests().length}},H);let z=await H.eventSystem.waitForActivity($);if(z){let K=H.eventSystem.getNewEvents();return I0({triggered_by:z.type,events:K.map((V)=>({id:V.id,type:V.type,server:V.server,createdAt:V.createdAt.toISOString(),data:V.data})),pending_server:{tasks:H.taskManager.getAllTasks().map((V)=>({taskId:V.taskId,server:V.server,toolName:V.toolName,status:V.status}))},pending_client:{sampling:H.pendingRequests.getPendingSamplingRequests().length,elicitation:H.pendingRequests.getPendingElicitationRequests().length}},H)}return I0({triggered_by:"timeout",events:[],pending_server:{tasks:H.taskManager.getAllTasks().map((K)=>({taskId:K.taskId,server:K.server,toolName:K.toolName,status:K.status}))},pending_client:{sampling:H.pendingRequests.getPendingSamplingRequests().length,elicitation:H.pendingRequests.getPendingElicitationRequests().length}},H)}),Q.registerTool("list_tasks",{description:"List proxy tasks (background tool executions that exceeded timeout)",inputSchema:{include_completed:v.boolean().default(!1).describe("Include completed/failed/cancelled tasks (default: false, only working tasks)"),server:v.string().optional().describe("Filter by server name")}},({include_completed:$,server:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");let B=H.taskManager.getAllTasks($);if(J)B=B.filter((K)=>K.server===J);if(B.length===0)return E0("No tasks",H);let z=B.map((K)=>({taskId:K.taskId,server:K.server,toolName:K.toolName,status:K.status,createdAt:K.createdAt.toISOString(),lastUpdatedAt:K.lastUpdatedAt.toISOString(),error:K.error,hasResult:K.result!==void 0}));return I0(z,H)}),Q.registerTool("get_task",{description:"Get details of a specific task including its result if completed",inputSchema:{task_id:v.string().describe("The task ID to retrieve")}},({task_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.taskManager.getTask($);if(!H)return h(`Task '${$}' not found`);return I0({taskId:H.taskId,server:H.server,toolName:H.toolName,args:H.args,status:H.status,createdAt:H.createdAt.toISOString(),lastUpdatedAt:H.lastUpdatedAt.toISOString(),ttl:H.ttl,error:H.error,result:H.result},G)}),Q.registerTool("cancel_task",{description:"Cancel a working task",inputSchema:{task_id:v.string().describe("The task ID to cancel")}},({task_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");if(G.taskManager.cancelTask($))return E0(`Task '${$}' cancelled`,G);else return h(`Task '${$}' not found or not in working state`)}),Q.registerTool("set_timer",{description:"Set a timer that will fire after a specified duration. When the timer expires, you'll receive a notification in the context info of subsequent tool responses, and it will also appear as a timer_expired event in await_activity.",inputSchema:{duration_ms:v.number().min(1).max(86400000).describe("Duration in milliseconds until the timer fires (max 24 hours)"),message:v.string().min(1).max(500).describe("Message to include in the notification when the timer fires"),interval:v.boolean().default(!1).describe("If true, timer repeats at the specified interval instead of firing once (default: false)")}},({duration_ms:$,message:J,interval:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");try{let z=B.timerManager.createTimer($,J,G);return I0({timerId:z.id,message:z.message,durationMs:z.durationMs,interval:z.interval,createdAt:z.createdAt.toISOString(),expiresAt:z.expiresAt.toISOString()},B)}catch(z){let K=z instanceof Error?z.message:String(z);return h(`Failed to set timer: ${K}`)}}),Q.registerTool("list_timers",{description:"List all timers for this session",inputSchema:{include_inactive:v.boolean().default(!1).describe("Include expired and deleted timers (default: false, only active timers)")}},({include_inactive:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.timerManager.getAllTimers($);if(H.length===0)return E0("No timers",G);let B=H.map((z)=>({id:z.id,message:z.message,durationMs:z.durationMs,status:z.status,interval:z.interval,fireCount:z.fireCount,createdAt:z.createdAt.toISOString(),expiresAt:z.expiresAt.toISOString()}));return I0(B,G)}),Q.registerTool("get_timer",{description:"Get details of a specific timer",inputSchema:{timer_id:v.string().describe("The timer ID to retrieve")}},({timer_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.timerManager.getTimer($);if(!H)return h(`Timer '${$}' not found`);return I0({id:H.id,message:H.message,durationMs:H.durationMs,status:H.status,interval:H.interval,fireCount:H.fireCount,createdAt:H.createdAt.toISOString(),expiresAt:H.expiresAt.toISOString()},G)}),Q.registerTool("delete_timer",{description:"Delete a timer. Returns the timer details before deletion.",inputSchema:{timer_id:v.string().describe("The timer ID to delete")}},({timer_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.timerManager.deleteTimer($);if(!H)return h(`Timer '${$}' not found`);return I0({deleted:!0,timer:{id:H.id,message:H.message,durationMs:H.durationMs,status:H.status,interval:H.interval,fireCount:H.fireCount,createdAt:H.createdAt.toISOString(),expiresAt:H.expiresAt.toISOString()}},G)})}function Bu(){let{configPath:Q,port:X,logLevel:Y}=Ju(),W=hj(Y);W.info("Starting MCP Proxy Server",{port:X,configPath:Q});let $=new bG({logger:W,sessionTimeoutMs:86400000,cleanupIntervalMs:3600000});if(Q)try{let V=Gu(Q);W.info("Loading servers from config",{count:V.servers.length,path:Q});for(let A of V.servers)if(yj(A))W.info("Adding HTTP server config",{name:A.name,url:A.url}),$.getServerConfigs().addConfig(A.name,A.url);else if(fj(A))W.info("Adding stdio server config",{name:A.name,command:A.command}),$.getServerConfigs().addStdioConfig(A.name,A.command,A.args,{env:A.env,cwd:A.cwd,restartConfig:A.restartConfig})}catch(V){W.error("Failed to load config",{error:V instanceof Error?V.message:String(V)}),process.exit(1)}let J=new ZG({logger:W}),G=new _J({name:"emceepee",version:"0.2.0"}),H=new Map,B=new Map;Hu(G,$,H,J);let z=Wu((V,A)=>{let F=V.headers.host??"localhost",L=new URL(V.url??"/",`http://${F}`);if(L.pathname==="/waterfall"||L.pathname==="/waterfall/"){A.writeHead(200,{"Content-Type":"text/html"}),A.end(lj(J));return}if(L.pathname==="/waterfall/json"){A.writeHead(200,{"Content-Type":"application/json"}),A.end(JSON.stringify(mj(J),null,2));return}if(L.pathname!=="/mcp"){A.writeHead(404,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Not found. Available endpoints: /mcp, /waterfall, /waterfall/json"}));return}let D=V.headers["mcp-session-id"];if(V.method==="POST"){let O=D?B.get(D):void 0;if(!O){if(D)W.warn("transport_not_found_for_session",{transportSessionId:D,transportCount:B.size,knownTransports:Array.from(B.keys())});let U=new PG({logger:W}),w=new lJ({sessionIdGenerator:()=>crypto.randomUUID(),eventStore:U,onsessioninitialized:(M)=>{B.set(M,w),$.createSession().then((S)=>{H.set(M,S.sessionId),W.info("Session created",{transportSessionId:M,sessionId:S.sessionId})})}});O=w,G.connect(w)}else{W.debug("using_existing_transport",{transportSessionId:D});let U=H.get(D??"");if(U)$.touchSession(U)}O.handleRequest(V,A)}else if(V.method==="GET"){if(!D){A.writeHead(400,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Missing mcp-session-id header"}));return}let O=B.get(D);if(!O){A.writeHead(404,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Session not found"}));return}A.on("close",()=>{W.info("sse_connection_closed",{transportSessionId:D});let w=B.get(D);if(w){w.close(),B.delete(D);let M=H.get(D);if(M)$.destroySession(M),H.delete(D),W.info("session_closed_via_sse",{transportSessionId:D,sessionId:M})}});let U=V.headers["last-event-id"]!==void 0;if(O.handleRequest(V,A),!U)setTimeout(()=>{W.debug("sending_sse_priming_notification",{transportSessionId:D}),G.sendToolListChanged()},100)}else if(V.method==="DELETE"){if(D&&B.has(D)){B.get(D)?.close(),B.delete(D);let U=H.get(D);if(U)$.destroySession(U),H.delete(D);W.info("Session closed",{transportSessionId:D})}A.writeHead(200),A.end()}else A.writeHead(405,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Method not allowed"}))}),K=async()=>{W.info("Shutting down...",{});for(let V of B.values())V.close();await $.shutdown(),z.close(),process.exit(0)};process.on("SIGINT",()=>void K()),process.on("SIGTERM",()=>void K()),z.listen(X,()=>{W.info("Server started",{url:`http://localhost:${String(X)}/mcp`}),console.log(`MCP Proxy Server running at http://localhost:${String(X)}/mcp`),console.log(`Waterfall UI available at http://localhost:${String(X)}/waterfall`),console.log(`
|
|
294
|
+
Stdio servers support automatic crash recovery with exponential backoff restart.`,inputSchema:{name:v.string().describe("Unique name for this server"),url:v.string().url().optional().describe("HTTP URL of the MCP server endpoint (for HTTP transport)"),headers:v.record(v.string()).optional().describe('Custom headers to send with HTTP requests (e.g., {"Authorization": "Bearer token"})'),command:v.string().optional().describe("Command to spawn (for stdio transport, e.g., 'node', 'npx', 'python')"),args:v.array(v.string()).optional().describe("Arguments for the command (for stdio transport)"),env:v.record(v.string()).optional().describe("Environment variables for the spawned process (stdio only)"),cwd:v.string().optional().describe("Working directory for the spawned process (stdio only)"),restartConfig:v.object({enabled:v.boolean().optional().describe("Enable automatic restart on crash (default: true)"),maxAttempts:v.number().optional().describe("Maximum restart attempts (default: 5)"),baseDelayMs:v.number().optional().describe("Base delay before restart in ms (default: 1000)"),maxDelayMs:v.number().optional().describe("Maximum delay between restarts in ms (default: 60000)"),backoffMultiplier:v.number().optional().describe("Backoff multiplier (default: 2)")}).optional().describe("Restart configuration for stdio servers")}},async({name:$,url:J,headers:G,command:H,args:B,env:z,cwd:K,restartConfig:V},A)=>{let F=H0(X,A,Y);if(!F)return h("Session not found");if(J&&H)return h("Provide either 'url' (for HTTP) or 'command' (for stdio), not both");if(!J&&!H)return h("Must provide either 'url' (for HTTP transport) or 'command' (for stdio transport)");try{let L,D;if(J)L=await X.addServer(F.sessionId,$,J,{headers:G}),D=J;else if(H)L=await X.addStdioServer(F.sessionId,$,H,B,{env:z,cwd:K,restartConfig:V}),D=`stdio://${H}${B?.length?` ${B.join(" ")}`:""}`;else return h("Internal error: no transport specified");let O=L.client.getInfo().capabilities;return E0(`Connected to server '${$}' at ${D}
|
|
295
|
+
Capabilities: ${JSON.stringify(O)}`,F)}catch(L){let D=L instanceof Error?L.message:String(L);return h(`Failed to add server: ${D}`)}}),Q.registerTool("remove_server",{description:"Disconnect from a backend MCP server and remove it from the configuration. This disconnects ALL sessions from the server.",inputSchema:{name:v.string().describe("Name of the server to remove")}},async({name:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{return await X.removeServer(G.sessionId,$),E0(`Disconnected from server '${$}'`,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to remove server: ${B}`)}}),Q.registerTool("reconnect_server",{description:"Force reconnection to a backend MCP server. Works on connected, disconnected, or reconnecting servers. Cancels any pending reconnection and immediately attempts a fresh connection.",inputSchema:{name:v.string().describe("Name of the server to reconnect")}},async({name:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{return await X.reconnectServer(G.sessionId,$),E0(`Reconnected to server '${$}'`,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to reconnect: ${B}`)}}),Q.registerTool("list_servers",{description:"List all configured backend MCP servers with their connection status for this session",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=X.listServers(G.sessionId);if(H.length===0)return E0("No servers configured",G);let B=H.map((z)=>{let K={name:z.name,url:z.url,status:z.status,connected:z.connected,connectedAt:z.connectedAt?.toISOString(),lastError:z.lastError};if(z.status==="reconnecting")K.reconnectAttempt=z.reconnectAttempt,K.nextRetryMs=z.nextRetryMs;if(z.status==="connected"){if(K.healthStatus=z.healthStatus,z.consecutiveHealthFailures!==void 0&&z.consecutiveHealthFailures>0)K.consecutiveHealthFailures=z.consecutiveHealthFailures}return K});return I0(B,G)}),Q.registerTool("list_tools",{description:"List tools available from backend servers",inputSchema:{server:v.string().default(".*").describe("Regex pattern to match server names (default: .*)"),tool:v.string().default(".*").describe("Regex pattern to match tool names (default: .*)")}},async({server:$,tool:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{let B=new RegExp($),z=new RegExp(J),K=[];for(let V of H.listConnectedServers()){if(!B.test(V))continue;let A=H.getConnection(V);if(A?.status!=="connected")continue;try{let F=await A.client.listTools();for(let L of F)if(z.test(L.name))K.push({server:V,name:L.name,description:L.description,inputSchema:L.inputSchema})}catch{}}if(K.length===0)return E0("No tools available",H);return I0(K,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to list tools: ${z}`)}}),Q.registerTool("execute_tool",{description:"Execute a tool on a specific backend server",inputSchema:{server:v.string().describe("Name of the backend server"),tool:v.string().describe("Name of the tool to execute"),args:v.record(v.unknown()).optional().describe("Arguments to pass to the tool")}},async({server:$,tool:J,args:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");let z=B.getConnection($);if(z?.status==="reconnecting"){let V=z.client.getReconnectionState(),A=V?` (attempt ${String(V.attempt)}, next retry in ${String(V.nextRetryMs)}ms)`:"";return h(`Server '${$}' is reconnecting${A}. Use reconnect_server to force immediate reconnection or await_activity to wait for reconnection.`)}let K=W.startRequest(B.sessionId,"backend_tool",J,{server:$,args:G});try{let A=await(await X.getOrCreateConnection(B.sessionId,$)).callTool(J,G??{}),F=A.isError?"error":"ok";W.completeRequest(K,F);let L=cj(B);if(L)return{content:[...A.content,{type:"text",text:JSON.stringify(L)}],isError:A.isError};return{content:A.content,isError:A.isError}}catch(V){let A=V instanceof Error?V.message:String(V);return W.failRequest(K,A),h(`Failed to execute tool: ${A}`)}}),Q.registerTool("list_resources",{description:"List resources available from backend servers",inputSchema:{server:v.string().optional().describe("Server name to filter by (omit for all servers)")}},async({server:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{let H=[],B=$?[$]:G.listConnectedServers();for(let z of B){let K=G.getConnection(z);if(K?.status!=="connected")continue;try{let V=await K.client.listResources();for(let A of V)H.push({server:z,uri:A.uri,name:A.name,description:A.description,mimeType:A.mimeType})}catch{}}if(H.length===0)return E0("No resources available",G);return I0(H,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to list resources: ${B}`)}}),Q.registerTool("list_resource_templates",{description:"List resource templates available from backend servers. Templates define parameterized resources that can be read with specific arguments.",inputSchema:{server:v.string().optional().describe("Server name to filter by (omit for all servers)")}},async({server:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{let H=[],B=$?[$]:G.listConnectedServers();for(let z of B){let K=G.getConnection(z);if(K?.status!=="connected")continue;try{let V=await K.client.listResourceTemplates();for(let A of V)H.push({server:z,uriTemplate:A.uriTemplate,name:A.name,description:A.description,mimeType:A.mimeType})}catch{}}if(H.length===0)return E0("No resource templates available",G);return I0(H,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to list resource templates: ${B}`)}}),Q.registerTool("read_resource",{description:"Read a specific resource from a backend server",inputSchema:{server:v.string().describe("Name of the backend server"),uri:v.string().describe("URI of the resource to read")}},async({server:$,uri:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");let B=W.startRequest(H.sessionId,"backend_resource",J,{server:$});try{let V=(await(await X.getOrCreateConnection(H.sessionId,$)).readResource(J)).contents.map((A)=>{if("text"in A&&typeof A.text==="string")return{uri:A.uri,mimeType:A.mimeType,text:A.text};else if("blob"in A&&typeof A.blob==="string")return{uri:A.uri,mimeType:A.mimeType,blob:`[base64 data, ${String(A.blob.length)} chars]`};return A});return W.completeRequest(B,`${String(V.length)} content(s)`),I0({contents:V},H)}catch(z){let K=z instanceof Error?z.message:String(z);return W.failRequest(B,K),h(`Failed to read resource: ${K}`)}}),Q.registerTool("subscribe_resource",{description:"Subscribe to updates for a specific resource. The server will send notifications when the resource changes. Use get_notifications or await_activity to receive updates.",inputSchema:{server:v.string().describe("Name of the backend server"),uri:v.string().describe("URI of the resource to subscribe to")}},async({server:$,uri:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{let B=await X.getOrCreateConnection(H.sessionId,$);if(!B.supportsResourceSubscriptions())return h(`Server '${$}' does not support resource subscriptions`);return await B.subscribeResource(J),E0(`Subscribed to resource '${J}' on server '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to subscribe to resource: ${z}`)}}),Q.registerTool("unsubscribe_resource",{description:"Unsubscribe from updates for a specific resource",inputSchema:{server:v.string().describe("Name of the backend server"),uri:v.string().describe("URI of the resource to unsubscribe from")}},async({server:$,uri:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{let B=await X.getOrCreateConnection(H.sessionId,$);if(!B.supportsResourceSubscriptions())return h(`Server '${$}' does not support resource subscriptions`);return await B.unsubscribeResource(J),E0(`Unsubscribed from resource '${J}' on server '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to unsubscribe from resource: ${z}`)}}),Q.registerTool("list_prompts",{description:"List prompts available from backend servers",inputSchema:{server:v.string().optional().describe("Server name to filter by (omit for all servers)")}},async({server:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");try{let H=[],B=$?[$]:G.listConnectedServers();for(let z of B){let K=G.getConnection(z);if(K?.status!=="connected")continue;try{let V=await K.client.listPrompts();for(let A of V)H.push({server:z,name:A.name,description:A.description,arguments:A.arguments})}catch{}}if(H.length===0)return E0("No prompts available",G);return I0(H,G)}catch(H){let B=H instanceof Error?H.message:String(H);return h(`Failed to list prompts: ${B}`)}}),Q.registerTool("get_prompt",{description:"Get a specific prompt from a backend server",inputSchema:{server:v.string().describe("Name of the backend server"),name:v.string().describe("Name of the prompt to get"),arguments:v.record(v.string()).optional().describe("Arguments to pass to the prompt")}},async({server:$,name:J,arguments:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");try{let K=await(await X.getOrCreateConnection(B.sessionId,$)).getPrompt(J,G??{});return I0(K,B)}catch(z){let K=z instanceof Error?z.message:String(z);return h(`Failed to get prompt: ${K}`)}}),Q.registerTool("get_notifications",{description:"Get and clear buffered notifications from backend servers for this session",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.bufferManager.getAndClearNotifications();if(H.length===0)return E0("No notifications",G);let B=H.map((z)=>({server:z.server,method:z.method,timestamp:z.timestamp.toISOString(),params:z.params}));return I0(B,G)}),Q.registerTool("get_logs",{description:"Get and clear buffered log messages from backend servers for this session",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.bufferManager.getAndClearLogs();if(H.length===0)return E0("No log messages",G);let B=H.map((z)=>({server:z.server,level:z.level,logger:z.logger,timestamp:z.timestamp.toISOString(),data:z.data}));return I0(B,G)}),Q.registerTool("get_sampling_requests",{description:"Get pending sampling requests from backend servers that need LLM responses. These are requests from MCP servers asking for LLM completions. URGENT: Backend servers are blocked waiting for these responses. You MUST respond promptly using respond_to_sampling.",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.pendingRequests.getPendingSamplingRequests();if(H.length===0)return E0("No pending sampling requests",G);let B=H.map((z)=>({requestId:z.requestId,server:z.server,timestamp:z.timestamp.toISOString(),maxTokens:z.params.maxTokens,systemPrompt:z.params.systemPrompt,temperature:z.params.temperature,messages:z.params.messages,modelPreferences:z.params.modelPreferences,tools:z.params.tools?.map((K)=>({name:K.name,description:K.description}))}));return I0(B,G)}),Q.registerTool("respond_to_sampling",{description:"Respond to a pending sampling request with an LLM result",inputSchema:{request_id:v.string().describe("The ID of the sampling request to respond to"),role:v.enum(["user","assistant"]).describe("The role of the message"),content:v.string().describe("The text content of the response"),model:v.string().describe("The model that generated the response"),stop_reason:v.enum(["endTurn","maxTokens","stopSequence","toolUse"]).optional().describe("Why the model stopped generating")}},({request_id:$,role:J,content:G,model:H,stop_reason:B},z)=>{let K=H0(X,z,Y);if(!K)return h("Session not found");try{return K.pendingRequests.respondToSampling($,{role:J,content:{type:"text",text:G},model:H,stopReason:B}),E0(`Responded to sampling request '${$}'`,K)}catch(V){let A=V instanceof Error?V.message:String(V);return h(`Failed to respond: ${A}`)}}),Q.registerTool("cancel_sampling_request",{description:"Cancel a pending sampling request without responding. Use this when you want to ignore a request or if it seems to be part of a loop.",inputSchema:{request_id:v.string().describe("The ID of the sampling request to cancel"),reason:v.string().default("User cancelled").describe("Optional reason for cancellation")}},({request_id:$,reason:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{return H.pendingRequests.cancelSampling($,J),E0(`Cancelled sampling request '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to cancel: ${z}`)}}),Q.registerTool("get_elicitations",{description:"Get pending elicitation requests from backend servers that need user input. These are requests from MCP servers asking for form data or user confirmation. URGENT: Backend servers are blocked waiting for user responses. You MUST respond promptly using respond_to_elicitation or the request may time out.",inputSchema:{}},($,J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.pendingRequests.getPendingElicitationRequests();if(H.length===0)return E0("No pending elicitation requests",G);let B=H.map((z)=>({requestId:z.requestId,server:z.server,timestamp:z.timestamp.toISOString(),mode:"mode"in z.params?z.params.mode:"form",message:z.params.message,requestedSchema:"requestedSchema"in z.params?z.params.requestedSchema:void 0,elicitationId:"elicitationId"in z.params?z.params.elicitationId:void 0,url:"url"in z.params?z.params.url:void 0}));return I0(B,G)}),Q.registerTool("respond_to_elicitation",{description:"Respond to a pending elicitation request with user input",inputSchema:{request_id:v.string().describe("The ID of the elicitation request to respond to"),action:v.enum(["accept","decline","cancel"]).describe("The user's action: accept (with content), decline, or cancel"),content:v.record(v.union([v.string(),v.number(),v.boolean(),v.array(v.string())])).optional().describe("The form field values (required if action is 'accept' for form mode)")}},({request_id:$,action:J,content:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");try{return B.pendingRequests.respondToElicitation($,{action:J,content:G}),E0(`Responded to elicitation request '${$}' with action '${J}'`,B)}catch(z){let K=z instanceof Error?z.message:String(z);return h(`Failed to respond: ${K}`)}}),Q.registerTool("cancel_elicitation_request",{description:"Cancel a pending elicitation request without responding.",inputSchema:{request_id:v.string().describe("The ID of the elicitation request to cancel"),reason:v.string().default("User cancelled").describe("Optional reason for cancellation")}},({request_id:$,reason:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");try{return H.pendingRequests.cancelElicitation($,J),E0(`Cancelled elicitation request '${$}'`,H)}catch(B){let z=B instanceof Error?B.message:String(B);return h(`Failed to cancel: ${z}`)}}),Q.registerTool("await_activity",{description:"Wait for activity (events, pending requests) or timeout. Use this to poll for changes efficiently instead of repeatedly calling get_* tools. IMPORTANT: If pending_client.sampling or pending_client.elicitation counts are non-zero, you MUST respond promptly - backend servers are blocked waiting.",inputSchema:{timeout_ms:v.number().min(100).max(900000).default(30000).describe("Maximum time to wait in milliseconds (100-900000, default: 30000)"),last_event_id:v.string().optional().describe("Only return events after this ID (for pagination/continuation)")}},async({timeout_ms:$,last_event_id:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");let B=J?H.eventSystem.getEventsAfter(J):H.eventSystem.getNewEvents();if(B.length>0)return I0({triggered_by:"existing_events",events:B.map((K)=>({id:K.id,type:K.type,server:K.server,createdAt:K.createdAt.toISOString(),data:K.data})),pending_server:{tasks:H.taskManager.getAllTasks().map((K)=>({taskId:K.taskId,server:K.server,toolName:K.toolName,status:K.status}))},pending_client:{sampling:H.pendingRequests.getPendingSamplingRequests().length,elicitation:H.pendingRequests.getPendingElicitationRequests().length}},H);let z=await H.eventSystem.waitForActivity($);if(z){let K=H.eventSystem.getNewEvents();return I0({triggered_by:z.type,events:K.map((V)=>({id:V.id,type:V.type,server:V.server,createdAt:V.createdAt.toISOString(),data:V.data})),pending_server:{tasks:H.taskManager.getAllTasks().map((V)=>({taskId:V.taskId,server:V.server,toolName:V.toolName,status:V.status}))},pending_client:{sampling:H.pendingRequests.getPendingSamplingRequests().length,elicitation:H.pendingRequests.getPendingElicitationRequests().length}},H)}return I0({triggered_by:"timeout",events:[],pending_server:{tasks:H.taskManager.getAllTasks().map((K)=>({taskId:K.taskId,server:K.server,toolName:K.toolName,status:K.status}))},pending_client:{sampling:H.pendingRequests.getPendingSamplingRequests().length,elicitation:H.pendingRequests.getPendingElicitationRequests().length}},H)}),Q.registerTool("list_tasks",{description:"List proxy tasks (background tool executions that exceeded timeout)",inputSchema:{include_completed:v.boolean().default(!1).describe("Include completed/failed/cancelled tasks (default: false, only working tasks)"),server:v.string().optional().describe("Filter by server name")}},({include_completed:$,server:J},G)=>{let H=H0(X,G,Y);if(!H)return h("Session not found");let B=H.taskManager.getAllTasks($);if(J)B=B.filter((K)=>K.server===J);if(B.length===0)return E0("No tasks",H);let z=B.map((K)=>({taskId:K.taskId,server:K.server,toolName:K.toolName,status:K.status,createdAt:K.createdAt.toISOString(),lastUpdatedAt:K.lastUpdatedAt.toISOString(),error:K.error,hasResult:K.result!==void 0}));return I0(z,H)}),Q.registerTool("get_task",{description:"Get details of a specific task including its result if completed",inputSchema:{task_id:v.string().describe("The task ID to retrieve")}},({task_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.taskManager.getTask($);if(!H)return h(`Task '${$}' not found`);return I0({taskId:H.taskId,server:H.server,toolName:H.toolName,args:H.args,status:H.status,createdAt:H.createdAt.toISOString(),lastUpdatedAt:H.lastUpdatedAt.toISOString(),ttl:H.ttl,error:H.error,result:H.result},G)}),Q.registerTool("cancel_task",{description:"Cancel a working task",inputSchema:{task_id:v.string().describe("The task ID to cancel")}},({task_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");if(G.taskManager.cancelTask($))return E0(`Task '${$}' cancelled`,G);else return h(`Task '${$}' not found or not in working state`)}),Q.registerTool("set_timer",{description:"Set a timer that will fire after a specified duration. When the timer expires, you'll receive a notification in the context info of subsequent tool responses, and it will also appear as a timer_expired event in await_activity.",inputSchema:{duration_ms:v.number().min(1).max(86400000).describe("Duration in milliseconds until the timer fires (max 24 hours)"),message:v.string().min(1).max(500).describe("Message to include in the notification when the timer fires"),interval:v.boolean().default(!1).describe("If true, timer repeats at the specified interval instead of firing once (default: false)")}},({duration_ms:$,message:J,interval:G},H)=>{let B=H0(X,H,Y);if(!B)return h("Session not found");try{let z=B.timerManager.createTimer($,J,G);return I0({timerId:z.id,message:z.message,durationMs:z.durationMs,interval:z.interval,createdAt:z.createdAt.toISOString(),expiresAt:z.expiresAt.toISOString()},B)}catch(z){let K=z instanceof Error?z.message:String(z);return h(`Failed to set timer: ${K}`)}}),Q.registerTool("list_timers",{description:"List all timers for this session",inputSchema:{include_inactive:v.boolean().default(!1).describe("Include expired and deleted timers (default: false, only active timers)")}},({include_inactive:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.timerManager.getAllTimers($);if(H.length===0)return E0("No timers",G);let B=H.map((z)=>({id:z.id,message:z.message,durationMs:z.durationMs,status:z.status,interval:z.interval,fireCount:z.fireCount,createdAt:z.createdAt.toISOString(),expiresAt:z.expiresAt.toISOString()}));return I0(B,G)}),Q.registerTool("get_timer",{description:"Get details of a specific timer",inputSchema:{timer_id:v.string().describe("The timer ID to retrieve")}},({timer_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.timerManager.getTimer($);if(!H)return h(`Timer '${$}' not found`);return I0({id:H.id,message:H.message,durationMs:H.durationMs,status:H.status,interval:H.interval,fireCount:H.fireCount,createdAt:H.createdAt.toISOString(),expiresAt:H.expiresAt.toISOString()},G)}),Q.registerTool("delete_timer",{description:"Delete a timer. Returns the timer details before deletion.",inputSchema:{timer_id:v.string().describe("The timer ID to delete")}},({timer_id:$},J)=>{let G=H0(X,J,Y);if(!G)return h("Session not found");let H=G.timerManager.deleteTimer($);if(!H)return h(`Timer '${$}' not found`);return I0({deleted:!0,timer:{id:H.id,message:H.message,durationMs:H.durationMs,status:H.status,interval:H.interval,fireCount:H.fireCount,createdAt:H.createdAt.toISOString(),expiresAt:H.expiresAt.toISOString()}},G)})}function Bu(){let{configPath:Q,port:X,logLevel:Y}=Ju(),W=hj(Y);W.info("Starting MCP Proxy Server",{port:X,configPath:Q});let $=new bG({logger:W,sessionTimeoutMs:86400000,cleanupIntervalMs:3600000});if(Q)try{let V=Gu(Q);W.info("Loading servers from config",{count:V.servers.length,path:Q});for(let A of V.servers)if(yj(A))W.info("Adding HTTP server config",{name:A.name,url:A.url}),$.getServerConfigs().addConfig(A.name,A.url);else if(fj(A))W.info("Adding stdio server config",{name:A.name,command:A.command}),$.getServerConfigs().addStdioConfig(A.name,A.command,A.args,{env:A.env,cwd:A.cwd,restartConfig:A.restartConfig})}catch(V){W.error("Failed to load config",{error:V instanceof Error?V.message:String(V)}),process.exit(1)}let J=new ZG({logger:W}),G=new _J({name:"emceepee",version:"0.2.0"}),H=new Map,B=new Map;Hu(G,$,H,J);let z=Wu((V,A)=>{let F=V.headers.host??"localhost",L=new URL(V.url??"/",`http://${F}`);if(L.pathname==="/waterfall"||L.pathname==="/waterfall/"){A.writeHead(200,{"Content-Type":"text/html"}),A.end(lj(J));return}if(L.pathname==="/waterfall/json"){A.writeHead(200,{"Content-Type":"application/json"}),A.end(JSON.stringify(mj(J),null,2));return}if(L.pathname!=="/mcp"){A.writeHead(404,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Not found. Available endpoints: /mcp, /waterfall, /waterfall/json"}));return}let D=V.headers["mcp-session-id"];if(V.method==="POST"){let O=D?B.get(D):void 0;if(!O){if(D)W.warn("transport_not_found_for_session",{transportSessionId:D,transportCount:B.size,knownTransports:Array.from(B.keys())});let U=new PG({logger:W}),w=new lJ({sessionIdGenerator:()=>crypto.randomUUID(),eventStore:U,onsessioninitialized:(M)=>{B.set(M,w),$.createSession().then((S)=>{H.set(M,S.sessionId),W.info("Session created",{transportSessionId:M,sessionId:S.sessionId})})}});O=w,G.connect(w)}else{W.debug("using_existing_transport",{transportSessionId:D});let U=H.get(D??"");if(U)$.touchSession(U)}O.handleRequest(V,A)}else if(V.method==="GET"){if(!D){A.writeHead(400,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Missing mcp-session-id header"}));return}let O=B.get(D);if(!O){A.writeHead(404,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Session not found"}));return}A.on("close",()=>{W.info("sse_connection_closed",{transportSessionId:D});let w=B.get(D);if(w){w.close(),B.delete(D);let M=H.get(D);if(M)$.destroySession(M),H.delete(D),W.info("session_closed_via_sse",{transportSessionId:D,sessionId:M})}});let U=V.headers["last-event-id"]!==void 0;if(O.handleRequest(V,A),!U)setTimeout(()=>{W.debug("sending_sse_priming_notification",{transportSessionId:D}),G.sendToolListChanged()},100)}else if(V.method==="DELETE"){if(D&&B.has(D)){B.get(D)?.close(),B.delete(D);let U=H.get(D);if(U)$.destroySession(U),H.delete(D);W.info("Session closed",{transportSessionId:D})}A.writeHead(200),A.end()}else A.writeHead(405,{"Content-Type":"application/json"}),A.end(JSON.stringify({error:"Method not allowed"}))}),K=async()=>{W.info("Shutting down...",{});for(let V of B.values())V.close();await $.shutdown(),z.close(),process.exit(0)};process.on("SIGINT",()=>void K()),process.on("SIGTERM",()=>void K()),z.listen(X,()=>{W.info("Server started",{url:`http://localhost:${String(X)}/mcp`}),console.log(`MCP Proxy Server running at http://localhost:${String(X)}/mcp`),console.log(`Waterfall UI available at http://localhost:${String(X)}/waterfall`),console.log(`
|
|
296
296
|
Available tools:`),console.log(" Server management: add_server, remove_server, reconnect_server, list_servers"),console.log(" Tools: list_tools, execute_tool"),console.log(" Resources: list_resources, list_resource_templates, read_resource, subscribe_resource, unsubscribe_resource"),console.log(" Prompts: list_prompts, get_prompt"),console.log(" Notifications: get_notifications, get_logs"),console.log(" Sampling: get_sampling_requests, respond_to_sampling"),console.log(" Elicitation: get_elicitations, respond_to_elicitation"),console.log(" Activity: await_activity"),console.log(" Tasks: list_tasks, get_task, cancel_task")})}Bu();
|