Skip to content
This repository was archived by the owner on Jul 23, 2025. It is now read-only.

Commit bebb0cd

Browse files
committed
Update K8s docs
1 parent 63545d1 commit bebb0cd

File tree

3 files changed

+208
-20
lines changed

3 files changed

+208
-20
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
label: 'Kubernetes deployment'
22
position: 30
3+
link:
4+
type: generated-index
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
---
22
title: ToolHive Kubernetes operator
33
description: Manage MCP servers in Kubernetes with the ToolHive operator
4+
sidebar_position: 1
5+
sidebar_label: Introduction
46
---
57

68
The ToolHive Kubernetes operator manages MCP servers in Kubernetes clusters. It

docs/toolhive/kubernetes/run-mcp-k8s.md

Lines changed: 204 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,100 @@ sidebar_position: 20
1212
- The ToolHive operator installed in your cluster (see
1313
[Deploy the operator using Helm](./deploy-operator-helm.md))
1414

15+
## Overview
16+
17+
The ToolHive operator deploys MCP servers in Kubernetes by creating proxy pods
18+
that manage the actual MCP server containers. Here's how the architecture works:
19+
20+
### High-level architecture
21+
22+
This diagram shows the basic relationship between components. The ToolHive
23+
operator watches for `MCPServer` resources and automatically creates the
24+
necessary infrastructure to run your MCP servers securely within the cluster.
25+
26+
```mermaid
27+
flowchart LR
28+
Client["Client"] --> Proxy["ToolHive Proxy"]
29+
Proxy --> MCP["MCP Server"]
30+
31+
subgraph K8s["Kubernetes Cluster"]
32+
subgraph NS["Namespace"]
33+
Operator["ToolHive Operator"]
34+
Proxy
35+
MCP
36+
end
37+
end
38+
39+
Operator -.->|creates| Proxy
40+
Proxy -.->|creates| MCP
41+
```
42+
43+
### STDIO transport flow
44+
45+
For MCP servers using STDIO transport, the proxy directly attaches to the MCP
46+
server pod's standard input/output streams.
47+
48+
```mermaid
49+
flowchart LR
50+
subgraph Proxy["Created by Operator"]
51+
direction TB
52+
ProxyService["SVC: ToolHive-Proxy"]
53+
ProxyPod["POD: ToolHive-Proxy"]
54+
ProxyService --> ProxyPod
55+
end
56+
57+
subgraph MCP["Created by Proxy"]
58+
direction TB
59+
MCPPod["POD: MCP Server"]
60+
end
61+
62+
Client["Client"] -->|HTTP/SSE| Proxy
63+
Proxy -->|Attaches/STDIO| MCP
64+
```
65+
66+
### SSE transport flow
67+
68+
For MCP servers using Server-Sent Events (SSE) transport, the proxy creates both
69+
a pod and a headless service. This allows direct HTTP/SSE communication between
70+
the proxy and MCP server while maintaining network isolation and service
71+
discovery.
72+
73+
```mermaid
74+
flowchart LR
75+
subgraph Proxy["Created by Operator"]
76+
direction TB
77+
ProxyService["SVC: ToolHive-Proxy"]
78+
ProxyPod["POD: ToolHive-Proxy"]
79+
ProxyService --> ProxyPod
80+
end
81+
82+
subgraph MCP["Created by Proxy"]
83+
direction TB
84+
MCPService["SVC: MCP-Headless"]
85+
MCPPod["POD: MCP Server"]
86+
end
87+
88+
Client["Client"] -->|HTTP/SSE| Proxy
89+
Proxy -->|HTTP/SSE| MCP
90+
MCPService --> MCPPod
91+
```
92+
1593
## Create an MCP Server
1694

