Skip to content

Commit 6bc2332

Browse files
committed
merge remote into local
2 parents 4303809 + 8989d46 commit 6bc2332

File tree

198 files changed

+12498
-5494
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+12498
-5494
lines changed

.github/workflows/image-build-and-publish.yml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
4040

4141
- name: Install Cosign
42-
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
42+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
4343

4444
- name: Build and Push Image to GHCR
4545
env:
@@ -103,7 +103,7 @@ jobs:
103103

104104
- name: Extract metadata
105105
id: meta
106-
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
106+
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
107107
with:
108108
images: ${{ env.BASE_REPO }}
109109
tags: |
@@ -125,7 +125,7 @@ jobs:
125125
126126
- name: Install Cosign
127127
if: startsWith(github.ref, 'refs/tags/')
128-
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
128+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
129129

130130
- name: Sign container image
131131
if: startsWith(github.ref, 'refs/tags/')
@@ -182,18 +182,19 @@ jobs:
182182

183183
- name: Extract UBI metadata
184184
id: ubi-meta
185-
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
185+
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
186186
with:
187187
images: ${{ env.BASE_REPO }}
188188
tags: |
189189
type=raw,value=${{ steps.version-string.outputs.tag }}-ubi
190+
type=raw,value=latest-ubi,enable=${{ startsWith(github.ref, 'refs/tags/') }}
190191
labels: |
191192
name=toolhive-operator
192193
vendor=Stacklok
193194
maintainer=Stacklok
194195
195196
- name: Install Cosign
196-
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
197+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
197198

198199
- name: Build and Push Image to GHCR
199200
env:
@@ -240,6 +241,7 @@ jobs:
240241
# Sign the latest tag if building from a tag
241242
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
242243
cosign sign -y $BASE_REPO:latest
244+
cosign sign -y $BASE_REPO:latest-ubi
243245
fi
244246
245247
proxyrunner-image-build-and-publish:
@@ -281,11 +283,12 @@ jobs:
281283

282284
- name: Extract UBI metadata
283285
id: ubi-meta
284-
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
286+
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
285287
with:
286288
images: ${{ env.BASE_REPO }}
287289
tags: |
288290
type=raw,value=${{ steps.version-string.outputs.tag }}-ubi
291+
type=raw,value=latest-ubi,enable=${{ startsWith(github.ref, 'refs/tags/') }}
289292
labels: |
290293
name=toolhive-proxyrunner
291294
vendor=Stacklok
@@ -337,6 +340,7 @@ jobs:
337340
# Sign the latest tag if building from a tag
338341
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
339342
cosign sign -y $BASE_REPO:latest
343+
cosign sign -y $BASE_REPO:latest-ubi
340344
fi
341345
342346
vmcp-image-build-and-publish:
@@ -386,7 +390,7 @@ jobs:
386390
uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
387391

388392
- name: Install Cosign
389-
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
393+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
390394

391395
- name: Build and Push Image to GHCR
392396
env:

.github/workflows/releaser-helm-charts.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
password: ${{ secrets.GITHUB_TOKEN }}
4444

4545
- name: Install Cosign
46-
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
46+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
4747

4848
- name: Publish and Sign OCI Charts
4949
run: |

.github/workflows/releaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
uses: anchore/sbom-action/download-syft@8e94d75ddd33f69f691467e42275782e4bfefe84 # v0.20.9
7676

7777
- name: Install Cosign
78-
uses: sigstore/cosign-installer@7e8b541eb2e61bf99390e1afd4be13a184e9ebc5 # v3.10.1
78+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
7979

8080
- name: Build and Verify Binary Version
8181
env:

.github/workflows/test-helm-charts.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
python-version: 3.13
2727

2828
- name: Set up chart-testing
29-
uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0
29+
uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0
3030

3131
- name: Run chart-testing (lint)
3232
run: ct lint --config ct.yaml

.goreleaser.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ signs:
106106
- "sign-blob"
107107
- "--output-signature=${signature}"
108108
- "--output-certificate=${certificate}"
109+
- "--bundle=${signature}" # added for cosign v3: required when using --output-signature or --signing-config
109110
- "${artifact}"
110111
- "--yes" # needed on cosign 2.0.0+
111112
artifacts: archive

CLAUDE.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ The test framework uses Ginkgo and Gomega for BDD-style testing.
8888
- `transport/`: Communication protocols (HTTP, SSE, stdio, streamable)
8989
- `workloads/`: Workload lifecycle management
9090

