Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ python/build/
python/dist/
python/kubernetes_mcp_server.egg-info/
!python/kubernetes-mcp-server

/bin/
hack/cert-manager-ca/
37 changes: 37 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,40 @@ lint: golangci-lint ## Lint the code
.PHONY: update-readme-tools
update-readme-tools: ## Update the README.md file with the latest toolsets
go run ./internal/tools/update-readme/main.go README.md

##@ Tools

.PHONY: tools
tools: ## Install all required tools (kind) to ./bin/
@echo "Checking and installing required tools to ./bin/ ..."
@if [ -f bin/kind ]; then echo "[OK] kind already installed"; else echo "Installing kind..."; $(MAKE) -s kind; fi
@echo "All tools ready!"

##@ Local Development

.PHONY: local-env-setup
local-env-setup: ## Setup complete local development environment with Kind cluster
@echo "========================================="
@echo "Kubernetes MCP Server - Local Setup"
@echo "========================================="
$(MAKE) tools
$(MAKE) kind-create-cluster
$(MAKE) keycloak-install
$(MAKE) build
@echo ""
@echo "========================================="
@echo "Local environment ready!"
@echo "========================================="
@echo ""
@echo "Run the MCP server with:"
@echo " ./$(BINARY_NAME) --port ..."
@echo ""
@echo "Or run with MCP inspector:"
@echo " npx @modelcontextprotocol/inspector@latest \$$(pwd)/$(BINARY_NAME)"

.PHONY: local-env-teardown
local-env-teardown: ## Tear down the local Kind cluster
$(MAKE) kind-delete-cluster

# Include build configuration files
-include build/*.mk
428 changes: 428 additions & 0 deletions build/keycloak.mk

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions build/kind.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Kind cluster management

KIND_CLUSTER_NAME ?= kubernetes-mcp-server

# Detect container engine (docker or podman)
CONTAINER_ENGINE ?= $(shell command -v docker 2>/dev/null || command -v podman 2>/dev/null)

.PHONY: kind-create-certs
kind-create-certs: ## Generate TLS certificates for Keycloak
@if [ ! -f hack/keycloak-certs/ca.crt ]; then \
echo "Generating Keycloak TLS certificates..."; \
./hack/generate-keycloak-certs.sh; \
else \
echo "✅ Certificates already exist"; \
fi

.PHONY: kind-create-cluster
kind-create-cluster: kind kind-create-certs ## Create the kind cluster for development
@# Set KIND provider for podman on Linux
@if [ "$(shell uname -s)" != "Darwin" ] && echo "$(CONTAINER_ENGINE)" | grep -q "podman"; then \
export KIND_EXPERIMENTAL_PROVIDER=podman; \
fi; \
if $(KIND) get clusters 2>/dev/null | grep -q "^$(KIND_CLUSTER_NAME)$$"; then \
echo "Kind cluster '$(KIND_CLUSTER_NAME)' already exists, skipping creation"; \
else \
echo "Creating Kind cluster '$(KIND_CLUSTER_NAME)'..."; \
$(KIND) create cluster --name $(KIND_CLUSTER_NAME) --config config/kind/cluster.yaml; \
echo "Adding ingress-ready label to control-plane node..."; \
kubectl label node $(KIND_CLUSTER_NAME)-control-plane ingress-ready=true --overwrite; \
echo "Installing nginx ingress controller..."; \
kubectl apply -f config/ingress/nginx-ingress.yaml; \
echo "Waiting for ingress controller to be ready..."; \
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=90s; \
echo "✅ Ingress controller ready"; \
echo "Installing cert-manager..."; \
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yaml; \
echo "Waiting for cert-manager to be ready..."; \
kubectl wait --namespace cert-manager --for=condition=ready pod --selector=app.kubernetes.io/instance=cert-manager --timeout=120s; \
kubectl wait --namespace cert-manager --for=condition=ready pod --selector=app.kubernetes.io/name=webhook --timeout=120s; \
echo "✅ cert-manager ready"; \
echo "Creating cert-manager ClusterIssuer..."; \
sleep 5; \
kubectl apply -f config/cert-manager/selfsigned-issuer.yaml; \
echo "✅ ClusterIssuer created"; \
fi

.PHONY: kind-delete-cluster
kind-delete-cluster: kind ## Delete the kind cluster
@# Set KIND provider for podman on Linux
@if [ "$(shell uname -s)" != "Darwin" ] && echo "$(CONTAINER_ENGINE)" | grep -q "podman"; then \
export KIND_EXPERIMENTAL_PROVIDER=podman; \
fi; \
$(KIND) delete cluster --name $(KIND_CLUSTER_NAME)
19 changes: 19 additions & 0 deletions build/tools.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Tools

# Platform detection
OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH := $(shell uname -m | tr '[:upper:]' '[:lower:]')
ifeq ($(ARCH),x86_64)
ARCH = amd64
endif
ifeq ($(ARCH),aarch64)
ARCH = arm64
endif

KIND = bin/kind
KIND_VERSION = v0.30.0
$(KIND):
GOBIN=$(PWD)/bin go install sigs.k8s.io/kind@$(KIND_VERSION)

.PHONY: kind
kind: $(KIND) ## Download kind locally if necessary
31 changes: 31 additions & 0 deletions config/cert-manager/selfsigned-issuer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: selfsigned-ca
namespace: cert-manager
spec:
isCA: true
commonName: selfsigned-ca
secretName: selfsigned-ca-secret
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-issuer
kind: ClusterIssuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-ca-issuer
spec:
ca:
secretName: selfsigned-ca-secret
Loading
Loading