95+
:::note
96+
97+
Currently, you must create `MCPServer` resources in the same namespace as the
98+
ToolHive operator, which is typically `toolhive-system`. We are working on
99+
support for multi-namespace deployments in the future. Watch
100+
[this issue](https://github.com/stacklok/toolhive/issues/538) for updates.
101+
102+
:::
103+
17104
To create an MCP server, define an `MCPServer` resource and apply it to your
18-
cluster. This example creates the
19-
[`osv` MCP server](https://github.com/StacklokLabs/osv-mcp).
105+
cluster. This minimal example creates the
106+
[`osv` MCP server](https://github.com/StacklokLabs/osv-mcp) which queries the
107+
[Open Source Vulnerability (OSV) database](https://osv.dev/) for vulnerability
108+
information.
20109

21110
```yaml title="my-mcpserver.yaml"
22111
apiVersion: toolhive.stacklok.dev/v1alpha1
@@ -46,7 +135,102 @@ Apply the resource:
46135
kubectl apply -f my-mcpserver.yaml
47136
```
48137

49-
## Run a server with secrets
138+
:::info What's happening?
139+
140+
When you apply an `MCPServer` resource, here's what happens:
141+
142+
1. The ToolHive operator running in the `toolhive-system` namespace detects the
143+
new resource
144+
2. The operator creates a new Deployment containing a ToolHive proxy pod and
145+
service to handle client connections
146+
3. The proxy creates the actual `MCPServer` pod containing your specified
147+
container image
148+
4. For STDIO transport, the proxy attaches directly to the pod; for SSE
149+
transport, a headless service is created for direct pod communication
150+
5. Clients can now connect through the service → proxy → MCP server chain to use
151+
the tools and resources (note: external clients will need an ingress
152+
controller or similar mechanism to access the service from outside the
153+
cluster)
154+
155+
:::
156+
157+
For more examples of `MCPServer` resources, see the
158+
[example MCP server manifests](https://github.com/stacklok/toolhive/tree/main/examples/operator/mcp-servers)
159+
in the ToolHive repo.
160+
161+
## Customize server settings
162+
163+
You can customize the MCP server by adding additional fields to the `MCPServer`
164+
resource. Below are some common configurations.
165+
166+
### Customize the MCP server pod
167+
168+
You can customize the MCP server pod that gets created by the proxy using the
169+
`podTemplateSpec` field. This gives you full control over the pod specification,
170+
allowing you to set security contexts, resource limits, node selectors, and
171+
other pod-level configurations.
172+
173+
The `podTemplateSpec` field follows the standard Kubernetes
174+
[`PodTemplateSpec`](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-template-v1/#PodTemplateSpec)
175+
format, so you can use any valid pod specification options.
176+
177+
This example sets security contexts and resource limits. It allows the MCP
178+
container to run as root, an unfortunate requirement for the Fetch MCP server
179+
image, while still applying some security restrictions.
180+
181+
```yaml title="my-mcpserver-custom-pod.yaml"
182+
apiVersion: toolhive.stacklok.dev/v1alpha1
183+
kind: MCPServer
184+
metadata:
185+
name: fetch
186+
namespace: toolhive-system
187+
spec:
188+
image: docker.io/mcp/fetch
189+
transport: stdio
190+
port: 8080
191+
permissionProfile:
192+
type: builtin
193+
name: network
194+
podTemplateSpec:
195+
spec:
196+
containers:
197+
- name: mcp # This name must be "mcp"
198+
securityContext:
199+
allowPrivilegeEscalation: false
200+
runAsNonRoot: false # Allows the MCP container to run as root
201+
runAsUser: 0
202+
capabilities:
203+
drop:
204+
- ALL
205+
resources: # These resources apply to the MCP container
206+
limits:
207+
cpu: '500m'
208+
memory: '512Mi'
209+
requests:
210+
cpu: '100m'
211+
memory: '128Mi'
212+
securityContext:
213+
runAsNonRoot: true # The pod itself can run as a non-root user
214+
seccompProfile:
215+
type: RuntimeDefault
216+
resources: # These resources apply to the proxy container
217+
limits:
218+
cpu: '100m'
219+
memory: '128Mi'
220+
requests:
221+
cpu: '50m'
222+
memory: '64Mi'
223+
```
224+
225+
:::info Container name requirement
226+
227+
When customizing containers in `podTemplateSpec`, you must use `name: mcp` for
228+
the main container. This ensures the proxy can properly manage the MCP server
229+
process.
230+
231+
:::
232+
233+
### Run a server with secrets
50234

51235
For MCP servers that require authentication tokens or other secrets, add the
52236
`secrets` field to the `MCPServer` resource. This example shows how to use a
@@ -86,7 +270,7 @@ Apply the MCPServer resource:
86270
kubectl apply -f my-mcpserver-with-secrets.yaml
87271
```
88272

89-
## Mount a volume
273+
### Mount a volume
90274

91275
:::warning TODO
92276

@@ -102,7 +286,7 @@ To check the status of your MCP servers:
102286
kubectl -n toolhive-system get mcpservers
103287
```
104288

105-
This will show the status, URL, and age of each MCP server.
289+
The status, URL, and age of each MCP server is displayed.
106290

107291
For more details about a specific MCP server:
108292

@@ -114,7 +298,8 @@ kubectl -n toolhive-system describe mcpserver <NAME>
114298

115299
:::tip QUESTION
116300

117-
TODO: Move to a /reference page?
301+
TODO: Move to a /reference page? Also could use a way to keep this in sync
302+
automatically.
118303

119304
:::
120305

@@ -132,16 +317,6 @@ TODO: Move to a /reference page?
132317
| `secrets` | References to secrets to mount in the container | No | - |
133318
| `permissionProfile` | Permission profile configuration | No | - |
134319

135-
### Volumes
136-
137-
The `volumes` field has the following parameters:
138-
139-
:::warning TODO
140-
141-
Need info!
142-
143-
:::
144-
145320
### Secrets
146321

147322
The `secrets` field has the following parameters:
@@ -152,6 +327,16 @@ The `secrets` field has the following parameters:
152327
secret in the MCP server (optional). If left unspecified, it defaults to the
153328
key.
154329

330+
### Volumes
331+
332+
The `volumes` field has the following parameters:
333+
334+
:::warning TODO
335+
336+
Need info!
337+
338+
:::
339+
155340
### Permission Profiles
156341

157342
Permission profiles can be configured in two ways:
@@ -175,8 +360,7 @@ Permission profiles can be configured in two ways:
175360

176361
The ConfigMap should contain a JSON permission profile.
177362

178-
## Examples
363+
## Next steps
179364

180-
See the
181-
[example MCP server manifests](https://github.com/stacklok/toolhive/tree/main/examples/operator/mcp-servers)
182-
in the ToolHive repo for example MCPServer resources.
365+
See the [Client compatibility](../reference/client-compatibility.mdx) reference
366+
to learn how to connect to MCP servers using different clients.

0 commit comments

Comments
 (0)