Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
205 commits
Select commit Hold shift + click to select a range
7b3cca1
Add upstream identity to DCR credential cache key (#5824)
tgrunnagle Jul 16, 2026
17aeba2
Update github/codeql-action digest to 7188fc3 (#5778)
renovate[bot] Jul 16, 2026
29b8d00
Guard upstream-DCR HTTP calls against SSRF (#5826)
tgrunnagle Jul 16, 2026
b9fcb21
Update module github.com/stacklok/toolhive-core to v0.0.29 (#5840)
renovate[bot] Jul 17, 2026
d76d4e3
feat: migrate from mark3labs/mcp-go to toolhive-core/mcpcompat (go-sd…
JAORMX Jul 17, 2026
e07da78
Update module github.com/stacklok/toolhive-catalog to v0.20260716.0 (…
renovate[bot] Jul 17, 2026
748ddd8
Return HTTP 403 for authz-denied vMCP calls (#5827) (#5841)
JAORMX Jul 17, 2026
61946f9
Update golang.org/x/exp/jsonrpc2 digest to 9ea1abe (#5780)
renovate[bot] Jul 17, 2026
e7c6fd5
Reconcile network isolation with network mode (#5794)
JAORMX Jul 17, 2026
8c5b00a
Resolve temp dirs in plugin adapter tests (#5849)
jhrozek Jul 17, 2026
234ecbd
Add MCP 2026-07-28 revision classification and method vocabulary (#5834)
jhrozek Jul 17, 2026
e14bb31
Harden vMCP authz gate: single parse source and reserved-name check (…
JAORMX Jul 17, 2026
3040872
Add RFC 8693 token exchange handler to the embedded AS (#5822)
jhrozek Jul 17, 2026
cab6e17
Follow list pagination cursors in vMCP capability discovery (#5851)
JAORMX Jul 17, 2026
505df83
Release v0.40.0 (#5855)
toolhive-release-app[bot] Jul 17, 2026
67f6ba7
Serve prompts per-session in vMCP (#5857)
JAORMX Jul 17, 2026
9df07fa
Strip hop-by-hop headers before SigV4 signing (#5836)
Yanhaoxi Jul 17, 2026
9f4b211
Stop auto-requesting changes on XL PRs (#5864)
jhrozek Jul 17, 2026
38b03b6
Capture proxy logs in conformance CI runs (#5863)
jhrozek Jul 17, 2026
52ecebc
Respect DCR-negotiated token endpoint auth method (#5866)
tgrunnagle Jul 17, 2026
1c60f0f
Stop VirtualMCPServer hot-reconcile on cleared podTemplateSpec (#5846)
jhrozek Jul 18, 2026
9bde3e4
Audit authorization denials on the proxy runner path (#5872)
JAORMX Jul 19, 2026
cd497a2
Update anthropics/claude-code-action digest to af0559e (#5868)
renovate[bot] Jul 20, 2026
ee9612b
Fix isolation error wording and log-level rationale from #5794 review…
aponcedeleonch Jul 20, 2026
5f0a414
Update module github.com/stacklok/toolhive-catalog to v0.20260717.0 (…
renovate[bot] Jul 20, 2026
b44556e
Update module github.com/stacklok/toolhive-catalog to v0.20260720.0 (…
renovate[bot] Jul 20, 2026
0b6e1f1
Release v0.40.1 (#5877)
toolhive-release-app[bot] Jul 20, 2026
217b0be
Add stateless routing to streamable MCP proxy (#5839)
jhrozek Jul 20, 2026
f0ffba7
Normalize opt-in multi-valued JWT claims for Cedar (#5880)
jhrozek Jul 20, 2026
62496e9
Bound delegated token audience by subject token (#5882)
jhrozek Jul 20, 2026
c1c9c45
Wire token exchange handler into fosite (#5881)
jhrozek Jul 20, 2026
8efeeb3
Implement Client Secret Expiry and Renewal for Dynamic Client Registr…
Sanskarzz Jul 20, 2026
db4ecb1
Serve MCP 2026-07-28 stateless requests through the transparent proxy…
jhrozek Jul 20, 2026
4f0ac15
Warm ingress Squid peer connections with standby=2 (#5887)
jhrozek Jul 21, 2026
2300257
Ignore flaky tools-call-sampling in conformance CI (#5888)
jhrozek Jul 21, 2026
fbf2f6d
Make vMCP MCP-conformant: completions, templates, subscribe, forwardi…
JAORMX Jul 21, 2026
193a7f2
Extract a swappable networkProxy seam from deployOps (#5906)
ChrisJBurns Jul 22, 2026
24de842
Isolate HTTP transport in vmcp backend tests (#5919)
JAORMX Jul 22, 2026
d8bf3b2
Add Envoy network-proxy backend behind TOOLHIVE_NETWORK_PROXY=envoy (…
ChrisJBurns Jul 22, 2026
ecae5e0
Add Envoy network-isolation e2e tests (#5918)
ChrisJBurns Jul 22, 2026
13bd72e
Default storage version migrator to enabled in operator chart (#5603)
ChrisJBurns Jul 22, 2026
e8d243d
Wire MCP 2026-07-28 revision classification into vMCP (#5913)
jhrozek Jul 23, 2026
a18f17e
Reject JSON-RPC batches to close authz blind spot (#5931)
JAORMX Jul 23, 2026
3dee7d6
Update batch e2e test to expect rejection (#5933)
JAORMX Jul 23, 2026
3441e75
Add project-level skills lock file schema package (#5892)
samuv Jul 23, 2026
54f62dd
Fix Envoy isolated-server readiness and enable e2e tests (#5926)
ChrisJBurns Jul 23, 2026
4529806
Deflake vMCP forwarding notification wait (#5941)
JAORMX Jul 23, 2026
1d3e866
Send current MCP protocol version in readiness probe (#5940)
JAORMX Jul 23, 2026
a7d5e4c
Translate AllowPort into Envoy egress RBAC policy (#5927)
ChrisJBurns Jul 23, 2026
c007e6a
Route server-to-client MCP messages per session (#5934)
JAORMX Jul 23, 2026
2da1fcb
Return JSON-RPC error for filtered tool calls (#5944)
JAORMX Jul 23, 2026
00b8159
Update standalone-SSE test for filtered-tool error (#5958)
JAORMX Jul 24, 2026
97a9dfa
Add opt-in strict MCP-Protocol-Version validation (#5957)
JAORMX Jul 24, 2026
32fa068
Add SkillLockService interface and managed install flag (#5893)
samuv Jul 24, 2026
0192285
Drain backend notifications before per-call client close (#5960)
JAORMX Jul 24, 2026
bd855dd
Deflake real-backend forwarding tests (#5963)
JAORMX Jul 24, 2026
669265e
Record project-scope skill installs in the lock file (#5894)
samuv Jul 24, 2026
52bc063
Add thv skill sync: restore project skills from the lock file (#5895)
samuv Jul 24, 2026
ff13bce
Propagate W3C trace context in outbound MCP _meta (#5964)
JAORMX Jul 24, 2026
8d00a6b
Add thv skill upgrade: re-resolve pinned skills to newer content (#5896)
samuv Jul 24, 2026
e047b0d
Add typed exit codes and confirmation gate to skill sync/upgrade (#5897)
samuv Jul 24, 2026
96eec94
Consume backend list_changed in vMCP and propagate to clients (#5965)
JAORMX Jul 24, 2026
5f6076e
Regenerate swagger docs to drop duplicate enums (#5970)
JAORMX Jul 24, 2026
8fc7109
Propagate MCPOIDCConfig CA bundle to vmcp OIDC config (#4923)
ChrisJBurns Jul 24, 2026
eaa632f
Harden Envoy backend: pin image digest, disable admin interface (#5949)
ChrisJBurns Jul 24, 2026
0017afc
Serve MCP 2026-07-28 Modern stateless requests through vMCP (#5953)
jhrozek Jul 24, 2026
d77dafc
Propagate backend resources/prompts list_changed in vMCP (#5971)
JAORMX Jul 24, 2026
f76096d
Add vMCP per-session security regression tests (#5974)
JAORMX Jul 24, 2026
1336f20
Fix digest-pinned image pulls failing at container create (#5978)
ChrisJBurns Jul 24, 2026
a424660
Add regression pins for TTL, DNS-rebind, bridge, schema (#5977)
JAORMX Jul 24, 2026
405b3c7
Update module google.golang.org/grpc to v1.82.1 [SECURITY] (#5943)
renovate[bot] Jul 24, 2026
d439f33
Update golang/govulncheck-action digest to 032d455 (#5869)
renovate[bot] Jul 24, 2026
fd01045
Update anthropics/claude-code-action digest to be7b93b (#5983)
renovate[bot] Jul 25, 2026
9ef27fa
Make swagger docgen deterministic (dedupe swag's doubled enums)
jhrozek Jul 25, 2026
885e8b1
Handle per-backend MCP revision in vMCP (client-side dual protocol)
jhrozek Jul 25, 2026
d65af0b
Bump toolhive-core for tool-schema ingestion fix (#5990)
JAORMX Jul 25, 2026
b928cc3
Unblock main CI: fix vMCP nil-registry panic and CRD docs drift (#5999)
jhrozek Jul 26, 2026
cfa2b40
Fall back to Legacy on an inconclusive vMCP revision probe (#6001)
jhrozek Jul 26, 2026
e3a8aaa
Preserve inner error codes through the skills lock-state wrap (#5966)
samuv Jul 27, 2026
c30fd75
Extract shared source-dispatch skeleton for skill sources (#5967)
samuv Jul 27, 2026
9c78c3d
Add live e2e tests for dual-era stateless proxy behavior (#5981)
jhrozek Jul 27, 2026
ff0ba2e
Validate subject tokens from external OIDC issuers (#5995)
jhrozek Jul 27, 2026
51248e1
Support MCP 2026-07-28 spec (go-sdk v1.7 via toolhive-core) (#5993)
JAORMX Jul 27, 2026
256d443
Unify e2e yardstick backend on 1.2.0 (#6004)
jhrozek Jul 27, 2026
894a5cb
Update module github.com/stacklok/toolhive-catalog to v0.20260727.0 (…
renovate[bot] Jul 27, 2026
a6a0d4c
Audit authentication failures and webhook denials (#5874)
JAORMX Jul 27, 2026
96f25d0
Audit stream opens on flush and pre-write panics (#6005)
JAORMX Jul 27, 2026
d390730
Pin forwarding tools/call against a stale-Legacy stateless backend (#…
JAORMX Jul 27, 2026
f1dae94
Make e2e workload readiness waits reliable (#6012)
JAORMX Jul 27, 2026
6ef7820
Add provenance and unsigned fields to the skills lock schema (#6015)
samuv Jul 27, 2026
83394ee
Reject backend tools with invalid x-mcp-header (#6013)
JAORMX Jul 27, 2026
0a9e32a
Document vMCP backend revision classification (#6016)
JAORMX Jul 27, 2026
7be5ec7
Consolidate the negotiate-down rationale (#6017)
JAORMX Jul 27, 2026
f0de82f
Strip reserved io.modelcontextprotocol/* keys from responses (#6024)
jhrozek Jul 27, 2026
08cbffd
Bridge era-mismatched client×backend cells in vMCP (#6006)
jhrozek Jul 27, 2026
4544ce2
Correct two references in the canonical rationale (#6025)
JAORMX Jul 27, 2026
a8745b8
Pin tools/list pagination completeness for >1000-tool vMCP sets (#6021)
JAORMX Jul 27, 2026
8a860d9
Fix bridge_regression_test build after reserved-meta API rename (#6029)
JAORMX Jul 27, 2026
e837d69
Fix Cedar deny-all when upstream JWT lacks identity claims (#6022)
JAORMX Jul 27, 2026
dc26afe
Bump klauspost/compress to v1.18.7 (#6041)
JAORMX Jul 27, 2026
8231924
Fix contradictory upstream ID token exp contract (#6036)
JAORMX Jul 27, 2026
cb1f9d1
Echo the request JSON-RPC id in session-not-found 404s (#6031)
JAORMX Jul 27, 2026
401eec7
Bind the vMCP test server's port directly (#6044)
JAORMX Jul 27, 2026
be0e0c3
Harden group e2e workload naming and waits (#6043)
JAORMX Jul 27, 2026
a099fa0
Speed up e2e(core) suite with Ginkgo procs and concurrent waits (#6070)
ChrisJBurns Jul 27, 2026
c1146a8
Stop deriving the ingress proxy port from a fixed upstream port (#6069)
jhrozek Jul 28, 2026
53127d0
Fix concurrent isolated-startup races (network create + ingress DNS l…
ChrisJBurns Jul 28, 2026
0d5acb3
Stop trimming binary HMAC secrets before use (#6067)
jhrozek Jul 28, 2026
0255856
Classify Modern mid-call capability refusals per spec (#6061)
JAORMX Jul 28, 2026
e3de20e
Gate dual-era e2e on the full replica count (#6057)
jhrozek Jul 28, 2026
57e681f
Omit absent JSON-RPC ids instead of emitting null (#6068)
jhrozek Jul 28, 2026
33023da
Deflake CI: TUF warn mode, readiness diagnostics, test races (#6063)
JAORMX Jul 28, 2026
793eb55
Make forwarding tests' Legacy dependency explicit (#6051)
JAORMX Jul 28, 2026
ca4eda4
Complete Modern client-facing dispatch (#6050)
JAORMX Jul 28, 2026
b4af1d0
Update github/codeql-action digest to e4fba86 (#5988)
renovate[bot] Jul 28, 2026
2e05f91
Update actions/checkout digest to d23441a (#5982)
renovate[bot] Jul 28, 2026
b5a4851
Add Redis-backed mixed-era vMCP e2e coverage (#6056)
jhrozek Jul 28, 2026
9b0d83a
Emit conformant JSON-RPC on denial and error paths (#6055)
jhrozek Jul 28, 2026
4a61bd1
Use standard JSON-RPC error codes and scrub leaked error text (#6066)
jhrozek Jul 28, 2026
f391d38
Stop splicing whole SSE buffers into error text (#6079)
jhrozek Jul 28, 2026
53908ef
Add Sigstore signer package for skill OCI artifacts (#6023)
samuv Jul 28, 2026
d79c3a9
Fix workload status poisoning and deflake Envoy AllowPort (#6076)
JAORMX Jul 28, 2026
e8f84ef
Recreate the shared external network on a lost teardown race (#6083)
jhrozek Jul 28, 2026
e2c4441
Retry dual-era backend startup on a lost port-bind race (#6080)
jhrozek Jul 28, 2026
e79d623
Capture RFC 8693 act claim in audit logs (#6046)
JAORMX Jul 28, 2026
bbdb633
Share one JSON-RPC error writer across HTTP denial paths (#6086)
JAORMX Jul 28, 2026
92c70db
Close authz response filter bypasses via media type and status (#6092)
JAORMX Jul 28, 2026
de1953e
Resolve aggregator conflicts for resources, templates and prompts (#6…
JAORMX Jul 28, 2026
f805322
Frame SSE filter-failure errors as SSE events (#6087)
jhrozek Jul 28, 2026
746ee70
Design MRTR for vMCP and land the typed input_required seam (#6074)
JAORMX Jul 28, 2026
919479d
Drop ambiguous prompt names instead of failing aggregation (#6099)
JAORMX Jul 28, 2026
cd373ec
Fix review findings in the act claim audit capture (#6096)
jhrozek Jul 28, 2026
6d6e9f9
operator helm: add opt-in image-discovery Deployment for offline inst…
reyortiz3 Jul 28, 2026
7530d35
Replace vMCP Modern kill-switch with a capability gate (#6033)
JAORMX Jul 28, 2026
e79be30
Parse SSE responses per event, not per line (#6088)
jhrozek Jul 28, 2026
07915a0
docs: fix missing trailing periods in CONTRIBUTING.md (#5961)
amir-rezaei Jul 28, 2026
9ce78fa
test(e2e): quarantine uvx arxiv test broken by Python mcp 2.0.0 (#6109)
JAORMX Jul 28, 2026
2858ac8
Adopt toolhive-core canonical delegation-chain schema (#6107)
JAORMX Jul 28, 2026
de0469e
Deflake TestWorkflowEngine_ParallelExecution (#6112)
ChrisJBurns Jul 28, 2026
ac16484
Add --uv-with constraint support for uvx:// builds; unskip arxiv e2e …
JAORMX Jul 28, 2026
735225f
Reject malformed prior act claims at token exchange (#6114)
jhrozek Jul 28, 2026
525a308
Emit event: message on streamable-http SSE frames (#5954)
stantheman0128 Jul 28, 2026
333d71d
Rename --uv-with to --build-with; reject constraints on unsupported e…
JAORMX Jul 28, 2026
ea5ae5c
Add commit-signature plumbing and sigstore bundle storage (#6084)
samuv Jul 28, 2026
1ae976c
Reallocate rate-limit error code to 429 (#6120)
JAORMX Jul 28, 2026
bb2bb0f
Extract shared event prologue in WorkflowAuditor (#6122)
JAORMX Jul 28, 2026
d722304
Release v0.41.0 (#6125)
toolhive-release-app[bot] Jul 28, 2026
724ad1f
Add plugin REST API, thv ai-plugin CLI, and HTTP client (Phase 4) (#5…
JAORMX Jul 28, 2026
0a0cbd9
Remove referencingWorkloads/referenceCount from config CRD statuses (…
ChrisJBurns Jul 28, 2026
ea71bd2
Wire tool_keywords into the BM25 search arm (#6124)
aponcedeleonch Jul 29, 2026
11a18f1
Refresh the cached MCP parse after webhook mutation
jhrozek Jul 29, 2026
742ae76
Add plugin registry catalog surface and name-based install (#6135)
JAORMX Jul 29, 2026
3d44435
Fix port-selection TOCTOU race in e2e tests (#6142)
jhrozek Jul 29, 2026
247480f
Adopt core MCP semconv bucket preset in telemetry (#6144)
JAORMX Jul 30, 2026
32f75d9
Delegate recovery middleware to toolhive-core with observability hook…
JAORMX Jul 30, 2026
33e06f4
Alias audit event constants and logger to toolhive-core (#6148)
JAORMX Jul 30, 2026
b7e824c
Pin ida-pro-mcp e2e image by digest (#6159)
aponcedeleonch Jul 31, 2026
e439d1f
Pin mcp-server-time e2e image by digest (#6160)
amirejaz Jul 31, 2026
09dfc7b
Confirm Modern promotion with a discover probe (#6158)
amirejaz Jul 31, 2026
a48448d
Strip session ID from proxied initialize requests (#6152)
amirejaz Jul 31, 2026
7bd378b
Update github.com/tailscale/hujson digest to b80ff77 (#6166)
renovate[bot] Aug 2, 2026
b7074f7
Update coverallsapp/github-action digest to 8d6379e (#6165)
renovate[bot] Aug 2, 2026
7d46711
Update github/codeql-action digest to f205ea1 (#6167)
renovate[bot] Aug 2, 2026
798f37c
Authorize and accept call_tool with nested tool_name (#6150)
Tanguille Aug 3, 2026
eedf566
Keep optimizer store's in-memory database alive (#6157)
aponcedeleonch Aug 3, 2026
d5e8996
Decode the call_tool target as dispatch does (#6175)
aponcedeleonch Aug 3, 2026
5fecff4
Serve repeat initialize from a cached result (#6153)
amirejaz Aug 3, 2026
ebbdcce
Await manager shutdown before stopping envtest (#6179)
aponcedeleonch Aug 3, 2026
ef1ce91
Add skills verifier wrapping toolhive-core Sigstore exports (#6091)
samuv Aug 3, 2026
262851f
Add gitsign commit-signature verification (#6121)
samuv Aug 3, 2026
6658f84
Verify skill signatures at install time (#6129)
samuv Aug 3, 2026
652f3c0
Adopt telemetry providers from toolhive-core (#6146)
JAORMX Aug 3, 2026
6a428a8
Opt Modern backends into log notifications via logLevel _meta (#6140)
JAORMX Aug 3, 2026
1f50e2b
Re-verify stored signatures offline during sync (#6131)
samuv Aug 3, 2026
b02a984
Update anthropics/claude-code-action action to v1.0.183 (#6173)
renovate[bot] Aug 3, 2026
baba8bf
Block upgrades that change the signer identity (#6132)
samuv Aug 4, 2026
4b5b53d
Set Windows DACL on discovery directory under LOCALAPPDATA (#5951)
stantheman0128 Aug 4, 2026
9cce585
Pin elicitation fail-fast without a standalone stream (#6182)
JAORMX Aug 4, 2026
63a0a9b
Expire the refuted-Modern-hint memory after a TTL (#6185)
JAORMX Aug 4, 2026
aa3f5b3
Forward resource-read _meta in vMCP and the transport bridge (#6180)
JAORMX Aug 4, 2026
227ee7b
Update module github.com/stacklok/toolhive-catalog to v0.20260804.0 (…
renovate[bot] Aug 5, 2026
2c623d5
Release v0.42.0 (#6207)
toolhive-release-app[bot] Aug 5, 2026
e7a995b
Pass CA-aware HTTP client to JWKS registration (#6220)
danbarr Aug 6, 2026
8863eb0
Handle non-fatal httprc errors in JWKS registration (#6221)
danbarr Aug 6, 2026
12ffd7a
Resolve relative --project-root before the API call (#6223)
samuv Aug 6, 2026
127cc88
Stop severing skill artifact pulls at fixed timeouts (#6224)
samuv Aug 6, 2026
d29e0d5
Block only repository moves, not tag moves, on upgrade (#6225)
samuv Aug 6, 2026
e91586a
Resolve relative --project-root for ai-plugin too (#6226)
samuv Aug 6, 2026
2e83cd1
Stop severing plugin artifact pulls at fixed timeouts (#6228)
samuv Aug 6, 2026
f3a2818
Keep the OIDC callback listener alive when an LLM proxy client discon…
jhrozek Aug 6, 2026
f178d9e
Skip logging/setLevel on a Modern-negotiated session (#6184)
amirejaz Aug 6, 2026
7544632
Add deny-by-default visibility to vMCP aggregation (#6163)
jerm-dro Aug 6, 2026
04198d4
Reject tools/call for tools hidden from tools/list (#6216)
jerm-dro Aug 6, 2026
91d6a79
Support MCP tool annotations for composite tools (#6208)
JAORMX Aug 7, 2026
39f38ce
Delegate images keychain to toolhive-core (#6147)
JAORMX Aug 7, 2026
acc6df3
Add a consent model for external OIDC subject tokens (#6149)
jhrozek Aug 7, 2026
3e5e65f
Clean up deny-visibility validator and CRD docs (#6233)
jerm-dro Aug 7, 2026
ee293aa
Skip known-bad backends when opening vMCP sessions (#6162)
jerm-dro Aug 7, 2026
3cb828f
Validate MCPOIDCConfig inline issuer and JWKS URLs (#5936)
lopster568 Aug 7, 2026
3208636
Update module github.com/go-git/go-git/v5 to v5.19.2 [SECURITY] (#6244)
renovate[bot] Aug 9, 2026
8a05edd
fix(authz): reject non-JSON POSTs instead of skipping authorization (…
SashaMIT Aug 10, 2026
06940e8
Release v0.42.1 (#6247)
toolhive-release-app[bot] Aug 10, 2026
3f02521
Merge upstream v0.42.1 into dp-stable
carlos-lopez-vecino Oct 16, 2026
79449b6
Document the fork patches after the v0.42.1 merge
carlos-lopez-vecino Oct 16, 2026
469eb01
Narrow the client-reply and Host header patches
carlos-lopez-vecino Oct 16, 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
  •  
  •  
  •  
7 changes: 4 additions & 3 deletions .claude/agents/mcp-protocol-expert.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ Defer to: oauth-expert (OAuth/OIDC), kubernetes-expert (K8s operator), toolhive-
- For the full, current set of pages under that version, fetch `https://modelcontextprotocol.io/sitemap.xml` and filter for the resolved version string — this is self-correcting as pages are added, renamed, or removed, unlike a hand-maintained list.
- Common pages to expect (verify against the sitemap, don't assume the exact path): architecture, basic, basic/authorization, basic/lifecycle, basic/transports, basic/utilities/{cancellation,ping,progress,tasks}, client/{elicitation,roots,sampling}, server, server/{tools,resources,prompts}, server/utilities/{completion,logging,pagination}, schema, changelog.
- Also check `https://modelcontextprotocol.io/extensions/auth/overview` for MCP auth extensions, which live outside the versioned spec tree.
3. Cross-reference whichever source answered with ToolHive's implementation.
4. Provide guidance based on the latest spec.
5. Explicitly note any discrepancies between spec and implementation, and note which source (context7 vs. WebFetch) backed the answer if it's non-obvious.
3. **For schema-level questions (exact field names, required-vs-optional, discriminated unions, literal error-code values), prefer the raw TypeScript schema over the rendered `.../schema` page or context7 snippets.** The rendered/curated sources can summarize or truncate a ~3k-line file; the ground truth both are generated from is `https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/<version>/schema.ts` (plain text, JSDoc-commented). Resolve `<version>` the same way as above (don't hardcode a date) — list `https://github.com/modelcontextprotocol/modelcontextprotocol/tree/main/schema` if unsure which dated folder is current — then WebFetch that file directly with a narrow prompt for the type in question.
4. Cross-reference whichever source answered with ToolHive's implementation.
5. Provide guidance based on the latest spec.
6. Explicitly note any discrepancies between spec and implementation, and note which source (context7, WebFetch docs, or schema.ts) backed the answer if it's non-obvious.

## Your Expertise

Expand Down
15 changes: 15 additions & 0 deletions .claude/rules/go-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,18 @@ Before implementing any non-trivial functionality from scratch:
3. **Look for existing Go packages** — search for well-maintained OSS libraries that solve the problem before writing custom implementations.

Implementing from scratch should be a last resort, justified by a specific gap no existing solution fills.

## JSON-RPC Envelopes

Never `json.Marshal` (or `json.NewEncoder().Encode`) a `jsonrpc2` type.
`jsonrpc2.Response` carries no json tags and `jsonrpc2.ID`'s only field is
unexported, so reflection emits Go-capitalized keys, drops the mandatory
`"jsonrpc":"2.0"` tag, and renders every id — valid or not — as `{}` (#5950).
Serialize through `jsonrpc2.EncodeMessage`; for HTTP error responses use
`pkg/mcp.EncodeJSONRPCError` / `pkg/mcp.WriteJSONRPCError`, which add
encode-before-header ordering and a conformant fallback body.

When an envelope must be hand-built as a map (only where no `jsonrpc2.ID` is
in hand), omit the `"id"` key when the id is absent — never emit `"id":null`.
MCP's `RequestId` is `string | number`, so null is not representable, and the
reference TypeScript SDK client throws on it inside its transport (#6038).
2 changes: 1 addition & 1 deletion .github/workflows/api-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout PR HEAD
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
fetch-depth: 1

Expand All @@ -59,7 +59,7 @@ jobs:

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@f1bd27ca5b54584506e40e17884d90bdaaa1a9b3 # v1
uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
# Security: Restrict tools to prevent arbitrary code execution.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-release-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-release-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
fetch-depth: 0

Expand Down
73 changes: 57 additions & 16 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
name: Build ToolHive Binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down Expand Up @@ -50,15 +50,20 @@ jobs:
- title: core
label_filter: core
artifact: e2e-test-results-core
procs: 4
- title: mcp-run
label_filter: mcp-run
artifact: e2e-test-results-mcp-run
- title: mcp-protocol
label_filter: mcp-protocol
artifact: e2e-test-results-mcp-protocol
- title: proxy
label_filter: proxy
label_filter: "proxy && !isolation"
artifact: e2e-test-results-proxy
- title: network-isolation
label_filter: isolation
artifact: e2e-test-results-network-isolation
test_timeout: 25m
- title: middleware
label_filter: 'middleware || stability'
artifact: e2e-test-results-middleware
Expand Down Expand Up @@ -86,7 +91,7 @@ jobs:
label_filter: llm
artifact: e2e-test-results-llm
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand All @@ -99,7 +104,7 @@ jobs:
go mod download
- name: Install Ginkgo CLI
run: |
go install github.com/onsi/ginkgo/v2/ginkgo@latest
go install github.com/onsi/ginkgo/v2/ginkgo@v2.28.1

- name: Download ToolHive binary
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
Expand All @@ -121,29 +126,60 @@ jobs:

- name: Pre-pull container images
run: |
# Pre-pull images used by E2E tests so that workload creation
# does not pay the image-pull cost inside the 60s API timeout.
docker pull ghcr.io/stackloklabs/osv-mcp/server:0.1.3 &
docker pull ghcr.io/stackloklabs/gofetch/server:1.0.2 &
docker pull ghcr.io/stacklok/toolhive/egress-proxy:latest &
# Pre-pull images used by E2E tests so that workload startup does not
# pay the image-pull cost inside a spec's readiness timeout.
#
# Images that tests reach through a registry server name (`thv run
# fetch`) are resolved from the binary under test instead of being
# hardcoded here. Renovate bumps github.com/stacklok/toolhive-catalog
# daily but has no manager for these docker pull lines, so hardcoded
# tags drift out of sync with the catalog silently and the pre-pull
# stops covering what the tests actually run.
servers="fetch osv"
images="ghcr.io/stacklok/toolhive/egress-proxy:latest"
# yardstick is only needed for the vmcp test suite
if [ "${{ matrix.label_filter }}" = "vmcp" ]; then
docker pull ghcr.io/stackloklabs/yardstick/yardstick-server:1.1.1 &
images="$images ghcr.io/stackloklabs/yardstick/yardstick-server:1.2.0"
fi
# the time server and yardstick (dual-era barrier mode) are only
# used by the proxy (streamable-http) test suite
if [ "${{ matrix.label_filter }}" = "proxy && !isolation" ]; then
servers="$servers time"
images="$images ghcr.io/stackloklabs/yardstick/yardstick-server:1.2.0"
fi
# the time server is only used by the proxy (streamable-http) test suite
if [ "${{ matrix.label_filter }}" = "proxy" ]; then
docker pull ghcr.io/stacklok/dockyard/uvx/mcp-server-time:2026.1.26 &
# Envoy is only used by the network-isolation test suite
if [ "${{ matrix.title }}" = "network-isolation" ]; then
images="$images envoyproxy/envoy-distroless:v1.32.3"
fi

for server in $servers; do
image="$(./bin/thv registry info "$server" --format json | jq -er '.image')"
echo "Resolved registry server '$server' -> $image"
images="$images $image"
done

for image in $images; do
docker pull -q "$image" &
done
wait

# `wait` reports success even when a background pull failed, so check
# each image landed locally. Failing here is far cheaper to diagnose
# than a spec timing out later while it waits on a live pull.
echo "Pre-pulled images:"
docker images --format '{{.Repository}}:{{.Tag}}' | grep -E 'osv-mcp|gofetch|egress-proxy|yardstick|mcp-server-time'
for image in $images; do
docker image inspect "$image" >/dev/null \
|| { echo "::error::failed to pre-pull $image"; exit 1; }
echo " $image"
done

- name: Run E2E tests (${{ matrix.title }})
env:
THV_BINARY: ${{ github.workspace }}/bin/thv
TOOLHIVE_EGRESS_IMAGE: ghcr.io/stacklok/toolhive/egress-proxy:latest
TEST_TIMEOUT: ${{ matrix.test_timeout || '15m' }}
LABEL_FILTER: ${{ matrix.label_filter }}
PROCS: ${{ matrix.procs || 1 }}
run: ./test/e2e/run_tests.sh

- name: Upload test results (${{ matrix.title }})
Expand All @@ -160,8 +196,12 @@ jobs:
runs-on: ubuntu-8cores-32gb
needs: build-binary
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
target: [proxy, vmcp]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
Expand All @@ -185,12 +225,13 @@ jobs:
- name: Run MCP conformance suite
env:
THV_BINARY: ${{ github.workspace }}/bin/thv
CONFORMANCE_TARGET: ${{ matrix.target }}
run: ./test/conformance/run-conformance.sh

- name: Upload conformance results
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: conformance-results
name: conformance-results-${{ matrix.target }}
path: test/conformance/results
retention-days: 7
2 changes: 1 addition & 1 deletion .github/workflows/helm-charts-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
fetch-depth: 0

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/helm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
contents: read
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Verify tag matches VERSION file
run: |
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
path: deploy/charts/operator-crds
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Extract version
id: version
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/image-build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Compute version number
id: version-string
Expand Down Expand Up @@ -147,7 +147,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down Expand Up @@ -227,7 +227,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down Expand Up @@ -296,7 +296,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
fetch-depth: 0

- name: Run Claude Code for Issue Triage
uses: anthropics/claude-code-action@558b1d6cab4085c7753fe402c10bef0fbb92ac7a # v1.0.165
uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1.0.183
with:
prompt: |
You are an issue triage assistant. Analyze issue #${{ github.event.issue.number }} in ${{ github.repository }} and apply appropriate labels.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/license-headers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
name: Check License Headers
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
name: Lint Go Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/operator-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
name: Operator Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand All @@ -33,7 +33,7 @@ jobs:
name: Operator Tests Integration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand All @@ -54,7 +54,7 @@ jobs:
name: Build Operator
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand All @@ -75,7 +75,7 @@ jobs:
name: Generate CRDs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:
name: Generate CRD Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
Expand Down Expand Up @@ -157,7 +157,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- name: Set up Helm
uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
Expand Down
Loading
Loading