Compare commits

...
43 Commits
Author SHA1 Message Date
olb042 78b1119710 Fix full VMCP redirect URI 2026-06-23 19:15:35 +01:00
olb042 48476c7dac Fix full VMCP audience 2026-06-23 19:12:19 +01:00
olb042 d393f66d47 add back ingress 2026-06-17 17:37:24 +01:00
olb042 de8f55c253 move to public-mcp 2026-06-17 17:25:52 +01:00
olb042 a72a2055af move to public-mcp 2026-06-17 16:48:38 +01:00
olb042 676bad4dd2 Implement shared public MCP federation gateway
- full-vmcp serves as public entry point at mcp.ngorse.com
- Single Keycloak client (public-mcp) for all external tools
- authServerConfig proxies auth to Keycloak
- state-docs-vmcp becomes internal-only (no auth required)
- Shared OIDC config for token validation
- All external clients authenticate once at gateway
2026-06-17 16:26:48 +01:00
olb042 d1d8c6aa3f change audidence 2026-06-17 15:35:15 +01:00
olb042 a7f069bdd7 add ngorse ingress 2026-06-17 15:28:57 +01:00
olb042 95fcbb5441 seperate ingress 2026-06-17 15:27:40 +01:00
olb042 841bb8e6c8 Simplify authServerConfig to only required CRD fields 2026-06-17 15:02:35 +01:00
olb042 d402c1726e test toolhive.stacklok.dev/v1beta1 2026-06-17 14:59:12 +01:00
olb042 919888aba6 test toolhive.stacklok.dev/v1beta1 2026-06-17 14:57:49 +01:00
olb042 b6f6c3ebe4 Configure OIDC auth servers for VMCP servers to proxy through Keycloak 2026-06-17 14:52:02 +01:00
olb042 4de136186f change auth for vmcp 2026-06-17 14:49:54 +01:00
olb042andClaude Sonnet 4.6 ad0e5df277 fix: add required audience field to oidcConfigRef on both VirtualMCPServers
spec.incomingAuth.oidcConfigRef.audience is Required by the CRD validator.
Set to the Keycloak client ID for each server (unique per server as required
to prevent token replay attacks).

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-15 13:34:33 +00:00
olb042andClaude Sonnet 4.6 3caeeb2997 fix: replace invalid incomingAuth.oidc with MCPOIDCConfig + oidcConfigRef
The .spec.incomingAuth.oidc inline block is not a valid field in the
v0.29.3 VirtualMCPServer CRD schema, causing ArgoCD ComparisonErrors.

The correct v0.29.3 API separates OIDC provider config into a dedicated
MCPOIDCConfig (v1beta1) resource, referenced from the VirtualMCPServer
via spec.incomingAuth.oidcConfigRef.name.

- Add MCPOIDCConfig resources for state-docs-vmcp and full-vmcp (inline
  type, Keycloak issuer, replicated client secrets from keycloak ns)
- Update state-docs-vmcp and full-vmcp VirtualMCPServer manifests to
  reference the new MCPOIDCConfig resources via oidcConfigRef
