Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
6a79259
Add Kimi Code CLI as a supported MCP client (#4788)
samuv Apr 13, 2026
052ecdd
Support stateless streamable-HTTP remote servers (#4515)
gkatz2 Apr 13, 2026
08e4b52
Remove redundant storage.Load from NotifyBackendExpired (#4779)
yrobla Apr 14, 2026
c165329
Add more claude rules (#4782)
yrobla Apr 14, 2026
32c23f4
Add VS Code and VS Code Insiders as skill-supporting clients (#4773)
samuv Apr 14, 2026
f6903bb
Fix skill install failure when multiple clients share the same direct…
samuv Apr 14, 2026
71c8585
Add Factory.ai as a supported MCP client (#4795)
samuv Apr 14, 2026
0ef6368
Add regression guard for auth context propagation through Close() (#4…
yrobla Apr 14, 2026
c63b10e
Propagate protectedResourceAllowPrivateIP through OIDC resolver and c…
ChrisJBurns Apr 14, 2026
c49ec9e
Clean up health check dead code and timeout (#4791)
gkatz2 Apr 14, 2026
15dad99
Add Goose, Gemini CLI, and Amp as skill-supporting clients (#4799)
samuv Apr 14, 2026
943bafb
Add OpenAPI annotations to v0.1 skills registry endpoints (#4800)
samuv Apr 14, 2026
2dedbae
Add Kiro as a skill-supporting client (#4803)
samuv Apr 14, 2026
c9a2642
Update module go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlp…
renovate[bot] Apr 14, 2026
28426ca
Bump go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichtt…
dependabot[bot] Apr 14, 2026
cd34d0e
Update dependency helm/helm to v3.20.2 (#4756)
renovate[bot] Apr 14, 2026
3688694
Add Cline, Roo Code, Windsurf, Mistral Vibe, Trae, and Antigravity as…
samuv Apr 14, 2026
fa955cd
Add TelemetryConfigRef support to VirtualMCPServer CRD (#4801)
ChrisJBurns Apr 14, 2026
f9119cb
Update registry API image to v1.1.1 (#4806)
rdimitrov Apr 14, 2026
25fe475
Grant default `aud` when `resource` is absent (#4805)
blkt Apr 14, 2026
1fa05ee
Add `Audience` to authserver test client fixture (#4814)
blkt Apr 14, 2026
0fb1b42
Isolate `TestParseGitReference` from ambient env (#4813)
blkt Apr 14, 2026
be40131
Add ConfigMap content assertions to vMCP telemetry integration tests …
ChrisJBurns Apr 14, 2026
0c5213e
Change GroupRef from bare string to typed MCPGroupRef struct (#4809)
ChrisJBurns Apr 14, 2026
b250b90
Add --remote-auth-scope-param-name for non-standard OAuth scope param…
gmogmzGithub Apr 14, 2026
7c3cdc7
Release v0.20.0 (#4816)
stacklokbot Apr 14, 2026
4298cfe
Remove stale OpenShift values overlay from Helm chart (#4817)
ChrisJBurns Apr 14, 2026
6c8d7d4
Introduce script engine package for vMCP code mode (#4748)
jerm-dro Apr 14, 2026
940fc7b
Allow local key provider to bypass OIDC discovery failure (#4774)
jhrozek Apr 14, 2026
47f4289
Fix port reuse test using hardcoded port number (#4812)
blkt Apr 14, 2026
8c4f765
Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp …
dependabot[bot] Apr 14, 2026
daea31b
Address review findings from v0.1 skills OpenAPI PR (#4802)
samuv Apr 14, 2026
42f7395
Add integration test for default audience without resource parameter …
jhrozek Apr 14, 2026
14a1e6c
Remove deprecated inline telemetry field from CRDs (#4819)
ChrisJBurns Apr 14, 2026
d27e676
Remove deprecated inline oidcConfig from MCPServer and MCPRemoteProxy…
ChrisJBurns Apr 14, 2026
9176e93
Add horizontal scaling tests for vmcp (#4724)
yrobla Apr 15, 2026
5e1e1d5
Remove Upsert from DataStorage interface — closes #4726 (#4797)
yrobla Apr 15, 2026
7339bbd
fix lint issues with mcpgroup (#4838)
yrobla Apr 15, 2026
2fd2d3b
Add GetContent API for on-the-fly SKILL.md retrieval from OCI and git…
samuv Apr 15, 2026
60108a1
Remove deprecated incomingAuth.oidcConfig from VirtualMCPServer (#4822)
ChrisJBurns Apr 15, 2026
cafa963
Remove config.groupRef fallback and external_auth_config_ref enum (#4…
ChrisJBurns Apr 15, 2026
caa31f5
Remove orphaned OIDCConfigRef type and OIDCConfigurable interface (#4…
ChrisJBurns Apr 15, 2026
afce182
Add color annotations to agent definitions (#4853)
ChrisJBurns Apr 15, 2026
9d5982d
Add RoleClaimName to Cedar ConfigOptions (#4847)
jhrozek Apr 15, 2026
bb213f1
Return error from `UpdateConfig` callbacks (#4845)
blkt Apr 15, 2026
2ce2509
Split OTLP endpoint path to fix Langfuse/LangSmith integration (#4815)
ChrisJBurns Apr 15, 2026
bfac267
Simplify `UpdateConfig` error path and add test (#4858)
blkt Apr 15, 2026
300d659
Add resourceUrl field to MCPOIDCConfigReference (#4855)
ChrisJBurns Apr 15, 2026
a954dc4
Add release-notes skill for generating release notes (#4852)
ChrisJBurns Apr 15, 2026
e92dba4
Update module github.com/stacklok/toolhive-catalog to v0.20260415.0 (…
renovate[bot] Apr 15, 2026
12f25e5
Expand singleflight boundary in ValidatingCache.Get to cover full hit…
yrobla Apr 16, 2026
e54e6ae
Update module github.com/stacklok/toolhive-catalog to v0.20260416.0 (…
renovate[bot] Apr 16, 2026
bcc9588
Persist restored session metadata to Redis in loadSession (#4842)
yrobla Apr 16, 2026
d5addcd
Enforce go.mod patch version check in Taskfile and CI (#4864)
reyortiz3 Apr 16, 2026
96c4d49
Drop registry-based group support (#4873)
rdimitrov Apr 16, 2026
d944774
Use scoped secrets provider for registry auth (#4893)
eleftherias Apr 16, 2026
c2a8154
Add v0.1 server browse endpoints (#4871)
rdimitrov Apr 16, 2026
3c5ac7e
Fix reconcile loop caused by non-deterministic env var ordering in di…
lujunsan Apr 16, 2026
22e4fd9
Store serverName on Cedar Authorizer (#4861)
jhrozek Apr 16, 2026
26aab50
Release v0.21.0 (#4902)
stacklokbot Apr 16, 2026
dfd794d
Remove empty parent directories on skill uninstall (#4895)
samuv Apr 16, 2026
ab2a821
Only install skills for clients detected on the system (#4899)
samuv Apr 16, 2026
7433522
Detect JSON-RPC application errors in proxy audit middleware (#4709)
gmogmzGithub Apr 16, 2026
98894b8
Update operator architecture docs for authServerRef (#4780)
tgrunnagle Apr 16, 2026
50044f3
Add AdditionalAuthorizationParams to upstream OAuth configs (#4862)
jhrozek Apr 16, 2026
34e877d
Replace groups parameter with variadic parents on entity factory (#4901)
jhrozek Apr 16, 2026
0e5e576
Fix partialFailureMode validator to accept CRD enum values (#4865)
jhrozek Apr 16, 2026
03f5025
Bump github.com/moby/spdystream from 0.5.0 to 0.5.1 (#4906)
dependabot[bot] Apr 16, 2026
d96922d
Validate audience matches resourceUrl for embedded auth server (#4904)
tgrunnagle Apr 16, 2026
5342824
Extract vMCP serve/validate logic into pkg/vmcp/cli/ (#4891)
yrobla Apr 17, 2026
cfd835c
Add name attribute alias on Resource entities (#4907)
jhrozek Apr 17, 2026
dce0ac7
Update module github.com/stacklok/toolhive-catalog to v0.20260417.0 (…
renovate[bot] Apr 17, 2026
b8b76cc
Add unit tests for pkg/vmcp/cli serve and validate logic (#4898)
yrobla Apr 17, 2026
ee988f3
Add pkg/vmcp/cli/init.go for vMCP config scaffolding (#4903)
yrobla Apr 17, 2026
e4bfbfe
Add thv vmcp serve and thv vmcp validate subcommands (#4900)
yrobla Apr 17, 2026
4ebcf3b
Update README (#4915)
danbarr Apr 17, 2026
2136387
Treat unauthenticated backends as routable in vMCP health (#4866)
lorr1 Apr 18, 2026
f5e0dbd
Bump github.com/go-git/go-git/v5 from 5.17.2 to 5.18.0 (#4921)
dependabot[bot] Apr 20, 2026
eb7ddef
Add EmbeddingServiceManager for TEI container lifecycle (#4912)
yrobla Apr 20, 2026
c331aa4
Fix skill install for qualified namespace/name references and missing…
samuv Apr 20, 2026
8223bec
Add zero-config quick mode for thv vmcp serve (#4913)
yrobla Apr 20, 2026
92897a6
embedding_manager: address Copilot review findings from #4912 (#4938)
yrobla Apr 20, 2026
e6c453a
Add thv vmcp init subcommand (#4939)
yrobla Apr 20, 2026
c17cb40
Add --system flag to secret list and delete commands (#4910)
amirejaz Apr 20, 2026
d687eb7
Wire optimizer flags into thv vmcp serve (#4940)
yrobla Apr 20, 2026
8504427
Document category-based redis ACLs (#4946)
tgrunnagle Apr 20, 2026
ee823d8
Add policy_stopped workload status and enforce policy gate on restart…
reyortiz3 Apr 20, 2026
c1292c4
Extend group extraction with dual-claim and dot-notation support (#4911)
jhrozek Apr 20, 2026
c334edf
vmcp: stop the TEI manager on Start failure and apply image default i…
SAY-5 Apr 21, 2026
ee01104
Update alpine Docker tag to v3.23.4 (#4927)
renovate[bot] Apr 21, 2026
e0c11d6
Update github/codeql-action digest to 95e58e9 (#4926)
renovate[bot] Apr 21, 2026
9f021b9
Update anthropics/claude-code-action digest to 5d5c10a (#4925)
renovate[bot] Apr 21, 2026
c2b4186
Bump github.com/sigstore/timestamp-authority/v2 from 2.0.3 to 2.0.6 (…
dependabot[bot] Apr 21, 2026
109815b
Account for embedded auth env in deployment drift checks (#4878)
JAORMX Apr 21, 2026
ea4cfbc
Update actions/cache digest to 27d5ce7 (#4924)
renovate[bot] Apr 21, 2026
7a9d659
Split skillsvc into per-concern files (#4947)
samuv Apr 21, 2026
b2f6717
Finish defaultTEIImage rename in embedding_manager_test.go (#4957)
JAORMX Apr 21, 2026
b437352
Upgrade default go builder image to golang:1.26-alpine (#4955)
JAORMX Apr 21, 2026
ccf439d
Return 502 Bad Gateway when OCI skill pull fails (#4956)
samuv Apr 21, 2026
f472476
Upgrade default uvx builder image to python:3.14-slim (#4953)
JAORMX Apr 21, 2026
b4f391b
Upgrade default npx builder image to node:24-alpine (#4954)
JAORMX Apr 21, 2026
06d2746
Update module github.com/stacklok/toolhive-catalog to v0.20260421.0 (…
renovate[bot] Apr 21, 2026
14fe9b6
Document 502 Bad Gateway failure for installSkill in OpenAPI spec (#4…
samuv Apr 21, 2026
829c4bd
Add registry-aware workload creation (#4872)
rdimitrov Apr 21, 2026
cb37b8b
Add unit and integration tests for Cedar group-based authorization (#…
jhrozek Apr 21, 2026
108f6fa
Add e2e tests for thv vmcp CLI (#4941)
yrobla Apr 21, 2026
f6cdfc2
Thread image verification mode through workload service (#4966)
rdimitrov Apr 21, 2026
e516be4
Hide thv vmcp command from CLI help (#4967)
JAORMX Apr 21, 2026
ee39caf
Release v0.22.0 (#4968)
stacklokbot Apr 21, 2026
f3c9f24
Set MCP parent on resource entities for server-scoped policies (#4965)
jhrozek Apr 21, 2026
117be04
Default redirectUri on upstream providers as documented in CRD (#4905)
tgrunnagle Apr 21, 2026
3dbbf5a
Graduate CRDs from v1alpha1 to v1beta1 (#4849)
ChrisJBurns Apr 21, 2026
81e23e2
Release v0.23.0 (#4973)
stacklokbot Apr 21, 2026
63ee62a
Propagate auth errors through stale cache fallback (#4981)
reyortiz3 Apr 21, 2026
7ee0772
Unify docs-website release pipeline: new assets + retire dispatch cha…
rdimitrov Apr 21, 2026
69fb2b7
Add advisory CRD schema compatibility CI check (#4980)
ChrisJBurns Apr 21, 2026
7fb840a
Release v0.23.1 (#4985)
stacklokbot Apr 21, 2026
74e7a00
Merge upstream v0.23.1 into dp-stable
carlos-lopez-vecino Sep 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .claude/agents/code-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: code-reviewer
description: Reviews code for ToolHive best practices, security patterns, Go conventions, and architectural consistency
tools: [Read, Glob, Grep]
model: inherit
color: yellow
---

# Code Reviewer Agent
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/golang-code-writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ description: Write, generate, or create new Go code — functions, structs, inte
tools: [Read, Write, Edit, Glob, Grep, Bash]
permissionMode: acceptEdits
model: inherit
color: blue
---

# Go Code Writer Agent
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/kubernetes-expert.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: kubernetes-expert
description: Specialized in Kubernetes operator patterns, CRDs, controllers, and cloud-native architecture for ToolHive
tools: [Read, Write, Edit, Glob, Grep, Bash, WebFetch]
model: inherit
color: blue
---

# Kubernetes Expert Agent
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/toolhive-expert.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name: toolhive-expert
description: Codebase knowledge, navigation, and implementation guidance — use for understanding existing code and patterns
tools: [Read, Glob, Grep, Bash]
color: green
model: inherit
---

Expand Down
66 changes: 66 additions & 0 deletions .claude/rules/go-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,72 @@ if someCondition {
}
```

## Copy Before Mutating Caller Input

Never mutate a value passed in by a caller. Maps and slices have reference semantics — passing them copies the header but shares the underlying data, so mutations are visible to the caller. Pointer parameters (`*T`) directly expose the caller's original value. Plain struct values (`T`) are copies and safe to modify, but structs passed as `*T`, or whose fields include maps, slices, or pointers, can still reach caller-visible data through those fields. In-place mutation surprises callers, can cause data races, and breaks the assumption that the caller's original value is unchanged after the call.

Always copy the input first and mutate the copy:

```go
// Good
meta := maps.Clone(callerMeta)
meta["key"] = "value"

// Avoid
callerMeta["key"] = "value" // mutates the caller's map
```

Note that `maps.Clone` (and `slices.Clone`) perform a **shallow copy** — if map values or slice elements contain pointers, slices, or nested maps, mutating those nested values will still affect the caller's data. Use a deep copy when the value type requires it.

This applies to function parameters, values extracted from context, and values returned by storage/cache loads. If the function's doc comment does not explicitly state "the caller's value will be modified", treat all inputs as read-only.

## Keep Comments Synchronized With Code

When you change behavior, update every comment that describes it. A comment that contradicts the code is worse than no comment — it actively misleads future readers and causes incorrect changes.

- After any refactor, search for comments referencing the old behavior and update them.
- If a comment names a specific function, variable, or mechanism, verify the name is still accurate.
- Comments describing concurrency semantics (eviction timing, lazy vs. eager, which lock is held) are especially prone to drift — treat them as part of the implementation, not decoration.

## Constructor Validation: Fail Loudly on Invalid Input

Constructors must validate their required inputs and fail loudly (return an error or panic) rather than silently accepting invalid values and producing surprising behavior.

- Required parameters: check for nil and return a descriptive error.
- Numeric bounds: reject values outside the valid range (e.g., `capacity < 1`). Zero is Go's default — don't let it silently mean "unlimited" or "disabled".
- Enum/string config: reject unknown values explicitly; don't fall back silently to a default that the caller didn't request.

Misconfiguration that fails at startup is far easier to diagnose than misconfiguration that silently degrades behavior at runtime.

## One Synchronization Primitive Per Data Structure

Use a single synchronization mechanism per data set. Mixing `sync.Mutex` and `sync.Map` (or channels) on the same underlying data is a correctness hazard — future contributors cannot reason about which operations are atomic with respect to each other.

If atomicity requirements grow beyond what `sync.Map` provides (e.g., you need read-modify-write), replace it with a plain `map` guarded by a `sync.Mutex` for all operations. The performance difference at typical cardinalities is negligible compared to the clarity gained.

## Drain HTTP Response Bodies Before Closing

Always drain a response body before closing it in error paths. Closing without reading prevents `net/http` from reusing the underlying TCP connection, causing unnecessary connection churn.

```go
// Good
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()

// Avoid — prevents connection reuse
resp.Body.Close()
```

This applies in every code path that discards a response early (error handling, retries, fallbacks).

## Write to Durable Storage Before Updating In-Memory State

When a write must update both durable storage (database, Redis, file) and an in-memory structure (cache, map, struct field), always write to the authoritative store first. Update local state only after the durable write succeeds.

- If the durable write fails, leave in-memory state unchanged — the next read will reload from the source of truth.
- If the process crashes after the durable write but before the in-memory update, the next read reloads correctly.
- Reversing the order leaves a window where in-memory state diverges permanently from durable state on any error.

## Error Handling

- Return errors by default — never silently swallow errors
Expand Down
49 changes: 49 additions & 0 deletions .claude/rules/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ Applies to test files and test directories.
5. **Naming**: Test names must match what they actually assert — if the assertion changes, update the name too.
6. **Boilerplate**: Minimize setup code; extract shared setup into helpers with `t.Helper()`

## Running Operator E2E Tests

Operator E2E tests live in `test/e2e/thv-operator/` and require a Kind cluster. All tasks are defined in `cmd/thv-operator/Taskfile.yml` and must be run from the repo root with `task -d cmd/thv-operator <task>` (or `cd cmd/thv-operator && task <task>`).

**Full automated run** (creates cluster, deploys, tests, destroys on exit):
```
task -d cmd/thv-operator thv-operator-e2e-test
```

**Iterative manual workflow** (keep the cluster alive between test runs):
```
task -d cmd/thv-operator kind-setup-e2e # Kind cluster with NodePort mappings
task -d cmd/thv-operator operator-install-crds
task -d cmd/thv-operator operator-deploy-local # builds & loads local images via ko
task -d cmd/thv-operator thv-operator-e2e-test-run # re-run as many times as needed
task -d cmd/thv-operator kind-destroy # when done
```

**Cluster variants:**
- `kind-setup` — plain cluster, no port mappings (general use)
- `kind-setup-e2e` — cluster with NodePort mappings required by Ginkgo E2E tests

**Chainsaw (operator unit-level E2E):**
```
task -d cmd/thv-operator operator-e2e-test
```
Runs `chainsaw` against `test/e2e/chainsaw/operator/` scenarios. Installs `chainsaw` automatically if missing.

The Ginkgo suite runs with `--procs=8` and uses `kconfig.yaml` (written to repo root by the kind-setup tasks) as its `KUBECONFIG`.

## E2E Test Coverage

E2E tests must verify functional behavior, not just infrastructure state. Confirming that pods are ready or that counts are correct is not sufficient — the test must also exercise the actual code path (send traffic, trigger the feature) to prove it works end-to-end.
Expand Down Expand Up @@ -70,6 +100,25 @@ Avoid adding test-only hook fields (nil-checked `func()` fields) to production s

Existing instances in the codebase are legacy — do not expand them. When touching a struct that already has hook fields, consider extracting them as part of the change.

## Use `t.Cleanup` for Resource Teardown in Parallel Tests

In tests using `t.Parallel()`, always register resource teardown (stopping servers, closing connections, cancelling contexts) with `t.Cleanup`, not just `defer`.

In parallel tests, `defer` runs when the parent test function returns — which can happen before `t.Parallel()` subtests finish. `t.Cleanup` handlers are tied to the test's full lifecycle and run after all subtests complete, preventing leaked goroutines, ports, and connections.

Note: `require.*` uses `runtime.Goexit`, and panics unwind the stack — both run deferred functions. The difference is not about defers being skipped; it's about *when* they run relative to subtests.

```go
// Good — runs after all subtests complete
server := httptest.NewServer(handler)
t.Cleanup(server.Close)

// Avoid in parallel tests — may run before subtests finish
defer server.Close()
```

Make stop/close functions idempotent (`sync.Once`) when registering with both `t.Cleanup` and an explicit mid-test shutdown.

## Concurrent Tests: Always Add Timeouts to Blocking Barriers

Blocking operations in tests (`WaitGroup.Wait()`, channel receives, `sync.Cond.Wait()`) must have a timeout/fail-fast path. Without one, a panicking goroutine or regression in synchronization logic causes the test to hang until the global `go test` timeout.
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/implement-story/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ After changes that affect generated artifacts, run the appropriate tasks:

| Change Type | Regeneration Command |
|-------------|---------------------|
| CRD type definitions (`api/v1alpha1/*_types.go`) | `task operator-manifests operator-generate` |
| CRD type definitions (`api/v1beta1/*_types.go`) | `task operator-manifests operator-generate` |
| Mock interfaces | `task gen` |
| CLI commands or API endpoints | `task docs` |
| Helm chart values | `task helm-docs` |
Expand Down
Loading
Loading