91+
4. **Virtual MCP Server (`cmd/vmcp/`)**
92+
- Core packages in `pkg/vmcp/`:
93+
- `aggregator/`: Backend discovery (CLI/K8s), capability querying, conflict resolution (prefix/priority/manual)
94+
- `router/`: Routes MCP requests (tools/resources/prompts) to backends
95+
- `auth/`: Two-boundary auth model (incoming: clients→vMCP; outgoing: vMCP→backends)
96+
- `composer/`: Multi-step workflow execution with DAG-based parallel/sequential support
97+
- `config/`: Platform-agnostic config model (works for CLI YAML and K8s CRDs)
98+
- `server/`: HTTP server implementation with session management and auth middleware
99+
- `client/`: Backend MCP client using mark3labs/mcp-go SDK
100+
- `cache/`: Token caching with pluggable backends
101+
- K8s CRDs in `cmd/thv-operator/api/v1alpha1/`:
102+
- `VirtualMCPServer`: Main vMCP server resource (GroupRef, auth configs, aggregation, composite tools)
103+
- `VirtualMCPCompositeToolDefinition`: Reusable composite tool workflows
104+
- `MCPGroup`: Defines backend workload collections
105+
- `MCPServer`, `MCPRegistry`, `MCPRemoteProxy`: Backend workload types
106+
- `MCPExternalAuthConfig`, `ToolConfig`: Supporting config resources
107+
91108
### Key Design Patterns
92109

93110
- **Factory Pattern**: Used extensively for creating runtime-specific implementations (Docker/Colima/Podman vs Kubernetes)

cmd/thv-operator/api/v1alpha1/virtualmcpserver_types.go

