From 9d8e75dfbb254db858c807deea53747c23fbe887 Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Fri, 25 Jul 2025 11:49:34 +0200 Subject: [PATCH 1/5] =?UTF-8?q?-=20=F0=9F=90=9B=20Fix=20stdio=20implementa?= =?UTF-8?q?tion=20-=20=F0=9F=9A=80=20Add=20quickstart=20guide=20for=20agen?= =?UTF-8?q?tgateway=20-=20=F0=9F=93=9D=20Update=20cursor=20MCP=20documenta?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dmytro Rashko --- Makefile | 15 +++++ README.md | 16 +++++- cmd/main.go | 2 +- docs/quickstart.md | 79 ++++++++++++++++++++++++++ helm/kagent-tools/Chart-template.yaml | 3 +- internal/logger/logger.go | 24 ++++++-- internal/logger/logger_test.go | 3 +- scripts/agentgateway-config-tools.yaml | 19 +++++++ 8 files changed, 151 insertions(+), 10 deletions(-) create mode 100644 docs/quickstart.md create mode 100644 scripts/agentgateway-config-tools.yaml diff --git a/Makefile b/Makefile index 6be3920..214db36 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,13 @@ LDFLAGS := -X github.com/kagent-dev/tools/internal/version.Version=$(VERSION) -X ## Location to install dependencies to LOCALBIN ?= $(shell pwd)/bin +PATH := $HOME/local/bin:$(LOCALBIN):$(PATH) HELM_DIST_FOLDER ?= $(shell pwd)/dist .PHONY: clean clean: rm -rf ./bin/kagent-tools-* + rm -rf $(HOME)/.local/bin/kagent-tools-* .PHONY: fmt fmt: ## Run go fmt against code. @@ -210,6 +212,19 @@ otel-local: docker run -d --name jaeger-desktop --restart=always -p 16686:16686 -p 4317:4317 -p 4318:4318 jaegertracing/jaeger:2.7.0 open http://localhost:16686/ +.PHONY: tools-install +tools-install: clean + mkdir -p $HOME/.local/bin + go build -ldflags "$(LDFLAGS)" -o $(LOCALBIN)/kagent-tools ./cmd + go build -ldflags "$(LDFLAGS)" -o $(HOME)/.local/bin/kagent-tools ./cmd + $HOME/.local/bin/kagent-tools --version + +.PHONY: run-agentgateway +run-agentgateway: tools-install + open http://localhost:15000/ui + cd scripts \ + && agentgateway -f agentgateway-config-tools.yaml + .PHONY: report/image-cve report/image-cve: docker-build govulncheck echo "Running CVE scan :: CVE -> CSV ... reports/$(SEMVER)/" diff --git a/README.md b/README.md index f26ccf9..0bc29be 100644 --- a/README.md +++ b/README.md @@ -28,16 +28,26 @@ This directory contains the Go implementation of all KAgent tools, migrated from - **Bash:** -`curl -sL https://github.com/kagent-dev/tools/blob/main/scripts/install.sh | bash` +```bash +curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/install.sh | bash +``` - **Docker:** -`docker run -it --rm ghcr.io/kagent-dev/kagent/tools:` +```bash +docker run -it --rm -p 8084:8084 ghcr.io/kagent-dev/kagent/tools:0.0.10 +``` - **Kubernetes** -`helm upgrade -i kagent-tools --version oci://ghcr.io/kagent-dev/tools/helm/` +```bash +helm upgrade -i -n kagent --create-namespace kagent-tools oci://ghcr.io/kagent-dev/tools/helm/kagent-tools --version 0.0.10 +helm ls -A +``` + +## Quickstart Guide +For a quickstart guide on how to run KAgent tools using AgentGateway, please refer to the [Quickstart Guide](docs/quickstart.md). ## Architecture diff --git a/cmd/main.go b/cmd/main.go index 03a2665..fa737dd 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -89,7 +89,7 @@ func run(cmd *cobra.Command, args []string) { return } - logger.Init() + logger.Init(stdio) defer logger.Sync() // Setup context with cancellation for graceful shutdown diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..e521f0f --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,79 @@ + +# Quickstart Guide for KAgnet Tools + +## About this guide + +This guide provides a quick overview of how to set up and run KAgent tools using AgentGateway. + +For more detaled information on KAgent tools, please refer to the [KAgent Tools Documentation](https://kagent.dev/tools). + +To learn more about agentgateway, see [AgentGateway](https://agentgateway.dev/docs/about/) + +### Running KAgent Tools using AgentGateway + +1. Download the agentgateway binary and install it. +2. Download KAgent tools binary and install it. +3. Download a basic configuration file for your agentgateway. +4. Run the agentgateway with the configuration file. +5. open http://localhost:15000/ui + +```bash +curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/install.sh | bash +curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/agentgateway-config-tools.yaml +curl -sL https://raw.githubusercontent.com/agentgateway/agentgateway/refs/heads/main/common/scripts/get-agentproxy | bash +curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/install.sh | bash + +export PATH=$PATH:$HOME/.local/bin/ +agentgateway -f agentgateway-config-tools.yaml +``` + +agentgateway-config-tools.yaml: +```yaml +binds: + - port: 30805 + listeners: + - routes: + - policies: + cors: + allowOrigins: + - "*" + allowHeaders: + - mcp-protocol-version + - content-type + backends: + - mcp: + name: default + targets: + - name: kagent-tools + stdio: + cmd: kagent-tools + args: ["--stdio", "--kubeconfig", "~/.kube/config"] +``` +Afterwards, you can run it with make command +```bash +make run-agentgateway +``` + +### Running KAgent Tools using Cursor MCP + + +1. Download the agentgateway binary and install it. +``` +curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/install.sh | bash +``` + +2. Create `.cursor/mcp.json` + +```json +{ + "mcpServers": { + "kagent-tools": { + "command": "kagent-tools", + "args": ["--stdio", "--kubeconfig", "~/.kube/config"] + } + } +} +``` + + + diff --git a/helm/kagent-tools/Chart-template.yaml b/helm/kagent-tools/Chart-template.yaml index 6fb1a68..3d2eb2b 100644 --- a/helm/kagent-tools/Chart-template.yaml +++ b/helm/kagent-tools/Chart-template.yaml @@ -1,5 +1,6 @@ apiVersion: v2 name: kagent-tools -description: A Helm chart for kagent-tools, +description: A Helm chart for kagent-tools type: application version: ${VERSION} +appVersion: ${VERSION} \ No newline at end of file diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 041d499..b9a078f 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -10,23 +10,39 @@ import ( var globalLogger *slog.Logger -func Init() { +// Init initializes the global logger +// If useStderr is true, logs will be written to stderr (for stdio mode) +// If useStderr is false, logs will be written to stdout (for HTTP mode) +func Init(useStderr bool) { opts := &slog.HandlerOptions{ Level: slog.LevelInfo, } + // Choose output destination based on mode + output := os.Stdout + if useStderr { + output = os.Stderr + } + if os.Getenv("KAGENT_LOG_FORMAT") == "json" { - globalLogger = slog.New(slog.NewJSONHandler(os.Stdout, opts)) + globalLogger = slog.New(slog.NewJSONHandler(output, opts)) } else { - globalLogger = slog.New(slog.NewTextHandler(os.Stdout, opts)) + globalLogger = slog.New(slog.NewTextHandler(output, opts)) } slog.SetDefault(globalLogger) } +// InitWithEnv initializes the logger using environment variables +// This is a convenience function that defaults to stdout unless KAGENT_USE_STDERR is set +func InitWithEnv() { + useStderr := os.Getenv("KAGENT_USE_STDERR") == "true" + Init(useStderr) +} + func Get() *slog.Logger { if globalLogger == nil { - Init() + InitWithEnv() } return globalLogger } diff --git a/internal/logger/logger_test.go b/internal/logger/logger_test.go index ad5c988..efca71e 100644 --- a/internal/logger/logger_test.go +++ b/internal/logger/logger_test.go @@ -64,7 +64,8 @@ func TestGet(t *testing.T) { } func TestInit(t *testing.T) { - assert.NotPanics(t, Init) + assert.NotPanics(t, func() { Init(false) }) + assert.NotPanics(t, func() { Init(true) }) } func TestSync(t *testing.T) { diff --git a/scripts/agentgateway-config-tools.yaml b/scripts/agentgateway-config-tools.yaml new file mode 100644 index 0000000..958ca0b --- /dev/null +++ b/scripts/agentgateway-config-tools.yaml @@ -0,0 +1,19 @@ +binds: + - port: 30805 + listeners: + - routes: + - policies: + cors: + allowOrigins: + - "*" + allowHeaders: + - mcp-protocol-version + - content-type + backends: + - mcp: + name: default + targets: + - name: kagent-tools + stdio: + cmd: kagent-tools + args: ["--stdio", "--kubeconfig", "~/.kube/config"] \ No newline at end of file From 5d8d504de995a456dc1550ac7954f1d5906232ea Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Fri, 25 Jul 2025 12:30:40 +0200 Subject: [PATCH 2/5] =?UTF-8?q?-=20=F0=9F=90=9B=20Fix=20stdio=20implementa?= =?UTF-8?q?tion=20-=20=F0=9F=9A=80=20Add=20quickstart=20guide=20for=20agen?= =?UTF-8?q?tgateway=20-=20=F0=9F=93=9D=20Update=20cursor=20MCP=20documenta?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dmytro Rashko --- scripts/agentgateway-config-tools.yaml | 40 ++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/scripts/agentgateway-config-tools.yaml b/scripts/agentgateway-config-tools.yaml index 958ca0b..67863bb 100644 --- a/scripts/agentgateway-config-tools.yaml +++ b/scripts/agentgateway-config-tools.yaml @@ -1,19 +1,23 @@ binds: - - port: 30805 - listeners: - - routes: - - policies: - cors: - allowOrigins: - - "*" - allowHeaders: - - mcp-protocol-version - - content-type - backends: - - mcp: - name: default - targets: - - name: kagent-tools - stdio: - cmd: kagent-tools - args: ["--stdio", "--kubeconfig", "~/.kube/config"] \ No newline at end of file +- port: 30805 + listeners: + - routes: + - backends: + - mcp: + name: default + targets: + - name: kagent-tools + stdio: + cmd: kagent-tools + args: + - --stdio + - --kubeconfig + - ~/.kube/config + policies: + cors: + allowOrigins: + - '*' + allowHeaders: + - mcp-protocol-version + - content-type + - cache-control From 30e0dbea78d499a2b4cf388cee11704bbeda29a7 Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Fri, 25 Jul 2025 12:34:07 +0200 Subject: [PATCH 3/5] add homebrew path Signed-off-by: Dmytro Rashko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 214db36..8f9fcf9 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ LDFLAGS := -X github.com/kagent-dev/tools/internal/version.Version=$(VERSION) -X ## Location to install dependencies to LOCALBIN ?= $(shell pwd)/bin -PATH := $HOME/local/bin:$(LOCALBIN):$(PATH) +PATH := $HOME/local/bin:/opt/homebrew/bin/:$(LOCALBIN):$(PATH) HELM_DIST_FOLDER ?= $(shell pwd)/dist .PHONY: clean From 4279f9c430843a084f9f2cc8351397712b51cf61 Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Fri, 25 Jul 2025 12:44:39 +0200 Subject: [PATCH 4/5] increase default timeout Signed-off-by: Dmytro Rashko --- internal/commands/builder.go | 11 +++++++++-- internal/commands/builder_test.go | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/internal/commands/builder.go b/internal/commands/builder.go index f3e75ce..e0ec477 100644 --- a/internal/commands/builder.go +++ b/internal/commands/builder.go @@ -15,6 +15,13 @@ import ( "go.opentelemetry.io/otel/attribute" ) +const ( + // DefaultTimeout is the default timeout for command execution + DefaultTimeout = 2 * time.Minute + // DefaultCacheTTL is the default cache TTL + DefaultCacheTTL = 1 * time.Minute +) + // CommandBuilder provides a fluent interface for building CLI commands type CommandBuilder struct { command string @@ -43,10 +50,10 @@ func NewCommandBuilder(command string) *CommandBuilder { args: make([]string, 0), labels: make(map[string]string), annotations: make(map[string]string), - timeout: 60 * time.Second, + timeout: DefaultTimeout, useTimeout: false, // Only enable timeout when explicitly requested validate: true, - cacheTTL: 1 * time.Minute, + cacheTTL: DefaultCacheTTL, } } diff --git a/internal/commands/builder_test.go b/internal/commands/builder_test.go index 52dc0ec..377afeb 100644 --- a/internal/commands/builder_test.go +++ b/internal/commands/builder_test.go @@ -19,8 +19,8 @@ func TestNewCommandBuilder(t *testing.T) { assert.Empty(t, cb.output) assert.NotNil(t, cb.labels) assert.NotNil(t, cb.annotations) - assert.Equal(t, 60*time.Second, cb.timeout) - assert.Equal(t, 1*time.Minute, cb.cacheTTL) + assert.Equal(t, DefaultTimeout, cb.timeout) + assert.Equal(t, DefaultCacheTTL, cb.cacheTTL) assert.True(t, cb.validate) assert.False(t, cb.cached) assert.False(t, cb.dryRun) From d5869953b59dbdb2f9c50cda3a20e3702638b269 Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Fri, 25 Jul 2025 14:22:31 +0200 Subject: [PATCH 5/5] quickstart updated Signed-off-by: Dmytro Rashko --- docs/quickstart.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index e521f0f..85b86cc 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -11,9 +11,9 @@ To learn more about agentgateway, see [AgentGateway](https://agentgateway.dev/do ### Running KAgent Tools using AgentGateway -1. Download the agentgateway binary and install it. -2. Download KAgent tools binary and install it. -3. Download a basic configuration file for your agentgateway. +1. Download tools binary and install it. +2. Download tools configuration file for agentgateway. +3. Download the agentgateway binary and install it. 4. Run the agentgateway with the configuration file. 5. open http://localhost:15000/ui @@ -21,7 +21,6 @@ To learn more about agentgateway, see [AgentGateway](https://agentgateway.dev/do curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/install.sh | bash curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/agentgateway-config-tools.yaml curl -sL https://raw.githubusercontent.com/agentgateway/agentgateway/refs/heads/main/common/scripts/get-agentproxy | bash -curl -sL https://raw.githubusercontent.com/kagent-dev/tools/refs/heads/main/scripts/install.sh | bash export PATH=$PATH:$HOME/.local/bin/ agentgateway -f agentgateway-config-tools.yaml