From 07e1f2efec0c9e7a25c8d15582f2901118fa1a60 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:27:05 +0000 Subject: [PATCH 1/2] feat: Allow passing environment variables to stdio command This commit adds a new `--env` (or `-e`) flag to the `stdio` command. This allows the user to pass environment variables to the server process that is started by the command. The implementation appends the provided environment variables to the existing environment of the `mcp-cli` process, ensuring that the child process inherits the parent's environment as well as the new variables. The README.md file has been updated to document this new flag and its usage. --- README.md | 6 ++++-- main.go | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index da4d0c7..bf4c51b 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,15 @@ The `mcp-cli` tool has three main commands, one for each transport protocol. Connect to an MCP server that communicates over standard input/output. ```sh -mcp-cli stdio "" +mcp-cli stdio --env "VAR=value" --env "ANOTHER_VAR=another_value" "" ``` +The `--env` (or `-e`) flag can be used multiple times to pass environment variables to the server process. + **Example:** ```sh -mcp-cli stdio "python /path/to/mcp/server.py" +mcp-cli stdio -e "API_KEY=12345" "python /path/to/mcp/server.py" ``` ### `sse` diff --git a/main.go b/main.go index fb0e833..c0ef7c0 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,7 @@ func Execute() { func init() { rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output") + stdioCmd.Flags().StringSliceP("env", "e", []string{}, "Environment variables to pass to the command") } var stdioCmd = &cobra.Command{ @@ -49,11 +50,15 @@ var stdioCmd = &cobra.Command{ log.Printf("Command: %s", command) } + env, _ := cmd.Flags().GetStringSlice("env") + ctx := context.Background() client := mcp.NewClient(&mcp.Implementation{Name: "mcp-cli", Version: "v0.1.0"}, nil) cmdParts := strings.Fields(command) - transport := &mcp.CommandTransport{Command: exec.Command(cmdParts[0], cmdParts[1:]...)} + execCmd := exec.Command(cmdParts[0], cmdParts[1:]...) + execCmd.Env = append(os.Environ(), env...) + transport := &mcp.CommandTransport{Command: execCmd} session, err := client.Connect(ctx, transport, nil) if err != nil { log.Fatalf("Failed to connect to stdio server: %v", err) From 4c74213e20fa4199d41656cd8ead121bf2aa1775 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 15:52:47 +0000 Subject: [PATCH 2/2] feat: Add --env and --header flags This commit introduces two new features for passing configuration to MCP servers: 1. The `stdio` command now has an `--env` (or `-e`) flag that allows passing environment variables to the server process. 2. The `sse` and `http` commands now have a `--header` (or `-H`) flag that allows passing custom HTTP headers to the remote server. This provides more flexibility for configuring and authenticating with MCP servers. The README.md file has been updated to document these new flags. --- README.md | 12 ++++++++---- main.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bf4c51b..36c8f80 100644 --- a/README.md +++ b/README.md @@ -63,13 +63,15 @@ mcp-cli stdio -e "API_KEY=12345" "python /path/to/mcp/server.py" Connect to an MCP server that uses Server-Sent Events (SSE). ```sh -mcp-cli sse +mcp-cli sse --header "Header-Name: header-value" ``` +The `--header` (or `-H`) flag can be used multiple times to pass custom HTTP headers to the server. + **Example:** ```sh -mcp-cli sse http://localhost:8080/mcp +mcp-cli sse -H "Authorization: Bearer my-token" http://localhost:8080/mcp ``` ### `http` @@ -77,13 +79,15 @@ mcp-cli sse http://localhost:8080/mcp Connect to an MCP server that uses streamable HTTP. ```sh -mcp-cli http +mcp-cli http --header "Header-Name: header-value" ``` +The `--header` (or `-H`) flag can be used multiple times to pass custom HTTP headers to the server. + **Example:** ```sh -mcp-cli http http://localhost:8080/mcp +mcp-cli http -H "Authorization: Bearer my-token" http://localhost:8080/mcp ``` ### Global Flags diff --git a/main.go b/main.go index c0ef7c0..380bcc2 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "log" + "net/http" "os" "os/exec" "sort" @@ -38,6 +39,8 @@ func Execute() { func init() { rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output") stdioCmd.Flags().StringSliceP("env", "e", []string{}, "Environment variables to pass to the command") + sseCmd.Flags().StringSliceP("header", "H", []string{}, "Headers to pass to the server") + httpCmd.Flags().StringSliceP("header", "H", []string{}, "Headers to pass to the server") } var stdioCmd = &cobra.Command{ @@ -83,10 +86,22 @@ var sseCmd = &cobra.Command{ log.Printf("URL: %s", url) } + headerStrings, _ := cmd.Flags().GetStringSlice("header") + var httpClient *http.Client + if len(headerStrings) > 0 { + headers := parseHeaders(headerStrings) + httpClient = &http.Client{ + Transport: &headerTransport{ + base: http.DefaultTransport, + headers: headers, + }, + } + } + ctx := context.Background() client := mcp.NewClient(&mcp.Implementation{Name: "mcp-cli", Version: "v0.1.0"}, nil) - transport := &mcp.SSEClientTransport{Endpoint: url} + transport := &mcp.SSEClientTransport{Endpoint: url, HTTPClient: httpClient} session, err := client.Connect(ctx, transport, nil) if err != nil { log.Fatalf("Failed to connect to SSE server: %v", err) @@ -111,10 +126,22 @@ var httpCmd = &cobra.Command{ log.Printf("URL: %s", url) } + headerStrings, _ := cmd.Flags().GetStringSlice("header") + var httpClient *http.Client + if len(headerStrings) > 0 { + headers := parseHeaders(headerStrings) + httpClient = &http.Client{ + Transport: &headerTransport{ + base: http.DefaultTransport, + headers: headers, + }, + } + } + ctx := context.Background() client := mcp.NewClient(&mcp.Implementation{Name: "mcp-cli", Version: "v0.1.0"}, nil) - transport := &mcp.StreamableClientTransport{Endpoint: url} + transport := &mcp.StreamableClientTransport{Endpoint: url, HTTPClient: httpClient} session, err := client.Connect(ctx, transport, nil) if err != nil { log.Fatalf("Failed to connect to streamable HTTP server: %v", err) @@ -129,6 +156,33 @@ var httpCmd = &cobra.Command{ }, } +// headerTransport is an http.RoundTripper that adds custom headers to each request. +type headerTransport struct { + base http.RoundTripper + headers http.Header +} + +// RoundTrip adds the custom headers to the request before sending it. +func (t *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) { + for k, v := range t.headers { + req.Header[k] = v + } + return t.base.RoundTrip(req) +} + +func parseHeaders(headerStrings []string) http.Header { + headers := http.Header{} + for _, h := range headerStrings { + parts := strings.SplitN(h, ":", 2) + if len(parts) == 2 { + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) + headers.Add(key, value) + } + } + return headers +} + // -- Bubble Tea TUI ----------------------------------------------------------- type viewState int