Help us shape the future of Go! Take the 2026 Go Developer Survey

client

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Command = &cli.Command{
	Name:        "client",
	Aliases:     []string{"c"},
	Usage:       "Act as the proxy client",
	ArgsUsage:   fmt.Sprintf("ws(s)://proxy-server-address:%d", protocol.DefaultPort),
	Description: "It will connect to the proxy server and forward stdin to it while forwarding back the server's response to stdout. To be launched by your application expecting a stdio MCP server.",
	Flags: []cli.Flag{

		&cli.StringFlag{
			Name:     "cert",
			Usage:    "Path to the client certificate file",
			Aliases:  []string{"c"},
			Category: "mTLS",
			OnlyOnce: true,
		},
		&cli.StringFlag{
			Name:     "key",
			Usage:    "Path to the client key file",
			Aliases:  []string{"k"},
			Category: "mTLS",
			OnlyOnce: true,
		},
		&cli.StringFlag{
			Name:     "ca",
			Usage:    "Path to the CA certificate file",
			Aliases:  []string{"a"},
			Category: "mTLS",
			OnlyOnce: true,
		},
	},
	Before: func(ctx context.Context, cmd *cli.Command) (actionCtx context.Context, err error) {
		defer func() {
			if err != nil {
				err = cli.Exit(err, 1)
			}
		}()

		if cmd.Args().Len() != 1 {
			err = errors.New("expected exactly one argument: the websocket URL")
			return
		}
		if target, err = url.Parse(cmd.Args().Get(0)); err != nil {
			err = fmt.Errorf("invalid URL: %w", err)
			return
		}

		certFile := cmd.String("cert")
		keyFile := cmd.String("key")
		caFile := cmd.String("ca")
		if certFile != "" || keyFile != "" || caFile != "" {
			if certFile == "" || keyFile == "" || caFile == "" {
				err = errors.New("--cert, --key and --ca must be specified together")
				return
			}
			if tlsConf, err = protocol.GetClientTLSConfig(caFile, certFile, keyFile); err != nil {
				err = fmt.Errorf("failed to generate client TLS configuration: %w", err)
				return
			}
		}

		switch target.Scheme {
		case "ws":
			if tlsConf != nil {
				err = errors.New("TLS configuration is not supported for ws:// URLs")
				return
			}
		case "wss":
			if tlsConf == nil {
				err = errors.New("TLS configuration is required for wss:// URLs")
				return
			}
		default:
			err = fmt.Errorf("invalid URL scheme, expecting 'ws' or 'wss': %s", target.Scheme)
			return
		}

		if isLoopbackHost(target.Host) {
			compressionMode = websocket.CompressionDisabled
		} else {
			compressionMode = protocol.CompressionMode
		}

		actionCtx = ctx
		return
	},
	Action: func(ctx context.Context, cmd *cli.Command) (err error) {

		httpTransport := cleanhttp.DefaultTransport()
		httpTransport.TLSClientConfig = tlsConf
		conn, _, err := websocket.Dial(ctx, target.String(), &websocket.DialOptions{
			HTTPClient: &http.Client{
				Transport: httpTransport,
			},
			CompressionMode: compressionMode,
		})
		if err != nil {
			return cli.Exit(fmt.Errorf("failed to connect to server: %w", err), 2)
		}
		defer func() {

			if err := conn.CloseNow(); err != nil && !errors.Is(err, net.ErrClosed) {
				fmt.Fprintf(os.Stderr, "warning: failed to close websocket: %v\n", err)
			}
		}()

		if err = proxy(ctx, conn); err != nil {
			err = cli.Exit(err, 3)
		}
		return
	},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL