@@ -6,6 +6,25 @@ import Foundation
66 @preconcurrency import SystemPackage
77#endif
88
9+ /// Information about a required URL elicitation
10+ public struct URLElicitationInfo : Codable , Hashable , Sendable {
11+ /// Elicitation mode (must be "url")
12+ public var mode : String
13+ /// Unique identifier for this elicitation
14+ public var elicitationId : String
15+ /// URL for the user to visit
16+ public var url : String
17+ /// Message describing the elicitation
18+ public var message : String
19+
20+ public init ( mode: String = " url " , elicitationId: String , url: String , message: String ) {
21+ self . mode = mode
22+ self . elicitationId = elicitationId
23+ self . url = url
24+ self . message = message
25+ }
26+ }
27+
928/// A model context protocol error.
1029public enum MCPError : Swift . Error , Sendable {
1130 // Standard JSON-RPC 2.0 errors (-32700 to -32603)
@@ -18,6 +37,9 @@ public enum MCPError: Swift.Error, Sendable {
1837 // Server errors (-32000 to -32099)
1938 case serverError( code: Int , message: String )
2039
40+ // MCP specific errors
41+ case urlElicitationRequired( message: String , elicitations: [ URLElicitationInfo ] ) // -32042
42+
2143 // Transport specific errors
2244 case connectionClosed
2345 case transportError( Swift . Error )
@@ -31,6 +53,7 @@ public enum MCPError: Swift.Error, Sendable {
3153 case . invalidParams: return - 32602
3254 case . internalError: return - 32603
3355 case . serverError( let code, _) : return code
56+ case . urlElicitationRequired: return - 32042
3457 case . connectionClosed: return - 32000
3558 case . transportError: return - 32001
3659 }
@@ -68,6 +91,8 @@ extension MCPError: LocalizedError {
6891 return " Internal error " + ( detail. map { " : \( $0) " } ?? " " )
6992 case . serverError( _, let message) :
7093 return " Server error: \( message) "
94+ case . urlElicitationRequired( let message, _) :
95+ return " URL elicitation required: \( message) "
7196 case . connectionClosed:
7297 return " Connection closed "
7398 case . transportError( let error) :
@@ -89,6 +114,8 @@ extension MCPError: LocalizedError {
89114 return " Internal JSON-RPC error "
90115 case . serverError:
91116 return " Server-defined error occurred "
117+ case . urlElicitationRequired:
118+ return " The server requires user authentication or input via external URL "
92119 case . connectionClosed:
93120 return " The connection to the server was closed "
94121 case . transportError( let error) :
@@ -106,6 +133,11 @@ extension MCPError: LocalizedError {
106133 return " Check the method name and ensure it is supported by the server "
107134 case . invalidParams:
108135 return " Verify the parameters match the method's expected parameters "
136+ case . urlElicitationRequired( _, let elicitations) :
137+ if let first = elicitations. first {
138+ return " Visit \( first. url) to complete the required authentication or input "
139+ }
140+ return " Complete the required URL-based elicitation "
109141 case . connectionClosed:
110142 return " Try reconnecting to the server "
111143 default :
@@ -154,6 +186,20 @@ extension MCPError: Codable {
154186 case . serverError( _, _) :
155187 // No additional data for server errors
156188 break
189+ case . urlElicitationRequired( _, let elicitations) :
190+ // Encode elicitations array as structured data
191+ let elicitationsData = elicitations. map { info -> [ String : Value ] in
192+ return [
193+ " mode " : . string( info. mode) ,
194+ " elicitationId " : . string( info. elicitationId) ,
195+ " url " : . string( info. url) ,
196+ " message " : . string( info. message)
197+ ]
198+ }
199+ try container. encode (
200+ [ " elicitations " : Value . array ( elicitationsData. map { . object( $0) } ) ] ,
201+ forKey: . data
202+ )
157203 case . connectionClosed:
158204 break
159205 case . transportError( let error) :
@@ -188,6 +234,25 @@ extension MCPError: Codable {
188234 self = . invalidParams( unwrapDetail ( message) )
189235 case - 32603 :
190236 self = . internalError( unwrapDetail ( nil ) )
237+ case - 32042 :
238+ // Extract elicitations array from data
239+ var elicitations : [ URLElicitationInfo ] = [ ]
240+ if case . array( let items) = data ? [ " elicitations " ] {
241+ for item in items {
242+ if case . object( let dict) = item,
243+ case . string( let mode) = dict [ " mode " ] ,
244+ case . string( let elicitationId) = dict [ " elicitationId " ] ,
245+ case . string( let url) = dict [ " url " ] ,
246+ case . string( let msg) = dict [ " message " ] {
247+ elicitations. append ( URLElicitationInfo (
248+ mode: mode,
249+ elicitationId: elicitationId,
250+ url: url,
251+ message: msg) )
252+ }
253+ }
254+ }
255+ self = . urlElicitationRequired( message: message, elicitations: elicitations)
191256 case - 32000 :
192257 self = . connectionClosed
193258 case - 32001 :
@@ -236,6 +301,9 @@ extension MCPError: Hashable {
236301 hasher. combine ( detail)
237302 case . serverError( _, let message) :
238303 hasher. combine ( message)
304+ case . urlElicitationRequired( let message, let elicitations) :
305+ hasher. combine ( message)
306+ hasher. combine ( elicitations)
239307 case . connectionClosed:
240308 break
241309 case . transportError( let error) :
0 commit comments