Lines changed: 11 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ type VirtualMCPServerSpec struct {
4242
// +optional
4343
Operational *OperationalConfig `json:"operational,omitempty"`
4444

45+
// ServiceType specifies the Kubernetes service type for the Virtual MCP server
46+
// +kubebuilder:validation:Enum=ClusterIP;NodePort;LoadBalancer
47+
// +kubebuilder:default=ClusterIP
48+
// +optional
49+
ServiceType string `json:"serviceType,omitempty"`
50+
4551
// PodTemplateSpec defines the pod template to use for the Virtual MCP server
4652
// This allows for customizing the pod configuration beyond what is provided by the other fields.
4753
// Note that to modify the specific container the Virtual MCP server runs in, you must specify
@@ -62,6 +68,11 @@ type GroupRef struct {
6268

6369
// IncomingAuthConfig configures authentication for clients connecting to the Virtual MCP server
6470
type IncomingAuthConfig struct {
71+
// Type defines the authentication type: anonymous, local, or oidc
72+
// +kubebuilder:validation:Enum=anonymous;local;oidc
73+
// +optional
74+
Type string `json:"type,omitempty"`
75+
6576
// OIDCConfig defines OIDC authentication configuration
6677
// Reuses MCPServer OIDC patterns
6778
// +optional
@@ -426,14 +437,6 @@ type VirtualMCPServerStatus struct {
426437
// +optional
427438
Conditions []metav1.Condition `json:"conditions,omitempty"`
428439

429-
// DiscoveredBackends lists discovered backend configurations when source=discovered
430-
// +optional
431-
DiscoveredBackends []DiscoveredBackend `json:"discoveredBackends,omitempty"`
432-
433-
// Capabilities summarizes aggregated capabilities from all backends
434-
// +optional
435-
Capabilities *CapabilitiesSummary `json:"capabilities,omitempty"`
436-
437440
// ObservedGeneration is the most recent generation observed for this VirtualMCPServer
438441
// +optional
439442
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
@@ -452,54 +455,6 @@ type VirtualMCPServerStatus struct {
452455
URL string `json:"url,omitempty"`
453456
}
454457

455-
// DiscoveredBackend represents a discovered backend MCPServer
456-
type DiscoveredBackend struct {
457-
// Name is the name of the backend MCPServer
458-
// +kubebuilder:validation:Required
459-
Name string `json:"name"`
460-
461-
// AuthConfigRef is the name of the discovered MCPExternalAuthConfig
462-
// Empty if backend has no external auth config
463-
// +optional
464-
AuthConfigRef string `json:"authConfigRef,omitempty"`
465-
466-
// AuthType is the type of authentication configured
467-
// +optional
468-
AuthType string `json:"authType,omitempty"`
469-
470-
// Status is the current status of the backend
471-
// +kubebuilder:validation:Enum=ready;degraded;unavailable
472-
// +optional
473-
Status string `json:"status,omitempty"`
474-
475-
// LastHealthCheck is the timestamp of the last health check
476-
// +optional
477-
LastHealthCheck *metav1.Time `json:"lastHealthCheck,omitempty"`
478-
479-
// URL is the URL of the backend MCPServer
480-
// +optional
481-
URL string `json:"url,omitempty"`
482-
}
483-
484-
// CapabilitiesSummary summarizes aggregated capabilities
485-
type CapabilitiesSummary struct {
486-
// ToolCount is the total number of tools exposed
487-
// +optional
488-
ToolCount int `json:"toolCount,omitempty"`
489-
490-
// ResourceCount is the total number of resources exposed
491-
// +optional
492-
ResourceCount int `json:"resourceCount,omitempty"`
493-
494-
// PromptCount is the total number of prompts exposed
495-
// +optional
496-
PromptCount int `json:"promptCount,omitempty"`
497-
498-
// CompositeToolCount is the number of composite tools defined
499-
// +optional
500-
CompositeToolCount int `json:"compositeToolCount,omitempty"`
501-
}
502-
503458
// VirtualMCPServerPhase represents the lifecycle phase of a VirtualMCPServer
504459
// +kubebuilder:validation:Enum=Pending;Ready;Degraded;Failed
505460
type VirtualMCPServerPhase string
@@ -524,36 +479,18 @@ const (
524479
// ConditionTypeVirtualMCPServerReady indicates whether the VirtualMCPServer is ready
525480
ConditionTypeVirtualMCPServerReady = "Ready"
526481

527-
// ConditionTypeBackendsDiscovered indicates whether backends have been discovered
528-
ConditionTypeBackendsDiscovered = "BackendsDiscovered"
529-
530482
// ConditionTypeVirtualMCPServerGroupRefValidated indicates whether the GroupRef is valid
531483
ConditionTypeVirtualMCPServerGroupRefValidated = "GroupRefValidated"
532484
)
533485

534486
// Condition reasons for VirtualMCPServer
535487
const (
536-
// ConditionReasonAllBackendsReady indicates all backends are ready
537-
ConditionReasonAllBackendsReady = "AllBackendsReady"
538-
539-
// ConditionReasonSomeBackendsUnavailable indicates some backends are unavailable
540-
ConditionReasonSomeBackendsUnavailable = "SomeBackendsUnavailable"
541-
542-
// ConditionReasonNoBackends indicates no backends were discovered
543-
ConditionReasonNoBackends = "NoBackends"
544-
545488
// ConditionReasonIncomingAuthValid indicates incoming auth is valid
546489
ConditionReasonIncomingAuthValid = "IncomingAuthValid"
547490

548491
// ConditionReasonIncomingAuthInvalid indicates incoming auth is invalid
549492
ConditionReasonIncomingAuthInvalid = "IncomingAuthInvalid"
550493

551-
// ConditionReasonDiscoveryComplete indicates backend discovery is complete
552-
ConditionReasonDiscoveryComplete = "DiscoveryComplete"
553-
554-
// ConditionReasonDiscoveryFailed indicates backend discovery failed
555-
ConditionReasonDiscoveryFailed = "DiscoveryFailed"
556-
557494
// ConditionReasonGroupRefValid indicates the GroupRef is valid
558495
ConditionReasonVirtualMCPServerGroupRefValid = "GroupRefValid"
559496

@@ -604,8 +541,6 @@ const (
604541
//+kubebuilder:subresource:status
605542
//+kubebuilder:resource:shortName=vmcp;virtualmcp
606543
//+kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="The phase of the VirtualMCPServer"
607-
//+kubebuilder:printcolumn:name="Tools",type="integer",JSONPath=".status.capabilities.toolCount",description="Total tools"
608-
//+kubebuilder:printcolumn:name="Backends",type="integer",JSONPath=".status.discoveredBackends[*]",description="Backends"
609544
//+kubebuilder:printcolumn:name="URL",type="string",JSONPath=".status.url",description="Virtual MCP server URL"
610545
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"
611546
//+kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status"

0 commit comments

Comments
 (0)