Add lazy tools/list discovery for Kubernetes sources - #852
beersoccer wants to merge 2 commits into
Conversation
59b7e63 to
140b98a
Compare
WHY: Manually annotating every tool on each MCPServer/VirtualMCPServer/ MCPRemoteProxy CRD is error-prone and goes stale as proxies evolve. The registry should self-populate tool metadata by querying the running proxy instead of relying on operators to keep annotations in sync. Adds `discoverTools` to the K8s controller reconcile path: when a CRD is exported (`registry-export: "true"`) but carries no `tool-definitions` annotation, the controller opens a Streamable-HTTP (SSE fallback) MCP connection to the `registry-url` endpoint and calls `tools/list`. The result is written to the DB via the existing sync writer; no K8s patch is performed and no new RBAC is required. Adds `discoverOAuth2` to `KubernetesConfig` so that a client_credentials grant can be configured for environments where MCP proxies enforce Cedar authorization. The client secret is read from a file path per `secrets.md` §1; tokens are cached and auto-refreshed by `x/oauth2/clientcredentials`. Discovery failures are non-fatal — a warning is logged and `ToolDefinitions` is left empty, with retry on the next reconcile. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: beersoccer <beersoccer@gmail.com>
140b98a to
11437d4
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #852 +/- ##
==========================================
- Coverage 62.07% 60.85% -1.22%
==========================================
Files 109 25 -84
Lines 10724 4665 -6059
==========================================
- Hits 6657 2839 -3818
+ Misses 3482 1472 -2010
+ Partials 585 354 -231 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
CVE-2026-39822 (CVSS 7.8 HIGH) affects Go 1.26.0 through 1.26.4 via an os.Root symlink escape on Unix, fixed in Go 1.26.5 (2026-07-07). Raising the go directive ensures the module cannot be built with a vulnerable toolchain and clears the Grype HIGH finding that was blocking CI. The vulnerability predates this PR and is present in the upstream main branch as well. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The second commit (5143ee1) bumps the go directive in go.mod from 1.26.0 to 1.26.5 to resolve the Grype HIGH finding that blocked CI. CVE-2026-39822 (CVSS 7.8 HIGH) — os.Root symlink escape on Unix — affects Go 1.26.0 through 1.26.4 and was fixed in Go 1.26.5 (released 2026-07-07). This vulnerability predates this PR; the upstream main branch is equally affected since it also declares go 1.26.0. Raising the directive to 1.26.5 ensures the module cannot be compiled with a vulnerable toolchain. |
Summary
When a
MCPServer,VirtualMCPServer, orMCPRemoteProxyCRD is exported to the registry (toolhive.stacklok.dev/registry-export: "true") but carries notool-definitionsannotation, the K8s controller now automatically connects to the proxy'sregistry-urland callstools/listat reconcile time, storing the discovered tools in the database.This removes the need for operators to manually annotate every tool on each CRD — the registry self-populates from the running proxy and stays up-to-date on every reconcile.
Changes
internal/kubernetes/discover.go(new) — Streamable-HTTP MCP client with SSE fallback; injects OAuth2 Bearer token whenTokenSourceis configuredinternal/kubernetes/oauth.go(new) —golang.org/x/oauth2/clientcredentialswrapper; nilTokenSourcemeans anonymous (backward compatible)internal/config/config.go— NewdiscoverTimeoutanddiscoverOAuth2fields onKubernetesConfig; client secret read from file path per project secrets policyinternal/kubernetes/types.go—extractServer,extractVirtualMCPServer,extractMCPRemoteProxyfall back todiscoverToolswhentool-definitionsannotation is absentinternal/kubernetes/controller.go—extractorFuncextended withctxandtokenSourceinternal/app/builder.go— ConstructsTokenSourcefrom config and injects it viaWithDiscoverTokenSourcedocs/lazy-tool-discovery.md(new) — Feature overview, OAuth2 setup, Helm deployment guide, annotation referencedocs/configuration.md—discoverOAuth2field table added to Kubernetes source sectiondeploy/charts/.../values.yaml— ExamplediscoverOAuth2block added to Helm values commentsBehavior
tool-definitionsannotationregistry-urlannotationtools/listcalled at reconcile timeDiscovery failures are non-fatal: a warning is logged and the entry is still registered; retry happens on the next reconcile.
OAuth2 support
Production MCP proxies typically enforce Cedar authorization. The new
discoverOAuth2config block enablesclient_credentialsauthentication:When
discoverOAuth2is omitted, discovery runs anonymously (backward compatible).Testing
task lint-fix— 0 issuestask test PACKAGES=./internal/kubernetes/...— all pass, no data racetask test PACKAGES=./internal/config/...— all passtools/listreturns discovered tools which appear in/registry/{name}/v0.1/servers