You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refresh docs/arch/ to match current codebase (#5388)
The architecture docs had drifted since the v1beta1 graduation and the
migration of several packages into toolhive-core. This refresh
cross-references every claim against the current code in both repos and
brings the docs back in sync.
Highlights:
- Repoint moved packages: pkg/permissions, pkg/registry/types,
pkg/registry/data/registry.json, secrets/aes key derivation, runtime
monitor, and the registry-api manager
- Expand the operator CRD inventory: add EmbeddingServer (Auxiliary,
StatefulSet) and MCPWebhookConfig; rename ToolConfig -> MCPToolConfig
- Fix CRD field paths: spec.config.compositeToolRefs;
spec.incomingAuth.oidcConfigRef on VirtualMCPServer; MCPGroupRef
consumers expanded to all four CRDs
- Rewrite vMCP middleware order to match server.go wrap order; correct
Reporter interface naming; note logging reporter is Debug-level
- Add Cluster mode to the auth-server storage doc; flatten the
timeouts CRD shape; fix sentinelTls casing; surface DCRCredentialStore
- Replace stale registry pieces: built-in catalog source, legacy
top-level JSON examples, registry-API endpoint paths
(/v0.1/servers, /v0.1/servers/:name/versions/latest), deprecation of
thv group run
- Expand transport docs: NamedMiddleware constructor type; MCP env vars
emitted only by pkg/runtime/setup.go; 127.0.0.1 default lives in the
config builder; SSE rewrite in sse_response_processor.go
- Complete middleware enumeration in 02 and 05 (upstreamswap, awssts,
obo, ratelimit, usagemetrics, recovery, header-forward, validating-
webhook, mutating-webhook); fix authz -> authorization constant
- Restore pkg/secrets/types.go reference (EnvVarPrefix + Provider
interface); point pod builder at pkg/controllerutil
- Skills: replace nonexistent skillsvc.go with real file inventory;
add GET /content endpoint; mark oci_tags as reserved; correct OCI
artifact name-match (last path component)
- Smaller fixes: OrbStack across runtime lists; runtime detection order
Podman -> Docker -> Colima; drop bogus TOOLHIVE_DETACHED env var
and SENTRY_TRACES_SAMPLE_RATE env-var fallback; add unknown and
policy_stopped lifecycle states; add inspector transport
- Preserve correct StatefulSet wording throughout (proxy-runner is a
Deployment; the MCP server pod is a StatefulSet created via
pkg/container/kubernetes/client.go applyStatefulSet)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/arch/00-overview.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,7 +87,7 @@ thv run go://package-name
87
87
88
88
Manages MCP servers in Kubernetes clusters using custom resources.
89
89
90
-
The operator watches for `MCPServer`, `MCPRegistry`, `MCPToolConfig`, `MCPExternalAuthConfig`, `MCPGroup`, and `VirtualMCPServer` CRDs, reconciling them into Kubernetes resources (Deployments, StatefulSets, Services).
90
+
The operator watches a layered set of CRDs (Core: `MCPServer`, `MCPRemoteProxy`, `MCPServerEntry`; Organization: `MCPGroup`; Aggregation: `VirtualMCPServer`, `VirtualMCPCompositeToolDefinition`; Discovery: `MCPRegistry`; Configuration: `MCPToolConfig`, `MCPExternalAuthConfig`, `MCPOIDCConfig`, `MCPTelemetryConfig`, `MCPWebhookConfig`; Auxiliary: `EmbeddingServer`) and reconciles them into Kubernetes resources (proxy-runner Deployments and Services; ConfigMaps; the MCP server itself is created as a StatefulSet by the proxy-runner, while `EmbeddingServer`'s StatefulSet is created by the operator directly). See [Operator Architecture](09-operator-architecture.md) for the full taxonomy.
91
91
92
92
**For details**, see:
93
93
-[`cmd/thv-operator/README.md`](../../cmd/thv-operator/README.md) - Operator overview and usage
@@ -173,7 +173,7 @@ Via [ToolHive Studio](https://github.com/stacklok/toolhive-studio):
- Creates Kubernetes-native resources (Deployments, Services, ConfigMaps for the proxy-runner; StatefulSets are created by the proxy-runner for MCP server pods)
(*optional middleware, only present if configured)
138
+
Middleware is applied in reverse configuration order, and the chain composed for a given workload depends on which features are enabled. See [`docs/middleware.md`](../middleware.md) for the complete chain, ordering rules, and per-middleware semantics.
127
139
128
140
**Implementation:**
129
141
- Interface: `pkg/transport/types/transport.go`
@@ -187,9 +199,7 @@ A **permission profile** defines security boundaries for MCP servers:
187
199
-`network` - Full network access
188
200
189
201
**Implementation:**
190
-
- Definition: `pkg/permissions/profile.go`
191
-
- Network: `pkg/permissions/profile.go`
192
-
- Mount declarations: `pkg/permissions/profile.go`
202
+
- Definition, network permissions, and mount declarations: `github.com/stacklok/toolhive-core/permissions` (imported as `permissions` in `pkg/runner/`)
Runtimes are registered with a numeric `Priority` (lower wins) in the runtime registry (`pkg/container/runtime/registry.go`). Today the registered runtimes are:
403
+
404
+
- **Docker runtime** (`Priority: 100`, registered in `pkg/container/docker/register.go`) — covers Docker, Podman, Colima, Rancher Desktop, and OrbStack via per-runtime socket discovery (Podman → Docker → Colima).
405
+
- **Kubernetes runtime** (`Priority: 200`, registered in `pkg/container/kubernetes/register.go`) — activated when running in-cluster (via `KUBERNETES_SERVICE_HOST`) or when `TOOLHIVE_RUNTIME=kubernetes` is set.
393
406
394
407
**Implementation:**
395
408
- Interface: `pkg/container/runtime/types.go`
396
-
- Factory: `pkg/container/factory.go`
409
+
- Registry: `pkg/container/runtime/registry.go`
410
+
- Docker SDK factory and socket discovery: `pkg/container/docker/sdk/factory.go`, `pkg/container/docker/sdk/client_unix.go`
@@ -449,7 +463,7 @@ A **skill** is an Agent Skill -- a markdown-based instruction set (SKILL.md) tha
449
463
5. **Uninstall** - Remove files and metadata
450
464
451
465
**Implementation:**
452
-
- Service: `pkg/skills/skillsvc/skillsvc.go`
466
+
- Service interface: `pkg/skills/service.go`; implementation in `pkg/skills/skillsvc/` (entry point `pkg/skills/skillsvc/service.go`)
453
467
- Types: `pkg/skills/types.go`
454
468
- Storage: `pkg/storage/sqlite/skill_store.go`
455
469
- CLI: `cmd/thv/app/skill*.go`
@@ -480,7 +494,7 @@ A **skill** is an Agent Skill -- a markdown-based instruction set (SKILL.md) tha
480
494
2. Start proxy
481
495
3. Configure authentication (if needed)
482
496
4. Apply middleware
483
-
4. Update state
497
+
5. Update state
484
498
485
499
**Commands:**
486
500
- `thv run <image|url>`- Deploy and start
@@ -717,7 +731,7 @@ See `pkg/audit/mcp_events.go` for complete list of event types.
717
731
- Shutdown if unhealthy
718
732
719
733
**Implementation:**
720
-
- Monitor: `pkg/container/docker/monitor.go`
734
+
- Monitor: `pkg/container/runtime/monitor.go`
721
735
- Health checker: `pkg/healthcheck/healthcheck.go`
722
736
723
737
**Related concepts:** Workload, Transport, Proxy
@@ -759,7 +773,7 @@ graph LR
759
773
style Chain fill:#fff9c4
760
774
```
761
775
762
-
Requests pass through up to 9 middleware components (Auth, Token Exchange, Tool Filter, Tool Call Filter, Parser, Usage Metrics, Telemetry, Authorization, Audit). See `docs/middleware.md` for complete middleware architecture and execution order.
776
+
Requests pass through a configurable chain of middleware components. See [`docs/middleware.md`](../middleware.md) for the complete chain and execution order.
Copy file name to clipboardExpand all lines: docs/arch/03-transport-architecture.md
+8-10Lines changed: 8 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -226,9 +226,9 @@ graph LR
226
226
```
227
227
228
228
**Implementation:**
229
-
-`pkg/transport/types/transport.go` - MiddlewareFunction type
229
+
-`pkg/transport/types/transport.go` - `MiddlewareFunction` and `NamedMiddleware` types
230
230
- Middleware applied in reverse order (last registered = outermost)
231
-
- Each transport type accepts `[]MiddlewareFunction` in constructor
231
+
- Each transport type accepts `[]NamedMiddleware` in constructor (each wraps a `MiddlewareFunction` with its name for logging)
232
232
233
233
## Remote MCP Server Proxying
234
234
@@ -446,25 +446,23 @@ ToolHive uses two port concepts:
446
446
447
447
### MCP Environment Variables
448
448
449
-
**Implementation**: `pkg/transport/http.go`
449
+
**Implementation**: `pkg/environment/environment.go` sets `MCP_TRANSPORT`, `MCP_PORT`, and `FASTMCP_PORT` for the CLI/local path. `pkg/runtime/setup.go` sets all four variables (`MCP_TRANSPORT`, `MCP_PORT`, `FASTMCP_PORT`, and `MCP_HOST`) when deploying workloads through the runtime (used by both local and Kubernetes/proxy-runner paths). The `TargetHost` default of `127.0.0.1` (`transport.LocalhostIPv4`) is established by `WithTargetHost` in `pkg/runner/config_builder.go` (around line 204), not by the env-emitting code — both code paths simply read `RunConfig.TargetHost`.
450
450
451
451
Environment variables set automatically for container configuration:
452
452
453
453
-`MCP_TRANSPORT`: Transport type (stdio, sse, streamable-http)
454
454
-`MCP_PORT`: Target port (for SSE/Streamable HTTP)
455
-
-`MCP_HOST`: Target host - always `127.0.0.1` (both local and Kubernetes)
455
+
-`MCP_HOST`: Target host - defaults to `127.0.0.1` (`transport.LocalhostIPv4`), with the default applied by `WithTargetHost` in `pkg/runner/config_builder.go` when `RunConfig.TargetHost` is empty
456
456
-`FASTMCP_PORT`: Alias for `MCP_PORT` (legacy support)
457
457
458
458
**Architecture distinction:**
459
-
-**Target host** (`MCP_HOST` env var): Where containerlistens - always`127.0.0.1`
460
-
-**Proxy host**: Where proxy binds - `127.0.0.1` in local mode, `0.0.0.0` in Kubernetes for cluster access
459
+
-**Target host** (`MCP_HOST` env var): Where the container's MCP server listens - defaults to`127.0.0.1`
460
+
-**Proxy host**: Where the proxy binds - `127.0.0.1` in local mode, `0.0.0.0` in Kubernetes for cluster access
461
461
462
462
**Merge strategy**:
463
463
- User-provided values take precedence
464
464
- ToolHive sets deployment-appropriate defaults
465
465
466
-
**Reference**: PR #1890 - Runtime Authoring Guide
467
-
468
466
## Container Attach (Stdio Transport)
469
467
470
468
For stdio transport, ToolHive attaches to container stdin/stdout:
-`pkg/secrets/types.go` defines the `Provider` interface (the contract every provider implements) and the `EnvVarPrefix` constant (`"TOOLHIVE_SECRET_"`) used by the environment provider
30
32
31
33
### 1. Encrypted
32
34
@@ -68,7 +70,7 @@ MCPServer resources reference Kubernetes Secrets via `SecretRef`. Secrets are in
2.**OIDC Authentication (MCPOIDCConfig)**: OIDC client secrets for token introspection
82
-
-**CRD field**: `InlineOIDCSharedConfig.ClientSecretRef` in `cmd/thv-operator/api/v1beta1/mcpoidcconfig_types.go`
84
+
-**CRD field**: `spec.inline.clientSecretRef` on the `MCPOIDCConfig` resource (Go: `MCPOIDCConfig.Spec.Inline.ClientSecretRef`, where `Inline` is of type `*InlineOIDCSharedConfig`), defined in `cmd/thv-operator/api/v1beta1/mcpoidcconfig_types.go`
0 commit comments