11package main
22
33import (
4+ "bytes"
45 "context"
56 "encoding/json"
67 "flag"
@@ -21,18 +22,101 @@ var version = "dev"
2122
2223// DevPodWorkspace represents a DevPod workspace
2324type DevPodWorkspace struct {
24- Name string `json:"name"`
25- Provider string `json:"provider"`
26- Status string `json:"status"`
27- IDE string `json:"ide,omitempty"`
25+ ID string `json:"id"`
26+ UID string `json:"uid"`
27+ Picture string `json:"picture,omitempty"`
28+ Provider DevPodWorkspaceProvider `json:"provider"`
29+ Machine map [string ]interface {} `json:"machine"`
30+ IDE DevPodWorkspaceIDE `json:"ide"`
31+ Source DevPodWorkspaceSource `json:"source"`
32+ CreationTimestamp string `json:"creationTimestamp"`
33+ LastUsed string `json:"lastUsed"`
34+ Context string `json:"context"`
35+ }
36+
37+ // DevPodWorkspaceProvider represents the provider configuration for a workspace
38+ type DevPodWorkspaceProvider struct {
39+ Name string `json:"name"`
40+ Options map [string ]interface {} `json:"options"`
41+ }
42+
43+ // DevPodWorkspaceIDE represents the IDE configuration for a workspace
44+ type DevPodWorkspaceIDE struct {
45+ Name string `json:"name"`
46+ }
47+
48+ // DevPodWorkspaceSource represents the source configuration for a workspace
49+ type DevPodWorkspaceSource struct {
50+ Image string `json:"image,omitempty"`
51+ GitRepository string `json:"gitRepository,omitempty"`
2852}
2953
3054// DevPodProvider represents a DevPod provider
3155type DevPodProvider struct {
32- Name string `json:"name"`
33- Description string `json:"description"`
34- Version string `json:"version"`
35- Default bool `json:"default"`
56+ Config DevPodProviderConfig `json:"config"`
57+ State DevPodProviderState `json:"state"`
58+ }
59+
60+ // DevPodProviderConfig represents the configuration of a DevPod provider
61+ type DevPodProviderConfig struct {
62+ Name string `json:"name"`
63+ Version string `json:"version"`
64+ Description string `json:"description"`
65+ Icon string `json:"icon,omitempty"`
66+ Home string `json:"home,omitempty"`
67+ Source map [string ]interface {} `json:"source"`
68+ OptionGroups []interface {} `json:"optionGroups"`
69+ Options map [string ]interface {} `json:"options"`
70+ Agent map [string ]interface {} `json:"agent"`
71+ Exec map [string ]interface {} `json:"exec"`
72+ }
73+
74+ // DevPodProviderState represents the state of a DevPod provider
75+ type DevPodProviderState struct {
76+ Initialized bool `json:"initialized"`
77+ Options map [string ]interface {} `json:"options"`
78+ CreationTimestamp string `json:"creationTimestamp"`
79+ }
80+
81+ // executeDevPodCommandWithDebug executes a DevPod command with comprehensive debug logging
82+ func executeDevPodCommandWithDebug (ctx context.Context , args []string ) ([]byte , error ) {
83+ log .Printf ("DEBUG: Executing devpod command with args: %v" , args )
84+ fmt .Fprintf (os .Stderr , "DEBUG: Executing devpod command with args: %v\n " , args )
85+
86+ cmd := exec .CommandContext (ctx , "devpod" , args ... )
87+
88+ // Set environment variables
89+ cmd .Env = os .Environ ()
90+
91+ // Capture both stdout and stderr separately for better debugging
92+ var stdout , stderr bytes.Buffer
93+ cmd .Stdout = & stdout
94+ cmd .Stderr = & stderr
95+
96+ err := cmd .Run ()
97+
98+ stdoutBytes := stdout .Bytes ()
99+ stderrBytes := stderr .Bytes ()
100+ stdoutStr := string (stdoutBytes )
101+ stderrStr := string (stderrBytes )
102+
103+ log .Printf ("DEBUG: Command completed with error: %v" , err )
104+ log .Printf ("DEBUG: Command stdout (%d bytes): %q" , len (stdoutBytes ), stdoutStr )
105+ log .Printf ("DEBUG: Command stderr (%d bytes): %q" , len (stderrBytes ), stderrStr )
106+
107+ fmt .Fprintf (os .Stderr , "DEBUG: Command completed with error: %v\n " , err )
108+ fmt .Fprintf (os .Stderr , "DEBUG: Command stdout (%d bytes): %q\n " , len (stdoutBytes ), stdoutStr )
109+ fmt .Fprintf (os .Stderr , "DEBUG: Command stderr (%d bytes): %q\n " , len (stderrBytes ), stderrStr )
110+
111+ if err != nil {
112+ log .Printf ("ERROR: devpod command failed: %v" , err )
113+ fmt .Fprintf (os .Stderr , "ERROR: devpod command failed: %v\n " , err )
114+ return nil , fmt .Errorf ("devpod command failed: %v, stdout: %s, stderr: %s" , err , stdoutStr , stderrStr )
115+ }
116+
117+ log .Printf ("DEBUG: Command completed successfully, returning %d bytes" , len (stdoutBytes ))
118+ fmt .Fprintf (os .Stderr , "DEBUG: Command completed successfully, returning %d bytes\n " , len (stdoutBytes ))
119+ return stdoutBytes , nil
36120}
37121
38122func checkDevPodAvailable () error {
@@ -395,24 +479,44 @@ func registerDevPodHandlers(server *mcp.Server) {
395479 log .Printf ("Registering devpod_listWorkspaces handler" )
396480 fmt .Fprintf (os .Stderr , "Registering devpod_listWorkspaces handler\n " )
397481 server .RegisterHandler ("devpod_listWorkspaces" , func (ctx context.Context , params json.RawMessage ) (interface {}, error ) {
482+ log .Printf ("DEBUG: devpod_listWorkspaces called with params: %s" , string (params ))
483+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_listWorkspaces called with params: %s\n " , string (params ))
484+
398485 if ! devpodAvailable {
486+ log .Printf ("ERROR: DevPod is not available on this system" )
487+ fmt .Fprintf (os .Stderr , "ERROR: DevPod is not available on this system\n " )
399488 return nil , fmt .Errorf ("DevPod is not available on this system" )
400489 }
401- cmd := exec . CommandContext ( ctx , "devpod" , "list" , "--output" , "json" )
402- output , err := cmd . Output ( )
490+
491+ output , err := executeDevPodCommandWithDebug ( ctx , [] string { "list" , "--output" , "json" } )
403492 if err != nil {
493+ log .Printf ("ERROR: devpod_listWorkspaces failed: %v" , err )
494+ fmt .Fprintf (os .Stderr , "ERROR: devpod_listWorkspaces failed: %v\n " , err )
404495 return nil , fmt .Errorf ("failed to list workspaces: %w" , err )
405496 }
406497
407498 var workspaces []DevPodWorkspace
408499 if err := json .Unmarshal (output , & workspaces ); err != nil {
500+ log .Printf ("DEBUG: JSON parsing failed, trying text parsing. Error: %v" , err )
501+ fmt .Fprintf (os .Stderr , "DEBUG: JSON parsing failed, trying text parsing. Error: %v\n " , err )
409502 // If JSON parsing fails, try to parse the text output
410- return parseTextWorkspaceList (string (output )), nil
503+ textResult := parseTextWorkspaceList (string (output ))
504+ result := map [string ]interface {}{
505+ "workspaces" : textResult ,
506+ }
507+ log .Printf ("DEBUG: devpod_listWorkspaces returning text-parsed result: %v" , result )
508+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_listWorkspaces returning text-parsed result: %v\n " , result )
509+ fmt .Printf ("RESPONSE: devpod_listWorkspaces text-parsed result: %v\n " , result )
510+ return result , nil
411511 }
412512
413- return map [string ]interface {}{
513+ result := map [string ]interface {}{
414514 "workspaces" : workspaces ,
415- }, nil
515+ }
516+ log .Printf ("DEBUG: devpod_listWorkspaces returning JSON-parsed result: %v" , result )
517+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_listWorkspaces returning JSON-parsed result: %v\n " , result )
518+ fmt .Printf ("RESPONSE: devpod_listWorkspaces result: %v\n " , result )
519+ return result , nil
416520 })
417521
418522 // Create workspace
@@ -548,35 +652,57 @@ func registerDevPodHandlers(server *mcp.Server) {
548652
549653 // List providers
550654 server .RegisterHandler ("devpod_listProviders" , func (ctx context.Context , params json.RawMessage ) (interface {}, error ) {
551- cmd := exec .CommandContext (ctx , "devpod" , "provider" , "list" , "--output" , "json" )
552- output , err := cmd .Output ()
655+ output , err := executeDevPodCommandWithDebug (ctx , []string {"provider" , "list" , "--output" , "json" })
553656 if err != nil {
657+ log .Printf ("ERROR: devpod_listProviders failed: %v" , err )
658+ fmt .Fprintf (os .Stderr , "ERROR: devpod_listProviders failed: %v\n " , err )
554659 return nil , fmt .Errorf ("failed to list providers: %w" , err )
555660 }
556661
557- var providers []DevPodProvider
558- if err := json .Unmarshal (output , & providers ); err != nil {
662+ // DevPod provider list returns an object with provider names as keys
663+ var providersMap map [string ]DevPodProvider
664+ if err := json .Unmarshal (output , & providersMap ); err != nil {
665+ log .Printf ("DEBUG: JSON parsing failed, trying text parsing. Error: %v" , err )
666+ fmt .Fprintf (os .Stderr , "DEBUG: JSON parsing failed, trying text parsing. Error: %v\n " , err )
559667 // If JSON parsing fails, try to parse the text output
560- return parseTextProviderList (string (output )), nil
668+ textResult := parseTextProviderList (string (output ))
669+ result := map [string ]interface {}{
670+ "providers" : textResult ,
671+ }
672+ log .Printf ("DEBUG: devpod_listProviders returning text-parsed result: %v" , result )
673+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_listProviders returning text-parsed result: %v\n " , result )
674+ fmt .Printf ("RESPONSE: devpod_listProviders text-parsed result: %v\n " , result )
675+ return result , nil
561676 }
562677
563- return map [string ]interface {}{
564- "providers" : providers ,
565- }, nil
678+ result := map [string ]interface {}{
679+ "providers" : providersMap ,
680+ }
681+ log .Printf ("DEBUG: devpod_listProviders returning JSON-parsed result: %v" , result )
682+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_listProviders returning JSON-parsed result: %v\n " , result )
683+ fmt .Printf ("RESPONSE: devpod_listProviders result: %v\n " , result )
684+ return result , nil
566685 })
567686
568687 // Add provider
569688 server .RegisterHandler ("devpod_addProvider" , func (ctx context.Context , params json.RawMessage ) (interface {}, error ) {
689+ log .Printf ("DEBUG: devpod_addProvider called with params: %s" , string (params ))
690+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_addProvider called with params: %s\n " , string (params ))
691+
570692 var addParams struct {
571693 Name string `json:"name"`
572694 Options map [string ]string `json:"options,omitempty"`
573695 }
574696
575697 if err := json .Unmarshal (params , & addParams ); err != nil {
698+ log .Printf ("ERROR: Failed to unmarshal addProvider params: %v" , err )
699+ fmt .Fprintf (os .Stderr , "ERROR: Failed to unmarshal addProvider params: %v\n " , err )
576700 return nil , mcp .NewInvalidParamsError ("Invalid add provider parameters" )
577701 }
578702
579703 if addParams .Name == "" {
704+ log .Printf ("ERROR: Provider name is required" )
705+ fmt .Fprintf (os .Stderr , "ERROR: Provider name is required\n " )
580706 return nil , mcp .NewInvalidParamsError ("Provider name is required" )
581707 }
582708
@@ -585,17 +711,26 @@ func registerDevPodHandlers(server *mcp.Server) {
585711 args = append (args , "-o" , fmt .Sprintf ("%s=%s" , key , value ))
586712 }
587713
588- cmd := exec .CommandContext (ctx , "devpod" , args ... )
589- output , err := cmd .CombinedOutput ()
714+ log .Printf ("DEBUG: Executing devpod provider add with args: %v" , args )
715+ fmt .Fprintf (os .Stderr , "DEBUG: Executing devpod provider add with args: %v\n " , args )
716+
717+ output , err := executeDevPodCommandWithDebug (ctx , args )
590718 if err != nil {
719+ log .Printf ("ERROR: devpod_addProvider failed: %v" , err )
720+ fmt .Fprintf (os .Stderr , "ERROR: devpod_addProvider failed: %v\n " , err )
591721 return nil , fmt .Errorf ("failed to add provider: %w\n Output: %s" , err , string (output ))
592722 }
593723
594- return map [string ]interface {}{
724+ result := map [string ]interface {}{
595725 "name" : addParams .Name ,
596726 "message" : "Provider added successfully" ,
597727 "output" : string (output ),
598- }, nil
728+ }
729+
730+ log .Printf ("DEBUG: devpod_addProvider returning result: %v" , result )
731+ fmt .Fprintf (os .Stderr , "DEBUG: devpod_addProvider returning result: %v\n " , result )
732+ fmt .Printf ("RESPONSE: devpod_addProvider result: %v\n " , result )
733+ return result , nil
599734 })
600735
601736 // SSH into workspace
0 commit comments