diff --git a/.ci-operator.yaml b/.ci-operator.yaml deleted file mode 100644 index b5c3b86..0000000 --- a/.ci-operator.yaml +++ /dev/null @@ -1,4 +0,0 @@ -build_root_image: - name: nodejs-18 - namespace: openshift - tag: latest \ No newline at end of file diff --git a/.github/workflows/obs-mcp-unit.yaml b/.github/workflows/unit.yaml similarity index 82% rename from .github/workflows/obs-mcp-unit.yaml rename to .github/workflows/unit.yaml index ca00861..2823001 100644 --- a/.github/workflows/obs-mcp-unit.yaml +++ b/.github/workflows/unit.yaml @@ -1,13 +1,11 @@ -name: obs-mcp-unit +name: unit on: push: pull_request: branches: - main - paths: - - "obs-mcp/**" - - ".github/workflows/obs-mcp-unit.yaml" + # To cancel running workflow when new commits pushed in a pull request concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -27,4 +25,4 @@ jobs: with: go-version: "${{ env.golang-version }}" check-latest: true - - run: make obs-mcp-test + - run: make test-unit diff --git a/.gitignore b/.gitignore index 361ebe8..11ff82e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ obs-mcp/obs-mcp .devcontainer/dev.env integration-tests/videos integration-tests/screenshots +.vscode/* diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3688a43..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "typescript.tsdk": "./node_modules/typescript/lib", - "search.exclude": { - "**/node_modules": true - }, - "files.watcherExclude": { - "**/node_modules/**": true - }, - "files.associations": { - "**/console-extensions.json": "jsonc" - }, - "yaml.schemas": { - "https://raw.githubusercontent.com/RedHat-UX/next-gen-ui-agent/refs/heads/main/spec/config/agent_config.schema.json": ["ngui_*.yaml", "ngui_*.yml"] - }, - "json.schemas": [ - { - "fileMatch": ["**/console-extensions.json"], - "url": "./node_modules/@openshift-console/dynamic-plugin-sdk-webpack/schema/console-extensions.json" - } - ] -} diff --git a/obs-mcp/Containerfile b/Containerfile similarity index 100% rename from obs-mcp/Containerfile rename to Containerfile diff --git a/obs-mcp/LICENSE b/LICENSE similarity index 100% rename from obs-mcp/LICENSE rename to LICENSE diff --git a/Makefile b/Makefile index 1df49ab..f700fc1 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CONTAINER_CLI ?= docker .PHONY: help help: ## Show this help message - @echo "Genie Plugin - Available commands:" + @echo "obs-mcp - Available commands:" @echo "" @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' @@ -14,26 +14,26 @@ check-tools: ## Check if required tools are installed @command -v $(CONTAINER_CLI) >/dev/null 2>&1 || echo "Warning: $(CONTAINER_CLI) is not installed. Container builds will fail." @echo "✓ All required tools are installed" -.PHONY: obs-mcp-build -obs-mcp-build: ## Build obs-mcp binary - @cd obs-mcp && go build -tags strictfipsruntime -o obs-mcp ./cmd/obs-mcp +.PHONY: build +build: ## Build obs-mcp binary + go build -tags strictfipsruntime -o obs-mcp ./cmd/obs-mcp -.PHONY: obs-mcp-test -obs-mcp-test: ## Run obs-mcp tests - @cd obs-mcp && go test -v -race ./... +.PHONY: test-unit +test-unit: ## Run obs-mcp unit tests + go test -v -race ./... -.PHONY: obs-mcp-clean -obs-mcp-clean: ## Clean obs-mcp build artifacts - @cd obs-mcp && go clean && rm -f obs-mcp/obs-mcp +.PHONY: clean +clean: ## Clean obs-mcp build artifacts + go clean && rm -f obs-mcp -.PHONY: obs-mcp-container -obs-mcp-container: obs-mcp-build ## Build obs-mcp container image - @cd obs-mcp && $(CONTAINER_CLI) build -f Containerfile -t obs-mcp:latest . +.PHONY: container +container: build ## Build obs-mcp container image + $(CONTAINER_CLI) build -f Containerfile -t obs-mcp:latest . .PHONY: format format: ## Format all code - @cd obs-mcp && go fmt ./... + go fmt ./... .PHONY: setup setup: check-tools ## Install dependencies for all components - @cd obs-mcp && go mod download + go mod download diff --git a/README.md b/README.md index 2afecfe..66c6e15 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,51 @@ -# obs-mcp +# obs mcp server -This is an [MCP](https://modelcontextprotocol.io/introduction) server to allow LLMs to interact with a running [Prometheus](https://prometheus.io/) instance via the API. +This is an [mcp](https://modelcontextprotocol.io/introduction) server to allow LLMs to interact with a running [Prometheus](https://prometheus.io/) instance via the API. > [!NOTE] > This project is moved from [jhadvig/genie-plugin](https://github.com/jhadvig/genie-plugin/tree/main/obs-mcp) preserving the history of commits. -## Pre-requisites +## Development Quickstart -Before starting, ensure you have the following: +The easiest way to get the obs-mcp connected to the cluster is via a kubeconfig: -- A working Lightspeed Core-based server with the capability to integrate the MCP server located in the `obs-mcp` directory of this project. -- Access to a model capable of tool calling. This project was tested with `gpt-4o-mini`. -- An environment where both Node.js (version 20 or higher) and Golang are available. Using `nvm` (Node Version Manager) and `gvm` (Go Version Manager) is recommended for managing multiple versions. -- Access to an OpenShift Container Platform (OCP) cluster with the monitoring plugin installed. + 1. Log into your OpenShift cluster + 2. Run the server with -## Getting Started + ```sh + go run ./cmd/obs-mcp/ --listen 127.0.0.1:9100 --auth-mode kubeconfig --insecure + ``` -See the [obs-mcp README](./obs-mcp/README.md) +This will connect the obs-mcp to the thanos querier running in the cluster. + +This procedure would not work if you're not using token-based auth (`oc whoami -t` to validate). +In that case, consider using serviceaccount + token auth. Alternatively, follow the procedure bellow. + +> [!NOTE] +> It is possible to hit the ground running locally as well: + +```shell +helm install prometheus-community/prometheus --name-template # sets up Prometheus (and exporters) on your local single-node k8s cluster +export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=alertmanager,app.kubernetes.io/instance=local" -o jsonpath="{.items[0].metadata.name}") && kubectl --namespace default port-forward $POD_NAME 9090 +go run ./cmd/obs-mcp/ --auth-mode header --insecure --listen :9100 +``` + +### Port-forwarding alternative + +This scenario opens a local port via port-forward that the obs-mcp will connect to: + + 1. Log into your OpenShift cluster + + 1. Port forward the OpenShift Thanos instance to a local port + +``` sh +PROM_POD=$(kubectl get pods -n openshift-monitoring -l app.kubernetes.io/instance=thanos-querier -o jsonpath="{.items[0].met +adata.name}") +kubectl port-forward -n openshift-monitoring $PROM_POD 9090:9090 +``` + + 1. Run the server with + +```sh +PROMETHEUS_URL=http://localhost:9090 go run ./cmd/obs-mcp/ --listen 127.0.0.1:9100 --auth-mode header +``` diff --git a/obs-mcp/cmd/obs-mcp/main.go b/cmd/obs-mcp/main.go similarity index 97% rename from obs-mcp/cmd/obs-mcp/main.go rename to cmd/obs-mcp/main.go index f48feb0..c380f39 100644 --- a/obs-mcp/cmd/obs-mcp/main.go +++ b/cmd/obs-mcp/main.go @@ -9,10 +9,10 @@ import ( "github.com/prometheus/common/promslog" - "github.com/inecas/obs-mcp/pkg/k8s" - "github.com/inecas/obs-mcp/pkg/mcp" - "github.com/inecas/obs-mcp/pkg/prometheus" "github.com/mark3labs/mcp-go/server" + "github.com/rhobs/obs-mcp/pkg/k8s" + "github.com/rhobs/obs-mcp/pkg/mcp" + "github.com/rhobs/obs-mcp/pkg/prometheus" ) const ( diff --git a/obs-mcp/evals/.gitignore b/evals/.gitignore similarity index 100% rename from obs-mcp/evals/.gitignore rename to evals/.gitignore diff --git a/obs-mcp/evals/README.md b/evals/README.md similarity index 100% rename from obs-mcp/evals/README.md rename to evals/README.md diff --git a/obs-mcp/evals/evals.yaml b/evals/evals.yaml similarity index 100% rename from obs-mcp/evals/evals.yaml rename to evals/evals.yaml diff --git a/obs-mcp/evals/pyproject.toml b/evals/pyproject.toml similarity index 100% rename from obs-mcp/evals/pyproject.toml rename to evals/pyproject.toml diff --git a/obs-mcp/evals/system.yaml b/evals/system.yaml similarity index 100% rename from obs-mcp/evals/system.yaml rename to evals/system.yaml diff --git a/obs-mcp/evals/uv.lock b/evals/uv.lock similarity index 100% rename from obs-mcp/evals/uv.lock rename to evals/uv.lock diff --git a/obs-mcp/go.mod b/go.mod similarity index 98% rename from obs-mcp/go.mod rename to go.mod index de60081..33fca80 100644 --- a/obs-mcp/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/inecas/obs-mcp +module github.com/rhobs/obs-mcp go 1.24.6 diff --git a/obs-mcp/go.sum b/go.sum similarity index 100% rename from obs-mcp/go.sum rename to go.sum diff --git a/obs-mcp/manifests/01_service_account.yaml b/manifests/01_service_account.yaml similarity index 100% rename from obs-mcp/manifests/01_service_account.yaml rename to manifests/01_service_account.yaml diff --git a/obs-mcp/manifests/02_deployment.yaml b/manifests/02_deployment.yaml similarity index 100% rename from obs-mcp/manifests/02_deployment.yaml rename to manifests/02_deployment.yaml diff --git a/obs-mcp/manifests/03_mcp_service.yaml b/manifests/03_mcp_service.yaml similarity index 100% rename from obs-mcp/manifests/03_mcp_service.yaml rename to manifests/03_mcp_service.yaml diff --git a/obs-mcp/.gitignore b/obs-mcp/.gitignore deleted file mode 100644 index 5eec986..0000000 --- a/obs-mcp/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.claude diff --git a/obs-mcp/README.md b/obs-mcp/README.md deleted file mode 100644 index 9226dc8..0000000 --- a/obs-mcp/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# OBS MCP Server - -## About - -This is an [MCP](https://modelcontextprotocol.io/introduction) server to allow LLMs to interact with a running [Prometheus](https://prometheus.io/) instance via the API. - -## Development Quickstart - -The easiest way to get the obs-mcp connected to the cluster is via a kubeconfig: - - 1. log into your OpenShift cluster - 2. run the server with - ```sh - go run ./cmd/obs-mcp/ --listen 127.0.0.1:9100 --auth-mode kubeconfig --insecure - ``` - -This will connect the obs-mcp to the thanos querier running in the cluster. - -This procedure would not work if you're not using token-based auth (`oc whoami -t` to validate). -In that case, consider using serviceaccount + token auth. Alternatively, follow the procedure bellow. - -NOTE: It is possible to hit the ground running locally as well: -```shell -helm install prometheus-community/prometheus --name-template # sets up Prometheus (and exporters) on your local single-node k8s cluster -export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=alertmanager,app.kubernetes.io/instance=local" -o jsonpath="{.items[0].metadata.name}") && kubectl --namespace default port-forward $POD_NAME 9090 -go run ./cmd/obs-mcp/ --auth-mode header --insecure --listen :9100 -``` - -### Port-forwarding alternative - -This scenario opens a local port via port-forward that the obs-mcp will connect to: - - 1. log into your OpenShift cluster - 2. port-forward the OpenShift thanos instance to a local port -``` sh -PROM_POD=$(kubectl get pods -n openshift-monitoring -l app.kubernetes.io/instance=thanos-querier -o jsonpath="{.items[0].met -adata.name}") -kubectl port-forward -n openshift-monitoring $PROM_POD 9090:9090 -``` - 3. run the server with - -```sh -PROMETHEUS_URL=http://localhost:9090 go run ./cmd/obs-mcp/ --listen 127.0.0.1:9100 --auth-mode header -``` diff --git a/obs-mcp/pkg/k8s/client.go b/pkg/k8s/client.go similarity index 100% rename from obs-mcp/pkg/k8s/client.go rename to pkg/k8s/client.go diff --git a/obs-mcp/pkg/mcp/auth.go b/pkg/mcp/auth.go similarity index 98% rename from obs-mcp/pkg/mcp/auth.go rename to pkg/mcp/auth.go index 660d24f..8594f3d 100644 --- a/obs-mcp/pkg/mcp/auth.go +++ b/pkg/mcp/auth.go @@ -10,10 +10,10 @@ import ( "os" "strings" - "github.com/inecas/obs-mcp/pkg/k8s" - "github.com/inecas/obs-mcp/pkg/prometheus" promapi "github.com/prometheus/client_golang/api" promcfg "github.com/prometheus/common/config" + "github.com/rhobs/obs-mcp/pkg/k8s" + "github.com/rhobs/obs-mcp/pkg/prometheus" "k8s.io/client-go/rest" ) diff --git a/obs-mcp/pkg/mcp/handlers.go b/pkg/mcp/handlers.go similarity index 99% rename from obs-mcp/pkg/mcp/handlers.go rename to pkg/mcp/handlers.go index 92de75d..6b72bf2 100644 --- a/obs-mcp/pkg/mcp/handlers.go +++ b/pkg/mcp/handlers.go @@ -9,9 +9,9 @@ import ( promModel "github.com/prometheus/common/model" - "github.com/inecas/obs-mcp/pkg/prometheus" "github.com/mark3labs/mcp-go/mcp" "github.com/prometheus/common/model" + "github.com/rhobs/obs-mcp/pkg/prometheus" ) // errorResult is a helper to log and return an error result. diff --git a/obs-mcp/pkg/mcp/handlers_test.go b/pkg/mcp/handlers_test.go similarity index 99% rename from obs-mcp/pkg/mcp/handlers_test.go rename to pkg/mcp/handlers_test.go index abbf1b5..bc6a2a9 100644 --- a/obs-mcp/pkg/mcp/handlers_test.go +++ b/pkg/mcp/handlers_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - "github.com/inecas/obs-mcp/pkg/prometheus" "github.com/mark3labs/mcp-go/mcp" + "github.com/rhobs/obs-mcp/pkg/prometheus" ) // MockedLoader is a mock implementation of prometheus.PromClient for testing diff --git a/obs-mcp/pkg/mcp/server.go b/pkg/mcp/server.go similarity index 98% rename from obs-mcp/pkg/mcp/server.go rename to pkg/mcp/server.go index 39c9cf0..3147c4e 100644 --- a/obs-mcp/pkg/mcp/server.go +++ b/pkg/mcp/server.go @@ -11,8 +11,8 @@ import ( "syscall" "time" - "github.com/inecas/obs-mcp/pkg/prometheus" "github.com/mark3labs/mcp-go/server" + "github.com/rhobs/obs-mcp/pkg/prometheus" ) // ObsMCPOptions contains configuration options for the MCP server diff --git a/obs-mcp/pkg/mcp/tools.go b/pkg/mcp/tools.go similarity index 100% rename from obs-mcp/pkg/mcp/tools.go rename to pkg/mcp/tools.go diff --git a/obs-mcp/pkg/mcp/tools_test.go b/pkg/mcp/tools_test.go similarity index 100% rename from obs-mcp/pkg/mcp/tools_test.go rename to pkg/mcp/tools_test.go diff --git a/obs-mcp/pkg/prometheus/guardrails.go b/pkg/prometheus/guardrails.go similarity index 100% rename from obs-mcp/pkg/prometheus/guardrails.go rename to pkg/prometheus/guardrails.go diff --git a/obs-mcp/pkg/prometheus/guardrails_test.go b/pkg/prometheus/guardrails_test.go similarity index 100% rename from obs-mcp/pkg/prometheus/guardrails_test.go rename to pkg/prometheus/guardrails_test.go diff --git a/obs-mcp/pkg/prometheus/loader.go b/pkg/prometheus/loader.go similarity index 100% rename from obs-mcp/pkg/prometheus/loader.go rename to pkg/prometheus/loader.go diff --git a/obs-mcp/pkg/prometheus/utils.go b/pkg/prometheus/utils.go similarity index 100% rename from obs-mcp/pkg/prometheus/utils.go rename to pkg/prometheus/utils.go