@@ -67,6 +67,10 @@ export const Failed = NamedError.create("MCPFailed", {
6767 name : Schema . String ,
6868} )
6969
70+ export class NotFoundError extends Schema . TaggedErrorClass < NotFoundError > ( ) ( "MCP.NotFoundError" , {
71+ name : Schema . String ,
72+ } ) { }
73+
7074type MCPClient = Client
7175
7276const StatusConnected = Schema . Struct ( { status : Schema . Literal ( "connected" ) } ) . annotate ( {
@@ -242,8 +246,8 @@ export interface Interface {
242246 readonly prompts : ( ) => Effect . Effect < Record < string , PromptInfo & { client : string } > >
243247 readonly resources : ( ) => Effect . Effect < Record < string , ResourceInfo & { client : string } > >
244248 readonly add : ( name : string , mcp : ConfigMCP . Info ) => Effect . Effect < { status : Record < string , Status > | Status } >
245- readonly connect : ( name : string ) => Effect . Effect < void >
246- readonly disconnect : ( name : string ) => Effect . Effect < void >
249+ readonly connect : ( name : string ) => Effect . Effect < void , NotFoundError >
250+ readonly disconnect : ( name : string ) => Effect . Effect < void , NotFoundError >
247251 readonly getPrompt : (
248252 clientName : string ,
249253 name : string ,
@@ -253,11 +257,11 @@ export interface Interface {
253257 clientName : string ,
254258 resourceUri : string ,
255259 ) => Effect . Effect < Awaited < ReturnType < MCPClient [ "readResource" ] > > | undefined >
256- readonly startAuth : ( mcpName : string ) => Effect . Effect < { authorizationUrl : string ; oauthState : string } >
257- readonly authenticate : ( mcpName : string ) => Effect . Effect < Status >
258- readonly finishAuth : ( mcpName : string , authorizationCode : string ) => Effect . Effect < Status >
260+ readonly startAuth : ( mcpName : string ) => Effect . Effect < { authorizationUrl : string ; oauthState : string } , NotFoundError >
261+ readonly authenticate : ( mcpName : string ) => Effect . Effect < Status , NotFoundError >
262+ readonly finishAuth : ( mcpName : string , authorizationCode : string ) => Effect . Effect < Status , NotFoundError >
259263 readonly removeAuth : ( mcpName : string ) => Effect . Effect < void >
260- readonly supportsOAuth : ( mcpName : string ) => Effect . Effect < boolean >
264+ readonly supportsOAuth : ( mcpName : string ) => Effect . Effect < boolean , NotFoundError >
261265 readonly hasStoredTokens : ( mcpName : string ) => Effect . Effect < boolean >
262266 readonly getAuthStatus : ( mcpName : string ) => Effect . Effect < AuthStatus >
263267}
@@ -642,15 +646,12 @@ export const layer = Layer.effect(
642646 } )
643647
644648 const connect = Effect . fn ( "MCP.connect" ) ( function * ( name : string ) {
645- const mcp = yield * getMcpConfig ( name )
646- if ( ! mcp ) {
647- log . error ( "MCP config not found or invalid" , { name } )
648- return
649- }
649+ const mcp = yield * requireMcpConfig ( name )
650650 yield * createAndStore ( name , { ...mcp , enabled : true } )
651651 } )
652652
653653 const disconnect = Effect . fn ( "MCP.disconnect" ) ( function * ( name : string ) {
654+ yield * requireMcpConfig ( name )
654655 const s = yield * InstanceState . get ( state )
655656 yield * closeClient ( s , name )
656657 delete s . clients [ name ]
@@ -759,9 +760,14 @@ export const layer = Layer.effect(
759760 return mcpConfig
760761 } )
761762
762- const startAuth = Effect . fn ( "MCP.startAuth" ) ( function * ( mcpName : string ) {
763+ const requireMcpConfig = Effect . fnUntraced ( function * ( mcpName : string ) {
763764 const mcpConfig = yield * getMcpConfig ( mcpName )
764- if ( ! mcpConfig ) throw new Error ( `MCP server ${ mcpName } not found or disabled` )
765+ if ( ! mcpConfig ) return yield * new NotFoundError ( { name : mcpName } )
766+ return mcpConfig
767+ } )
768+
769+ const startAuth = Effect . fn ( "MCP.startAuth" ) ( function * ( mcpName : string ) {
770+ const mcpConfig = yield * requireMcpConfig ( mcpName )
765771 if ( mcpConfig . type !== "remote" ) throw new Error ( `MCP server ${ mcpName } is not a remote server` )
766772 if ( mcpConfig . oauth === false ) throw new Error ( `MCP server ${ mcpName } has OAuth explicitly disabled` )
767773 const url = remoteURL ( mcpName , mcpConfig . url )
@@ -825,11 +831,9 @@ export const layer = Layer.effect(
825831 const result = yield * startAuth ( mcpName )
826832 if ( ! result . authorizationUrl ) {
827833 const client = "client" in result ? result . client : undefined
828- const mcpConfig = yield * getMcpConfig ( mcpName )
829- if ( ! mcpConfig ) {
830- yield * Effect . tryPromise ( ( ) => client ?. close ( ) ?? Promise . resolve ( ) ) . pipe ( Effect . ignore )
831- return { status : "failed" , error : "MCP config not found after auth" } as Status
832- }
834+ const mcpConfig = yield * requireMcpConfig ( mcpName ) . pipe (
835+ Effect . tapError ( ( ) => Effect . tryPromise ( ( ) => client ?. close ( ) ?? Promise . resolve ( ) ) . pipe ( Effect . ignore ) ) ,
836+ )
833837
834838 const listed = client ? yield * defs ( mcpName , client , mcpConfig . timeout ) : undefined
835839 if ( ! client || ! listed ) {
@@ -880,6 +884,7 @@ export const layer = Layer.effect(
880884 } )
881885
882886 const finishAuth = Effect . fn ( "MCP.finishAuth" ) ( function * ( mcpName : string , authorizationCode : string ) {
887+ yield * requireMcpConfig ( mcpName )
883888 const transport = pendingOAuthTransports . get ( mcpName )
884889 if ( ! transport ) throw new Error ( `No pending OAuth flow for MCP server: ${ mcpName } ` )
885890
@@ -898,8 +903,7 @@ export const layer = Layer.effect(
898903 yield * auth . clearCodeVerifier ( mcpName )
899904 pendingOAuthTransports . delete ( mcpName )
900905
901- const mcpConfig = yield * getMcpConfig ( mcpName )
902- if ( ! mcpConfig ) return { status : "failed" , error : "MCP config not found after auth" } as Status
906+ const mcpConfig = yield * requireMcpConfig ( mcpName )
903907
904908 return yield * createAndStore ( mcpName , mcpConfig )
905909 } )
@@ -912,8 +916,7 @@ export const layer = Layer.effect(
912916 } )
913917
914918 const supportsOAuth = Effect . fn ( "MCP.supportsOAuth" ) ( function * ( mcpName : string ) {
915- const mcpConfig = yield * getMcpConfig ( mcpName )
916- if ( ! mcpConfig ) return false
919+ const mcpConfig = yield * requireMcpConfig ( mcpName )
917920 return mcpConfig . type === "remote" && mcpConfig . oauth !== false
918921 } )
919922
0 commit comments