@@ -21,6 +21,11 @@ import (
2121 "github.com/mark3labs/mcphost/pkg/llm"
2222)
2323
24+ const (
25+ transportStdio = "stdio"
26+ transportSSE = "sse"
27+ )
28+
2429var (
2530 // Tokyo Night theme colors
2631 tokyoPurple = lipgloss .Color ("99" ) // #9d7cd8
@@ -60,15 +65,66 @@ var (
6065)
6166
6267type MCPConfig struct {
63- MCPServers map [string ]ServerConfig `json:"mcpServers"`
68+ MCPServers map [string ]ServerConfigWrapper `json:"mcpServers"`
6469}
6570
66- type ServerConfig struct {
71+ type ServerConfig interface {
72+ GetType () string
73+ }
74+
75+ type STDIOServerConfig struct {
6776 Command string `json:"command"`
6877 Args []string `json:"args"`
6978 Env map [string ]string `json:"env,omitempty"`
7079}
7180
81+ func (s STDIOServerConfig ) GetType () string {
82+ return transportStdio
83+ }
84+
85+ type SSEServerConfig struct {
86+ Url string `json:"url"`
87+ Headers []string `json:"headers,omitempty"`
88+ }
89+
90+ func (s SSEServerConfig ) GetType () string {
91+ return transportSSE
92+ }
93+
94+ type ServerConfigWrapper struct {
95+ Config ServerConfig
96+ }
97+
98+ func (w * ServerConfigWrapper ) UnmarshalJSON (data []byte ) error {
99+ var typeField struct {
100+ Url string `json:"url"`
101+ }
102+
103+ if err := json .Unmarshal (data , & typeField ); err != nil {
104+ return err
105+ }
106+ if typeField .Url != "" {
107+ // If the URL field is present, treat it as an SSE server
108+ var sse SSEServerConfig
109+ if err := json .Unmarshal (data , & sse ); err != nil {
110+ return err
111+ }
112+ w .Config = sse
113+ } else {
114+ // Otherwise, treat it as a STDIOServerConfig
115+ var stdio STDIOServerConfig
116+ if err := json .Unmarshal (data , & stdio ); err != nil {
117+ return err
118+ }
119+ w .Config = stdio
120+ }
121+
122+ return nil
123+ }
124+ func (w ServerConfigWrapper ) MarshalJSON () ([]byte , error ) {
125+ return json .Marshal (w .Config )
126+ }
127+
72128func mcpToolsToAnthropicTools (
73129 serverName string ,
74130 mcpTools []mcp.Tool ,
@@ -108,7 +164,7 @@ func loadMCPConfig() (*MCPConfig, error) {
108164 if _ , err := os .Stat (configPath ); os .IsNotExist (err ) {
109165 // Create default config
110166 defaultConfig := MCPConfig {
111- MCPServers : make (map [string ]ServerConfig ),
167+ MCPServers : make (map [string ]ServerConfigWrapper ),
112168 }
113169
114170 // Create the file with default config
@@ -149,31 +205,45 @@ func createMCPClients(
149205 clients := make (map [string ]mcpclient.MCPClient )
150206
151207 for name , server := range config .MCPServers {
152- var env []string
153- for k , v := range server .Env {
154- env = append (env , fmt .Sprintf ("%s=%s" , k , v ))
155- }
156208 var client mcpclient.MCPClient
157209 var err error
158210
159- if server .Command == "sse_server" {
160- if len (server .Args ) == 0 {
161- return nil , fmt .Errorf (
162- "no arguments provided for sse command" ,
163- )
211+ if server .Config .GetType () == transportSSE {
212+ sseConfig := server .Config .(SSEServerConfig )
213+
214+ options := []mcpclient.ClientOption {}
215+
216+ if sseConfig .Headers != nil {
217+ // Parse headers from the config
218+ headers := make (map [string ]string )
219+ for _ , header := range sseConfig .Headers {
220+ parts := strings .SplitN (header , ":" , 2 )
221+ if len (parts ) == 2 {
222+ key := strings .TrimSpace (parts [0 ])
223+ value := strings .TrimSpace (parts [1 ])
224+ headers [key ] = value
225+ }
226+ }
227+ options = append (options , mcpclient .WithHeaders (headers ))
164228 }
165229
166230 client , err = mcpclient .NewSSEMCPClient (
167- server .Args [0 ],
231+ sseConfig .Url ,
232+ options ... ,
168233 )
169234 if err == nil {
170235 err = client .(* mcpclient.SSEMCPClient ).Start (context .Background ())
171236 }
172237 } else {
238+ stdioConfig := server .Config .(STDIOServerConfig )
239+ var env []string
240+ for k , v := range stdioConfig .Env {
241+ env = append (env , fmt .Sprintf ("%s=%s" , k , v ))
242+ }
173243 client , err = mcpclient .NewStdioMCPClient (
174- server .Command ,
244+ stdioConfig .Command ,
175245 env ,
176- server .Args ... )
246+ stdioConfig .Args ... )
177247 }
178248 if err != nil {
179249 for _ , c := range clients {
@@ -310,15 +380,37 @@ func handleServersCommand(config *MCPConfig) {
310380 } else {
311381 for name , server := range config .MCPServers {
312382 markdown .WriteString (fmt .Sprintf ("# %s\n \n " , name ))
313- markdown .WriteString ("*Command*\n " )
314- markdown .WriteString (fmt .Sprintf ("`%s`\n \n " , server .Command ))
315383
316- markdown .WriteString ("*Arguments*\n " )
317- if len (server .Args ) > 0 {
318- markdown .WriteString (fmt .Sprintf ("`%s`\n " , strings .Join (server .Args , " " )))
384+ if server .Config .GetType () == transportSSE {
385+ sseConfig := server .Config .(SSEServerConfig )
386+ markdown .WriteString ("*Url*\n " )
387+ markdown .WriteString (fmt .Sprintf ("`%s`\n \n " , sseConfig .Url ))
388+ markdown .WriteString ("*headers*\n " )
389+ if sseConfig .Headers != nil {
390+ for _ , header := range sseConfig .Headers {
391+ parts := strings .SplitN (header , ":" , 2 )
392+ if len (parts ) == 2 {
393+ key := strings .TrimSpace (parts [0 ])
394+ markdown .WriteString ("`" + key + ": [REDACTED]`\n " )
395+ }
396+ }
397+ } else {
398+ markdown .WriteString ("*None*\n " )
399+ }
400+
319401 } else {
320- markdown .WriteString ("*None*\n " )
402+ stdioConfig := server .Config .(STDIOServerConfig )
403+ markdown .WriteString ("*Command*\n " )
404+ markdown .WriteString (fmt .Sprintf ("`%s`\n \n " , stdioConfig .Command ))
405+
406+ markdown .WriteString ("*Arguments*\n " )
407+ if len (stdioConfig .Args ) > 0 {
408+ markdown .WriteString (fmt .Sprintf ("`%s`\n " , strings .Join (stdioConfig .Args , " " )))
409+ } else {
410+ markdown .WriteString ("*None*\n " )
411+ }
321412 }
413+
322414 markdown .WriteString ("\n " ) // Add spacing between servers
323415 }
324416 }
0 commit comments