@@ -28,10 +28,13 @@ import (
2828 "slices"
2929 "sort"
3030 "strings"
31+ "time"
3132
3233 "github.com/mark3labs/mcp-go/mcp"
3334
3435 "github.com/docker/mcp-registry/pkg/servers"
36+ mcpclient "github.com/mark3labs/mcp-go/client"
37+ "github.com/mark3labs/mcp-go/client/transport"
3538)
3639
3740func Tools (ctx context.Context , server servers.Server , pull , cleanup , debug bool ) ([]Tool , error ) {
@@ -167,6 +170,144 @@ func Tools(ctx context.Context, server servers.Server, pull, cleanup, debug bool
167170 return list , nil
168171}
169172
173+ func RemoteTools (ctx context.Context , server servers.Server ) ([]Tool , error ) {
174+ var c * mcpclient.Client
175+ var err error
176+
177+ ctx , cancel := context .WithTimeout (ctx , 60 * time .Second )
178+ defer cancel ()
179+
180+ switch server .Remote .TransportType {
181+ case "sse" :
182+ sseTransport , err := transport .NewSSE (server .Remote .URL )
183+ if err != nil {
184+ return nil , err
185+ }
186+ c = mcpclient .NewClient (sseTransport )
187+
188+ case "http" :
189+ case "streamable-http" :
190+ httpTransport , err := transport .NewStreamableHTTP (server .Remote .URL )
191+ if err != nil {
192+ return nil , err
193+ }
194+ c = mcpclient .NewClient (httpTransport )
195+
196+ default :
197+ return nil , fmt .Errorf ("invalid transport type: %s" , server .Remote .TransportType )
198+ }
199+
200+ err = c .Start (ctx )
201+ if err != nil {
202+ return nil , err
203+ }
204+ defer c .Close ()
205+
206+ initRequest := mcp.InitializeRequest {}
207+ initRequest .Params .ProtocolVersion = mcp .LATEST_PROTOCOL_VERSION
208+ initRequest .Params .ClientInfo = mcp.Implementation {
209+ Name : "docker" ,
210+ Version : "1.0.0" ,
211+ }
212+
213+ serverInfo , err := c .Initialize (ctx , initRequest )
214+ if err != nil {
215+ return nil , err
216+ }
217+
218+ if serverInfo .Capabilities .Tools == nil {
219+ return nil , fmt .Errorf ("tools not supported" )
220+ }
221+
222+ toolsRequest := mcp.ListToolsRequest {}
223+ toolsResult , err := c .ListTools (ctx , toolsRequest )
224+ if err != nil {
225+ return nil , err
226+ }
227+
228+ var list []Tool
229+ for _ , tool := range toolsResult .Tools {
230+ var arguments []ToolArgument
231+ var requiredPropertyNames []string
232+ var optionalPropertyNames []string
233+ for name := range tool .InputSchema .Properties {
234+ if slices .Contains (tool .InputSchema .Required , name ) {
235+ requiredPropertyNames = append (requiredPropertyNames , name )
236+ } else {
237+ optionalPropertyNames = append (optionalPropertyNames , name )
238+ }
239+ }
240+ sort .Strings (requiredPropertyNames )
241+ sort .Strings (optionalPropertyNames )
242+
243+ propertyNames := append (requiredPropertyNames , optionalPropertyNames ... )
244+
245+ for _ , name := range propertyNames {
246+ v := tool .InputSchema .Properties [name ]
247+
248+ // Type
249+ argumentType := "string"
250+ rawType := v .(map [string ]any )["type" ]
251+ if rawType != "" && rawType != nil {
252+ if str , ok := rawType .(string ); ok {
253+ argumentType = str
254+ }
255+ }
256+
257+ // Item types
258+ var items * Items
259+ if argumentType == "array" {
260+ itemsType := "string"
261+ if rawItems , found := v .(map [string ]any )["items" ]; found {
262+ if kv , ok := rawItems .(map [string ]any ); ok {
263+ if rawItemsType , found := kv ["type" ]; found {
264+ if str , ok := rawItemsType .(string ); ok {
265+ itemsType = str
266+ }
267+ }
268+ }
269+ }
270+ items = & Items {
271+ Type : itemsType ,
272+ }
273+ }
274+
275+ // Description
276+ desc := v .(map [string ]any )["description" ]
277+
278+ // Properties
279+ arguments = append (arguments , ToolArgument {
280+ Name : name ,
281+ Type : argumentType ,
282+ Items : items ,
283+ Optional : ! slices .Contains (tool .InputSchema .Required , name ),
284+ Description : argumentDescription (name , desc , tool .Description ),
285+ })
286+ }
287+
288+ // Annotations
289+ var annotations * ToolAnnotations
290+ if tool .Annotations != (mcp.ToolAnnotation {}) {
291+ annotations = & ToolAnnotations {
292+ Title : tool .Annotations .Title ,
293+ ReadOnlyHint : tool .Annotations .ReadOnlyHint ,
294+ DestructiveHint : tool .Annotations .DestructiveHint ,
295+ IdempotentHint : tool .Annotations .IdempotentHint ,
296+ OpenWorldHint : tool .Annotations .OpenWorldHint ,
297+ }
298+ }
299+
300+ list = append (list , Tool {
301+ Name : tool .Name ,
302+ Description : removeArgs (tool .Description ),
303+ Arguments : arguments ,
304+ Annotations : annotations ,
305+ })
306+ }
307+
308+ return list , nil
309+ }
310+
170311func removeArgs (input string ) string {
171312 var result []string
172313
0 commit comments