Skip to content

thv llm subcommand for LLM gateway authentication #5016

Description

@jerm-dro

User Story

As a developer using AI coding tools in an enterprise environment,
I want ToolHive to automatically configure my tools to authenticate with our OIDC-protected LLM gateway,
So that I don't have to manually manage tokens or deal with silent failures when they expire.

Context

RFC-0070 (stacklok/toolhive-rfcs#70) proposes a thv llm command group with two authentication modes:

  • Proxy mode — localhost reverse proxy for static-key-only tools (Cursor, VS Code, Xcode) that injects fresh OIDC tokens
  • Token helper modethv llm token prints a fresh JWT for OIDC-capable tools (Claude Code, Gemini CLI)

A single thv llm setup command detects installed tools, configures them, starts the proxy, and handles OIDC login.

Acceptance Criteria

Setup & teardown lifecycle

  • AT: thv llm setup --gateway-url <url> --issuer <issuer> --client-id <id> detects installed AI tools, configures each for the gateway, starts the background proxy if any proxy-mode tool is detected, and triggers the OIDC browser login
  • AT: thv llm teardown removes gateway configuration from all tool config files, stops the background proxy, and optionally purges cached OIDC tokens with --purge-tokens
  • AT: thv llm teardown <tool-name> targets a single tool without affecting others

Proxy mode (static-key tools)

  • AT: The localhost proxy accepts requests on http://localhost:<port>/v1, strips the incoming Authorization header, injects a fresh OIDC bearer token, and forwards to the upstream gateway — preserving the original request path, query string, headers, and body
  • AT: The proxy passes through upstream responses faithfully — including SSE streaming (chat completions), non-streaming JSON (embeddings, completions), and error responses (4xx/5xx) — without buffering or modifying response bodies
  • Unit: Proxy rejects startup if the listen address is not a loopback interface. No AT because loopback validation is a startup guard with no observable e2e behavior beyond a failed start.

Token helper mode (OIDC-capable tools)

  • AT: thv llm token prints a fresh JWT to stdout (all other output on stderr) suitable for use as a tool's apiKeyHelper or auth.command
  • Unit: thv llm token exits with an error in non-interactive mode when no cached or refreshable token exists — it never launches a browser flow. No AT because this is a flag-gated code path tested without external dependencies.

Token lifecycle

  • Unit: Token source uses a three-tier strategy: in-memory cache → secrets-provider refresh token → browser OIDC+PKCE flow, with preemptive refresh 30s before expiry. No AT because all three tiers are tested with mocked OIDC provider and secrets provider.
  • Access tokens are held in memory only and never written to disk or logged
  • Refresh tokens are stored via ToolHive's existing secrets provider (OS keyring / encrypted file fallback)

Configuration management

  • thv llm config set persists gateway URL, OIDC settings, and proxy port to config.yaml under the llm: key
  • thv llm config show displays current LLM config; --output json produces valid JSON
  • thv llm config reset clears all LLM config and deletes cached tokens from the secrets provider
  • thv llm proxy start runs the proxy in the foreground with full log output (debugging aid)

Tool support

  • Claude Code is supported as a direct-mode (token helper) tool — setup patches apiKeyHelper and base URL in ~/.claude/settings.json
  • Gemini CLI is supported as a direct-mode (token helper) tool — setup patches the token command and base URL in Gemini CLI's config
  • Cursor is supported as a proxy-mode tool — setup patches base URL and placeholder API key in Cursor's config
  • VS Code (GitHub Copilot) is supported as a proxy-mode tool — setup patches base URL and placeholder API key in VS Code's settings
  • Apple Xcode is supported as a proxy-mode tool — setup patches base URL and placeholder API key in Xcode's config
  • Adding a new tool requires only implementing Detect/Apply/Revert functions and registering in the tool registry — no changes to setup/teardown orchestration, proxy, or token source

References

Metadata

Metadata

Assignees

Labels

authenticationcliChanges that impact CLI functionalityenhancementNew feature or requestgoPull requests that update go code
No fields configured for Story 🗺️.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions