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
2 changes: 1 addition & 1 deletion api/v1alpha1/mcpserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ type MCPServerDeployment struct {
// SecretRefs defines the list of Kubernetes secrets to reference.
// These secrets will be mounted as volumes to the MCP server container.
// +optional
SecretRefs []corev1.ObjectReference `json:"secretRefs,omitempty"`
SecretRefs []corev1.LocalObjectReference `json:"secretRefs,omitempty"`
}

// MCPServerAuthentication defines the authentication configuration for the MCP server.
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 7 additions & 35 deletions config/crd/bases/kagent.dev_mcpservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,47 +197,19 @@ spec:
SecretRefs defines the list of Kubernetes secrets to reference.
These secrets will be mounted as volumes to the MCP server container.
items:
description: ObjectReference contains enough information to
let you inspect or modify the referred object.
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: |-
If referring to a piece of an object instead of an entire object, this string
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within a pod, this would take on a value like:
"spec.containers{name}" (where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to have some well-defined way of
referencing a part of an object.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
namespace:
description: |-
Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
type: string
resourceVersion:
description: |-
Specific resourceVersion to which this reference is made, if any.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
type: string
uid:
description: |-
UID of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
type: string
type: object
x-kubernetes-map-type: atomic
type: array
Expand Down
1 change: 1 addition & 0 deletions helm/kmcp/templates/rbac/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ rules:
resources:
- configmaps
- services
- serviceaccounts
verbs:
- create
- delete
Expand Down
15 changes: 4 additions & 11 deletions pkg/cli/internal/commands/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/kagent-dev/kmcp/api/v1alpha1"
"github.com/kagent-dev/kmcp/pkg/cli/internal/manifest"
"github.com/kagent-dev/kmcp/pkg/cli/internal/wellknown"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -267,7 +266,7 @@ func generateMCPServer(
if err != nil {
return nil, fmt.Errorf("failed to get secret reference: %w", err)
}
var secretRefs []corev1.ObjectReference
var secretRefs []corev1.LocalObjectReference
if secretRef != nil {
secretRefs = append(secretRefs, *secretRef)
}
Expand Down Expand Up @@ -327,7 +326,7 @@ func generateMCPServer(
func getSecretRefFromManifest(
projectManifest *manifest.ProjectManifest,
environment string,
) (*corev1.ObjectReference, error) {
) (*corev1.LocalObjectReference, error) {
if environment == "" {
return nil, nil // No environment specified
}
Expand All @@ -342,15 +341,9 @@ func getSecretRefFromManifest(
if secretName == "" {
return nil, fmt.Errorf("secretName not found in secret provider config for environment %s", environment)
}
namespace := secretProvider.Namespace
if namespace == "" {
return nil, fmt.Errorf("namespace not found in secret provider config for environment %s", environment)
}

return &corev1.ObjectReference{
Kind: wellknown.SecretKind,
Name: secretName,
Namespace: namespace,
return &corev1.LocalObjectReference{
Name: secretName,
}, nil
}

Expand Down
46 changes: 30 additions & 16 deletions pkg/controller/internal/agentgateway/agentgateway_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,9 @@ const (
agentGatewayContainerImage = "ghcr.io/agentgateway/agentgateway:0.7.4-musl"
)

type Outputs struct {
// AgentGateway Deployment
Deployment *appsv1.Deployment
// AgentGateway Service
Service *corev1.Service
// AgentGateway Configmap
ConfigMap *corev1.ConfigMap
}

// Translator is the interface for translating MCPServer objects to AgentGateway objects.
type Translator interface {
TranslateAgentGatewayOutputs(ctx context.Context, server *v1alpha1.MCPServer) (*Outputs, error)
TranslateAgentGatewayOutputs(ctx context.Context, server *v1alpha1.MCPServer) ([]client.Object, error)
}

// agentGatewayTranslator is the implementation of the Translator interface.
Expand All @@ -53,7 +44,7 @@ func NewAgentGatewayTranslator(scheme *runtime.Scheme, client client.Client) Tra
func (t *agentGatewayTranslator) TranslateAgentGatewayOutputs(
ctx context.Context,
server *v1alpha1.MCPServer,
) (*Outputs, error) {
) ([]client.Object, error) {
deployment, err := t.translateAgentGatewayDeployment(server)
if err != nil {
return nil, fmt.Errorf("failed to translate AgentGateway deployment: %w", err)
Expand All @@ -66,10 +57,15 @@ func (t *agentGatewayTranslator) TranslateAgentGatewayOutputs(
if err != nil {
return nil, fmt.Errorf("failed to translate AgentGateway config map: %w", err)
}
return &Outputs{
Deployment: deployment,
Service: service,
ConfigMap: configMap,
serviceAccount, err := t.translateAgentGatewayServiceAccount(server)
if err != nil {
return nil, fmt.Errorf("failed to translate AgentGateway service account: %w", err)
}
return []client.Object{
deployment,
service,
configMap,
serviceAccount,
}, nil
}

Expand All @@ -89,6 +85,7 @@ func (t *agentGatewayTranslator) translateAgentGatewayDeployment(
case v1alpha1.TransportTypeStdio:
// copy the binary into the container when running with stdio
template = corev1.PodSpec{
ServiceAccountName: server.Name,
InitContainers: []corev1.Container{{
Name: "copy-binary",
Image: agentGatewayContainerImage,
Expand All @@ -115,6 +112,7 @@ func (t *agentGatewayTranslator) translateAgentGatewayDeployment(
"-f",
"/config/local.yaml",
},
Env: convertEnvVars(server.Spec.Deployment.Env),
EnvFrom: secretEnvFrom,
VolumeMounts: func() []corev1.VolumeMount {
mounts := []corev1.VolumeMount{
Expand Down Expand Up @@ -275,9 +273,25 @@ func (t *agentGatewayTranslator) translateAgentGatewayDeployment(
return deployment, controllerutil.SetOwnerReference(server, deployment, t.scheme)
}

func (t *agentGatewayTranslator) translateAgentGatewayServiceAccount(
server *v1alpha1.MCPServer,
) (*corev1.ServiceAccount, error) {
serviceAccount := &corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
Kind: "ServiceAccount",
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: server.Name,
Namespace: server.Namespace,
},
}
return serviceAccount, controllerutil.SetOwnerReference(server, serviceAccount, t.scheme)
}

// createSecretEnvFrom creates envFrom references from secret references
func (t *agentGatewayTranslator) createSecretEnvFrom(
secretRefs []corev1.ObjectReference,
secretRefs []corev1.LocalObjectReference,
) []corev1.EnvFromSource {
envFrom := make([]corev1.EnvFromSource, 0, len(secretRefs))

Expand Down
16 changes: 3 additions & 13 deletions pkg/controller/mcpserver_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,10 @@ func (r *MCPServerReconciler) SetupWithManager(mgr ctrl.Manager) error {
Complete(r)
}

func (r *MCPServerReconciler) reconcileOutputs(ctx context.Context, outputs *agentgateway.Outputs) error {
func (r *MCPServerReconciler) reconcileOutputs(ctx context.Context, outputs []client.Object) error {
// upsert the outputs to the cluster
if outputs.Deployment != nil {
if err := upsertOutput(ctx, r.Client, outputs.Deployment); err != nil {
return err
}
}
if outputs.Service != nil {
if err := upsertOutput(ctx, r.Client, outputs.Service); err != nil {
return err
}
}
if outputs.ConfigMap != nil {
if err := upsertOutput(ctx, r.Client, outputs.ConfigMap); err != nil {
for _, output := range outputs {
if err := upsertOutput(ctx, r.Client, output); err != nil {
return err
}
}
Expand Down
Loading