Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: stacklok/toolhive
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8fc2c71
Choose a base ref
...
head repository: stacklok/toolhive
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 70845b5
Choose a head ref
  • 12 commits
  • 71 files changed
  • 13 contributors

Commits on Mar 27, 2026

  1. Update diagrams and links in README (#4397)

    * Refresh diagrams and favicon
    
    Signed-off-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
    
    * Update README links
    
    Signed-off-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
    
    ---------
    
    Signed-off-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
    Co-authored-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
    danbarr and danbarr authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    bc24877 View commit details
    Browse the repository at this point in the history
  2. Add edited trigger to PR size labeler workflow (#4398)

    - Re-run the workflow when the submitter edits their PR description with
      the justification.
    
    Signed-off-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
    Co-authored-by: Dan Barr <6922515+danbarr@users.noreply.github.com>
    danbarr and danbarr authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    9ee7873 View commit details
    Browse the repository at this point in the history
  3. Fix macOS symlink test failures and upgrade phonenumbers dependency (#…

    …4399)
    
    On macOS, t.TempDir() returns paths under /var/folders which is a
    symlink to /private/var. This caused two test failures:
    - skillsvc tests failed because the skill extractor rejects paths
      containing symlinks; fix by resolving via EvalSymlinks using the
      existing tempDir(t) helper
    - health_test unix socket test failed because the resolved path
      exceeded macOS's 104-char socket path limit; fix by using
      os.MkdirTemp with a short prefix
    
    Also upgrades github.com/nyaruka/phonenumbers from v1.1.6 to v1.6.12
    to resolve GHSA-fmjh-f678-cv3x (Medium).
    
    Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
    reyortiz3 and claude authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    e52f3e9 View commit details
    Browse the repository at this point in the history
  4. Inject Redis session storage config into vMCP ConfigMap (#4387)

    Add SessionStorageConfig to pkg/vmcp/config.Config and populate it in
    the VirtualMCPServer converter when spec.sessionStorage.provider is
    "redis". This allows vMCP pods to discover Redis connection parameters
    (address, db, keyPrefix) at startup via the existing config injection
    path. The Redis password is excluded from the config type and is
    injected separately as the THV_SESSION_REDIS_PASSWORD environment
    variable by the deployment builder.
    
    Closes: #4214
    
    Co-authored-by: taskbot <taskbot@users.noreply.github.com>
    yrobla and taskbot authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    3561c5d View commit details
    Browse the repository at this point in the history
  5. fix: make experimental MCP server initialization non-fatal to thv ser…

    …ve (#4393)
    
    Make experimental MCP server initialization non-fatal to thv serve
    
    Move mcpserver.New() inside the goroutine so that a failure in MCP
    server creation (e.g. registry authentication error) only terminates
    the goroutine instead of crashing the entire thv serve process.
    The main HTTP API server continues running normally.
    
    Fixes #4392
    
    Made-with: Cursor
    peppescg authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    e1ade3c View commit details
    Browse the repository at this point in the history
  6. Add tests for horizontal scaling operator behaviors (#4388)

    * Inject Redis session storage config into vMCP ConfigMap
    
    Add SessionStorageConfig to pkg/vmcp/config.Config and populate it in
    the VirtualMCPServer converter when spec.sessionStorage.provider is
    "redis". This allows vMCP pods to discover Redis connection parameters
    (address, db, keyPrefix) at startup via the existing config injection
    path. The Redis password is excluded from the config type and is
    injected separately as the THV_SESSION_REDIS_PASSWORD environment
    variable by the deployment builder.
    
    Closes: #4214
    
    * Add tests for horizontal scaling operator behaviors
    
    Unit tests (controllers package):
    - TestConfigMapContent_SessionStorage: verifies that ensureVmcpConfigConfigMap
      produces a ConfigMap YAML with the sessionStorage section populated when
      provider=redis, and absent when nil or memory.
    - TestDeploymentForVirtualMCPServer_WithRedisPassword: verifies that
      deploymentForVirtualMCPServer injects THV_SESSION_REDIS_PASSWORD as a
      SecretKeyRef env var and never as a plaintext value.
    
    Integration tests (envtest with real CRDs + controller loop):
    - MCPServer: ScalingConfig (backend_replicas + session_redis) is written to
      the RunConfig ConfigMap when backendReplicas and Redis sessionStorage are
      set; omitted when absent.
    - VirtualMCPServer: spec.replicas is reflected in Deployment.Spec.Replicas;
      nil replicas produces a nil Deployment replicas field for HPA compatibility.
    
    E2E tests (Kind cluster via thv-operator-e2e-test-run):
    - VirtualMCPServer created with replicas=2 runs 2 ready pods and sets
      SessionStorageWarning condition when no Redis is configured.
    - Scale lifecycle (1→2→1): verifies Deployment replicas update in-place,
      2 pods come up, SessionStorageWarning fires on scale-up and clears on
      scale-down.
    
    Closes: #4220
    
    Fix ignored AddToScheme errors in unit tests
    
    Replace `_ = *.AddToScheme(scheme)` with `require.NoError(t, *.AddToScheme(scheme))`
    in virtualmcpserver_deployment_test.go and virtualmcpserver_vmcpconfig_test.go so
    that scheme registration failures cause an immediate, clear test failure rather than
    a confusing error later with a partially configured scheme.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    * Fix HPA-compat integration test: use spec change to trigger reconciliation
    
    Annotation changes do not increment metadata.generation on Kubernetes resources.
    The previous trigger used `vmcp.Annotations["test/trigger-reconcile"] = "true"`,
    which left generation unchanged, so `triggerGeneration = vmcp.Generation + 1`
    was always one ahead of ObservedGeneration and the Eventually timed out.
    
    Fix: trigger via `vmcp.Spec.ServiceType = "ClusterIP"` (the default value,
    semantically a no-op) which IS a spec change and DOES increment Generation.
    After the Update, controller-runtime populates the object in-place with the
    server response, so `vmcp.Generation` is already the post-increment value.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: taskbot <taskbot@users.noreply.github.com>
    Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
    3 people authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    a771117 View commit details
    Browse the repository at this point in the history
  7. Guard against invalid PIDs in process operations (#4401)

    Guard against invalid PIDs in process ops
    
    On Unix, kill(0, sig) sends the signal to every process in the
    calling process's group. KillProcess(0) would SIGTERM thv itself
    and any child processes sharing its group. FindProcess(0) falsely
    reports "alive" via kill(0, 0). Both can be reached when a status
    file contains PID 0 due to crashes or races during proxy startup.
    
    Fixes #4400
    
    Signed-off-by: Greg Katz <gkatz@indeed.com>
    Co-authored-by: Claude <noreply@anthropic.com>
    gkatz2 and claude authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    3f776f0 View commit details
    Browse the repository at this point in the history
  8. Return JSON 404 for OAuth discovery when auth is off (#4366)

    Return JSON 404 for OAuth discovery when auth is not configured
    
    Claude Code v2.1.83 sends GET /.well-known/oauth-protected-resource
    before connecting to any HTTP MCP server. When auth is not configured,
    no .well-known handler was registered, so the request fell through to
    the MCP catch-all handler whose headerValidatingMiddleware rejected it
    with HTTP 406 and a JSON-RPC error body (where "error" is an object).
    Claude Code expects "error" as a string for OAuth errors, causing Zod
    validation failure and a spurious "needs authentication" prompt.
    
    Always register a .well-known prefix handler. When AuthInfoHandler is
    nil, it returns HTTP 404 with {"error":"not_found"} — a clean signal
    that no auth metadata exists and the client should proceed without
    authentication.
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    JAORMX and claude authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    2a89245 View commit details
    Browse the repository at this point in the history
  9. feat: add authorizationEndpointBaseUrl override to embedded auth serv…

    …er (#4396)
    
    Add optional authorizationEndpointBaseUrl field to EmbeddedAuthServerConfig that overrides only the authorization_endpoint in the OAuth discovery document
    When set, the discovery document advertises {authorizationEndpointBaseUrl}/oauth/authorize instead of {issuer}/oauth/authorize; all other endpoints (token, registration, JWKS) remain derived from issuer
    This enables deployments where the browser-facing authorization endpoint needs to be on a different host than the issuer used for backend-to-backend calls
    jerm-dro authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    d57d73b View commit details
    Browse the repository at this point in the history
  10. Support RFC 8414 path-based issuer discovery URLs (#4406)

    PR #4348 (f64d807) replaced the /.well-known/ catch-all mux pattern
    with explicit exact registrations to prevent the auth server from
    intercepting /.well-known/oauth-protected-resource. This broke RFC 8414
    Section 3.1 discovery for path-based issuers: clients construct
    /.well-known/oauth-authorization-server/{issuer-path} but the exact
    pattern only matched /.well-known/oauth-authorization-server.
    
    Register trailing-slash prefix variants on both the http.ServeMux
    (Routes()) and chi router (WellKnownRoutes) so subpaths are routed
    to the discovery handlers.
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
    jhrozek and claude authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    e62f833 View commit details
    Browse the repository at this point in the history
  11. Block Docker gateway addresses in egress proxy by default (#4395)

    ## Why
    
    Containerized MCP servers can reach host services via `host.docker.internal`,
    `gateway.docker.internal`, and the Docker bridge gateway IP (`172.17.0.1`).
    This enables lateral movement from a compromised or malicious MCP server to
    services running on the host, bypassing the container network boundary.
    
    The existing `insecure_allow_all` permission flag does not protect against this:
    users enabling it intend to open general internet access, not necessarily host
    access. These are distinct threat surfaces and warrant separate opt-ins.
    
    ## What changed
    
    The Squid egress proxy config now emits ACL deny rules for the three Docker
    gateway addresses **before** any allow rules. Squid evaluates access control
    in first-match-wins order, so placing the deny first ensures it cannot be
    bypassed by a subsequent `http_access allow all`.
    
    A new `--allow-docker-gateway` CLI flag (default `false`) provides an explicit
    opt-in for the small number of MCP servers that legitimately need host access.
    The flag threads through the full call chain:
    
    ```
    --allow-docker-gateway (run_flags.go)
      → RunConfig.AllowDockerGateway (config.go)
      → runtime.Setup() (setup.go)
      → DeployWorkloadOptions.AllowDockerGateway (types.go)
      → createEgressSquidContainer() (client.go)
      → createTempEgressSquidConf() (squid.go)
    ```
    
    Generated Squid config with default settings (blocking active):
    
    ```squid
    acl docker_gateway_hosts dstdomain host.docker.internal gateway.docker.internal
    acl docker_gateway_ip dst 172.17.0.1
    http_access deny docker_gateway_hosts
    http_access deny docker_gateway_ip
    
    http_access allow all   # (or ACL-based allow rules)
    http_access deny all
    ```
    tgrunnagle authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    887b39c View commit details
    Browse the repository at this point in the history
  12. Release v0.13.1 (#4409)

    * Update VERSION for release
    
    Release-Triggered-By: jerm-dro
    
    * Update Chart.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update Chart.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update Chart.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update Chart.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update values.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update values.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update values.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update VERSION for release
    
    Release-Triggered-By: jerm-dro
    
    * Update Chart.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update README.md for release
    
    Release-Triggered-By: jerm-dro
    
    * Update Chart.yaml for release
    
    Release-Triggered-By: jerm-dro
    
    * Update README.md for release
    
    Release-Triggered-By: jerm-dro
    
    * Update values.yaml for release
    
    Release-Triggered-By: jerm-dro
    stacklokbot authored Mar 27, 2026
    Configuration menu
    Copy the full SHA
    70845b5 View commit details
    Browse the repository at this point in the history
Loading