# 11 -- Discovery: Kubernetes

Source: https://mcp-hangar.io/docs/cookbook/11-discovery-kubernetes

---
> **Prerequisite:** [01 -- HTTP Gateway](01-http-gateway.md)
> **You will need:** Running Hangar, Kubernetes cluster with the MCP-Hangar Operator
> **Time:** 15 minutes
> **Adds:** Auto-discover MCP servers from Kubernetes annotations

## Prerequisites

This recipe requires the **MCP-Hangar Operator** running in your cluster.
The operator ships from a separate repository:
<https://github.com/mcp-hangar/hangar-operator>.

Install via Helm (from the [helm-charts](https://github.com/mcp-hangar/helm-charts) repo):

```bash
helm repo add mcp-hangar https://mcp-hangar.github.io/helm-charts
helm repo update
helm install mcp-hangar-operator mcp-hangar/mcp-hangar-operator \
  --namespace mcp-system \
  --create-namespace
```

Verify the CRDs are installed:

```bash
kubectl get crd | grep mcp-hangar.io
# Expected:
#   mcpservers.mcp-hangar.io
#   mcpservergroups.mcp-hangar.io
#   mcpdiscoverysources.mcp-hangar.io
```

## The Problem

You run MCP servers as Kubernetes services. Teams deploy and scale MCP servers independently. You need Hangar to discover them from annotations without manual config updates.

## The Config

```yaml
# config.yaml -- Recipe 11: Kubernetes Discovery
discovery:
  enabled: true
  refresh_interval_s: 30
  auto_register: true                    # NEW: trust K8s annotations

  sources:
    - type: kubernetes                   # NEW: Kubernetes source
      mode: authoritative                # NEW: add AND remove on pod changes
      config:                            # NEW: K8s-specific config
        namespace: "mcp-servers"       # NEW: watch this namespace
        label_selector: "app.kubernetes.io/part-of=mcp"  # NEW: filter pods
```

## Try It

1. Deploy an MCP server with annotations:

   ```bash
   kubectl apply -f - <<EOF
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: math-mcp-server
     namespace: mcp-servers
     labels:
       app.kubernetes.io/part-of: mcp
     annotations:
       mcp-hangar.io/enabled: "true"
       mcp-hangar.io/name: "k8s-math"
       mcp-hangar.io/port: "8080"
   spec:
     replicas: 2
     selector:
       matchLabels:
         app: math-mcp-server
     template:
       metadata:
         labels:
           app: math-mcp-server
       spec:
         containers:
           - name: math
             image: my-registry/math-server:latest
             ports:
               - containerPort: 8080
   EOF
   ```

2. Expose the deployment:

   ```bash
   kubectl expose deployment math-mcp-server -n mcp-servers --port=8080
   ```

3. Verify Hangar discovers it:

   ```bash
   curl http://localhost:8000/api/discovery/sources
   ```

4. Check registered MCP servers:

   ```bash
   mcp-hangar status
   ```

   ```
   k8s-math    remote    cold    source=kubernetes:auto-discovery
   ```

5. Scale up and watch Hangar adapt:

   ```bash
   kubectl scale deployment math-mcp-server -n mcp-servers --replicas=3
   ```

## What Just Happened

The Kubernetes discovery source watches pods in the configured namespace matching the label selector. Pods with `mcp-hangar.io/enabled: "true"` annotations are registered as remote MCP servers. In `authoritative` mode, when a pod is deleted, the corresponding MCP server is deregistered.

For declarative management, use the MCP-Hangar Operator CRDs instead. See the [Kubernetes guide](../guides/KUBERNETES.md).

## Key Config Reference

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `discovery.sources[].type` | string | -- | Set to `kubernetes` |
| `discovery.sources[].mode` | string | -- | `additive` or `authoritative` |
| `discovery.sources[].config.namespace` | string | `default` | Kubernetes namespace to watch |
| `discovery.sources[].config.label_selector` | string | -- | Pod label selector |

### Kubernetes Annotations

| Annotation | Required | Default | Description |
|------------|----------|---------|-------------|
| `mcp-hangar.io/enabled` | Yes | -- | Must be `"true"` |
| `mcp-hangar.io/name` | No | Pod name | MCP Server name |
| `mcp-hangar.io/port` | No | `8080` | MCP Server port |
| `mcp-hangar.io/group` | No | -- | Auto-add to group |

## What's Next

You have discovery working. Now add authentication to control who can access your MCP servers.

--> [12 -- Auth & RBAC](12-auth-rbac.md)
