Skip to content

TLS support on RemoteMCPServer + companion-Secret API#1905

Open
iplay88keys wants to merge 6 commits into
mainfrom
iplay88keys/mcp-server-ca-cert
Open

TLS support on RemoteMCPServer + companion-Secret API#1905
iplay88keys wants to merge 6 commits into
mainfrom
iplay88keys/mcp-server-ca-cert

Conversation

@iplay88keys
Copy link
Copy Markdown
Contributor

@iplay88keys iplay88keys commented May 21, 2026

Description

Adds TLS configuration to RemoteMCPServer so declarative agents can connect to MCP servers behind private CAs, self-signed certs, or corporate internal CAs. Mirrors the existing ModelConfig.spec.tls shape so the operator-facing surface is consistent across resource types.

apiVersion: kagent.dev/v1alpha2
kind: RemoteMCPServer
metadata:
  name: corp-mcp
  namespace: kagent
spec:
  description: Corporate-CA MCP server
  url: https://mcp.corp.internal/mcp
  tls:
    caCertSecretRef: corp-ca
    caCertSecretKey: ca.crt

Things to note:

  • RemoteMCPServer.spec.tls *TLSConfig reuses the TLSConfig from ModelConfig and have shared CEL validation
  • The controller reads RemoteMCPServer.spec.tls so that listing tools with a custom CA cert works
  • Added RemoteMCPServerURLRewriter extension point to allow for rewriting URLs of RemoteMCPServers before being dialed by the Kagent Controller
  • Config hash annotation for agent workloads runs after plugins to capture secret changes
  • addTLSConfiguration mounts a per-Secret read-only volume at /etc/ssl/certs/custom/<secretName>/<key> (previously a single fixed-name volume that silently collided when multiple TLS sources referenced different Secrets on the same agent).
  • POST /api/toolservers accepts an optional secrets []SecretMaterial array so operators can create an RMS or MCPServer and its companion Secrets in a single round-trip. Mirrors the existing ModelConfig inline-Secret pattern.
  • The /mcp/new page has been updated to add TLS configuration with client side validation that mirrors the CEL expressions.

Testing

Go e2e (go test ./test/e2e/... against a kind cluster with kagent installed):

  • TestE2E_RMS_PrivateCAUpstream — private-CA HTTPS upstream via mockmcp; asserts Status.DiscoveredTools populates, /api/toolservers returns the same tools, and the agent invocation reaches mockmcp's tool handler.
  • TestE2E_RMS_DisableVerify — same fixture, skip-verify path.
  • TestE2E_RMS_SSE_TLS — SSE transport against a private-CA upstream.
  • TestE2E_API_ToolServerCompanionSecrets — one-POST RMS+Secret creation with OwnerReference cascade.

Uses kagent-dev/mockmcp as the upstream fixture (pinned to main HEAD commit for now).

Out of scope

  • mTLS (client certs to upstream)
  • ConfigMap-sourced CA bundles
  • UI form fields for spec.tls — the TypeScript type binding is in this PR; rendering the form is a UI follow-up.

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
…r-ca-cert

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
@iplay88keys iplay88keys marked this pull request as ready for review May 22, 2026 18:05
Copilot AI review requested due to automatic review settings May 22, 2026 18:05
@chromatic-com
Copy link
Copy Markdown

chromatic-com Bot commented May 22, 2026

Warning

Testing paused

Monthly snapshot limit reached. Update your plan to get more snapshots and resume testing.

Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds end-to-end TLS support for RemoteMCPServer (CRD + controller tool-discovery + agent runtime wiring) and introduces a companion-Secret materialization API so operators can create/update a tool server and its referenced Secrets in one POST, aligning the surface area with existing ModelConfig.spec.tls patterns.

Changes:

  • Extend RemoteMCPServer with spec.tls (reusing TLSConfig + shared CEL validation) and propagate TLS settings into both controller-side MCP tool discovery and agent-side MCP transport params, including per-Secret CA bundle mounting to avoid volume collisions.
  • Add an optional RemoteMCPServerURLRewriter extension point to rewrite dial URLs prior to tool discovery.
  • Add companion Secret support to POST /api/toolservers (mirroring ModelConfig inline-Secret behavior), refactoring companion-secret logic into a shared helper and adding e2e/unit coverage.

Reviewed changes

