@@ -62,9 +62,10 @@ type MCPServerOptions struct {
62
62
63
63
func NewMCPServerOptions (streams genericiooptions.IOStreams ) * MCPServerOptions {
64
64
return & MCPServerOptions {
65
- IOStreams : streams ,
66
- Profile : "full" ,
67
- ListOutput : "table" ,
65
+ IOStreams : streams ,
66
+ Profile : "full" ,
67
+ ListOutput : "table" ,
68
+ StaticConfig : & config.StaticConfig {},
68
69
}
69
70
}
70
71
@@ -76,7 +77,7 @@ func NewMCPServer(streams genericiooptions.IOStreams) *cobra.Command {
76
77
Long : long ,
77
78
Example : examples ,
78
79
RunE : func (c * cobra.Command , args []string ) error {
79
- if err := o .Complete (); err != nil {
80
+ if err := o .Complete (c ); err != nil {
80
81
return err
81
82
}
82
83
if err := o .Validate (); err != nil {
@@ -98,16 +99,14 @@ func NewMCPServer(streams genericiooptions.IOStreams) *cobra.Command {
98
99
cmd .Flags ().StringVar (& o .SSEBaseUrl , "sse-base-url" , o .SSEBaseUrl , "SSE public base URL to use when sending the endpoint message (e.g. https://example.com)" )
99
100
cmd .Flags ().StringVar (& o .Kubeconfig , "kubeconfig" , o .Kubeconfig , "Path to the kubeconfig file to use for authentication" )
100
101
cmd .Flags ().StringVar (& o .Profile , "profile" , o .Profile , "MCP profile to use (one of: " + strings .Join (mcp .ProfileNames , ", " )+ ")" )
101
- cmd .Flags ().StringVar (& o .ListOutput , "list-output" , o .ListOutput , "Output format for resource list operations (one of: " + strings .Join (output .Names , ", " )+ ")" )
102
+ cmd .Flags ().StringVar (& o .ListOutput , "list-output" , o .ListOutput , "Output format for resource list operations (one of: " + strings .Join (output .Names , ", " )+ "). Defaults to table. " )
102
103
cmd .Flags ().BoolVar (& o .ReadOnly , "read-only" , o .ReadOnly , "If true, only tools annotated with readOnlyHint=true are exposed" )
103
104
cmd .Flags ().BoolVar (& o .DisableDestructive , "disable-destructive" , o .DisableDestructive , "If true, tools annotated with destructiveHint=true are disabled" )
104
105
105
106
return cmd
106
107
}
107
108
108
- func (m * MCPServerOptions ) Complete () error {
109
- m .initializeLogging ()
110
-
109
+ func (m * MCPServerOptions ) Complete (cmd * cobra.Command ) error {
111
110
if m .ConfigPath != "" {
112
111
cnf , err := config .ReadConfig (m .ConfigPath )
113
112
if err != nil {
@@ -116,16 +115,47 @@ func (m *MCPServerOptions) Complete() error {
116
115
m .StaticConfig = cnf
117
116
}
118
117
118
+ m .loadFlags (cmd )
119
+
120
+ m .initializeLogging ()
121
+
119
122
return nil
120
123
}
121
124
125
+ func (m * MCPServerOptions ) loadFlags (cmd * cobra.Command ) {
126
+ if cmd .Flag ("log-level" ).Changed {
127
+ m .StaticConfig .LogLevel = m .LogLevel
128
+ }
129
+ if cmd .Flag ("sse-port" ).Changed {
130
+ m .StaticConfig .SSEPort = m .SSEPort
131
+ }
132
+ if cmd .Flag ("http-port" ).Changed {
133
+ m .StaticConfig .HTTPPort = m .HttpPort
134
+ }
135
+ if cmd .Flag ("sse-base-url" ).Changed {
136
+ m .StaticConfig .SSEBaseURL = m .SSEBaseUrl
137
+ }
138
+ if cmd .Flag ("kubeconfig" ).Changed {
139
+ m .StaticConfig .KubeConfig = m .Kubeconfig
140
+ }
141
+ if cmd .Flag ("list-output" ).Changed || m .StaticConfig .ListOutput == "" {
142
+ m .StaticConfig .ListOutput = m .ListOutput
143
+ }
144
+ if cmd .Flag ("read-only" ).Changed {
145
+ m .StaticConfig .ReadOnly = m .ReadOnly
146
+ }
147
+ if cmd .Flag ("disable-destructive" ).Changed {
148
+ m .StaticConfig .DisableDestructive = m .DisableDestructive
149
+ }
150
+ }
151
+
122
152
func (m * MCPServerOptions ) initializeLogging () {
123
153
flagSet := flag .NewFlagSet ("klog" , flag .ContinueOnError )
124
154
klog .InitFlags (flagSet )
125
155
loggerOptions := []textlogger.ConfigOption {textlogger .Output (m .Out )}
126
- if m .LogLevel >= 0 {
127
- loggerOptions = append (loggerOptions , textlogger .Verbosity (m .LogLevel ))
128
- _ = flagSet .Parse ([]string {"--v" , strconv .Itoa (m .LogLevel )})
156
+ if m .StaticConfig . LogLevel >= 0 {
157
+ loggerOptions = append (loggerOptions , textlogger .Verbosity (m .StaticConfig . LogLevel ))
158
+ _ = flagSet .Parse ([]string {"--v" , strconv .Itoa (m .StaticConfig . LogLevel )})
129
159
}
130
160
logger := textlogger .NewLogger (textlogger .NewConfig (loggerOptions ... ))
131
161
klog .SetLoggerWithOptions (logger )
@@ -140,16 +170,16 @@ func (m *MCPServerOptions) Run() error {
140
170
if profile == nil {
141
171
return fmt .Errorf ("Invalid profile name: %s, valid names are: %s\n " , m .Profile , strings .Join (mcp .ProfileNames , ", " ))
142
172
}
143
- listOutput := output .FromString (m .ListOutput )
173
+ listOutput := output .FromString (m .StaticConfig . ListOutput )
144
174
if listOutput == nil {
145
- return fmt .Errorf ("Invalid output name: %s, valid names are: %s\n " , m .ListOutput , strings .Join (output .Names , ", " ))
175
+ return fmt .Errorf ("Invalid output name: %s, valid names are: %s\n " , m .StaticConfig . ListOutput , strings .Join (output .Names , ", " ))
146
176
}
147
177
klog .V (1 ).Info ("Starting kubernetes-mcp-server" )
148
178
klog .V (1 ).Infof (" - Config: %s" , m .ConfigPath )
149
179
klog .V (1 ).Infof (" - Profile: %s" , profile .GetName ())
150
180
klog .V (1 ).Infof (" - ListOutput: %s" , listOutput .GetName ())
151
- klog .V (1 ).Infof (" - Read-only mode: %t" , m .ReadOnly )
152
- klog .V (1 ).Infof (" - Disable destructive tools: %t" , m .DisableDestructive )
181
+ klog .V (1 ).Infof (" - Read-only mode: %t" , m .StaticConfig . ReadOnly )
182
+ klog .V (1 ).Infof (" - Disable destructive tools: %t" , m .StaticConfig . DisableDestructive )
153
183
154
184
if m .Version {
155
185
_ , _ = fmt .Fprintf (m .Out , "%s\n " , version .Version )
@@ -158,9 +188,9 @@ func (m *MCPServerOptions) Run() error {
158
188
mcpServer , err := mcp .NewServer (mcp.Configuration {
159
189
Profile : profile ,
160
190
ListOutput : listOutput ,
161
- ReadOnly : m .ReadOnly ,
162
- DisableDestructive : m .DisableDestructive ,
163
- Kubeconfig : m .Kubeconfig ,
191
+ ReadOnly : m .StaticConfig . ReadOnly ,
192
+ DisableDestructive : m .StaticConfig . DisableDestructive ,
193
+ Kubeconfig : m .StaticConfig . KubeConfig ,
164
194
StaticConfig : m .StaticConfig ,
165
195
})
166
196
if err != nil {
@@ -170,19 +200,19 @@ func (m *MCPServerOptions) Run() error {
170
200
171
201
ctx := context .Background ()
172
202
173
- if m .SSEPort > 0 {
174
- sseServer := mcpServer .ServeSse (m .SSEBaseUrl )
203
+ if m .StaticConfig . SSEPort > 0 {
204
+ sseServer := mcpServer .ServeSse (m .StaticConfig . SSEBaseURL )
175
205
defer func () { _ = sseServer .Shutdown (ctx ) }()
176
- klog .V (0 ).Infof ("SSE server starting on port %d and path /sse" , m .SSEPort )
177
- if err := sseServer .Start (fmt .Sprintf (":%d" , m .SSEPort )); err != nil {
206
+ klog .V (0 ).Infof ("SSE server starting on port %d and path /sse" , m .StaticConfig . SSEPort )
207
+ if err := sseServer .Start (fmt .Sprintf (":%d" , m .StaticConfig . SSEPort )); err != nil {
178
208
return fmt .Errorf ("failed to start SSE server: %w\n " , err )
179
209
}
180
210
}
181
211
182
- if m .HttpPort > 0 {
212
+ if m .StaticConfig . HTTPPort > 0 {
183
213
httpServer := mcpServer .ServeHTTP ()
184
- klog .V (0 ).Infof ("Streaming HTTP server starting on port %d and path /mcp" , m .HttpPort )
185
- if err := httpServer .Start (fmt .Sprintf (":%d" , m .HttpPort )); err != nil {
214
+ klog .V (0 ).Infof ("Streaming HTTP server starting on port %d and path /mcp" , m .StaticConfig . HTTPPort )
215
+ if err := httpServer .Start (fmt .Sprintf (":%d" , m .StaticConfig . HTTPPort )); err != nil {
186
216
return fmt .Errorf ("failed to start streaming HTTP server: %w\n " , err )
187
217
}
188
218
}
0 commit comments