diff --git a/cmd/thv-operator/controllers/mcpserver_resource_overrides_test.go b/cmd/thv-operator/controllers/mcpserver_resource_overrides_test.go index 5bcb9f5ac1..93a0fc9cce 100644 --- a/cmd/thv-operator/controllers/mcpserver_resource_overrides_test.go +++ b/cmd/thv-operator/controllers/mcpserver_resource_overrides_test.go @@ -647,7 +647,8 @@ func TestDeploymentForMCPServer_PodTemplateOverridesPreserveRunConfigChecksum(t }, } - deployment := r.deploymentForMCPServer(t.Context(), mcpServer, "C1") + deployment, err := r.deploymentForMCPServer(t.Context(), mcpServer, "C1") + require.NoError(t, err) require.NotNil(t, deployment) assert.Equal(t, "C1", @@ -688,7 +689,8 @@ func TestDeploymentNeedsUpdate_StableAfterBuildWithPodTemplateOverrides(t *testi } const runConfigChecksum = "stable-checksum" - built := r.deploymentForMCPServer(t.Context(), mcpServer, runConfigChecksum) + built, err := r.deploymentForMCPServer(t.Context(), mcpServer, runConfigChecksum) + require.NoError(t, err) require.NotNil(t, built) // Constructor and comparator must agree on the same input — otherwise the diff --git a/cmd/thv/app/llm.go b/cmd/thv/app/llm.go index 1ee1c5bd28..88cd45d1af 100644 --- a/cmd/thv/app/llm.go +++ b/cmd/thv/app/llm.go @@ -24,13 +24,12 @@ import ( func newLLMCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "llm", - Hidden: true, - Short: "Manage LLM gateway authentication", + Use: "llm", + Short: "Manage LLM gateway authentication", Long: `Configure and manage authentication for OIDC-protected LLM gateways. The llm command bridges AI coding tools to LLM gateways by handling OIDC -authentication transparently. Two modes are planned: +authentication transparently. Two modes are supported: Proxy mode — a localhost reverse proxy injects fresh tokens for tools that only accept static API keys (e.g. Cursor). @@ -476,13 +475,12 @@ func runLLMProxyForeground(ctx context.Context, llmCfg *llm.Config) error { return p.Start(ctx) } -// ── token helper (hidden) ───────────────────────────────────────────────────── +// ── token helper ────────────────────────────────────────────────────────────── func newLLMTokenCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "token", - Hidden: true, - Short: "Print a fresh LLM gateway access token to stdout", + Use: "token", + Short: "Print a fresh LLM gateway access token to stdout", Long: `Print a fresh OIDC access token to stdout (all other output on stderr). Intended for use as apiKeyHelper or auth.command in OIDC-capable AI tools. Runs non-interactively — will not launch a browser flow.`, diff --git a/docs/cli/thv.md b/docs/cli/thv.md index bc0975da92..2749ca7656 100644 --- a/docs/cli/thv.md +++ b/docs/cli/thv.md @@ -42,6 +42,7 @@ thv [flags] * [thv group](thv_group.md) - Manage logical groupings of MCP servers * [thv inspector](thv_inspector.md) - Launches the MCP Inspector UI and connects it to the specified MCP server * [thv list](thv_list.md) - List running MCP servers +* [thv llm](thv_llm.md) - Manage LLM gateway authentication * [thv logs](thv_logs.md) - Output the logs of an MCP server or manage log files * [thv mcp](thv_mcp.md) - Interact with MCP servers for debugging * [thv proxy](thv_proxy.md) - Create a transparent proxy for an MCP server with authentication support diff --git a/docs/cli/thv_llm.md b/docs/cli/thv_llm.md new file mode 100644 index 0000000000..b39471c6f0 --- /dev/null +++ b/docs/cli/thv_llm.md @@ -0,0 +1,57 @@ +--- +title: thv llm +hide_title: true +description: Reference for ToolHive CLI command `thv llm` +last_update: + author: autogenerated +slug: thv_llm +mdx: + format: md +--- + +## thv llm + +Manage LLM gateway authentication + +### Synopsis + +Configure and manage authentication for OIDC-protected LLM gateways. + +The llm command bridges AI coding tools to LLM gateways by handling OIDC +authentication transparently. Two modes are supported: + + Proxy mode — a localhost reverse proxy injects fresh tokens for tools + that only accept static API keys (e.g. Cursor). + Token helper — "thv llm token" prints a fresh JWT suitable for use as + apiKeyHelper or auth.command in OIDC-capable tools + (e.g. Claude Code). + +To configure the gateway connection settings, use: + + thv llm config set --gateway-url https://llm.example.com \ + --issuer https://auth.example.com \ + --client-id my-client-id + +Use "thv llm config show" to view the current configuration. + +### Options + +``` + -h, --help help for llm +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv](thv.md) - ToolHive (thv) is a lightweight, secure, and fast manager for MCP servers +* [thv llm config](thv_llm_config.md) - Manage LLM gateway configuration +* [thv llm proxy](thv_llm_proxy.md) - Manage the LLM gateway localhost proxy +* [thv llm setup](thv_llm_setup.md) - Configure detected AI tools to use the LLM gateway +* [thv llm teardown](thv_llm_teardown.md) - Remove LLM gateway configuration from all (or one) configured tools +* [thv llm token](thv_llm_token.md) - Print a fresh LLM gateway access token to stdout + diff --git a/docs/cli/thv_llm_config.md b/docs/cli/thv_llm_config.md new file mode 100644 index 0000000000..bd8e654372 --- /dev/null +++ b/docs/cli/thv_llm_config.md @@ -0,0 +1,38 @@ +--- +title: thv llm config +hide_title: true +description: Reference for ToolHive CLI command `thv llm config` +last_update: + author: autogenerated +slug: thv_llm_config +mdx: + format: md +--- + +## thv llm config + +Manage LLM gateway configuration + +### Synopsis + +The config command provides subcommands to manage LLM gateway connection settings. + +### Options + +``` + -h, --help help for config +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm](thv_llm.md) - Manage LLM gateway authentication +* [thv llm config reset](thv_llm_config_reset.md) - Clear all LLM gateway configuration and cached tokens +* [thv llm config set](thv_llm_config_set.md) - Set LLM gateway connection settings +* [thv llm config show](thv_llm_config_show.md) - Display current LLM gateway configuration + diff --git a/docs/cli/thv_llm_config_reset.md b/docs/cli/thv_llm_config_reset.md new file mode 100644 index 0000000000..9b5402f9a3 --- /dev/null +++ b/docs/cli/thv_llm_config_reset.md @@ -0,0 +1,40 @@ +--- +title: thv llm config reset +hide_title: true +description: Reference for ToolHive CLI command `thv llm config reset` +last_update: + author: autogenerated +slug: thv_llm_config_reset +mdx: + format: md +--- + +## thv llm config reset + +Clear all LLM gateway configuration and cached tokens + +### Synopsis + +Remove all LLM gateway settings from config.yaml and delete cached OIDC +tokens from the secrets provider. + +``` +thv llm config reset [flags] +``` + +### Options + +``` + -h, --help help for reset +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm config](thv_llm_config.md) - Manage LLM gateway configuration + diff --git a/docs/cli/thv_llm_config_set.md b/docs/cli/thv_llm_config_set.md new file mode 100644 index 0000000000..2d5a89afbc --- /dev/null +++ b/docs/cli/thv_llm_config_set.md @@ -0,0 +1,52 @@ +--- +title: thv llm config set +hide_title: true +description: Reference for ToolHive CLI command `thv llm config set` +last_update: + author: autogenerated +slug: thv_llm_config_set +mdx: + format: md +--- + +## thv llm config set + +Set LLM gateway connection settings + +### Synopsis + +Persist LLM gateway connection settings to config.yaml. + +Example: + thv llm config set \ + --gateway-url https://llm.example.com \ + --issuer https://auth.example.com \ + --client-id my-client-id + +``` +thv llm config set [flags] +``` + +### Options + +``` + --audience string OIDC audience (optional) + --callback-port int OIDC callback port (omit to keep current; default: ephemeral) + --client-id string OIDC client ID + --gateway-url string LLM gateway base URL (must use HTTPS) + -h, --help help for set + --issuer string OIDC issuer URL + --proxy-port int Localhost proxy listen port (omit to keep current; default: 14000) + --tls-skip-verify Skip TLS certificate verification for the upstream gateway (local dev only; use --tls-skip-verify=false to clear) +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm config](thv_llm_config.md) - Manage LLM gateway configuration + diff --git a/docs/cli/thv_llm_config_show.md b/docs/cli/thv_llm_config_show.md new file mode 100644 index 0000000000..f1e48b7c86 --- /dev/null +++ b/docs/cli/thv_llm_config_show.md @@ -0,0 +1,36 @@ +--- +title: thv llm config show +hide_title: true +description: Reference for ToolHive CLI command `thv llm config show` +last_update: + author: autogenerated +slug: thv_llm_config_show +mdx: + format: md +--- + +## thv llm config show + +Display current LLM gateway configuration + +``` +thv llm config show [flags] +``` + +### Options + +``` + --format string Output format (json, text) (default "text") + -h, --help help for show +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm config](thv_llm_config.md) - Manage LLM gateway configuration + diff --git a/docs/cli/thv_llm_proxy.md b/docs/cli/thv_llm_proxy.md new file mode 100644 index 0000000000..bdb8a3f38b --- /dev/null +++ b/docs/cli/thv_llm_proxy.md @@ -0,0 +1,32 @@ +--- +title: thv llm proxy +hide_title: true +description: Reference for ToolHive CLI command `thv llm proxy` +last_update: + author: autogenerated +slug: thv_llm_proxy +mdx: + format: md +--- + +## thv llm proxy + +Manage the LLM gateway localhost proxy + +### Options + +``` + -h, --help help for proxy +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm](thv_llm.md) - Manage LLM gateway authentication +* [thv llm proxy start](thv_llm_proxy_start.md) - Start the LLM gateway localhost proxy + diff --git a/docs/cli/thv_llm_proxy_start.md b/docs/cli/thv_llm_proxy_start.md new file mode 100644 index 0000000000..77b9e58ee2 --- /dev/null +++ b/docs/cli/thv_llm_proxy_start.md @@ -0,0 +1,46 @@ +--- +title: thv llm proxy start +hide_title: true +description: Reference for ToolHive CLI command `thv llm proxy start` +last_update: + author: autogenerated +slug: thv_llm_proxy_start +mdx: + format: md +--- + +## thv llm proxy start + +Start the LLM gateway localhost proxy + +### Synopsis + +Start a localhost reverse proxy that injects fresh OIDC tokens for AI tools +that only accept static API keys (e.g. Cursor). + +The proxy runs in the foreground and blocks until interrupted (Ctrl+C). +To run it in the background, use your shell or a process manager: + + thv llm proxy start & + +``` +thv llm proxy start [flags] +``` + +### Options + +``` + -h, --help help for start + --tls-skip-verify Skip TLS certificate verification for the upstream gateway (overrides stored config; local dev only) +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm proxy](thv_llm_proxy.md) - Manage the LLM gateway localhost proxy + diff --git a/docs/cli/thv_llm_setup.md b/docs/cli/thv_llm_setup.md new file mode 100644 index 0000000000..95d19b0103 --- /dev/null +++ b/docs/cli/thv_llm_setup.md @@ -0,0 +1,64 @@ +--- +title: thv llm setup +hide_title: true +description: Reference for ToolHive CLI command `thv llm setup` +last_update: + author: autogenerated +slug: thv_llm_setup +mdx: + format: md +--- + +## thv llm setup + +Configure detected AI tools to use the LLM gateway + +### Synopsis + +Detect installed AI coding tools (Claude Code, Gemini CLI, Cursor, VS Code, +Xcode) and patch each tool's configuration to route through the LLM gateway. + +Token-helper tools (Claude Code, Gemini CLI) are configured to call +"thv llm token" to obtain a fresh OIDC token on demand. + +Proxy-mode tools (Cursor, VS Code, Xcode) are configured to send requests to +the localhost reverse proxy started by "thv llm proxy start". + +Use --client to configure only a single named tool instead of all detected +tools. An error is returned if the named client is not installed. + +Inline flags (--gateway-url, --issuer, --client-id, etc.) are applied for this +run and persisted to config only after login and tool patching succeed. This +lets you combine "config set" and "setup" into a single command. + +Run "thv llm teardown" to revert all changes. + +``` +thv llm setup [flags] +``` + +### Options + +``` + --anthropic-path-prefix string Path prefix appended to the gateway URL when writing ANTHROPIC_BASE_URL for direct-mode tools (e.g. /anthropic). When omitted, the gateway is probed automatically. + --audience string OIDC audience (optional) + --callback-port int OIDC callback port (omit to keep current; default: ephemeral) + --client string Configure only this AI tool by name (e.g. claude-code, cursor). Omit to configure all detected tools. + --client-id string OIDC client ID + --gateway-url string LLM gateway base URL (must use HTTPS) + -h, --help help for setup + --issuer string OIDC issuer URL + --proxy-port int Localhost proxy listen port (omit to keep current; default: 14000) + --tls-skip-verify Skip TLS certificate verification for the upstream gateway (local dev only). For direct-mode tools (Claude Code, Gemini CLI) this sets NODE_TLS_REJECT_UNAUTHORIZED=0, disabling TLS for ALL of that tool's outbound connections. For proxy-mode tools only the proxy-to-gateway connection is affected. +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm](thv_llm.md) - Manage LLM gateway authentication + diff --git a/docs/cli/thv_llm_teardown.md b/docs/cli/thv_llm_teardown.md new file mode 100644 index 0000000000..5a91facb85 --- /dev/null +++ b/docs/cli/thv_llm_teardown.md @@ -0,0 +1,45 @@ +--- +title: thv llm teardown +hide_title: true +description: Reference for ToolHive CLI command `thv llm teardown` +last_update: + author: autogenerated +slug: thv_llm_teardown +mdx: + format: md +--- + +## thv llm teardown + +Remove LLM gateway configuration from all (or one) configured tools + +### Synopsis + +Revert the configuration changes made by "thv llm setup" for all configured +tools, or for a single tool when tool-name is provided as a positional argument +or via --client. + +Use --purge-tokens to also remove cached OIDC tokens from the secrets provider. + +``` +thv llm teardown [tool-name] [flags] +``` + +### Options + +``` + --client string Remove configuration for only this AI tool by name (e.g. claude-code, cursor). Omit to revert all configured tools. + -h, --help help for teardown + --purge-tokens Also delete cached OIDC tokens from the secrets provider +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm](thv_llm.md) - Manage LLM gateway authentication + diff --git a/docs/cli/thv_llm_token.md b/docs/cli/thv_llm_token.md new file mode 100644 index 0000000000..b5a175b985 --- /dev/null +++ b/docs/cli/thv_llm_token.md @@ -0,0 +1,41 @@ +--- +title: thv llm token +hide_title: true +description: Reference for ToolHive CLI command `thv llm token` +last_update: + author: autogenerated +slug: thv_llm_token +mdx: + format: md +--- + +## thv llm token + +Print a fresh LLM gateway access token to stdout + +### Synopsis + +Print a fresh OIDC access token to stdout (all other output on stderr). +Intended for use as apiKeyHelper or auth.command in OIDC-capable AI tools. +Runs non-interactively — will not launch a browser flow. + +``` +thv llm token [flags] +``` + +### Options + +``` + -h, --help help for token +``` + +### Options inherited from parent commands + +``` + --debug Enable debug mode +``` + +### SEE ALSO + +* [thv llm](thv_llm.md) - Manage LLM gateway authentication + diff --git a/pkg/llm/tokensource.go b/pkg/llm/tokensource.go index c8dcca1fc2..7661ed3a34 100644 --- a/pkg/llm/tokensource.go +++ b/pkg/llm/tokensource.go @@ -19,7 +19,7 @@ import ( // refresh token is persisted for subsequent non-interactive calls. var ErrTokenRequired = errors.New( "LLM gateway authentication required: no cached credentials found; " + - "complete an interactive login first (\"thv llm setup\" — coming soon)", + "run \"thv llm setup\" to log in", ) // TokenRefUpdater is a callback invoked when the refresh token changes — either