Skip to content

Commit 42267da

Browse files
Document local vMCP CLI mode for toolhive v0.24.0
thv vmcp serve/validate/init became user-visible in v0.24.0. Add a local CLI mode guide covering quick mode, config-file mode, optimizer tiers, and audit logging, plus cross-links from the vMCP index, intro, and concept pages.
1 parent 9e190bd commit 42267da

6 files changed

Lines changed: 267 additions & 11 deletions

File tree

SUMMARY.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Summary of changes
2+
3+
- Added `docs/toolhive/guides-vmcp/local-cli.mdx` documenting the new local
4+
vMCP CLI mode (`thv vmcp serve`/`init`/`validate`), which became user-visible
5+
in toolhive v0.24.0 when the subcommands were un-hidden in PR
6+
stacklok/toolhive#5001. Covers quick mode, config-file mode, optimizer
7+
tiers, audit logging, and a comparison to the Kubernetes operator path.
8+
- Updated `docs/toolhive/guides-vmcp/index.mdx` and
9+
`docs/toolhive/guides-vmcp/intro.mdx` to surface the local CLI mode
10+
alongside the existing Kubernetes-focused content.
11+
- Updated `docs/toolhive/concepts/vmcp.mdx` intro to note that vMCP now ships
12+
in two forms (operator CRD and CLI) and link to the new guide.
13+
- Updated `sidebars.ts` to include the new local CLI guide under Virtual MCP
14+
Server.

docs/toolhive/concepts/vmcp.mdx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ description:
66
for simpler client configuration.
77
---
88

9-
This document explains Virtual MCP Server (vMCP), a feature of the ToolHive
10-
Kubernetes Operator. You'll learn why it exists, when to use it, and how it
11-
simplifies managing multiple MCP servers while enabling powerful multi-system
12-
workflows.
9+
This document explains Virtual MCP Server (vMCP). You'll learn why it exists,
10+
when to use it, and how it simplifies managing multiple MCP servers while
11+
enabling powerful multi-system workflows. vMCP runs either as a Kubernetes
12+
Operator feature (via the `VirtualMCPServer` CRD) or as a local process
13+
through the `thv vmcp` CLI command - both share the same aggregation
14+
runtime. See [Run vMCP locally with the CLI](../guides-vmcp/local-cli.mdx)
15+
for the CLI option.
1316

1417
## The problem vMCP solves
1518

docs/toolhive/guides-vmcp/index.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ connection.
1717
- **Evaluating vMCP?** Read
1818
[Understanding Virtual MCP Server](../concepts/vmcp.mdx) for the full picture
1919
of what it does and when it's the right fit.
20-
- **Ready to try it?** Follow the [Quickstart](./quickstart.mdx) to deploy your
21-
first vMCP on a Kubernetes cluster.
20+
- **Ready to try it on Kubernetes?** Follow the [Quickstart](./quickstart.mdx)
21+
to deploy your first vMCP using the operator.
22+
- **Want to try it locally first?** Run vMCP as a single CLI process with
23+
[Run vMCP locally with the CLI](./local-cli.mdx), no cluster required.
2224
- **Already running vMCP?** Jump to [Configuration](./configuration.mdx) or
2325
[Authentication](./authentication.mdx).
2426

docs/toolhive/guides-vmcp/intro.mdx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@ description:
77

88
## What is vMCP?
99

10-
Virtual MCP Server (vMCP) is a feature of the ToolHive Kubernetes Operator that
11-
acts as an aggregation proxy, consolidating multiple backend MCP servers into a
12-
single unified interface. Instead of configuring clients to connect to each MCP
13-
server individually, you connect once to vMCP and access all backend tools
14-
through a single endpoint.
10+
Virtual MCP Server (vMCP) acts as an aggregation proxy, consolidating multiple
11+
backend MCP servers into a single unified interface. Instead of configuring
12+
clients to connect to each MCP server individually, you connect once to vMCP
13+
and access all backend tools through a single endpoint.
14+
15+
vMCP ships in two forms that share the same runtime:
16+
17+
- As a **Kubernetes Operator** feature, deployed via the `VirtualMCPServer`
18+
CRD. This is the path documented throughout the rest of these guides.
19+
- As the **`thv vmcp` CLI command**, which runs the same aggregation runtime
20+
as a local process. See
21+
[Run vMCP locally with the CLI](./local-cli.mdx) for details.
1522

