Skip to content

Commit c5d4804

Browse files
committed
ROX-31475: add stdio support
Signed-off-by: Tomasz Janiszewski <[email protected]> # Conflicts: # internal/server/server.go
1 parent e5a4d8d commit c5d4804

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

internal/config/config.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Config struct {
2929
}
3030

3131
type authType string
32+
type serverType string
3233

3334
const (
3435
// AuthTypePassthrough defines auth flow where API token, used to communicate with MCP server,
@@ -38,6 +39,9 @@ const (
3839
// AuthTypeStatic defines auth flow where API token is statically configured and
3940
// defined in configuration or environment variable.
4041
AuthTypeStatic authType = "static"
42+
43+
ServerTypeStdio serverType = "stdio"
44+
ServerTypeStreamableHttp serverType = "streamable-http"
4145
)
4246

4347
// CentralConfig contains StackRox Central connection configuration.
@@ -62,8 +66,9 @@ type GlobalConfig struct {
6266

6367
// ServerConfig contains HTTP server configuration.
6468
type ServerConfig struct {
65-
Address string `mapstructure:"address"`
66-
Port int `mapstructure:"port"`
69+
Type serverType `mapstructure:"type"`
70+
Address string `mapstructure:"address"`
71+
Port int `mapstructure:"port"`
6772
}
6873

6974
// ToolsConfig contains configuration for individual MCP tools.
@@ -138,6 +143,7 @@ func setDefaults(viper *viper.Viper) {
138143

139144
viper.SetDefault("server.address", "0.0.0.0")
140145
viper.SetDefault("server.port", defaultPort)
146+
viper.SetDefault("server.type", ServerTypeStreamableHttp)
141147

142148
viper.SetDefault("tools.vulnerability.enabled", false)
143149
viper.SetDefault("tools.config_manager.enabled", false)
@@ -207,6 +213,12 @@ func (cc *CentralConfig) validate() error {
207213
}
208214

209215
func (sc *ServerConfig) validate() error {
216+
if sc.Type != ServerTypeStreamableHttp && sc.Type != ServerTypeStdio {
217+
return errors.New("server.type must be either streamable-http or stdio")
218+
}
219+
if sc.Type == ServerTypeStdio {
220+
return nil
221+
}
210222
if sc.Address == "" {
211223
return errors.New("server.address is required")
212224
}

internal/config/config_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,24 @@ tools:
201201
assert.Contains(t, err.Error(), "central.url is required")
202202
}
203203

204+
func TestLoadConfig_ValidationPass(t *testing.T) {
205+
validYAMLInvalidConfig := `
206+
central:
207+
url: "localhost:8080"
208+
server:
209+
type: stdio
210+
address: ""
211+
port: 0
212+
tools:
213+
vulnerability:
214+
enabled: true
215+
`
216+
217+
configPath := testutil.WriteYAMLFile(t, validYAMLInvalidConfig)
218+
_, err := LoadConfig(configPath)
219+
require.NoError(t, err)
220+
}
221+
204222
func TestValidate_MissingURL(t *testing.T) {
205223
cfg := getDefaultConfig()
206224
cfg.Central.URL = ""

internal/logging/logging.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func SetupLogging() {
3131
}
3232

3333
// Initialize slog with JSON handler.
34-
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
34+
logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
3535
Level: logLevel,
3636
}))
3737

internal/server/server.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ func NewServer(cfg *config.Config, registry *toolsets.Registry) *Server {
5353
func (s *Server) Start(ctx context.Context) error {
5454
s.registerTools()
5555

56+
if s.cfg.Server.Type == "stdio" {
57+
return s.mcp.Run(ctx, &mcp.StdioTransport{})
58+
}
59+
5660
// Create a new ServeMux for routing.
5761
mux := http.NewServeMux()
5862
s.registerRouteHealth(mux)

0 commit comments

Comments
 (0)