eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 4.83 kB
JavaScript
import{isObject}from"#shared/guards.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{evictScopedToken,resolveScopedToken}from"#runtime/connections/scoped-authorization.js";import{ConnectionAuthorizationRequiredError}from"#connections/errors.js";import{resolveConnectionAuthorization}from"#runtime/connections/resolve-authorization.js";import{createMCPClient}from"#compiled/@ai-sdk/mcp/index.js";import{omitProvidedArgumentsFromSchema,resolveProvidedArguments}from"#runtime/connections/provided-arguments.js";var McpConnectionClient=class{#e;#t;#n;#r;#i;constructor(e){this.#i=e}async connect(){if(this.#t!==void 0)return this.#t;if(this.#e!==void 0)return this.#e;this.#e=this.#a();try{return this.#t=await this.#e,this.#t}catch(e){throw this.#e=void 0,e}}async#a(){let e=await resolveHeaders(this.#i),t=this.#i.url;try{return await createMCPClient({transport:{type:`http`,url:t,headers:e}})}catch(n){if(!isMcpHttpFallbackRetryableError(n))throw n;return await createMCPClient({transport:{type:`sse`,url:t,headers:e}})}}async getToolMetadata(){return(await this.#o()).metadata}async getTools(){return(await this.#o()).tools}async executeTool(e,t,n){try{let{tools:r}=await this.#o(),i=r[e];if(i?.execute===void 0)throw Error(`Tool "${e}" not found in connection "${this.#i.connectionName}".`);let a=await resolveProvidedArguments({args:t,callId:n.callId,connection:this.#i,toolName:e});return await i.execute(a,{abortSignal:n.abortSignal})}catch(e){return await this.#l(e)}}async#o(){if(this.#r!==void 0)return this.#r;if(this.#n!==void 0)return this.#n;this.#n=this.#s();try{return this.#r=await this.#n,this.#r}catch(e){throw this.#n=void 0,e}}async#s(){try{return await this.#c()}catch(e){return await this.#l(e)}}async#c(){let e=await this.connect(),t=await e.listTools(),n=this.#i.tools,r=n===void 0?t.tools:t.tools.filter(e=>passesToolFilter(e.name,n)),i=Object.keys(this.#i.toolCall?.providedArguments??{}),a=r.map(e=>({...e,inputSchema:omitProvidedArgumentsFromSchema(e.inputSchema,i)})),o=e.toolsFromDefinitions({tools:a});return{metadata:a.map(e=>({annotations:e.annotations,description:e.description??``,inputSchema:e.inputSchema??{},name:e.name,outputSchema:`outputSchema`in e&&e.outputSchema!==void 0?e.outputSchema:void 0})),tools:o}}async close(){this.#t!==void 0&&(await this.#t.close(),this.#t=void 0),this.#e=void 0,this.#n=void 0,this.#r=void 0}async#l(e){throw isMcpAuthRequiredError(e)?(await this.#u(),await this.close(),new ConnectionAuthorizationRequiredError(this.#i.connectionName,{message:`Connection "${this.#i.connectionName}" requires authorization (the server rejected the token).`})):e}async#u(){let e=await resolveConnectionAuthorization(this.#i);e!==void 0&&await evictScopedToken({authorization:e,connection:{url:this.#i.url},instanceId:this.#i.instanceId,scope:this.#i.connectionName})}};function isMcpAuthRequiredError(e){return readHttpStatus(e)===401}function isMcpHttpFallbackRetryableError(e){let t=readHttpStatus(e);return t===400||t===404||t===405}function readHttpStatus(e){for(let t of walkErrorChain(e)){if(!isObject(t))continue;let e=readStatusField(t);if(e!==void 0)return e;let n=t.response;if(isObject(n)){let e=readStatusField(n);if(e!==void 0)return e}if(typeof t.message==`string`){let e=/\bHTTP\s+(\d{3})\b/u.exec(t.message);if(e?.[1]!==void 0)return Number(e[1])}}}function readStatusField(e){if(typeof e.status==`number`)return e.status;if(typeof e.statusCode==`number`)return e.statusCode}function*walkErrorChain(e){let t=e,n=new Set;for(;t!=null&&!n.has(t);){if(n.add(t),yield t,!isObject(t)||!(`cause`in t))return;t=t.cause}}function passesToolFilter(e,t){return t===void 0?!0:`allow`in t?t.allow.includes(e):!t.block.includes(e)}async function resolveHeaders(e){let t={},n,getCallbackContext=()=>n??=buildCallbackContext(),r=await resolveConnectionAuthorization(e,typeof e.authorization==`function`?getCallbackContext():void 0);if(r!==void 0&&(t.Authorization=`Bearer ${(await resolveToken(e,r)).token}`),e.headers!==void 0){let n=await resolveHeadersDefinition(e.headers,getCallbackContext);for(let[i,a]of Object.entries(n)){if(r!==void 0&&i.toLowerCase()===`authorization`)throw Error(`Connection "${e.connectionName}" headers must not include an "Authorization" key when "authorization" is also provided.`);t[i]=a}}return t}async function resolveToken(e,t){return await resolveScopedToken({authorization:t,connection:{url:e.url},instanceId:e.instanceId,scope:e.connectionName})}async function resolveHeadersDefinition(e,t){if(typeof e==`function`)return{...await e(t())};let n={},r=Object.entries(e);for(let[e,i]of r)n[e]=await resolveHeaderValue(i,t);return n}async function resolveHeaderValue(e,t){return typeof e==`function`?await e(t()):await e}export{McpConnectionClient,isMcpAuthRequiredError,passesToolFilter,resolveHeaders};