Skip to content
Merged
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
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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:/opt/homebrew/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.
Expand Down Expand Up @@ -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)/"
Expand Down
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:<version>`
```bash
docker run -it --rm -p 8084:8084 ghcr.io/kagent-dev/kagent/tools:0.0.10
```

- **Kubernetes**

`helm upgrade -i kagent-tools --version <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

Expand Down
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
78 changes: 78 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

# 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 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

```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
Comment thread
dimetron marked this conversation as resolved.
curl -sL https://raw.githubusercontent.com/agentgateway/agentgateway/refs/heads/main/common/scripts/get-agentproxy | 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.
Comment thread
dimetron marked this conversation as resolved.
```
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"]
}
}
}
```



3 changes: 2 additions & 1 deletion helm/kagent-tools/Chart-template.yaml
Original file line number Diff line number Diff line change
@@ -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}
11 changes: 9 additions & 2 deletions internal/commands/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/commands/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
24 changes: 20 additions & 4 deletions internal/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
3 changes: 2 additions & 1 deletion internal/logger/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
23 changes: 23 additions & 0 deletions scripts/agentgateway-config-tools.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
binds:
- 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