- Register new MCPOIDCConfig files in vmcp-servers kustomization

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-15 13:31:45 +00:00
olb042andClaude Sonnet 4.6 d09eb39701 narrow ignoreApplicationDifferences to /automated/enabled only
Previously ignoring the entire /spec/syncPolicy prevented the ApplicationSet
controller from propagating syncOption changes (like ServerSideDiff=true) to
the live Application. Now only /automated/enabled is ignored, preserving
manual auto-sync control while allowing syncOptions to reconcile normally.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-15 13:04:59 +00:00
olb042andClaude Sonnet 4.6 50fdec56cb add ServerSideDiff=true to bypass incomingAuth.oidc schema error
ArgoCD's client-side structured merge diff fails on VirtualMCPServer
resources that use spec.incomingAuth.oidc because the CRD schema does
not declare that subfield. ServerSideDiff=true switches diff computation
to a server-side dry-run which handles preserved-unknown-fields correctly.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-15 13:03:54 +00:00
olb042 457d042569 add vmcp 2026-06-15 13:54:03 +01:00
olb042andClaude Sonnet 4.6 f82d0b449b remove stale TODO for state-docs-vmcp sealed secret
Secret is replicated from Keycloak into toolhive-system; no sealed secret needed.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-15 12:10:25 +00:00
olb042 9f162958bf oidc auth 2026-06-15 12:59:34 +01:00
olb042 f74bf9e50f temp oidc auth 2026-06-15 12:58:50 +01:00
olb042 adc06573cc update version 2026-06-15 12:49:25 +01:00
olb042andClaude Sonnet 4.6 b497211278 add OIDC auth to state-docs-vmcp VirtualMCPServer
Switch incomingAuth from anonymous to oidc, wiring Keycloak (home-lab realm
at cloak.olb42.com) as the provider with clientId state-docs-vmcp. Secret
ref (state-docs-vmcp-secret, key: client-secret) is added to kustomization
as a TODO comment pending the sealed secret creation.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-06-14 16:55:43 +00:00
olb042 8b9e54a924 update ingress 2026-06-14 02:40:20 +01:00
olb042 4da61242df update ssl 2026-06-14 02:29:04 +01:00
olb042 6ff5eaafa2 add second ingressroute 2026-06-14 02:11:42 +01:00
olb042 6da4451697 add internal dns 2026-06-14 02:05:02 +01:00
olb042 b58c369d11 embedding 2026-06-13 20:47:48 +01:00
olb042 cc1bb128e1 enable tools 2026-06-13 20:45:37 +01:00
olb042 62b1214926 add incoming auth 2026-06-13 20:19:53 +01:00
olb042 ab95db2782 add state doc 2026-06-13 20:16:18 +01:00
olb042 ccd0093f00 add state docs 2026-06-13 20:09:43 +01:00
olb042 3e78b15f19 add registry visible remote mcp proxies 2026-06-13 19:59:04 +01:00
olb042 13d58831b4 fix registry discovery rbac for mcp entries 2026-06-13 19:55:57 +01:00
olb042 bf86461753 argocd and kube mcp to read-write 2026-06-13 19:33:23 +01:00
olb042 5a1f1f352b pangolin ingress 2026-06-13 19:29:32 +01:00
olb042 596c464754 glance reg 2026-06-06 00:21:16 +01:00
olb042 5106b5e73c vmcp glance 2026-06-06 00:16:30 +01:00
olb042 6a8328ec88 radar 2026-06-06 00:13:34 +01:00
olb042 d9dda8fef8 pod glance 2026-06-05 23:57:31 +01:00
olb042 6a15fbe49f argocd mcp podtemplate/metadata/annotations/glances.parent 2026-06-05 23:56:49 +01:00
olb042 1bbb463bfe glances changes 2026-06-05 16:25:10 +01:00
25 changed files with 338 additions and 60 deletions
+5 -2
View File
@@ -6,7 +6,7 @@ metadata:
spec:
ignoreApplicationDifferences:
- jsonPointers:
- /spec/syncPolicy
- /spec/syncPolicy/automated/enabled
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
@@ -15,7 +15,7 @@ spec:
- environment: production
namespace: toolhive-system
overlay: production
chartVersion: 0.28.3
chartVersion: 0.29.3
template:
metadata:
name: 'toolhive-{{ .environment }}'
@@ -60,3 +60,6 @@ spec:
- CreateNamespace=true
# CRD schemas are large; SSA avoids the last-applied-config annotation limit.
- ServerSideApply=true
# Use server-side dry-run for diff computation to bypass CRD schema
# validation errors on fields marked x-kubernetes-preserve-unknown-fields.
- ServerSideDiff=true
+14 -29
View File
@@ -7,35 +7,20 @@ metadata:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mcp-kubernetes-readonly
name: mcp-kubernetes-admin
namespace: toolhive-system
rules:
- apiGroups: [""]
resources:
- pods
- pods/log
- pods/status
- services
- endpoints
- events
- namespaces
- nodes
- configmaps
- persistentvolumeclaims
- replicationcontrollers
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs", "cronjobs"]
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses", "networkpolicies"]
verbs: ["get", "list", "watch"]
- apiGroups: ["argoproj.io"]
resources: ["applications", "applicationsets", "appprojects"]
verbs: ["get", "list", "watch"]
- apiGroups: ["*"]
resources: ["*"]
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- deletecollection
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list"]
@@ -43,12 +28,12 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: mcp-kubernetes-readonly
name: mcp-kubernetes-admin
namespace: toolhive-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: mcp-kubernetes-readonly
name: mcp-kubernetes-admin
subjects:
- kind: ServiceAccount
name: kubernetes-mcp
@@ -6,6 +6,8 @@ namespace: toolhive-system
resources:
- mcpserver-gitea.yaml
- mcpserver-radar.yaml
- mcpremoteproxy-automem.yaml
- mcpremoteproxy-radar.yaml
- mcpserver-argocd.yaml
- mcpserver-kubernetes.yaml
- mcp-headless-services.yaml
@@ -0,0 +1,32 @@
apiVersion: toolhive.stacklok.dev/v1beta1
kind: MCPRemoteProxy
metadata:
name: automem
namespace: toolhive-system
labels:
app.kubernetes.io/environment: production
app.kubernetes.io/part-of: automem
annotations:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: AutoMem MCP
toolhive.stacklok.dev/registry-description: AutoMem MCP bridge for persistent cross-session memory.
toolhive.stacklok.dev/registry-url: http://mcp-automem-remote-proxy.toolhive-system.svc.cluster.local:8080
spec:
remoteUrl: http://automem-mcp-bridge.automem:8080/mcp
transport: streamable-http
proxyPort: 8080
groupRef:
name: homelab-core
headerForward:
addHeadersFromSecret:
- headerName: X-API-Key
valueSecretRef:
name: automem-mcp-client-auth
key: authorization
resourceOverrides:
proxyDeployment:
annotations:
glance/parent: automem
proxyService:
annotations:
glance/parent: automem
@@ -0,0 +1,24 @@
apiVersion: toolhive.stacklok.dev/v1beta1
kind: MCPRemoteProxy
metadata:
name: radar
namespace: toolhive-system
annotations:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: Radar MCP
toolhive.stacklok.dev/registry-description: Radar MCP Server
toolhive.stacklok.dev/registry-url: https://radar.olb42.com/mcp
glance/parent: radar
spec:
remoteUrl: http://radar.radar:9280/mcp
transport: streamable-http
proxyPort: 8080
groupRef:
name: homelab-core
resourceOverrides:
proxyDeployment:
annotations:
glance/parent: radar
proxyService:
annotations:
glance/parent: radar
@@ -6,8 +6,9 @@ metadata:
annotations:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: Argo CD MCP
toolhive.stacklok.dev/registry-description: Read-only Argo CD MCP server for inspecting homelab GitOps applications and resources.
toolhive.stacklok.dev/registry-description: Write-capable Argo CD MCP server for inspecting and operating homelab GitOps applications and resources.
toolhive.stacklok.dev/registry-url: http://mcp-argocd-mcp-proxy.toolhive-system.svc.cluster.local:8080/mcp
glance/parent: argocd
spec:
# argoproj-labs MCP server for Argo CD. v0.7.0 starts streamable HTTP on
# port 3000 by default; setting args: ["stdio"] makes the image try to run
@@ -23,9 +24,8 @@ spec:
# argocd-server serves a self-signed cert in-cluster.
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
# Start read-only; drop this to enable sync/write tools later.
- name: MCP_READ_ONLY
value: "true"
value: "false"
# ToolHive 0.28.3 does not translate spec.secrets into the workload, so inject
# the token natively on the `mcp` container via podTemplateSpec.
resourceOverrides:
@@ -33,6 +33,9 @@ spec:
annotations:
glance/parent: argocd
podTemplateSpec:
metadata:
annotations:
glance/parent: argocd
spec:
groupRef:
name: homelab-core
@@ -8,6 +8,7 @@ metadata:
toolhive.stacklok.dev/registry-title: Gitea MCP
toolhive.stacklok.dev/registry-description: Gitea MCP server for repository, issue, and pull request workflows in the homelab Gitea instance.
toolhive.stacklok.dev/registry-url: http://mcp-gitea-mcp-proxy.toolhive-system.svc.cluster.local:8080/mcp
glance/parent: gitea
spec:
# Upstream Gitea MCP server. Speaks stdio; ToolHive's proxy runner wraps it and
# exposes streamable-http at http://mcp-gitea-mcp-proxy.mcp-services:8080/mcp.
@@ -29,6 +30,9 @@ spec:
annotations:
glance/parent: gitea
podTemplateSpec:
metadata:
annotations:
glance/parent: gitea
spec:
groupRef:
name: homelab-core
@@ -6,11 +6,11 @@ metadata:
annotations:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: Kubernetes MCP
toolhive.stacklok.dev/registry-description: Read-only Kubernetes MCP server for safe cluster inspection and troubleshooting.
toolhive.stacklok.dev/registry-description: Write-capable Kubernetes MCP server for cluster inspection, troubleshooting, and GitOps maintenance actions.
toolhive.stacklok.dev/registry-url: http://mcp-kubernetes-mcp-proxy.toolhive-system.svc.cluster.local:8080/mcp
spec:
# containers/kubernetes-mcp-server. Authenticates to the API in-cluster via the
# kubernetes-mcp ServiceAccount (read-only ClusterRole, see rbac file). Speaks
# kubernetes-mcp ServiceAccount (write-capable ClusterRole, see rbac file). Speaks
# stdio; ToolHive proxies to streamable-http at
# http://mcp-kubernetes-mcp-proxy.mcp-services:8080/mcp.
image: ghcr.io/containers/kubernetes-mcp-server:latest
@@ -20,14 +20,12 @@ spec:
args:
- --log-file
- stderr
- --read-only
- --disable-destructive
proxyMode: streamable-http
proxyPort: 8080
groupRef:
name: homelab-core
# Pin the MCP server pod to our read-only ServiceAccount. The ClusterRole is
# the real guardrail: even if a write tool is invoked, the API rejects it.
# Pin the MCP server pod to the ServiceAccount that carries its Kubernetes API
# write permissions.
serviceAccount: kubernetes-mcp
permissionProfile:
type: builtin
@@ -3,6 +3,12 @@ kind: MCPServerEntry
metadata:
name: radar
namespace: toolhive-system
annotations:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: Radar MCP
toolhive.stacklok.dev/registry-description: Radar MCP Server
toolhive.stacklok.dev/registry-url: https://radar.olb42.com/mcp
glance/parent: radar
spec:
remoteUrl: http://radar.radar:9280/mcp
transport: streamable-http
@@ -5,14 +5,36 @@ metadata:
namespace: toolhive-system
spec:
toolsFilter:
- get_application
- get_application_health
- get_application_history
- get_pods
- describe_pod
- get_events
- get_pod_logs
- list_org_repos
- search_repos
- get_repository_tree
- get_dir_contents
- get_file_contents
- list_branches
- list_commits
- get_commit
- create_or_update_file
- get_file
- memory_search
- upsert_memory
- recall_memory
- store_memory
- update_memory
- associate_memories
- list_applications
- get_application
- get_application_resource_tree
- get_application_managed_resources
- get_application_workload_logs
- get_application_events
- get_resource_events
- get_resources
- configuration_view
- namespaces_list
- events_list
- pods_get
- pods_list
- pods_list_in_namespace
- pods_log
- pods_top
- nodes_top
- nodes_stats_summary
- resources_get
- resources_list
@@ -9,7 +9,8 @@ rules:
- mcpservers
- mcpremoteproxies
- virtualmcpservers
- mcpserverentry
- mcpserverentries
- mcpgroups
verbs:
- get
- list
@@ -6,6 +6,10 @@ spec:
pgpassSecretRef:
name: toolhive-reg-pg-app
key: pgpass
podTemplateSpec:
metadata:
annotations:
glance/parent: toolhive
configYAML: |
database:
host: toolhive-reg-pg-rw
@@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: toolhive-system
resources:
- public-mcp-secret.sealed.secret.yaml
@@ -0,0 +1,22 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
annotations:
sealedsecrets.bitnami.com/cluster-wide: "true"
name: public-mcp-secret
namespace: keycloak
spec:
encryptedData:
client-id: AgANqLN6opyrUHiqVaUKvHwUr4chY38qb03WxUzXWll6SDh7bRvHcZ3wAMHfsmigEz2cSWVMWg0VmEcP16r6gcEiYGQ2/Ol182oXbtI/bWad/3rFFzMlLrKie8H9oGS/LgyRyhEiQ2hDzsdAJWARdHrRhbpFvJ1QeUJtcIBGKy8CcjTm8YfW7u/IqNyo0X+NIK2vImO9UdrmzIIDwQav0e30dRkmtbL5lamR563Qa1k4alEdOTF/E2fe6OVxaIqjpbzHnjmbKRA1ymhYGOasm8hTUeE/IVicAZNeQAg0ps31PSHpwjnEzyDZ1k7p5Dvc4+RhNXhOmONnI38/EbTA0dXra2ZeRxdcmErGrN2KrVZmlxyBK3462z8yWbiGU4esAdHJAdAjBkD+sDP2jYIsy7wvzArYM/hbFqDBrLs9vf29bYyUfRoRo/0BS+iO06zBjr0ssUT95FBrs1RLXDJUaomFkylz32L+jLfalKc4N1xeIwA76VOk4m3lVllmZP0YFC/mifHJ6qzuOgJqBw8fTkYhASiwyfsbbk3c8f4VlHqvXPKhJKkJvaUMMve59XpKuVX8O3phW2nJG4hl86OVkfOQRIZgPqn6t5UiHyJCPv6JoxAITs40thG06QUn263MTyZyaNGw9/PPVmSO/O5N2DIElWl75FpAEg3fqsljJiq2NGVQWLmT3C7tdyUwDEuu0r91cQmfUY7EehBD
client-secret: AgCCe5CH8xoDedXE9iM4GGEw/K7LhdXzH3lPynjlJ85OdMLuM6yYkaN37xF9FbdwhkQQnX3pjM08ILjEnpWtIx8zNmzTl+U90sSo85YqbSyZcNK7uy3oCTaRB6sdtPmdcDWEjtUcvv7+2WZcnAH8IfpT7wpesrjkO7uND0ZFX2bqhR26goq40gSiNahfCLp5QkZlsnTb6r6uw2N0utOLFDp3m233Nh268kxamlvr8E1IYDZFBC8KDIz9rfKvuMNBV6CA++FDeYybS1WNkgK3hQ+tGRVy5L7zB6x06zKzh4UIBn1t9sEga1x2ZH2Szgcb6EgBXmQ3rFaJ7O52dUltLV4GHX4uqRmjj+aZFQQuaJuvgp1Dc0rhFFwKveH5R0VcEarSDHeRlQmPiszKTsk8tgfCw8U64uoe6ACPq0isWVYBvUxttm/nB3MNSEl3TOquw9UtsiV1CaqC5LpI4qO1EatpARF57uqxw1Ewl8e8WrcBQ3WlI+7kjsJ2jHODx8sTlByqW7PZeJB4pk8sIq3NXA4VK/7f+852itxE0R7S67nZ4xFi75V6omyaEcniDVaPzxoC6EiFsPrUj8QpA+eRlKZRFTS4fmQRUkKVGYEnSWxDTkM1ot5dPx1MkA6MsEwq7wiuZwIbXeLK9Z3NqqsJ5LyTwidXhim5vf4iMHqH6Fj9ZL0RZTjMqfLXSjDD+Tu9qwMnXfkZx6EMsOLKc5uz73lP2VpGoUyq9ndqHsEbqYjbHQ==
template:
metadata:
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: keycloak, toolhive-system
sealedsecrets.bitnami.com/cluster-wide: "true"
sealedsecrets.bitnami.com/managed: "true"
name: public-mcp-secret
namespace: keycloak
@@ -1,4 +1,4 @@
apiVersion: toolhive.stacklok.dev/v1alpha1
apiVersion: toolhive.stacklok.dev/v1beta1
kind: VirtualMCPServer
metadata:
name: dev-safe-vmcp
@@ -5,10 +5,10 @@ metadata:
namespace: toolhive-system
labels:
app.kubernetes.io/name: full-vmcp
annotations:
dns.public: 'true'
dns.public.access.policy: google-ws
dns.public.hostname: full-vmcp.olb42.com
# annotations:
# dns.public: 'false'
# dns.public.access.policy: google-ws
# dns.public.hostname: full-vmcp.olb42.com
spec:
entryPoints:
- websecure
@@ -0,0 +1,30 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: full-vmcp-ngorse-ingress
namespace: toolhive-system
labels:
app.kubernetes.io/name: full-vmcp
annotations:
dns.internal: 'true'
dns.internal.hostname: full-vmcp.ngorse.com
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`mcp.ngorse.com`)
services:
- name: vmcp-full-vmcp
namespace: toolhive-system
port: 4483
- kind: Rule
match: Host(`full-vmcp.ngorse.com`)
services:
- name: vmcp-full-vmcp
namespace: toolhive-system
port: 4483
# No default TLSStore in this cluster, so reference the wildcard cert
# explicitly. olb42-wildcard-tls is auto-reflected into every namespace.
tls:
secretName: ngorse-wildcard-tls
@@ -1,4 +1,4 @@
apiVersion: toolhive.stacklok.dev/v1alpha1
apiVersion: toolhive.stacklok.dev/v1beta1
kind: VirtualMCPServer
metadata:
name: full-vmcp
@@ -7,14 +7,31 @@ metadata:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: Full Homelab Virtual MCP
toolhive.stacklok.dev/registry-description: Full virtual MCP exposing the homelab MCP tool group through ToolHive aggregation.
toolhive.stacklok.dev/registry-url: http://vmcp-full-vmcp.toolhive-system.svc.cluster.local:4483
toolhive.stacklok.dev/registry-url: https://mcp.ngorse.com
glance/parent: toolhive
spec:
groupRef:
name: homelab-core
podTemplateSpec:
metadata:
annotations:
glance/parent: toolhive
embeddingServerRef:
name: homelab-embedding
incomingAuth:
type: anonymous
type: oidc
oidcConfigRef:
name: public-mcp-oidc
audience: http://full-vmcp.toolhive-system.svc.cluster.local:4483
authServerConfig:
issuer: https://mcp.ngorse.com
upstreamProviders:
- name: keycloak
type: oidc
oidcConfig:
issuerUrl: https://cloak.olb42.com/realms/home-lab
clientId: public-mcp
redirectUri: https://mcp.ngorse.com/oauth/callback
config:
aggregation:
conflictResolution: prefix
@@ -4,9 +4,16 @@ kind: Kustomization
namespace: toolhive-system
resources:
- oidcconfig-public-mcp.yaml
- oidcconfig-state-docs-vmcp.yaml
- full-vmcp.yaml
- full-vmcp-ingress.yaml
- full-vmcp-ngorse-ingress.yaml
- dev-safe-vmcp.yaml
- dev-safe-vmcp-ingress.yaml
- ops-safe-vmcp.yaml
- ops-safe-vmcp-ingress.yaml
- state-docs-vmcp.yaml
- state-docs-vmcp-ingress.yaml
- state-docs-ngorse-ingress.yaml
@@ -0,0 +1,13 @@
apiVersion: toolhive.stacklok.dev/v1beta1
kind: MCPOIDCConfig
metadata:
name: public-mcp-oidc
namespace: toolhive-system
spec:
type: inline
inline:
issuer: https://mcp.ngorse.com
clientId: public-mcp
clientSecretRef:
name: public-mcp-secret
key: client-secret
@@ -0,0 +1,13 @@
apiVersion: toolhive.stacklok.dev/v1beta1
kind: MCPOIDCConfig
metadata:
name: state-docs-vmcp-oidc
namespace: toolhive-system
spec:
type: inline
inline:
issuer: https://state-docs.ngorse.com
clientId: state-docs-vmcp
clientSecretRef:
name: state-docs-vmcp-secret
key: client-secret
@@ -1,4 +1,4 @@
apiVersion: toolhive.stacklok.dev/v1alpha1
apiVersion: toolhive.stacklok.dev/v1beta1
kind: VirtualMCPServer
metadata:
name: ops-safe-vmcp
@@ -0,0 +1,24 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: state-docs-vmcp-ngorse-ingress
namespace: toolhive-system
labels:
app.kubernetes.io/name: state-docs-vmcp
annotations:
dns.internal: 'true'
dns.internal.hostname: state-docs.ngorse.com
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`state-docs.ngorse.com`)
services:
- name: vmcp-state-docs-vmcp
namespace: toolhive-system
port: 4483
# No default TLSStore in this cluster, so reference the wildcard cert
# explicitly. olb42-wildcard-tls is auto-reflected into every namespace.
tls:
secretName: ngorse-wildcard-tls
@@ -0,0 +1,21 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: state-docs-vmcp-ingress
namespace: toolhive-system
labels:
app.kubernetes.io/name: state-docs-vmcp
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`state-docs.olb42.com`)
services:
- name: vmcp-state-docs-vmcp
namespace: toolhive-system
port: 4483
# No default TLSStore in this cluster, so reference the wildcard cert
# explicitly. olb42-wildcard-tls is auto-reflected into every namespace.
tls:
secretName: olb42-wildcard-tls
@@ -0,0 +1,40 @@
apiVersion: toolhive.stacklok.dev/v1beta1
kind: VirtualMCPServer
metadata:
name: state-docs-vmcp
namespace: toolhive-system
annotations:
toolhive.stacklok.dev/registry-export: "true"
toolhive.stacklok.dev/registry-title: Document State Virtual MCP
toolhive.stacklok.dev/registry-description: Virtual MCP which is focused on enabling documentation of the current state
toolhive.stacklok.dev/registry-url: https://state-docs.ngorse.com
spec:
groupRef:
name: homelab-core
embeddingServerRef:
name: homelab-embedding
incomingAuth:
type: anonymous
config:
aggregation:
conflictResolution: prefix
excludeAllTools: false
tools:
- workload: gitea-mcp
toolConfigRef:
name: state-doc-tools
- workload: automem
toolConfigRef:
name: state-doc-tools
- workload: argocd-mcp
toolConfigRef:
name: state-doc-tools
- workload: kubernetes-mcp
toolConfigRef:
name: state-doc-tools
- workload: radar
excludeAll: true
compositeTools: []
operational:
failureHandling:
partialFailureMode: best_effort