Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
95aeb47
add helm chart
ilackarms Jul 11, 2025
7bfc654
wire helm chart to e2e test
ilackarms Jul 11, 2025
0dcf72b
add make target to generate crds from kubebuilder outputs
ilackarms Jul 11, 2025
29f9127
update readme
ilackarms Jul 12, 2025
382fab6
put down base for kmcp cli; stubs for init and build
ilackarms Jul 13, 2025
562dcc5
feat: modernize Python templates with uv package manager and add core…
ilackarms Jul 14, 2025
79038cd
add templates for other frameworks
ilackarms Jul 14, 2025
fdbb438
Refactor template system to replace old tool types (database/filesyst…
ilackarms Jul 15, 2025
43cd75e
remove tool type and fix dynamic loader
ilackarms Jul 16, 2025
3c4045e
wip: deploy; fixing container
ilackarms Jul 16, 2025
12c0033
regenerate init file when adding tools
ilackarms Jul 16, 2025
4a7b11a
fix mcp deployment default args
jmhbh Jul 17, 2025
d063c77
remove non-fast mcp framework implementations, additional cli options…
jmhbh Jul 17, 2025
67f1d0c
fix lint issues
jmhbh Jul 18, 2025
1c9aa14
undo make target change, more lint fixes
jmhbh Jul 18, 2025
dffc910
fix lint issues
jmhbh Jul 18, 2025
a47c8f6
replace print stmts with logs so they aren't sent to stdout which bre…
jmhbh Jul 18, 2025
b9c7047
add Helm chart (#2)
ilackarms Jul 19, 2025
a42f0c1
Merge branch 'main' into buildpacks
jmhbh Jul 21, 2025
d02dcfe
add controller deployment support to kmcp cli, + additionally ergonom…
jmhbh Jul 21, 2025
1d95ddf
fix helm unit tests
jmhbh Jul 21, 2025
dffd06e
fix lint issues
jmhbh Jul 21, 2025
34e53a9
remove unused func
jmhbh Jul 21, 2025
8ab1d4d
use kcmp cli to deploy mcp server in e2e test
jmhbh Jul 21, 2025
21c40fa
fix lint issues
jmhbh Jul 22, 2025
12f68b2
remove unnecessary make target
jmhbh Jul 22, 2025
29b4089
fix tag and push workflow release step to only build cli and include …
jmhbh Jul 22, 2025
ce030b8
remove duplicate build-cli step
jmhbh Jul 22, 2025
043ba45
add kmcp deploy cmd usage to readme.md
jmhbh Jul 22, 2025
ff13489
update e2e test to use binary in dist folder
jmhbh Jul 22, 2025
8f44655
refactor mcp generation
ilackarms Jul 22, 2025
8fc421a
refactor(templates): modularize framework generators
ilackarms Jul 22, 2025
d3b5183
remove typescript references
jmhbh Jul 22, 2025
9428318
fix lint issue
jmhbh Jul 22, 2025
c41d6e9
fix incorrect generation of secret yaml and add cmd to generate secre…
jmhbh Jul 22, 2025
3aa066a
make controller deployment sub command
jmhbh Jul 22, 2025
b4be453
fix generated README
jmhbh Jul 22, 2025
4822a60
first pass at adding secrets to mcp server
jmhbh Jul 22, 2025
239bd1b
fix e2e test
jmhbh Jul 23, 2025
23f98ba
update helm template mcp server crd
jmhbh Jul 23, 2025
e94dfd8
fix lint issues
jmhbh Jul 23, 2025
c4cbcf3
fix lint issues
jmhbh Jul 23, 2025
9f9c115
continued secrets work
jmhbh Jul 23, 2025
ad96603
envFrom approach working, updated tests and removed obsolete generate…
jmhbh Jul 23, 2025
80a9596
add more instructions for local development in init command, clean up…
jmhbh Jul 23, 2025
195f3aa
remove unused changes
jmhbh Jul 23, 2025
a3a5cde
fix go & python lint issues
jmhbh Jul 23, 2025
22c8fa5
lint issue
jmhbh Jul 23, 2025
c10d4ef
update cmd description
jmhbh Jul 24, 2025
411454e
change help text
ilackarms Jul 25, 2025
001ab70
remove tool / template type
ilackarms Jul 25, 2025
a8afa45
sanitize label value
ilackarms Jul 25, 2025
b099afd
remove regenerate init
ilackarms Jul 25, 2025
f9b3258
refactor init, deploy, and secrets commands
ilackarms Jul 26, 2025
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
2 changes: 2 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: Lint

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
lint:
Expand Down
109 changes: 109 additions & 0 deletions .github/workflows/tag.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Tag and Push

on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
version:
description: 'Version number'

# https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#release
# GITHUB_SHA = Last commit in the tagged release
# GITHUB_REF = Tag ref of release refs/tags/<tag_name>
jobs:
push-images:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@main

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
name: kmcp-builder-v0.23.0
platforms: linux/amd64,linux/arm64
version: v0.23.0
use: 'true'
- name: 'Build Images'
env:
DOCKER_BUILDER: "docker buildx"
DOCKER_BUILD_ARGS: "--push --platform linux/amd64,linux/arm64"
run: |
# if workflow_dispatch is used, use the version input
if [ -n "${{ github.event.inputs.version }}" ]; then
export VERSION=${{ github.event.inputs.version }}
else
export VERSION=$(echo "$GITHUB_REF" | cut -c12-)
fi
echo "Building Docker image with version: ${VERSION}"
make docker-build VERSION=${VERSION}
push-helm-chart:
needs:
- push-images
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@main

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: 'Build and Publish Helm Chart'
run: |
# if workflow_dispatch is used, use the version input
if [ -n "${{ github.event.inputs.version }}" ]; then
export VERSION=${{ github.event.inputs.version }}
else
export VERSION=$(echo "$GITHUB_REF" | cut -c12-)
fi
echo "Publishing Helm chart with version: ${VERSION}"
make helm-publish VERSION=${VERSION}
release:
# Only run release after images and helm chart are pushed
# In the future we can take the chart from the helm action,
# and build the CLI beforehand.
needs:
- push-helm-chart
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build
run: |
# if workflow_dispatch is used, use the version input
if [ -n "${{ github.event.inputs.version }}" ]; then
export VERSION=${{ github.event.inputs.version }}
else
export VERSION=$(echo "$GITHUB_REF" | cut -c12-)
fi
echo "Building release artifacts with version: ${VERSION}"
make build-cli VERSION=${VERSION}
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
dist/kmcp
17 changes: 5 additions & 12 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: E2E Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test-e2e:
Expand All @@ -17,19 +19,10 @@ jobs:
with:
go-version-file: go.mod

- name: Install the latest version of kind
run: |
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

- name: Verify kind installation
run: kind version

- name: Create kind cluster
run: kind create cluster

- name: Create k8s Kind Cluster
uses: helm/kind-action@v1
- name: Running Test e2e
run: |
kind create cluster
go mod tidy
make test-e2e
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.DS_Store

# Binaries for programs and plugins
*.exe
*.exe~
Expand Down Expand Up @@ -25,3 +27,5 @@ go.work
*.swp
*.swo
*~
# helm
dist/
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM docker.io/golang:1.24 AS builder
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.24 AS builder
ARG TARGETOS
ARG TARGETARCH

Expand Down Expand Up @@ -31,4 +31,9 @@ WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532


LABEL org.opencontainers.image.source=https://github.com/kagent-dev/kmcp
LABEL org.opencontainers.image.description="KMCP is the Kubernetes MCP Server Controller."
LABEL org.opencontainers.image.authors="KAgent Creators 🤖"

ENTRYPOINT ["/manager"]
145 changes: 85 additions & 60 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# Image configuration
DOCKER_REGISTRY ?= ghcr.io
BASE_IMAGE_REGISTRY ?= cgr.dev
DOCKER_REPO ?= kagent-dev/kmcp
HELM_REPO ?= oci://ghcr.io/kagent-dev

BUILD_DATE := $(shell date -u '+%Y-%m-%d')
GIT_COMMIT := $(shell git rev-parse --short HEAD || echo "unknown")
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null | sed 's/-dirty//' | grep v || echo "v0.0.1+$(GIT_COMMIT)")

# Local architecture detection to build for the current platform
LOCALARCH ?= $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')

# Docker buildx configuration
BUILDKIT_VERSION = v0.23.0
BUILDX_NO_DEFAULT_ATTESTATIONS=1
BUILDX_BUILDER_NAME ?= kmcp-builder-$(BUILDKIT_VERSION)
DOCKER_BUILDER ?= docker buildx
DOCKER_BUILD_ARGS ?= --builder $(BUILDX_BUILDER_NAME) --pull --load --platform linux/$(LOCALARCH)

# Image configuration
CONTROLLER_IMAGE_NAME ?= controller
CONTROLLER_IMAGE_TAG ?= $(VERSION)
CONTROLLER_IMG ?= $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(CONTROLLER_IMAGE_NAME):$(CONTROLLER_IMAGE_TAG)

# Image URL to use all building/pushing image targets (backward compatibility)
IMG ?= $(CONTROLLER_IMG)
DIST_FOLDER ?= dist

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
Expand All @@ -8,12 +34,6 @@ else
GOBIN=$(shell go env GOBIN)
endif

# CONTAINER_TOOL defines the container tool to be used for building images.
# Be aware that the target commands are only tested with Docker which is
# scaffolded by default. However, you might want to replace it to use other
# tools. (i.e. podman)
CONTAINER_TOOL ?= docker

# Setting SHELL to bash allows bash commands to be executed by recipes.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
Expand Down Expand Up @@ -45,6 +65,52 @@ help: ## Display this help.
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases

.PHONY: helm-lint
helm-lint:
helm lint helm/kmcp

.PHONY: helm-package
helm-package:
mkdir -p $(DIST_FOLDER)
@echo "Packaging Helm chart with version $(VERSION)..."
@cp helm/kmcp/Chart.yaml helm/kmcp/Chart.yaml.bak
@sed "s/^version: .*/version: $(VERSION)/" helm/kmcp/Chart.yaml.bak > helm/kmcp/Chart.yaml
@helm package helm/kmcp --version $(VERSION) -d $(DIST_FOLDER)
@mv helm/kmcp/Chart.yaml.bak helm/kmcp/Chart.yaml
@echo "Helm package created: $(DIST_FOLDER)/kmcp-$(VERSION).tgz"

.PHONY: helm-cleanup
helm-cleanup: ## Clean up Helm chart packages
rm -f $(DIST_FOLDER)/*.tgz

.PHONY: helm-build
helm-build: helm-lint helm-package ## Build and package the Helm chart
@echo "Helm chart built successfully"

.PHONY: helm-publish
helm-publish: helm-package ## Publish Helm chart to OCI registry
@echo "Publishing Helm chart to $(HELM_REPO)/kmcp/helm..."
@helm push $(DIST_FOLDER)/kmcp-$(VERSION).tgz $(HELM_REPO)/kmcp/helm
@echo "Helm chart published successfully"

.PHONY: helm-test
helm-test:
@echo "Running Helm chart unit tests..."
@command -v helm >/dev/null 2>&1 || { \
echo "Helm is not installed. Please install Helm manually."; \
exit 1; \
}
@helm plugin list | grep -q 'unittest' || { \
echo "Installing helm-unittest plugin..."; \
helm plugin install https://github.com/quintush/helm-unittest; \
}
@helm unittest helm/kmcp
@echo "Helm chart unit tests completed successfully"

.PHONY: manifests-all
manifests-all: manifests ## Generate Kustomize from source definitions.
@echo "All manifests (Kustomize and Helm) updated successfully"

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
Expand Down Expand Up @@ -76,7 +142,7 @@ test-e2e: manifests generate fmt vet ## Run the e2e tests. Expected an isolated
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
exit 1; \
}
go test ./test/e2e/ -v -ginkgo.v
go test ./test/e2e/ -v

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
Expand All @@ -96,6 +162,11 @@ lint-config: golangci-lint ## Verify golangci-lint linter configuration
build: manifests generate fmt vet ## Build manager binary.
go build -o bin/manager cmd/main.go

.PHONY: build-cli
build-cli: fmt vet ## Build kmcp CLI binary.
mkdir -p $(DIST_FOLDER)
go build -ldflags="-X 'kagent.dev/kmcp/cmd/kmcp/cmd.Version=$(VERSION)'" -o $(DIST_FOLDER)/kmcp cmd/kmcp/main.go

.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./cmd/main.go
Expand All @@ -105,57 +176,15 @@ run: manifests generate fmt vet ## Run a controller from your host.
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
.PHONY: docker-build
docker-build: ## Build docker image with the manager.
$(CONTAINER_TOOL) build -t ${IMG} .
- $(DOCKER_BUILDER) create --name $(BUILDX_BUILDER_NAME)
$(DOCKER_BUILDER) use $(BUILDX_BUILDER_NAME)
$(DOCKER_BUILDER) build $(DOCKER_BUILD_ARGS) -t ${CONTROLLER_IMG} .
- $(DOCKER_BUILDER) rm $(BUILDX_BUILDER_NAME)

.PHONY: docker-push
docker-push: ## Push docker image with the manager.
$(CONTAINER_TOOL) push ${IMG}

# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/
# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
.PHONY: docker-buildx
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name kmcp-builder
$(CONTAINER_TOOL) buildx use kmcp-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm kmcp-builder
rm Dockerfile.cross

.PHONY: build-installer
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
mkdir -p dist
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default > dist/install.yaml

##@ Deployment

ifndef ignore-not-found
ignore-not-found = false
endif

.PHONY: install
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -

.PHONY: uninstall
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
$(DOCKER_BUILDER) push ${CONTROLLER_IMG}

.PHONY: undeploy
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -

##@ Dependencies

Expand All @@ -180,10 +209,6 @@ ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller
ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d", $$3}')
GOLANGCI_LINT_VERSION ?= v1.63.4

.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE): $(LOCALBIN)
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))

.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
Expand Down
Loading