@@ -127,6 +127,7 @@ func (r *MCPServerReconciler) detectPlatform(ctx context.Context) (kubernetes.Pl
127
127
// +kubebuilder:rbac:groups=toolhive.stacklok.dev,resources=mcpservers,verbs=get;list;watch;create;update;patch;delete
128
128
// +kubebuilder:rbac:groups=toolhive.stacklok.dev,resources=mcpservers/status,verbs=get;update;patch
129
129
// +kubebuilder:rbac:groups=toolhive.stacklok.dev,resources=mcpservers/finalizers,verbs=update
130
+ // +kubebuilder:rbac:groups=toolhive.stacklok.dev,resources=mcptoolconfigs,verbs=get;list;watch
130
131
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=create;delete;get;list;patch;update;watch
131
132
// +kubebuilder:rbac:groups="",resources=services,verbs=create;delete;get;list;patch;update;watch;apply
132
133
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles,verbs=create;delete;get;list;patch;update;watch
@@ -162,6 +163,17 @@ func (r *MCPServerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
162
163
return ctrl.Result {}, err
163
164
}
164
165
166
+ // Check if MCPToolConfig is referenced and handle it
167
+ if err := r .handleToolConfig (ctx , mcpServer ); err != nil {
168
+ ctxLogger .Error (err , "Failed to handle MCPToolConfig" )
169
+ // Update status to reflect the error
170
+ mcpServer .Status .Phase = mcpv1alpha1 .MCPServerPhaseFailed
171
+ if statusErr := r .Status ().Update (ctx , mcpServer ); statusErr != nil {
172
+ ctxLogger .Error (statusErr , "Failed to update MCPServer status after MCPToolConfig error" )
173
+ }
174
+ return ctrl.Result {}, err
175
+ }
176
+
165
177
// Check if the MCPServer instance is marked to be deleted
166
178
if mcpServer .GetDeletionTimestamp () != nil {
167
179
// The object is being deleted
@@ -393,6 +405,50 @@ func (r *MCPServerReconciler) updateRBACResourceIfNeeded(
393
405
}
394
406
395
407
// ensureRBACResources ensures that the RBAC resources are in place for the MCP server
408
+
409
+ // handleToolConfig handles MCPToolConfig reference for an MCPServer
410
+ func (r * MCPServerReconciler ) handleToolConfig (ctx context.Context , m * mcpv1alpha1.MCPServer ) error {
411
+ if m .Spec .ToolConfigRef == nil {
412
+ // No MCPToolConfig referenced, clear any stored hash
413
+ if m .Status .ToolConfigHash != "" {
414
+ m .Status .ToolConfigHash = ""
415
+ if err := r .Status ().Update (ctx , m ); err != nil {
416
+ return fmt .Errorf ("failed to clear MCPToolConfig hash from status: %w" , err )
417
+ }
418
+ }
419
+ return nil
420
+ }
421
+
422
+ // Get the referenced MCPToolConfig
423
+ toolConfig , err := GetToolConfigForMCPServer (ctx , r .Client , m )
424
+ if err != nil {
425
+ return err
426
+ }
427
+
428
+ if toolConfig == nil {
429
+ return fmt .Errorf ("MCPToolConfig %s not found" , m .Spec .ToolConfigRef .Name )
430
+ }
431
+
432
+ // Check if the MCPToolConfig hash has changed
433
+ if m .Status .ToolConfigHash != toolConfig .Status .ConfigHash {
434
+ ctxLogger .Info ("MCPToolConfig has changed, updating MCPServer" ,
435
+ "mcpserver" , m .Name ,
436
+ "toolconfig" , toolConfig .Name ,
437
+ "oldHash" , m .Status .ToolConfigHash ,
438
+ "newHash" , toolConfig .Status .ConfigHash )
439
+
440
+ // Update the stored hash
441
+ m .Status .ToolConfigHash = toolConfig .Status .ConfigHash
442
+ if err := r .Status ().Update (ctx , m ); err != nil {
443
+ return fmt .Errorf ("failed to update MCPToolConfig hash in status: %w" , err )
444
+ }
445
+
446
+ // The change in hash will trigger a reconciliation of the RunConfig
447
+ // which will pick up the new tool configuration
448
+ }
449
+
450
+ return nil
451
+ }
396
452
func (r * MCPServerReconciler ) ensureRBACResources (ctx context.Context , mcpServer * mcpv1alpha1.MCPServer ) error {
397
453
proxyRunnerNameForRBAC := proxyRunnerServiceAccountName (mcpServer .Name )
398
454
0 commit comments