11import Foundation
2+ import JSONRPC
23import JSONSchema
34import JSONSchemaBuilder
45import MCPInterface
@@ -17,7 +18,7 @@ import MCPInterface
1718
1819/// Definition for a tool the client can call.
1920public protocol CallableTool {
20- associatedtype Input : Decodable
21+ associatedtype Input
2122 /// A JSON Schema object defining the expected parameters for the tool.
2223 var inputSchema : JSON { get }
2324 /// The name of the tool.
@@ -85,44 +86,22 @@ extension Tool where Input: Schemable {
8586 description: description,
8687 inputSchema: Input . schema. schemaValue. json,
8788 decodeInput: { data in
88- let json = try JSONDecoder ( ) . decode ( JSONValue . self, from: data)
89+ let json = try JSONDecoder ( ) . decode ( JSONSchema_JSONValue . self, from: data)
90+
8991 switch Input . schema. parse ( json) {
9092 case . valid( let value) :
9193 return value
92- case . invalid( let errors ) :
93- throw errors . first ?? MCPServerError . toolCallError ( errors )
94+ case . invalid:
95+ throw MCPServerError . decodingError ( input : data , schema : Input . schema . schemaValue . json )
9496 }
9597 } ,
9698 call: call)
9799 }
98100}
99101
100- extension Tool where Input: Decodable {
101- public init (
102- name: String ,
103- description: String ? = nil ,
104- inputSchema: JSON ,
105- call: @escaping ( Input ) async throws -> [ TextContentOrImageContentOrEmbeddedResource ] )
106- {
107- self . init (
108- name: name,
109- description: description,
110- inputSchema: inputSchema,
111- decodeInput: { data in
112- try JSONDecoder ( ) . decode ( Input . self, from: data)
113- } ,
114- call: call)
115- }
116- }
117-
118102extension CallableTool {
119- public func decodeInput( _ input: JSON ? ) throws -> Input {
120- let data = try JSONEncoder ( ) . encode ( input)
121- return try JSONDecoder ( ) . decode ( Input . self, from: data)
122- }
123-
124- public func call( _ input: JSON ? ) async throws -> [ TextContentOrImageContentOrEmbeddedResource ] {
125- let input = try decodeInput ( input)
103+ public func call( json: JSON ? ) async throws -> [ TextContentOrImageContentOrEmbeddedResource ] {
104+ let input : Input = try decodeInput ( json)
126105 return try await call ( input)
127106 }
128107}
@@ -138,11 +117,13 @@ extension Array where Element == any CallableTool {
138117 handler: { request in
139118 let name = request. name
140119 guard let tool = toolsByName [ name] else {
141- throw MCPError . notSupported
120+ throw JSONRPCResponseError < JSONRPC . JSONValue > (
121+ code: JRPCErrorCodes . invalidParams. rawValue,
122+ message: " Unknown tool: \( name) " )
142123 }
143124 let arguments = request. arguments
144125 do {
145- let content = try await tool. call ( arguments)
126+ let content = try await tool. call ( json : arguments)
146127 return CallToolResult ( content: content)
147128 } catch {
148129 return CallToolResult ( content: [ . text( . init( text: error. localizedDescription) ) ] , isError: true )
@@ -158,13 +139,13 @@ extension Array where Element == any CallableTool {
158139}
159140
160141/// Convert between the JSON representation from `JSONSchema` and ours
161- extension [ KeywordIdentifier : JSONValue ] {
142+ extension [ KeywordIdentifier : JSONSchema_JSONValue ] {
162143 fileprivate var json : JSON {
163144 . object( mapValues { $0. value } )
164145 }
165146}
166147
167- extension JSONValue {
148+ extension JSONSchema_JSONValue {
168149 fileprivate var value : JSON . Value {
169150 switch self {
170151 case . null:
@@ -184,7 +165,3 @@ extension JSONValue {
184165 }
185166 }
186167}
187-
188- // MARK: - ParseIssue + Error
189-
190- extension ParseIssue : @retroactive Error { }
0 commit comments