1623
vMCP supports two types of backends:
1724

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
---
2+
title: Run vMCP locally with the CLI
3+
sidebar_label: Local CLI mode
4+
description:
5+
Run a Virtual MCP Server on your workstation with thv vmcp, without
6+
Kubernetes.
7+
---
8+
9+
Most of the Virtual MCP Server (vMCP) guides deploy vMCP to Kubernetes using
10+
the operator. The ToolHive CLI also ships a local mode for the same vMCP
11+
runtime, so you can aggregate MCP servers from a ToolHive group on your
12+
workstation without a cluster.
13+
14+
Local mode is useful for:
15+
16+
- **Prototyping aggregation** against a handful of MCP servers before
17+
committing to a `VirtualMCPServer` resource in Kubernetes.
18+
- **Local development** against the same optimizer, conflict resolution, and
19+
composite-tool logic that the operator uses.
20+
- **Demos** where you want a single endpoint fronting several MCP servers
21+
without the operator overhead.
22+
23+
The CLI command is `thv vmcp` with three subcommands: `serve`, `init`, and
24+
`validate`. They share the `pkg/vmcp/` runtime with the Kubernetes operator,
25+
so configuration, tool aggregation, and the optimizer behave the same way in
26+
both environments.
27+
28+
## Prerequisites
29+
30+
- ToolHive CLI `v0.24.0` or later. See
31+
[Install the ToolHive CLI](../guides-cli/install.mdx).
32+
- One or more MCP servers running in a ToolHive group. See
33+
[Run MCP servers](../guides-cli/run-mcp-servers.mdx) and
34+
[Group management](../guides-cli/group-management.mdx) to create a group
35+
and add servers to it.
36+
- Docker or Podman if you plan to enable the Tier 2 semantic optimizer, which
37+
starts a Text Embeddings Inference (TEI) container.
38+
39+
## Quick mode: aggregate a group in one command
40+
41+
When you already have a ToolHive group with running MCP servers, the fastest
42+
way to start vMCP is quick mode. Pass `--group` and vMCP generates a minimal
43+
in-memory configuration from the group at startup:
44+
45+
```bash
46+
thv vmcp serve --group demo-tools
47+
```
48+
49+
This is equivalent to creating a config file with:
50+
51+
- `groupRef: demo-tools`
52+
- `incomingAuth.type: anonymous`
53+
- `outgoingAuth.source: inline`
54+
- `aggregation.conflictResolution: prefix` with prefix format `{workload}_`
55+
56+
vMCP binds to `127.0.0.1:4483` and aggregates every accessible MCP server in
57+
the group behind that single endpoint.
58+
59+
:::warning[Quick mode is loopback-only]
60+
61+
Because quick mode uses anonymous authentication, `thv vmcp serve --group`
62+
rejects non-loopback bind addresses. Valid values for `--host` are
63+
`127.0.0.1`, `localhost`, or any other loopback address. To expose vMCP on
64+
another interface or add real authentication, switch to a config file (see
65+
below).
66+
67+
:::
68+
69+
### Connect a client
70+
71+
In another terminal, register the vMCP endpoint as a remote MCP server so your
72+
configured AI clients can discover it:
73+
74+
```bash
75+
thv run http://localhost:4483/mcp --name local-vmcp
76+
```
77+
78+
If you haven't registered any AI clients yet, run `thv client setup` first.
79+
See [Client configuration](../guides-cli/client-configuration.mdx) for
80+
details.
81+
82+
## Config-file mode: generate, review, serve
83+
84+
When you need incoming OIDC auth, a non-loopback bind, per-backend outgoing
85+
auth, or composite tools, use a configuration file. The `init` subcommand
86+
scaffolds one from an existing group, `validate` checks it, and `serve`
87+
runs it.
88+
89+
### Step 1: generate a starter config
90+
91+
`thv vmcp init` enumerates the workloads in a group and emits a YAML config
92+
with one backend entry per accessible server:
93+
94+
```bash
95+
thv vmcp init --group demo-tools --output vmcp.yaml
96+
```
97+
98+
The `--group` flag is required. If you omit `--output`, the generated YAML
99+
is written to stdout so you can pipe it through `less` or redirect it
100+
yourself.
101+
102+
A generated file looks similar to this (comments trimmed):
103+
104+
```yaml title="vmcp.yaml"
105+
name: demo-tools-vmcp
106+
groupRef: demo-tools
107+
108+
incomingAuth:
109+
type: anonymous
110+
111+
outgoingAuth:
112+
source: inline
113+
114+
aggregation:
115+
conflictResolution: prefix
116+
conflictResolutionConfig:
117+
prefixFormat: "{workload}_"
118+
119+
backends:
120+
- name: fetch
121+
url: http://localhost:24162/mcp
122+
transport: streamable-http
123+
- name: osv
124+
url: http://localhost:24163/mcp
125+
transport: streamable-http
126+
```
127+
128+
Edit the file to switch to OIDC, change the conflict-resolution strategy, add
129+
composite tool definitions, or enable the optimizer. See
130+
[Configure vMCP servers](./configuration.mdx) for the complete schema.
131+
132+
### Step 2: validate the config
133+
134+
Before starting the server, run the validator to catch syntax errors and
135+
schema violations:
136+
137+
```bash
138+
thv vmcp validate --config vmcp.yaml
139+
```
140+
141+
A valid config exits with status `0` and no output. An invalid config exits
142+
non-zero with a descriptive error, for example:
143+
144+
```text
145+
Error: validation failed: aggregation.conflictResolution: unknown strategy "preffix"
146+
```
147+
148+
### Step 3: start the server
149+
150+
Once the config validates, start vMCP:
151+
152+
```bash
153+
thv vmcp serve --config vmcp.yaml
154+
```
155+
156+
When `--config` is set, `--group` is ignored. Pass `--host` and `--port` to
157+
override the default `127.0.0.1:4483` bind address (non-loopback addresses
158+
are allowed in config-file mode).
159+
160+
## Enable the optimizer
161+
162+
vMCP supports the same [tool optimizer](./optimizer.mdx) in local mode as in
163+
Kubernetes. The CLI exposes three tiers through flags on `thv vmcp serve`.
164+
165+
| Tier | Flag | What it does | External service |
166+
| ---- | ----------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------- |
167+
| 0 | _(none)_ | Pass-through: backends' tools are exposed as-is. | None |
168+
| 1 | `--optimizer` | FTS5 keyword optimizer: clients see only `find_tool` and `call_tool`, backed by an in-process SQLite FTS5 index. | None |
169+
| 2 | `--optimizer-embedding` | Tier 1 plus TEI semantic search. Implies `--optimizer`. | Managed TEI container |
170+
171+
Tier 2 starts a managed TEI container on first run and stops it when the
172+
server exits. Customize the model and image with `--embedding-model` and
173+
`--embedding-image`:
174+
175+
```bash
176+
thv vmcp serve --group demo-tools \
177+
--optimizer-embedding \
178+
--embedding-model BAAI/bge-small-en-v1.5 \
179+
--embedding-image ghcr.io/huggingface/text-embeddings-inference:cpu-latest
180+
```
181+
182+
The defaults use the upstream CPU image; switch to a GPU image if you have
183+
one available. First-start container pulls can take 30-60 seconds.
184+
185+
## Enable audit logging
186+
187+
Pass `--enable-audit` to log each incoming request with the default audit
188+
configuration. If your config file already defines an `audit` section, the
189+
flag has no effect and the file's configuration wins.
190+
191+
```bash
192+
thv vmcp serve --config vmcp.yaml --enable-audit
193+
```
194+
195+
See [Audit logging](./audit-logging.mdx) for the event format and how to
196+
customize it from a config file.
197+
198+
## Local CLI vs Kubernetes deployment
199+
200+
| Aspect | `thv vmcp serve` | `VirtualMCPServer` CRD |
201+
| --------------------- | ----------------------------------------------- | ---------------------------------------- |
202+
| Where it runs | Your workstation | Kubernetes cluster |
203+
| Backend discovery | Local ToolHive group | MCPGroup with MCPServer/MCPRemoteProxy |
204+
| Default bind | `127.0.0.1:4483` | Service in the cluster |
205+
| Authentication | Anonymous (quick mode) or as configured | Full OIDC, token exchange, embedded auth |
206+
| Lifecycle | Foreground process; Ctrl-C stops | Operator-managed Deployment |
207+
| Optimizer | Flag-driven (Tier 0/1/2) | `embeddingServerRef` on the CRD |
208+
209+
Both paths load the same vMCP runtime from `pkg/vmcp/`, so a config file
210+
that validates locally will behave the same way when the operator loads it
211+
as a ConfigMap. This makes local mode useful for iterating on aggregation,
212+
conflict resolution, and composite-tool definitions before moving to
213+
Kubernetes.
214+
215+
## Next steps
216+
217+
- [Configure vMCP servers](./configuration.mdx) for the full config schema.
218+
- [Optimize tool discovery](./optimizer.mdx) for details on Tier 1 and
219+
Tier 2.
220+
- [Run vMCP in Kubernetes](./quickstart.mdx) when you're ready to move from a
221+
local process to the operator.
222+
223+
## Related information
224+
225+
- [`thv vmcp` command reference](../reference/cli/thv_vmcp.md)
226+
- [`thv vmcp serve`](../reference/cli/thv_vmcp_serve.md),
227+
[`thv vmcp init`](../reference/cli/thv_vmcp_init.md),
228+
[`thv vmcp validate`](../reference/cli/thv_vmcp_validate.md)
229+
- [Understanding Virtual MCP Server](../concepts/vmcp.mdx)

sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ const sidebars: SidebarsConfig = {
176176
items: [
177177
'toolhive/guides-vmcp/intro',
178178
'toolhive/guides-vmcp/quickstart',
179+
'toolhive/guides-vmcp/local-cli',
179180
'toolhive/guides-vmcp/configuration',
180181
'toolhive/guides-vmcp/backend-discovery',
181182
'toolhive/guides-vmcp/authentication',

0 commit comments

Comments
 (0)