Skip to content

Conversation

@amirejaz
Copy link
Contributor

Summary

This PR implements automatic discovery and resolution of MCPExternalAuthConfig resources for backend MCPServers in the VirtualMCPServer controller. The feature enables VirtualMCPServer to automatically discover and apply external authentication configurations (e.g., OAuth2 Token Exchange) from referenced MCPServer resources without requiring manual configuration.

Changes

Core Implementation

  • buildOutgoingAuthConfig: New function that builds OutgoingAuthConfig by discovering ExternalAuthConfig from MCPServer resources when using "discovered" or "mixed" source modes
  • convertExternalAuthConfigToStrategy: Converts MCPExternalAuthConfig CRD resources to internal BackendAuthStrategy format, handling token exchange configuration including client secrets, scopes, and token types
  • convertBackendAuthConfigToVMCP: Converts inline BackendAuthConfig from CRD spec to BackendAuthStrategy, supporting both direct references and ExternalAuthConfigRef references
  • Updated discoverBackends: Now uses the resolved OutgoingAuthConfig (including discovered external auth configs) when creating the UnifiedBackendDiscoverer
  • Updated ensureVmcpConfigConfigMap: Ensures that fully resolved OutgoingAuthConfig (including discovered external auths) is written to the ConfigMap consumed by VirtualMCPServer pods

Features

  • Three source modes supported:

    • discovered: Automatically discover auth configs from all referenced MCPServers
    • mixed: Discover from MCPServers but allow inline overrides per backend
    • inline: Use only explicitly specified auth configs (existing behavior)
  • Token Exchange support: Full support for OAuth2 Token Exchange (RFC 8693) including:

    • Token URL, client ID, audience, scopes
    • Client secret references (via Kubernetes Secrets)
    • Subject token type normalization
    • Custom external token header names

Testing

  • Unit tests: Comprehensive test coverage in virtualmcpserver_externalauth_test.go:

    • TestConvertExternalAuthConfigToStrategy: Tests conversion logic with various configurations
    • TestBuildOutgoingAuthConfig: Tests building OutgoingAuthConfig in all three modes
    • TestConvertBackendAuthConfigToVMCP: Tests inline config conversion
    • TestDiscoverBackendsWithExternalAuthConfigIntegration: Integration test for end-to-end discovery flow
  • Manual testing: Added complete manual testing setup:

    • Test manifests for all three modes (manual-test-external-auth-discovery.yaml, manual-test-mixed-mode.yaml, manual-test-inline-mode.yaml)
    • Verification script (verify-external-auth.sh) to validate ConfigMap content and deployment configuration
    • Comprehensive guides (QUICK_START.md, MANUAL_TESTING_GUIDE.md) with step-by-step instructions

How It Works

  1. When a VirtualMCPServer is created/updated, the controller discovers all referenced MCPServers from the specified groups
  2. For each MCPServer with an ExternalAuthConfigRef, the controller:
    • Fetches the MCPExternalAuthConfig resource
    • Converts it to a BackendAuthStrategy with appropriate metadata
    • Adds it to the OutgoingAuthConfig for that backend
  3. The resolved configuration (including discovered auth configs) is written to the vmcp ConfigMap
  4. The VirtualMCPServer pod consumes this ConfigMap and uses the auth strategies when communicating with backends

Example Usage

l

MCPExternalAuthConfig defines token exchange configuration

apiVersion: toolhive.stacklok.dev/v1alpha1
kind: MCPExternalAuthConfig
metadata:
name: backend-1-auth-config
spec:
type: tokenExchange
tokenExchange:
tokenUrl: https://oauth.example.com/token
clientId: my-client-id
clientSecretRef:
name: oauth-secret
key: client-secret
audience: backend-service
scopes: [read, write]

MCPServer references the ExternalAuthConfig

apiVersion: toolhive.stacklok.dev/v1alpha1
kind: MCPServer
metadata:
name: backend-1
spec:
externalAuthConfigRef:
name: backend-1-auth-config

... other spec fields

VirtualMCPServer automatically discovers and applies the auth config

apiVersion: toolhive.stacklok.dev/v1alpha1
kind: VirtualMCPServer
metadata:
name: my-vmcp
spec:
groups:
- name: my-group
outgoingAuth:
source: discovered # Automatically discover from MCPServers## Notes

  • Client secret environment variables are referenced in the ConfigMap metadata but are not yet automatically mounted in the deployment (this will be addressed in a follow-up PR)
  • The implementation gracefully handles missing or invalid MCPExternalAuthConfig resources by logging and skipping affected backends
  • Inline configurations always take precedence over discovered configurations when both are present

Related Issues

Fixes the issue where ExternalAuthConfig was not being resolved and used by the VirtualMCPServer controller to populate backend authentication configurations.

Testing

  • Unit tests pass
  • Manual testing completed with Kind cluster
  • Verified ConfigMap contains discovered auth configs
  • Verified all three source modes work correctly

@github-actions github-actions bot added the size/XL Extra large PR: 1000+ lines changed label Nov 25, 2025
@codecov
Copy link

codecov bot commented Nov 25, 2025

Codecov Report

❌ Patch coverage is 37.39496% with 149 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.19%. Comparing base (e724609) to head (f979c24).

Files with missing lines Patch % Lines
...perator/controllers/virtualmcpserver_deployment.go 9.84% 119 Missing ⚠️
...perator/controllers/virtualmcpserver_controller.go 76.08% 14 Missing and 8 partials ⚠️
...perator/controllers/virtualmcpserver_vmcpconfig.go 42.85% 4 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2726      +/-   ##
==========================================
- Coverage   56.29%   56.19%   -0.10%     
==========================================
  Files         319      319              
  Lines       30753    30956     +203     
==========================================
+ Hits        17312    17396      +84     
- Misses      11953    12062     +109     
- Partials     1488     1498      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@amirejaz amirejaz requested review from jhrozek and yrobla November 25, 2025 11:56
@amirejaz
Copy link
Contributor Author

implements #2704

- Merge latest main branch into PR branch
- Refactor convertExternalAuthConfigToStrategy to use converter registry
  instead of manual conversion, enabling support for all auth types
  (token exchange, header injection, etc.)
- Remove all references to pass_through strategy (removed in main)
- Update tests to use external_auth_config_ref instead of pass_through
- Add header injection test case
- All tests pass and linting is clean
@github-actions github-actions bot removed the size/XL Extra large PR: 1000+ lines changed label Nov 27, 2025
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Large PR Detected

This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.

How to unblock this PR:

Add a section to your PR description with the following format:

## Large PR Justification

[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformation

Alternative:

Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.

See our Contributing Guidelines for more details.


This review will be automatically dismissed once you add the justification section.

@github-actions github-actions bot added the size/XL Extra large PR: 1000+ lines changed label Nov 27, 2025
The 'discovered' type is not a valid vmcp strategy type - it's only used
at the CRD level to indicate that discovery should happen. When used in
inline mode (as a BackendAuthConfig type), it should be rejected with
an error since it cannot be converted to a valid vmcp strategy.

This fixes e2e test failures where VirtualMCPServer was not becoming
ready due to invalid auth configuration being written to the ConfigMap.

- Add validation to reject 'discovered' type in convertBackendAuthConfigToVMCP
- Update test to expect error for 'discovered' type
- All unit tests pass
@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Nov 27, 2025
@amirejaz amirejaz marked this pull request as draft November 27, 2025 14:12
@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Nov 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large PR: 1000+ lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants