Skip to content

Commit da802a1

Browse files
authored
Fix and polish CLI help (#1226)
1. Adds the `mdx.format: md` hint to the generated markdown front matter for Docusarus to avoid issues with the MDX renderer failing on placeholders like "<path>" like we saw on v0.2.1 2. Polishes several of the longer CLI command synopses so they render more consistently on both the CLI help output and in the rendered Markdown. There are minor changes to indentation / line breaks in the CLI output to accommodate markdown rendering (like converting "real" tabs into code blocks) but I don't think it hurts the CLI experience at all. See screenshots below. 3. Stared polishing some of the help text for more consistent language.
1 parent e6a161c commit da802a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+418
-136
lines changed

cmd/help/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ description: %s
2222
last_update:
2323
author: autogenerated
2424
slug: %s
25+
mdx:
26+
format: md
2527
---
2628
2729
`

cmd/thv/app/client.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ var clientRegisterCmd = &cobra.Command{
3434
Use: "register [client]",
3535
Short: "Register a client for MCP server configuration",
3636
Long: `Register a client for MCP server configuration.
37-
Valid clients are:
37+
38+
Valid clients:
3839
- claude-code: Claude Code CLI
3940
- cline: Cline extension for VS Code
4041
- cursor: Cursor editor
@@ -51,7 +52,8 @@ var clientRemoveCmd = &cobra.Command{
5152
Use: "remove [client]",
5253
Short: "Remove a client from MCP server configuration",
5354
Long: `Remove a client from MCP server configuration.
54-
Valid clients are:
55+
56+
Valid clients:
5557
- claude-code: Claude Code CLI
5658
- cline: Cline extension for VS Code
5759
- cursor: Cursor editor

cmd/thv/app/export.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ func newExportCmd() *cobra.Command {
1616
Short: "Export a workload's run configuration to a file",
1717
Long: `Export a workload's run configuration to a file for sharing or backup.
1818
19-
The exported configuration can be used with 'thv run --from-config <path>' to recreate
20-
the same workload with identical settings.
19+
The exported configuration can be used with 'thv run --from-config <path>' to recreate
20+
the same workload with identical settings.
21+
22+
Examples:
2123
22-
Examples:
2324
# Export a workload configuration to a file
2425
thv export my-server ./my-server-config.json
2526

cmd/thv/app/otel.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ var setOtelEndpointCmd = &cobra.Command{
2121
Use: "set-endpoint <endpoint>",
2222
Short: "Set the OpenTelemetry endpoint URL",
2323
Long: `Set the OpenTelemetry OTLP endpoint URL for tracing and metrics.
24+
2425
This endpoint will be used by default when running MCP servers unless overridden by the --otel-endpoint flag.
2526
2627
Example:
27-
thv config otel set-endpoint https://api.honeycomb.io`,
28+
29+
thv config otel set-endpoint https://api.honeycomb.io`,
2830
Args: cobra.ExactArgs(1),
2931
RunE: setOtelEndpointCmdFunc,
3032
}
@@ -47,10 +49,12 @@ var setOtelSamplingRateCmd = &cobra.Command{
4749
Use: "set-sampling-rate <rate>",
4850
Short: "Set the OpenTelemetry sampling rate",
4951
Long: `Set the OpenTelemetry trace sampling rate (between 0.0 and 1.0).
52+
5053
This sampling rate will be used by default when running MCP servers unless overridden by the --otel-sampling-rate flag.
5154
5255
Example:
53-
thv config otel set-sampling-rate 0.1`,
56+
57+
thv config otel set-sampling-rate 0.1`,
5458
Args: cobra.ExactArgs(1),
5559
RunE: setOtelSamplingRateCmdFunc,
5660
}
@@ -73,10 +77,12 @@ var setOtelEnvVarsCmd = &cobra.Command{
7377
Use: "set-env-vars <var1,var2,...>",
7478
Short: "Set the OpenTelemetry environment variables",
7579
Long: `Set the list of environment variable names to include in OpenTelemetry spans.
80+
7681
These environment variables will be used by default when running MCP servers unless overridden by the --otel-env-vars flag.
7782
7883
Example:
79-
thv config otel set-env-vars USER,HOME,PATH`,
84+
85+
thv config otel set-env-vars USER,HOME,PATH`,
8086
Args: cobra.ExactArgs(1),
8187
RunE: setOtelEnvVarsCmdFunc,
8288
}

cmd/thv/app/proxy.go

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,46 +28,55 @@ var proxyCmd = &cobra.Command{
2828
Use: "proxy [flags] SERVER_NAME",
2929
Short: "Create a transparent proxy for an MCP server with authentication support",
3030
Long: `Create a transparent HTTP proxy that forwards requests to an MCP server endpoint.
31+
3132
This command starts a standalone proxy without creating a workload, providing:
3233
33-
• Transparent request forwarding to the target MCP server
34-
• Optional OAuth/OIDC authentication to remote MCP servers
35-
• Automatic authentication detection via WWW-Authenticate headers
36-
• OIDC-based access control for incoming proxy requests
37-
• Secure credential handling via files or environment variables
34+
- Transparent request forwarding to the target MCP server
35+
- Optional OAuth/OIDC authentication to remote MCP servers
36+
- Automatic authentication detection via WWW-Authenticate headers
37+
- OIDC-based access control for incoming proxy requests
38+
- Secure credential handling via files or environment variables
39+
40+
#### Authentication modes
3841
39-
AUTHENTICATION MODES:
4042
The proxy supports multiple authentication scenarios:
4143
4244
1. No Authentication: Simple transparent forwarding
4345
2. Outgoing Authentication: Authenticate to remote MCP servers using OAuth/OIDC
4446
3. Incoming Authentication: Protect the proxy endpoint with OIDC validation
4547
4. Bidirectional: Both incoming and outgoing authentication
4648
47-
OAUTH CLIENT SECRET SOURCES:
49+
#### OAuth client secret sources
50+
4851
OAuth client secrets can be provided via (in order of precedence):
52+
4953
1. --remote-auth-client-secret flag (not recommended for production)
5054
2. --remote-auth-client-secret-file flag (secure file-based approach)
5155
3. ` + envOAuthClientSecret + ` environment variable
5256
53-
EXAMPLES:
54-
# Basic transparent proxy
55-
thv proxy my-server --target-uri http://localhost:8080
57+
#### Examples
58+
59+
Basic transparent proxy:
60+
61+
thv proxy my-server --target-uri http://localhost:8080
62+
63+
Proxy with OAuth authentication to remote server:
64+
65+
thv proxy my-server --target-uri https://api.example.com \
66+
--remote-auth --remote-auth-issuer https://auth.example.com \
67+
--remote-auth-client-id my-client-id \
68+
--remote-auth-client-secret-file /path/to/secret
69+
70+
Proxy with OIDC protection for incoming requests:
5671
57-
# Proxy with OAuth authentication to remote server
58-
thv proxy my-server --target-uri https://api.example.com \
59-
--remote-auth --remote-auth-issuer https://auth.example.com \
60-
--remote-auth-client-id my-client-id \
61-
--remote-auth-client-secret-file /path/to/secret
72+
thv proxy my-server --target-uri http://localhost:8080 \
73+
--oidc-issuer https://auth.example.com \
74+
--oidc-audience my-audience
6275
63-
# Proxy with OIDC protection for incoming requests
64-
thv proxy my-server --target-uri http://localhost:8080 \
65-
--oidc-issuer https://auth.example.com \
66-
--oidc-audience my-audience
76+
Auto-detect authentication requirements:
6777
68-
# Auto-detect authentication requirements
69-
thv proxy my-server --target-uri https://protected-api.com \
70-
--remote-auth-client-id my-client-id`,
78+
thv proxy my-server --target-uri https://protected-api.com \
79+
--remote-auth-client-id my-client-id`,
7180
Args: cobra.ExactArgs(1),
7281
RunE: proxyCmdFunc,
7382
}

cmd/thv/app/run.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,34 @@ var runCmd = &cobra.Command{
2727
ToolHive supports four ways to run an MCP server:
2828
2929
1. From the registry:
30-
$ thv run server-name [-- args...]
30+
31+
$ thv run server-name [-- args...]
32+
3133
Looks up the server in the registry and uses its predefined settings
3234
(transport, permissions, environment variables, etc.)
3335
3436
2. From a container image:
35-
$ thv run ghcr.io/example/mcp-server:latest [-- args...]
37+
38+
$ thv run ghcr.io/example/mcp-server:latest [-- args...]
39+
3640
Runs the specified container image directly with the provided arguments
3741
3842
3. Using a protocol scheme:
39-
$ thv run uvx://package-name [-- args...]
40-
$ thv run npx://package-name [-- args...]
41-
$ thv run go://package-name [-- args...]
42-
$ thv run go://./local-path [-- args...]
43+
44+
$ thv run uvx://package-name [-- args...]
45+
$ thv run npx://package-name [-- args...]
46+
$ thv run go://package-name [-- args...]
47+
$ thv run go://./local-path [-- args...]
48+
4349
Automatically generates a container that runs the specified package
4450
using either uvx (Python with uv package manager), npx (Node.js),
4551
or go (Golang). For Go, you can also specify local paths starting
4652
with './' or '../' to build and run local Go projects.
4753
4854
4. From an exported configuration:
49-
$ thv run --from-config <path>
55+
56+
$ thv run --from-config <path>
57+
5058
Runs an MCP server using a previously exported configuration file.
5159
5260
The container will be started with the specified transport mode and

cmd/thv/app/secret.go

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ func newSecretCommand() *cobra.Command {
1919
cmd := &cobra.Command{
2020
Use: "secret",
2121
Short: "Manage secrets",
22-
Long: "The secret command provides subcommands to set, get, delete, and list secrets.",
22+
Long: `Manage secrets using the configured secrets provider.
23+
24+
The secret command provides subcommands to configure, store, retrieve, and manage secrets securely.
25+
26+
Run "thv secret setup" first to configure a secrets provider before using any secret operations.`,
2327
}
2428

2529
cmd.AddCommand(
@@ -38,12 +42,18 @@ func newSecretCommand() *cobra.Command {
3842
func newSecretProviderCommand() *cobra.Command {
3943
return &cobra.Command{
4044
Use: "provider <name>",
41-
Short: "Configure the secrets provider directly",
42-
Long: `For most users, it is recommended to use "thv secret setup" instead.
43-
Configure the secrets provider.
44-
Valid secrets providers are:
45-
- encrypted: Full read-write secrets provider
46-
- 1password: Read-only secrets provider`,
45+
Short: "Set the secrets provider directly",
46+
Long: `Configure the secrets provider directly.
47+
48+
Note: The "thv secret setup" command is recommended for interactive configuration.
49+
50+
Use this command to set the secrets provider directly without interactive prompts,
51+
making it suitable for scripted deployments and automation.
52+
53+
Valid secrets providers:
54+
- encrypted: Full read-write secrets provider using AES-256-GCM encryption
55+
- 1password: Read-only secrets provider (requires OP_SERVICE_ACCOUNT_TOKEN)
56+
- none: Disables secrets functionality`,
4757
Args: cobra.ExactArgs(1),
4858
RunE: func(_ *cobra.Command, args []string) error {
4959
provider := args[0]
@@ -57,15 +67,17 @@ func newSecretSetupCommand() *cobra.Command {
5767
Use: "setup",
5868
Short: "Set up secrets provider",
5969
Long: fmt.Sprintf(`Interactive setup for configuring a secrets provider.
60-
This command will guide you through selecting and configuring
61-
a secrets provider for storing and retrieving secrets.
70+
71+
This command guides you through selecting and configuring a secrets provider
72+
for storing and retrieving secrets. The setup process validates your
73+
configuration and ensures the selected provider initializes properly.
6274
6375
Available providers:
64-
- %s: Stores secrets in an encrypted file using AES-256-GCM using the OS Keyring
65-
- %s: Read-only access to 1Password secrets (requires OP_SERVICE_ACCOUNT_TOKEN)
76+
- %s: Stores secrets in an encrypted file using AES-256-GCM using the OS keyring
77+
- %s: Read-only access to 1Password secrets (requires OP_SERVICE_ACCOUNT_TOKEN environment variable)
6678
- %s: Disables secrets functionality
6779
68-
You must run this command before using any other secrets functionality.`,
80+
Run this command before using any other secrets functionality.`,
6981
string(secrets.EncryptedType), string(secrets.OnePasswordType), string(secrets.NoneType)), //nolint:gofmt,gci
7082
Args: cobra.NoArgs,
7183
RunE: runSecretsSetup,
@@ -76,21 +88,29 @@ func newSecretSetCommand() *cobra.Command {
7688
return &cobra.Command{
7789
Use: "set <name>",
7890
Short: "Set a secret",
79-
Long: `Set a secret with the given name.
80-
81-
Input Methods:
82-
- Piped Input: If data is piped to the command, the secret value will be read from stdin.
83-
Examples:
84-
echo "my-secret-value" | thv secret set my-secret
85-
cat secret-file.txt | thv secret set my-secret
86-
87-
- Interactive Input: If no data is piped, you will be prompted to enter the secret value securely
88-
(input will be hidden).
89-
Example:
90-
thv secret set my-secret
91-
Enter secret value (input will be hidden): _
92-
93-
The secret will be stored securely using the configured secrets provider.`,
91+
Long: `Create or update a secret with the specified name.
92+
93+
This command supports two input methods for maximum flexibility:
94+
95+
Piped input:
96+
97+
When you pipe data to the command, it reads the secret value from stdin.
98+
Examples:
99+
100+
$ echo "my-secret-value" | thv secret set my-secret
101+
$ cat secret-file.txt | thv secret set my-secret
102+
103+
Interactive input:
104+
105+
When you don't pipe data, the command prompts you to enter the secret value securely.
106+
The input remains hidden for security.
107+
Example:
108+
109+
$ thv secret set my-secret
110+
Enter secret value (input will be hidden): _
111+
112+
The command stores the secret securely using your configured secrets provider.
113+
Note that some providers (like 1Password) are read-only and do not support setting secrets.`,
94114
Args: cobra.ExactArgs(1),
95115
Run: func(cmd *cobra.Command, args []string) {
96116
name := args[0]
@@ -166,7 +186,14 @@ func newSecretGetCommand() *cobra.Command {
166186
return &cobra.Command{
167187
Use: "get <name>",
168188
Short: "Get a secret",
169-
Args: cobra.ExactArgs(1),
189+
Long: `Retrieve and display the value of a secret by name.
190+
191+
This command fetches the specified secret from your configured secrets provider
192+
and displays its value. The secret value prints to stdout, making it
193+
suitable for use in scripts or command substitution.
194+
195+
The secret must exist in your configured secrets provider, otherwise the command returns an error.`,
196+
Args: cobra.ExactArgs(1),
170197
Run: func(cmd *cobra.Command, args []string) {
171198
ctx := cmd.Context()
172199
name := args[0]
@@ -197,7 +224,14 @@ func newSecretDeleteCommand() *cobra.Command {
197224
return &cobra.Command{
198225
Use: "delete <name>",
199226
Short: "Delete a secret",
200-
Args: cobra.ExactArgs(1),
227+
Long: `Remove a secret from the configured secrets provider.
228+
229+
This command permanently deletes the specified secret from your secrets provider.
230+
Once you delete a secret, you cannot recover it unless you have a backup.
231+
232+
Note that some secrets providers may not support deletion operations.
233+
If your provider is read-only or doesn't support deletion, this command returns an error.`,
234+
Args: cobra.ExactArgs(1),
201235
Run: func(cmd *cobra.Command, args []string) {
202236
ctx := cmd.Context()
203237
name := args[0]
@@ -235,7 +269,11 @@ func newSecretListCommand() *cobra.Command {
235269
return &cobra.Command{
236270
Use: "list",
237271
Short: "List all available secrets",
238-
Args: cobra.NoArgs,
272+
Long: `Display all secrets available in the configured secrets provider.
273+
274+
This command shows the names of all secrets stored in your secrets provider.
275+
If descriptions exist for the secrets, the command displays them alongside the names.`,
276+
Args: cobra.NoArgs,
239277
Run: func(cmd *cobra.Command, _ []string) {
240278
ctx := cmd.Context()
241279
manager, err := getSecretsManager()
@@ -278,8 +316,23 @@ func newSecretListCommand() *cobra.Command {
278316
func newSecretResetKeyringCommand() *cobra.Command {
279317
return &cobra.Command{
280318
Use: "reset-keyring",
281-
Short: "Reset the keyring secret",
282-
Args: cobra.NoArgs,
319+
Short: "Reset the keyring password",
320+
Long: `Reset the keyring password used to encrypt secrets.
321+
322+
This command resets the master password stored in your OS keyring that
323+
encrypts and decrypts secrets when using the 'encrypted' secrets provider.
324+
325+
Use this command if:
326+
- You've forgotten your keyring password
327+
- You want to change your encryption password
328+
- Your keyring has become corrupted
329+
330+
Warning: Resetting the keyring password makes any existing encrypted secrets
331+
inaccessible unless you remember the previous password. You will need to set up
332+
your secrets again after resetting.
333+
334+
This command only works with the 'encrypted' secrets provider.`,
335+
Args: cobra.NoArgs,
283336
Run: func(_ *cobra.Command, _ []string) {
284337
if err := secrets.ResetKeyringSecret(); err != nil {
285338
fmt.Fprintf(os.Stderr, "Failed to reset keyring secret: %v\n", err)

docs/cli/thv.md

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)