Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions internal/config/config_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ func applyGatewayDefaults(cfg *GatewayConfig) {
}
}

// EnsureGatewayDefaults guarantees that cfg.Gateway is non-nil and that all
// gateway-level fields have sensible defaults applied. This matches the
// invariants enforced by the standard loaders (LoadFromFile, LoadFromStdin),
// and can be used by callers that construct Config values manually (e.g. in
// tests) to avoid nil-pointer panics and ensure consistent defaults.
func (cfg *Config) EnsureGatewayDefaults() {
if cfg.Gateway == nil {
cfg.Gateway = &GatewayConfig{}
}
applyGatewayDefaults(cfg.Gateway)
applyDefaults(cfg)
}

// LoadFromFile loads configuration from a TOML file.
//
// This function uses the BurntSushi/toml v1.6.0+ parser with TOML 1.1 support,
Expand Down
15 changes: 7 additions & 8 deletions internal/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,13 @@ func New(ctx context.Context, cfg *config.Config) *Launcher {
log.Println("[LAUNCHER] Detected running inside a container")
}

// Get startup timeout from config, default to config.DefaultStartupTimeout seconds
startupTimeout := time.Duration(config.DefaultStartupTimeout) * time.Second
if cfg.Gateway != nil && cfg.Gateway.StartupTimeout > 0 {
startupTimeout = time.Duration(cfg.Gateway.StartupTimeout) * time.Second
logLauncher.Printf("Using configured startup timeout: %v", startupTimeout)
} else {
logLauncher.Printf("Using default startup timeout: %v", startupTimeout)
}
// Guarantee cfg.Gateway is non-nil with defaults applied.
// LoadFromFile/LoadFromStdin already ensure this, but tests may
// construct configs manually without going through the load path.
cfg.EnsureGatewayDefaults()

startupTimeout := time.Duration(cfg.Gateway.StartupTimeout) * time.Second
logLauncher.Printf("Using startup timeout: %v", startupTimeout)

// Initialize OIDC provider from environment if available
var oidcProvider *oidc.Provider
Expand Down
6 changes: 4 additions & 2 deletions internal/launcher/launcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ func TestGetOrLaunchForSession_SessionReuse(t *testing.T) {
ctx := context.Background()
cfg := &config.Config{
Servers: map[string]*config.ServerConfig{},
Gateway: &config.GatewayConfig{StartupTimeout: config.DefaultStartupTimeout},
}
l := New(ctx, cfg)
defer l.Close()
Expand Down Expand Up @@ -606,7 +607,8 @@ func TestLauncher_StartupTimeout(t *testing.T) {
}

func TestLauncher_TimeoutWithNilGateway(t *testing.T) {
// Test that launcher uses default timeout when Gateway config is nil
// Test that launcher uses default timeout when Gateway config is nil.
// EnsureGatewayDefaults is called by launcher.New, so nil Gateway is safe.
ctx := context.Background()
cfg := &config.Config{
Servers: map[string]*config.ServerConfig{
Expand All @@ -615,7 +617,7 @@ func TestLauncher_TimeoutWithNilGateway(t *testing.T) {
URL: "http://example.com",
},
},
Gateway: nil, // No gateway config
Gateway: nil, // No gateway config — EnsureGatewayDefaults fills defaults
}

l := New(ctx, cfg)
Expand Down
23 changes: 6 additions & 17 deletions internal/server/unified.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,14 @@ type UnifiedServer struct {
// NewUnified creates a new unified MCP server
func NewUnified(ctx context.Context, cfg *config.Config) (*UnifiedServer, error) {
logUnified.Printf("Creating new unified server: sequentialLaunch=%v, servers=%d", cfg.SequentialLaunch, len(cfg.Servers))
l := launcher.New(ctx, cfg)

// Get payload directory from config, with fallback to default
payloadDir := config.DefaultPayloadDir
if cfg.Gateway != nil && cfg.Gateway.PayloadDir != "" {
payloadDir = cfg.Gateway.PayloadDir
}

// Get payload path prefix from config (empty by default)
payloadPathPrefix := ""
if cfg.Gateway != nil && cfg.Gateway.PayloadPathPrefix != "" {
payloadPathPrefix = cfg.Gateway.PayloadPathPrefix
}
l := launcher.New(ctx, cfg)

// Get payload size threshold from config, with fallback to default
payloadSizeThreshold := config.DefaultPayloadSizeThreshold
if cfg.Gateway != nil && cfg.Gateway.PayloadSizeThreshold > 0 {
payloadSizeThreshold = cfg.Gateway.PayloadSizeThreshold
}
// Config loading guarantees cfg.Gateway is non-nil and all fields
// have defaults applied via applyGatewayDefaults/applyDefaults.
payloadDir := cfg.Gateway.PayloadDir
payloadPathPrefix := cfg.Gateway.PayloadPathPrefix
payloadSizeThreshold := cfg.Gateway.PayloadSizeThreshold
logUnified.Printf("Payload configuration: dir=%s, pathPrefix=%s, sizeThreshold=%d bytes (%.2f KB)",
payloadDir, payloadPathPrefix, payloadSizeThreshold, float64(payloadSizeThreshold)/1024)

Expand Down
Loading