Skip to main content
Glama
ci.yml20.2 kB
name: ci on: push: branches: - main pull_request: permissions: contents: read jobs: build-and-test: runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [20.x, 22.x] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix['node-version'] }} cache: npm - run: npm ci - run: npm run lint - run: npm run build -w @prodisco/search-libs - run: npm run build -w @prodisco/prometheus-client - run: npm run build -w @prodisco/loki-client - run: npm run proto:generate -w @prodisco/sandbox-server - run: npm run build -w @prodisco/sandbox-server - run: npm run build - run: npm run test - name: Run transport security tests run: npm run test:security -w @prodisco/sandbox-server container-integration: runs-on: ubuntu-latest needs: build-and-test steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22.x cache: npm - name: Install dependencies run: npm ci - name: Build packages run: | npm run build -w @prodisco/search-libs npm run build -w @prodisco/prometheus-client npm run build -w @prodisco/loki-client npm run proto:generate -w @prodisco/sandbox-server npm run build -w @prodisco/sandbox-server npm run build - name: Install kind uses: helm/kind-action@v1 with: install_only: true - name: Install kubectl uses: azure/setup-kubectl@v4 - name: Run container integration tests run: ./scripts/integration/run-container-integration.sh - name: Upload artifacts on failure if: failure() uses: actions/upload-artifact@v4 with: name: container-integration-artifacts path: artifacts/container-integration/ retention-days: 7 npm-pack-integration: runs-on: ubuntu-latest needs: build-and-test steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22.x cache: npm - name: Install dependencies run: npm ci - name: Create Kind cluster uses: helm/kind-action@v1 with: cluster_name: npm-pack-int - name: Install kubectl uses: azure/setup-kubectl@v4 - name: Wait for cluster to be ready run: | kubectl wait --for=condition=Ready nodes --all --timeout=120s kubectl cluster-info - name: Run npm pack integration tests timeout-minutes: 5 run: ./scripts/integration/run-npm-pack-integration.sh - name: Upload artifacts on failure if: failure() uses: actions/upload-artifact@v4 with: name: npm-pack-integration-artifacts path: artifacts/npm-pack-integration/ retention-days: 7 cluster-integration: runs-on: ubuntu-latest needs: build-and-test steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22.x cache: npm - name: Install dependencies run: npm ci - name: Build packages run: | npm run build -w @prodisco/search-libs npm run build -w @prodisco/prometheus-client npm run build -w @prodisco/loki-client npm run proto:generate -w @prodisco/sandbox-server npm run build -w @prodisco/sandbox-server - name: Install helm uses: azure/setup-helm@v4 - name: Create Kind cluster uses: helm/kind-action@v1 with: cluster_name: cluster-int - name: Install kubectl uses: azure/setup-kubectl@v4 - name: Wait for cluster to be ready run: | kubectl wait --for=condition=Ready nodes --all --timeout=120s kubectl cluster-info - name: Install Prometheus run: | # Install kube-prometheus-stack via helm helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update kubectl create namespace monitoring helm install prometheus prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false \ --set grafana.enabled=false \ --set alertmanager.enabled=false \ --wait --timeout 5m - name: Port-forward Prometheus run: | kubectl -n monitoring port-forward svc/prometheus-kube-prometheus-prometheus 9090:9090 & sleep 5 # Verify Prometheus is accessible curl -s http://localhost:9090/-/healthy || echo "Prometheus health check failed" - name: Run cluster integration tests timeout-minutes: 10 run: npm test -w @prodisco/sandbox-server -- cluster-integration - name: Collect logs on failure if: failure() run: | mkdir -p artifacts/cluster-integration kubectl get pods -A > artifacts/cluster-integration/pods.txt kubectl -n monitoring logs -l app.kubernetes.io/name=prometheus --tail=100 > artifacts/cluster-integration/prometheus.log 2>&1 || true kubectl cluster-info dump > artifacts/cluster-integration/cluster-dump.txt 2>&1 || true - name: Upload artifacts on failure if: failure() uses: actions/upload-artifact@v4 with: name: cluster-integration-artifacts path: artifacts/cluster-integration/ retention-days: 7 http-transport-integration: runs-on: ubuntu-latest needs: build-and-test steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22.x cache: npm - name: Install dependencies run: npm ci - name: Build packages run: | npm run build -w @prodisco/search-libs npm run build -w @prodisco/prometheus-client npm run build -w @prodisco/loki-client npm run proto:generate -w @prodisco/sandbox-server npm run build -w @prodisco/sandbox-server npm run build - name: Create Kind cluster uses: helm/kind-action@v1 with: cluster_name: http-int - name: Install kubectl uses: azure/setup-kubectl@v4 - name: Wait for cluster to be ready run: | kubectl wait --for=condition=Ready nodes --all --timeout=120s kubectl cluster-info - name: Build and load Docker image run: | npm run docker:build:config -- --config examples/prodisco.kubernetes.yaml --tag test --mcp-image prodisco/mcp-server --skip-sandbox kind load docker-image prodisco/mcp-server:test --name http-int - name: Deploy MCP server run: kubectl apply -f k8s/mcp-server.yaml - name: Wait for deployment run: | kubectl wait --for=condition=Available --timeout=180s deployment/mcp-server -n prodisco kubectl wait --for=condition=Ready --timeout=60s pod -l app=mcp-server -n prodisco - name: Start port-forward run: | kubectl port-forward -n prodisco svc/mcp-server 3000:3000 & sleep 5 - name: Test health endpoint run: | HEALTH=$(curl -s http://localhost:3000/health) echo "Health response: $HEALTH" echo "$HEALTH" | grep -q '"status":"ok"' - name: Test MCP initialize run: | RESPONSE=$(curl -s -i -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"ci-test","version":"1.0.0"}}}') echo "$RESPONSE" # Verify we got a session ID echo "$RESPONSE" | grep -i "mcp-session-id:" # Verify response contains server info echo "$RESPONSE" | grep -q "kubernetes-mcp" - name: Test MCP tools/list run: | # Get session ID INIT_RESPONSE=$(curl -s -i -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"ci-test","version":"1.0.0"}}}') SESSION_ID=$(echo "$INIT_RESPONSE" | grep -i "mcp-session-id:" | cut -d' ' -f2 | tr -d '\r') echo "Session ID: $SESSION_ID" # List tools TOOLS=$(curl -s -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "mcp-session-id: $SESSION_ID" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}') echo "$TOOLS" echo "$TOOLS" | grep -q "prodisco.searchTools" echo "$TOOLS" | grep -q "prodisco.runSandbox" - name: Test prodisco.searchTools run: | # Get session ID INIT_RESPONSE=$(curl -s -i -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"ci-test","version":"1.0.0"}}}') SESSION_ID=$(echo "$INIT_RESPONSE" | grep -i "mcp-session-id:" | cut -d' ' -f2 | tr -d '\r') # Call searchTools with current schema (methodName, documentType, library, category) RESULT=$(curl -s -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "mcp-session-id: $SESSION_ID" \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"prodisco.searchTools","arguments":{"methodName":"listNamespace","documentType":"method","library":"@kubernetes/client-node","limit":3}}}') echo "$RESULT" echo "$RESULT" | grep -q "result" - name: Collect logs on failure if: failure() run: | mkdir -p artifacts/http-integration kubectl get pods -A > artifacts/http-integration/pods.txt kubectl -n prodisco logs -l app=mcp-server --tail=200 > artifacts/http-integration/mcp-server.log 2>&1 || true kubectl describe pod -n prodisco -l app=mcp-server > artifacts/http-integration/pod-describe.txt 2>&1 || true - name: Upload artifacts on failure if: failure() uses: actions/upload-artifact@v4 with: name: http-integration-artifacts path: artifacts/http-integration/ retention-days: 7 tls-integration: runs-on: ubuntu-latest needs: build-and-test steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22.x cache: npm - name: Install dependencies run: npm ci - name: Build packages run: | npm run build -w @prodisco/search-libs npm run build -w @prodisco/prometheus-client npm run build -w @prodisco/loki-client npm run proto:generate -w @prodisco/sandbox-server npm run build -w @prodisco/sandbox-server - name: Create Kind cluster uses: helm/kind-action@v1 with: cluster_name: prodisco-test - name: Install kubectl uses: azure/setup-kubectl@v4 - name: Wait for cluster to be ready run: | kubectl wait --for=condition=Ready nodes --all --timeout=120s kubectl cluster-info - name: Install cert-manager run: | kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml kubectl wait --for=condition=Available --timeout=120s deployment/cert-manager -n cert-manager kubectl wait --for=condition=Available --timeout=120s deployment/cert-manager-webhook -n cert-manager kubectl wait --for=condition=Available --timeout=120s deployment/cert-manager-cainjector -n cert-manager - name: Build and load Docker image run: | npm run docker:build:config -- --config examples/prodisco.kubernetes.yaml --tag test --sandbox-image prodisco/sandbox-server --skip-mcp kind load docker-image prodisco/sandbox-server:test --name prodisco-test - name: Create namespace run: kubectl create namespace prodisco - name: Apply cert-manager resources run: | kubectl apply -f packages/sandbox-server/k8s/cert-manager/issuer.yaml # Wait for CA secret to be created for i in {1..30}; do if kubectl get secret sandbox-ca-secret -n prodisco &>/dev/null; then echo "CA secret created" break fi echo "Waiting for CA secret... ($i/30)" sleep 2 done kubectl apply -f packages/sandbox-server/k8s/cert-manager/server-certificate.yaml kubectl apply -f packages/sandbox-server/k8s/cert-manager/client-certificate.yaml - name: Wait for certificates run: | for cert in sandbox-server-tls sandbox-client-tls; do for i in {1..30}; do STATUS=$(kubectl get certificate $cert -n prodisco -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "") if [ "$STATUS" = "True" ]; then echo "$cert is ready" break fi echo "Waiting for $cert... ($i/30)" sleep 2 done done - name: Deploy sandbox-server with TLS run: | # Apply deployment with TLS configuration cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: sandbox-server namespace: prodisco labels: app: sandbox-server spec: replicas: 1 selector: matchLabels: app: sandbox-server template: metadata: labels: app: sandbox-server spec: serviceAccountName: sandbox-server containers: - name: sandbox image: prodisco/sandbox-server:test imagePullPolicy: IfNotPresent ports: - containerPort: 50051 name: grpc protocol: TCP env: - name: SANDBOX_USE_TCP value: "true" - name: SANDBOX_TCP_HOST value: "0.0.0.0" - name: SANDBOX_TCP_PORT value: "50051" - name: SCRIPTS_CACHE_DIR value: "/tmp/prodisco-scripts" - name: SANDBOX_TRANSPORT_MODE value: "tls" - name: SANDBOX_TLS_CERT_PATH value: "/etc/sandbox-tls/tls.crt" - name: SANDBOX_TLS_KEY_PATH value: "/etc/sandbox-tls/tls.key" - name: SANDBOX_TLS_CA_PATH value: "/etc/sandbox-tls/ca.crt" resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m" # Note: Native gRPC probes don't support TLS, so we use exec probe readinessProbe: exec: command: - /bin/sh - -c - "kill -0 1" initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: exec: command: - /bin/sh - -c - "kill -0 1" initialDelaySeconds: 10 periodSeconds: 30 volumeMounts: - name: scripts-cache mountPath: /tmp/prodisco-scripts - name: tls-certs mountPath: /etc/sandbox-tls readOnly: true volumes: - name: scripts-cache emptyDir: {} - name: tls-certs secret: secretName: sandbox-server-tls --- apiVersion: v1 kind: ServiceAccount metadata: name: sandbox-server namespace: prodisco --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: sandbox-server rules: - apiGroups: [""] resources: ["pods", "pods/log", "services", "endpoints", "configmaps", "secrets", "namespaces", "nodes", "persistentvolumes", "persistentvolumeclaims", "events", "serviceaccounts"] verbs: ["get", "list", "watch"] - apiGroups: ["apps"] resources: ["deployments", "daemonsets", "replicasets", "statefulsets"] verbs: ["get", "list", "watch"] - apiGroups: ["batch"] resources: ["jobs", "cronjobs"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: sandbox-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: sandbox-server subjects: - kind: ServiceAccount name: sandbox-server namespace: prodisco --- apiVersion: v1 kind: Service metadata: name: sandbox-server namespace: prodisco labels: app: sandbox-server spec: type: ClusterIP ports: - port: 50051 targetPort: 50051 protocol: TCP name: grpc selector: app: sandbox-server EOF - name: Wait for deployment run: kubectl wait --for=condition=Available --timeout=120s deployment/sandbox-server -n prodisco - name: Run TLS integration tests timeout-minutes: 10 run: SANDBOX_E2E_TESTS=true npm run test:e2e -w @prodisco/sandbox-server - name: Collect logs on failure if: failure() run: | mkdir -p artifacts/tls-integration kubectl get pods -A > artifacts/tls-integration/pods.txt kubectl -n prodisco logs -l app=sandbox-server --tail=100 > artifacts/tls-integration/sandbox-server.log 2>&1 || true kubectl get certificates -n prodisco -o yaml > artifacts/tls-integration/certificates.yaml 2>&1 || true kubectl get secrets -n prodisco > artifacts/tls-integration/secrets.txt 2>&1 || true kubectl cluster-info dump > artifacts/tls-integration/cluster-dump.txt 2>&1 || true - name: Upload artifacts on failure if: failure() uses: actions/upload-artifact@v4 with: name: tls-integration-artifacts path: artifacts/tls-integration/ retention-days: 7

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harche/ProDisco'

If you have feedback or need assistance with the MCP directory API, please join our Discord server