|
| 1 | +--- |
| 2 | +title: Configure tools for MCP servers on Kubernetes |
| 3 | +description: |
| 4 | + Filter and rename MCP server tools using the MCPToolConfig CRD and |
| 5 | + toolConfigRef. |
| 6 | +--- |
| 7 | + |
| 8 | +## Overview |
| 9 | + |
| 10 | +Use the MCPToolConfig Custom Resource Definition (CRD) to centrally manage which |
| 11 | +tools an MCP server exposes, and optionally rename tools or override their |
| 12 | +descriptions. You reference the configuration from an MCPServer using the |
| 13 | +toolConfigRef field. |
| 14 | + |
| 15 | +- toolsFilter: allow‑list the tools to expose. |
| 16 | +- toolsOverride: rename tools and/or change their descriptions. |
| 17 | +- Same‑namespace only: an MCPServer can reference only MCPToolConfig objects in |
| 18 | + the same namespace. |
| 19 | +- Precedence: toolConfigRef takes precedence over the deprecated spec.tools |
| 20 | + field on MCPServer. |
| 21 | + |
| 22 | +## Prerequisites |
| 23 | + |
| 24 | +- ToolHive operator installed. See |
| 25 | + [Deploy the operator using Helm](./deploy-operator-helm.md). |
| 26 | +- Permissions to create namespaced resources (and optionally RBAC for servers |
| 27 | + that need cluster access). |
| 28 | + |
| 29 | +## Define a basic tool filter |
| 30 | + |
| 31 | +This example exposes only three tools on a server: |
| 32 | + |
| 33 | +```yaml title="toolconfig-basic.yaml" |
| 34 | +apiVersion: toolhive.stacklok.dev/v1alpha1 |
| 35 | +kind: MCPToolConfig |
| 36 | +metadata: |
| 37 | + name: basic-tool-filter |
| 38 | + namespace: default |
| 39 | +spec: |
| 40 | + toolsFilter: |
| 41 | + - read_file |
| 42 | + - write_file |
| 43 | + - list_directory |
| 44 | +``` |
| 45 | +
|
| 46 | +## Rename tools and override descriptions |
| 47 | +
|
| 48 | +You can rename tools to match your team's conventions and refine their |
| 49 | +descriptions: |
| 50 | +
|
| 51 | +```yaml title="toolconfig-with-overrides.yaml" |
| 52 | +apiVersion: toolhive.stacklok.dev/v1alpha1 |
| 53 | +kind: MCPToolConfig |
| 54 | +metadata: |
| 55 | + name: github-tools-config |
| 56 | + namespace: default |
| 57 | +spec: |
| 58 | + toolsFilter: |
| 59 | + - create_pull_request |
| 60 | + - get_pull_request |
| 61 | + - list_pull_requests |
| 62 | + - merge_pull_request |
| 63 | + toolsOverride: |
| 64 | + create_pull_request: |
| 65 | + name: github_create_pr |
| 66 | + description: Create a new GitHub pull request |
| 67 | + get_pull_request: |
| 68 | + name: github_get_pr |
| 69 | + description: Retrieve details of a GitHub pull request |
| 70 | + list_pull_requests: |
| 71 | + name: github_list_prs |
| 72 | + description: List pull requests in a repository |
| 73 | + merge_pull_request: |
| 74 | + name: github_merge_pr |
| 75 | + description: Merge a GitHub pull request |
| 76 | +``` |
| 77 | +
|
| 78 | +## Reference the configuration from an MCP server |
| 79 | +
|
| 80 | +Add toolConfigRef to your MCPServer. toolConfigRef overrides spec.tools |
| 81 | +(deprecated). |
| 82 | +
|
| 83 | +```yaml title="mcpserver-with-toolconfig.yaml" |
| 84 | +apiVersion: toolhive.stacklok.dev/v1alpha1 |
| 85 | +kind: MCPServer |
| 86 | +metadata: |
| 87 | + name: mkp |
| 88 | + namespace: toolhive-system |
| 89 | +spec: |
| 90 | + image: ghcr.io/stackloklabs/mkp/server:0.2.3 |
| 91 | + transport: streamable-http |
| 92 | + targetPort: 8080 |
| 93 | + port: 8080 |
| 94 | + serviceAccount: mkp-sa |
| 95 | + toolConfigRef: |
| 96 | + name: mkp-tools |
| 97 | + args: |
| 98 | + - '--read-write=true' |
| 99 | +``` |
| 100 | +
|
| 101 | +## End‑to‑end example (cluster‑scoped RBAC) |
| 102 | +
|
| 103 | +The following manifest shows a minimal, end‑to‑end setup that runs the MKP |
| 104 | +server inside the cluster, grants it wide permissions (for demo only), defines |
| 105 | +an MCPToolConfig, and references it from the server: |
| 106 | +
|
| 107 | +```yaml title="mkp-with-toolconfig.yaml" |
| 108 | +apiVersion: v1 |
| 109 | +kind: ServiceAccount |
| 110 | +metadata: |
| 111 | + name: mkp-sa |
| 112 | + namespace: toolhive-system |
| 113 | +--- |
| 114 | +apiVersion: rbac.authorization.k8s.io/v1 |
| 115 | +kind: ClusterRole |
| 116 | +metadata: |
| 117 | + name: mkp-cluster-role |
| 118 | +rules: |
| 119 | + - apiGroups: ['*'] |
| 120 | + resources: ['*'] |
| 121 | + verbs: ['*'] |
| 122 | +--- |
| 123 | +apiVersion: rbac.authorization.k8s.io/v1 |
| 124 | +kind: ClusterRoleBinding |
| 125 | +metadata: |
| 126 | + name: mkp-cluster-role-binding |
| 127 | +roleRef: |
| 128 | + apiGroup: rbac.authorization.k8s.io |
| 129 | + kind: ClusterRole |
| 130 | + name: mkp-cluster-role |
| 131 | +subjects: |
| 132 | + - kind: ServiceAccount |
| 133 | + name: mkp-sa |
| 134 | + namespace: toolhive-system |
| 135 | +--- |
| 136 | +apiVersion: toolhive.stacklok.dev/v1alpha1 |
| 137 | +kind: MCPToolConfig |
| 138 | +metadata: |
| 139 | + name: mkp-tools |
| 140 | + namespace: toolhive-system |
| 141 | +spec: |
| 142 | + toolsFilter: |
| 143 | + - homelab_k8s_apply_resource |
| 144 | + - homelab_k8s_delete_resource |
| 145 | + - homelab_k8s_get_resource |
| 146 | + - homelab_k8s_list_resources |
| 147 | + - homelab_k8s_post_resource |
| 148 | + toolsOverride: |
| 149 | + apply_resource: |
| 150 | + name: homelab_k8s_apply_resource |
| 151 | + description: | |
| 152 | + Apply (create or update) a Kubernetes resource. |
| 153 | + Required: |
| 154 | + - resource: plural resource name (e.g., deployments, services) |
| 155 | + - version: API version (e.g., v1, v1beta1) |
| 156 | + - manifest: full resource manifest (apiVersion, kind, metadata, spec) |
| 157 | + Optional: |
| 158 | + - group: API group (e.g., apps, networking.k8s.io) |
| 159 | + - resource_type: clustered|namespaced (default inferred from resource; use namespaced and provide namespace when required) |
| 160 | + - namespace: target namespace for namespaced resources |
| 161 | + delete_resource: |
| 162 | + name: homelab_k8s_delete_resource |
| 163 | + description: | |
| 164 | + Delete a Kubernetes resource. |
| 165 | + Required: |
| 166 | + - resource, version, name |
| 167 | + Optional: |
| 168 | + - group, namespace (for namespaced resources) |
| 169 | + get_resource: |
| 170 | + name: homelab_k8s_get_resource |
| 171 | + description: | |
| 172 | + Get a Kubernetes resource or its subresource (e.g., status, scale, logs). |
| 173 | + - For pod logs, supported parameters include: container, previous, sinceSeconds, sinceTime, timestamps, limitBytes, tailLines. |
| 174 | + - For subresources, set subresource: status|scale|logs etc. |
| 175 | + - For namespaced resources, set namespace. |
| 176 | + list_resources: |
| 177 | + name: homelab_k8s_list_resources |
| 178 | + description: | |
| 179 | + List Kubernetes resources with flexible filtering. |
| 180 | + Supported parameters: |
| 181 | + - namespace (for namespaced resources) |
| 182 | + - label_selector |
| 183 | + - include_annotations (bool), include_annotation_keys, exclude_annotation_keys (wildcards supported with *) |
| 184 | + - limit (0 = no limit), continue (for pagination) |
| 185 | + post_resource: |
| 186 | + name: homelab_k8s_post_resource |
| 187 | + description: | |
| 188 | + Post to a Kubernetes resource or subresource (e.g., exec). |
| 189 | + - Provide body according to subresource. |
| 190 | + - For exec, body fields: command (string or array), container (optional), timeout (seconds, optional). |
| 191 | + - For namespaced resources, set namespace. |
| 192 | +--- |
| 193 | +apiVersion: toolhive.stacklok.dev/v1alpha1 |
| 194 | +kind: MCPServer |
| 195 | +metadata: |
| 196 | + name: mkp |
| 197 | + namespace: toolhive-system |
| 198 | +spec: |
| 199 | + image: ghcr.io/stackloklabs/mkp/server:0.2.3 |
| 200 | + transport: streamable-http |
| 201 | + targetPort: 8080 |
| 202 | + port: 8080 |
| 203 | + serviceAccount: mkp-sa |
| 204 | + toolConfigRef: |
| 205 | + name: mkp-tools |
| 206 | + args: |
| 207 | + - '--read-write=true' |
| 208 | +``` |
| 209 | +
|
| 210 | +:::warning[Least privilege] |
| 211 | +
|
| 212 | +The ClusterRole above is intentionally broad for demonstration. In production, |
| 213 | +scope permissions to the minimum your workflows require. |
| 214 | +
|
| 215 | +::: |
| 216 | +
|
| 217 | +## Inspect status and troubleshoot |
| 218 | +
|
| 219 | +Use kubectl to inspect status and track change propagation: |
| 220 | +
|
| 221 | +```bash |
| 222 | +kubectl -n toolhive-system get mcptoolconfigs |
| 223 | +kubectl -n toolhive-system get mcptoolconfig mkp-tools -o yaml |
| 224 | +kubectl -n toolhive-system get mcpserver mkp -o yaml |
| 225 | +``` |
| 226 | + |
| 227 | +- If an MCPToolConfig is still referenced, deletion is blocked by a finalizer. |
| 228 | + Remove all toolConfigRef references first. |
| 229 | +- If an MCPServer references a missing MCPToolConfig, the server enters Failed |
| 230 | + and the controller logs include the missing name and namespace. |
| 231 | + |
| 232 | +## Related |
| 233 | + |
| 234 | +- See the [Kubernetes CRD reference](../reference/crd-spec.mdx) for the full |
| 235 | + MCPToolConfig and MCPServerSpec schemas. |
| 236 | +- Learn how to [run the MKP server in Kubernetes](../guides-mcp/k8s.mdx). |
0 commit comments