Add thv vmcp serve and thv vmcp validate subcommands#4900
Conversation
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
There was a problem hiding this comment.
Pull request overview
Adds a new thv vmcp command group (Phase 2 of RFC THV-0059 / Fixes #4883) so users can run and validate a Virtual MCP Server locally, and updates generated CLI docs accordingly.
Changes:
- Introduce
cmd/thv/app/vmcp.gowithvmcp serveandvmcp validateCobra subcommands delegating topkg/vmcp/cli. - Register
vmcpin the root command and mark it as an “informational” command to bypass container runtime preflight. - Regenerate CLI reference docs to include
thv vmcpand its subcommands (and add several “superpowers” spec/plan documents).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/thv/app/vmcp.go | Adds thv vmcp command and serve/validate subcommands that delegate to pkg/vmcp/cli. |
| cmd/thv/app/commands.go | Registers vmcp in NewRootCmd() and adds it to informationalCommands. |
| docs/cli/thv.md | Updates CLI index to include thv vmcp. |
| docs/cli/thv_vmcp.md | Adds generated docs for thv vmcp. |
| docs/cli/thv_vmcp_serve.md | Adds generated docs for thv vmcp serve flags and description. |
| docs/cli/thv_vmcp_validate.md | Adds generated docs for thv vmcp validate flags and description. |
| docs/superpowers/specs/2026-04-13-auth-context-propagation-regression-test-design.md | Adds a design spec document (not directly related to vmcp CLI wiring). |
| docs/superpowers/specs/2026-04-09-vmcp-horizontal-scaling-tests-design.md | Adds a design spec document for scaling tests. |
| docs/superpowers/plans/2026-04-13-auth-context-propagation-regression-test.md | Adds an implementation plan document for a regression test. |
| docs/superpowers/plans/2026-04-09-vmcp-horizontal-scaling-tests.md | Adds an implementation plan document for scaling tests. |
| docs/superpowers/plans/2026-04-09-cache-api-cleanup.md | Adds an implementation plan document for cache API cleanup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
PR size has been reduced below the XL threshold. Thank you for splitting this up!
|
✅ PR size has been reduced below the XL threshold. The size review has been dismissed and this PR can now proceed with normal review. Thank you for splitting this up! |
There was a problem hiding this comment.
Pull request overview
Adds a new thv vmcp command group to the ToolHive CLI to expose vMCP (“Virtual MCP Server”) functionality as first-class thv subcommands, wiring Cobra flag parsing to the existing pkg/vmcp/cli implementations (Phase 2 of RFC THV-0059; fixes #4883).
Changes:
- Introduces
cmd/thv/app/vmcp.gowithvmcp serveandvmcp validatesubcommands that delegate topkg/vmcp/cli. - Registers
vmcpin the root command and marks it as informational to bypass container runtime preflight. - Regenerates CLI reference docs under
docs/cli/for the new command tree.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/thv/app/vmcp.go | Adds Cobra command constructors for thv vmcp, serve, and validate, delegating to pkg/vmcp/cli. |
| cmd/thv/app/commands.go | Registers the new vmcp command and adds it to the informational preflight-bypass list. |
| docs/cli/thv_vmcp.md | New autogenerated CLI documentation for thv vmcp. |
| docs/cli/thv_vmcp_serve.md | New autogenerated CLI documentation for thv vmcp serve and its flags. |
| docs/cli/thv_vmcp_validate.md | New autogenerated CLI documentation for thv vmcp validate and its flags. |
| docs/cli/thv.md | Updates top-level CLI docs to include the new vmcp command. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4900 +/- ##
==========================================
+ Coverage 69.35% 69.37% +0.01%
==========================================
Files 538 538
Lines 55458 55462 +4
==========================================
+ Hits 38464 38476 +12
+ Misses 14033 14030 -3
+ Partials 2961 2956 -5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR adds first-class thv vmcp support (Phase 2 of RFC THV-0059) by wiring new Cobra subcommands into the ToolHive CLI and regenerating the CLI reference docs, enabling users to run and validate a Virtual MCP Server locally.
Changes:
- Added
thv vmcpcommand withserveandvalidatesubcommands that delegate topkg/vmcp/cli(Serve/Validate). - Registered
vmcpin the root command and marked it as “informational” to bypass container runtime preflight/migrations. - Regenerated CLI documentation to include
thv vmcp,thv vmcp serve, andthv vmcp validate.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
cmd/thv/app/vmcp.go |
Introduces the vmcp command tree and flags; thin wrappers around pkg/vmcp/cli. |
cmd/thv/app/commands.go |
Registers vmcp on the root command and adds it to informationalCommands. |
docs/cli/thv_vmcp.md |
Adds generated reference for thv vmcp. |
docs/cli/thv_vmcp_serve.md |
Adds generated reference for thv vmcp serve flags/help text. |
docs/cli/thv_vmcp_validate.md |
Adds generated reference for thv vmcp validate flags/help text. |
docs/cli/thv.md |
Updates top-level command list to include vmcp. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
There was a problem hiding this comment.
Pull request overview
This PR wires the vMCP functionality into the thv CLI by adding a new top-level vmcp command with serve and validate subcommands, and regenerates CLI docs accordingly. It also adjusts when/how the “default” group is ensured to exist, to support vMCP discovery behavior across local vs Kubernetes runtimes.
Changes:
- Add
thv vmcp serveandthv vmcp validateCobra subcommands that delegate topkg/vmcp/cli. - Register
vmcpin the root command and mark it as informational (skips container runtime preflight). - Update default-group migration behavior (signature change + new call sites) and regenerate CLI documentation.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
cmd/thv/app/vmcp.go |
Adds the vmcp command plus serve/validate wrappers and flags. |
cmd/thv/app/commands.go |
Registers vmcp in NewRootCmd and adds it to informationalCommands. |
docs/cli/thv_vmcp.md |
New autogenerated CLI docs for thv vmcp. |
docs/cli/thv_vmcp_serve.md |
New autogenerated CLI docs for thv vmcp serve. |
docs/cli/thv_vmcp_validate.md |
New autogenerated CLI docs for thv vmcp validate. |
docs/cli/thv.md |
Adds vmcp to the root CLI docs index. |
pkg/vmcp/cli/serve.go |
Ensures default group existence in local dynamic discovery; skips in Kubernetes runtime. |
pkg/migration/migration.go |
Changes EnsureDefaultGroupExists to return an error and removes sync.Once wrapper. |
cmd/thv/app/server.go |
Ensures default group exists before starting the API server. |
cmd/thv/main.go |
Removes the startup call that ensured the default group existed for non-informational commands. |
Comments suppressed due to low confidence (1)
pkg/migration/migration.go:36
EnsureDefaultGroupExistsdoes anExistscheck and thenCreate, which can still race (two concurrent processes/goroutines can both observe non-existence and one will then fail with a conflict on create). To make this idempotent and robust, treatgroups.ErrGroupAlreadyExists(or HTTP 409) fromCreateas success, or prefer a create-first approach that ignores the already-exists case.
func ensureDefaultGroupExists(ctx context.Context) error {
groupManager, err := groups.NewManager()
if err != nil {
return err
}
exists, err := groupManager.Exists(ctx, groups.DefaultGroupName)
if err != nil {
return err
}
if exists {
return nil
}
slog.Debug("creating default group", "name", groups.DefaultGroupName)
return groupManager.Create(ctx, groups.DefaultGroupName)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Adds first-class thv vmcp serve and thv vmcp validate CLI subcommands (Phase 2 of RFC THV-0059), wiring Cobra flag parsing to the existing pkg/vmcp/cli entrypoints and updating generated CLI docs.
Changes:
- Introduce
cmd/thv/app/vmcp.gowithvmcp→serve/validatesubcommands delegating topkg/vmcp/cli. - Register
vmcpon the root command and classify it as “informational” to bypass container runtime preflight. - Adjust vMCP backend discovery + default-group migration flow (including making
EnsureDefaultGroupExistsreturn an error) and regenerate CLI docs.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/vmcp/cli/serve.go | Skips default-group migration in Kubernetes and treats missing MCPGroup as “no backends” in K8s runtime. |
| pkg/vmcp/aggregator/discoverer.go | Uses groups.ErrGroupNotFound as a wrapped sentinel for missing group detection. |
| pkg/migration/migration.go | Changes EnsureDefaultGroupExists to return an error (no longer logs internally). |
| cmd/thv/main.go | Handles migration error from EnsureDefaultGroupExists (logs + exits non-zero). |
| cmd/thv/app/server.go | Ensures default group exists before starting API server. |
| cmd/thv/app/vmcp.go | Adds thv vmcp, thv vmcp serve, and thv vmcp validate Cobra commands and flags. |
| cmd/thv/app/commands.go | Registers vmcp subcommand and marks it informational. |
| docs/cli/thv*.md | Regenerated CLI reference docs to include vmcp commands. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR introduces the new thv vmcp command tree (with serve and validate subcommands) and publishes the generated CLI docs, enabling users to run/validate vMCP configs via the thv binary (Phase 2 of RFC THV-0059 / Fixes #4883). It also adjusts default-group migration behavior and vMCP backend discovery semantics to better support Kubernetes environments.
Changes:
- Add
cmd/thv/app/vmcp.goimplementingthv vmcp serveandthv vmcp validateas thin Cobra wrappers aroundpkg/vmcp/cli. - Register the new command under the root CLI and update the “informational commands” gating to include
vmcp. - Update migration and vMCP discovery behavior (default group creation semantics + group-not-found handling) and regenerate CLI docs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/vmcp/cli/serve.go | Adjust vMCP backend discovery startup behavior (default group ensure; tolerate missing group in K8s). |
| pkg/vmcp/aggregator/discoverer.go | Return a typed/sentinel groups.ErrGroupNotFound so callers can errors.Is it. |
| pkg/migration/migration.go | Change default-group ensure to return error and no-op in Kubernetes. |
| cmd/thv/main.go | Handle EnsureDefaultGroupExists() errors and exit non-zero on failure. |
| cmd/thv/app/vmcp.go | New vmcp Cobra command with serve and validate subcommands and flags. |
| cmd/thv/app/commands.go | Register vmcp command and add it to informationalCommands. |
| docs/cli/thv_vmcp.md | Generated docs for thv vmcp. |
| docs/cli/thv_vmcp_serve.md | Generated docs for thv vmcp serve. |
| docs/cli/thv_vmcp_validate.md | Generated docs for thv vmcp validate. |
| docs/cli/thv.md | Add vmcp to top-level CLI docs index. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new thv vmcp command group to expose vMCP “serve” and “validate” functionality from the ToolHive CLI, wiring Cobra flag parsing to the existing pkg/vmcp/cli entrypoints and regenerating CLI reference docs. It also adjusts vMCP backend discovery and default-group initialization behavior to better support local and Kubernetes runtime scenarios.
Changes:
- Add
thv vmcpwithserveandvalidatesubcommands (thin wrappers overpkg/vmcp/cli). - Register
vmcpin the root command and treat it as “informational” to bypass container runtime preflight/migrations. - Update vMCP discovery/migration behavior (default group ensure + typed
ErrGroupNotFound) and regenerate CLI docs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/vmcp/cli/serve.go | Ensures default group in dynamic mode; treats missing group as zero backends in Kubernetes; imports migration. |
| pkg/vmcp/aggregator/discoverer.go | Wraps missing-group error with groups.ErrGroupNotFound for errors.Is handling. |
| pkg/migration/migration.go | Changes EnsureDefaultGroupExists to return an error and be a no-op in Kubernetes. |
| cmd/thv/main.go | Handles EnsureDefaultGroupExists() errors explicitly during startup migrations. |
| cmd/thv/app/vmcp.go | Adds vmcp, vmcp serve, and vmcp validate Cobra commands delegating to pkg/vmcp/cli. |
| cmd/thv/app/commands.go | Registers vmcp and adds it to the informational command set. |
| docs/cli/thv_vmcp.md | Generated CLI docs for thv vmcp. |
| docs/cli/thv_vmcp_serve.md | Generated CLI docs for thv vmcp serve. |
| docs/cli/thv_vmcp_validate.md | Generated CLI docs for thv vmcp validate. |
| docs/cli/thv.md | Adds vmcp to the generated command index. |
Comments suppressed due to low confidence (1)
pkg/vmcp/cli/serve.go:433
- In dynamic mode this calls
migration.EnsureDefaultGroupExists()(which itself creates agroups.Manager) and then immediately creates anothergroups.Managerviagroups.NewManager(). This duplicates initialization work (and in Kubernetes modegroups.NewManager()can be relatively heavy). Consider restructuring so the manager is constructed once and reused for the default-group check + discoverer creation (e.g., by passing a manager into the migration helper or moving the existence/create logic next to the singlegroups.NewManager()call).
slog.Info("dynamic mode: initializing group manager for backend discovery")
// EnsureDefaultGroupExists is a no-op in Kubernetes (service account has no
// create permission on MCPGroup CRDs). If the group does not exist,
// Discover returns ErrGroupNotFound which is handled below.
if err := migration.EnsureDefaultGroupExists(); err != nil {
return nil, nil, nil, fmt.Errorf("failed to ensure default group exists: %w", err)
}
groupsManager, err := groups.NewManager()
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to create groups manager: %w", err)
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Create cmd/thv/app/vmcp.go with newVMCPCommand(), newVMCPServeCommand(), and newVMCPValidateCommand() — thin wrappers that parse flags and delegate to pkg/vmcp/cli/Serve and pkg/vmcp/cli/Validate respectively. Register the command in NewRootCmd() and add "vmcp" to the informationalCommands map so it bypasses container runtime preflight. Regenerate CLI docs via task docs. This is Phase 2 of RFC THV-0059, making thv vmcp serve and thv vmcp validate available to users for the first time. Closes #4883
Summary
Create cmd/thv/app/vmcp.go with newVMCPCommand(), newVMCPServeCommand(), and newVMCPValidateCommand() — thin wrappers that parse flags and delegate to pkg/vmcp/cli/Serve and pkg/vmcp/cli/Validate respectively.
Register the command in NewRootCmd() and add "vmcp" to the informationalCommands map so it bypasses container runtime preflight. Regenerate CLI docs via task docs.
This is Phase 2 of RFC THV-0059, making thv vmcp serve and thv vmcp validate available to users for the first time.
Fixes #4883
Type of change
Test plan
task test)task test-e2e)task lint-fix)Changes
Does this introduce a user-facing change?
Implementation plan
Approved implementation plan
Special notes for reviewers