Copilot reviewed 33 out of 35 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ui/src/types/index.ts Adds RemoteMCPServerSpec.tls typing and optional secrets payload on toolserver create requests.
python/packages/kagent-adk/src/kagent/adk/types.py Lifts TLS fields from nested MCP params and installs a TLS-aware httpx_client_factory for MCP sessions.
python/packages/kagent-adk/src/kagent/adk/models/_ssl.py Updates TLS examples to match new per-Secret CA mount paths.
python/packages/kagent-adk/tests/unittests/test_mcp_tls.py Unit tests for TLS field lifting + factory installation for HTTP/SSE MCP transports.
python/packages/kagent-adk/tests/unittests/models/test_tls_e2e.py Adjusts expected CA path in SSL troubleshooting assertions.
python/packages/kagent-adk/tests/unittests/models/test_openai.py Updates custom CA path expectations to include per-Secret directory.
helm/kagent-crds/templates/kagent.dev_remotemcpservers.yaml Adds spec.tls schema + CEL validations to RemoteMCPServer CRD (Helm template).
helm/kagent-crds/templates/kagent.dev_modelconfigs.yaml Moves TLS CEL validations into the TLSConfig schema for ModelConfig CRD (Helm template).
go/api/v1alpha2/modelconfig_types.go Adds shared kubebuilder XValidations to TLSConfig and introduces TLSConfig.IsEmpty().
go/api/v1alpha2/remotemcpserver_types.go Adds RemoteMCPServerSpec.TLS *TLSConfig.
go/api/v1alpha2/zz_generated.deepcopy.go Updates deepcopy generation for the new RemoteMCPServerSpec.TLS field.
go/api/config/crd/bases/kagent.dev_remotemcpservers.yaml Adds spec.tls schema + CEL validations to RemoteMCPServer CRD (base YAML).
go/api/config/crd/bases/kagent.dev_modelconfigs.yaml Moves TLS CEL validations into the TLSConfig schema for ModelConfig CRD (base YAML).
go/core/internal/controller/reconciler/reconciler.go Applies RMS TLS to controller tool discovery HTTP client; adds optional URL rewrite hook.
go/core/internal/controller/reconciler/reconciler_test.go Tests for RMS TLS config building, URL rewriting, and new TLS-aware HTTP client transport wiring.
go/core/internal/controller/reconciler/mcp_server_reconciler_test.go Updates reconciler constructor usage for the new URL rewriter arg.
go/core/pkg/translator/adk_api_translator_types.go Introduces RemoteMCPServerURLRewriter interface.
go/core/pkg/app/app.go Plumbs URL rewriter through extension config into the reconciler.
go/core/internal/controller/translator/agent/adk_api_translator.go Derives TLS wire fields via TLSConfig.IsEmpty(), mounts per-Secret CA bundles, and avoids mount/volume collisions.
go/core/internal/controller/translator/agent/compiler.go Threads modelDeploymentData into MCP translation so RMS TLS can add mounts.
go/core/internal/controller/translator/agent/manifest_builder.go Defers/stamps kagent.dev/config-hash after plugins so plugin mutations trigger rollouts.
go/core/internal/controller/translator/agent/manifest_builder_test.go Adds regression coverage for post-plugin config-hash stamping (deployment + sandbox paths).
go/core/internal/controller/translator/agent/tls_mounting_test.go Validates new per-Secret CA mount path/volume naming behavior and collision avoidance.
go/core/internal/controller/translator/agent/remotemcpserver_tls_test.go Tests RMS TLS propagation into wire params and CA Secret mounts in the agent deployment.
go/core/internal/controller/translator/agent/testdata/outputs/tls-with-custom-ca.json Updates golden output for per-Secret CA mount path and config hash changes.
go/core/internal/controller/translator/agent/testdata/outputs/tls-with-system-cas-disabled.json Updates golden output for per-Secret CA mount path and config hash changes.
go/core/internal/httpserver/handlers/companion_secrets.go Extracts shared companion-secret validation + create/update logic for multiple owner kinds.
go/core/internal/httpserver/handlers/modelconfig.go Switches ModelConfig companion-secret creation to shared helper with explicit GVK.
go/core/internal/httpserver/handlers/toolservers.go Adds secrets support to toolserver create request and uses shared companion-secret helper.
go/core/internal/httpserver/handlers/toolservers_test.go Adds unit tests for toolserver companion-secret creation, grouping, and rejection cases.
go/core/test/e2e/remotemcpserver_tls_test.go Adds e2e coverage for RMS TLS (private CA / skip-verify / SSE) and toolserver companion secrets.
go/core/test/e2e/mocks/invoke_remotemcpserver_tls_agent.json Adds mock LLM script used by the RMS TLS e2e tests.
go/go.mod Adds github.com/kagent-dev/mockmcp dependency for e2e fixture.
go/go.sum Adds checksums for github.com/kagent-dev/mockmcp.
examples/modelconfig-with-tls.yaml Updates troubleshooting paths to reflect per-Secret CA mount directory structure.
Files not reviewed (1)
  • go/api/v1alpha2/zz_generated.deepcopy.go: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go/core/internal/httpserver/handlers/toolservers.go
Comment thread helm/kagent-crds/templates/kagent.dev_remotemcpservers.yaml Outdated
Comment thread go/api/config/crd/bases/kagent.dev_remotemcpservers.yaml Outdated
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Signed-off-by: Jeremy Alvis <jeremy.alvis@solo.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants