From 5d4b062dd8225dec13bd9861f624d6286758ea25 Mon Sep 17 00:00:00 2001 From: bussyjd Date: Tue, 20 May 2025 20:09:22 +0400 Subject: [PATCH] Add obol-agent deployment with Docker and API key integration - Add obol-agent Docker deployment configuration - Add Dockerfiles for each MCP in agent-py - Implement automatic Google API key fetch in obolup script - Update documentation --- obol-adk/README.md | 16 ++++++- obol-adk/dockerfiles/Dockerfile.filesystem | 15 +++++++ obol-adk/dockerfiles/Dockerfile.foundry | 12 +++++ obol-adk/dockerfiles/Dockerfile.kubernetes | 11 +++++ obol-adk/dockerfiles/Dockerfile.obol | 14 ++++++ obolup/obolup | 52 +++++++++++++++++++++- 6 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 obol-adk/dockerfiles/Dockerfile.filesystem create mode 100644 obol-adk/dockerfiles/Dockerfile.foundry create mode 100644 obol-adk/dockerfiles/Dockerfile.kubernetes create mode 100644 obol-adk/dockerfiles/Dockerfile.obol mode change 100755 => 100644 obolup/obolup diff --git a/obol-adk/README.md b/obol-adk/README.md index 35b4b903..f7b16460 100644 --- a/obol-adk/README.md +++ b/obol-adk/README.md @@ -60,4 +60,18 @@ This agent is designed to be run using the ADK Web UI. It connects to Filesystem ## Improvements -- Awaiting MCP public package for Foundry MCP server https://github.com/PraneshASP/foundry-mcp-server?tab=readme-ov-file#setup-using-npm-package \ No newline at end of file +- Awaiting MCP public package for Foundry MCP server https://github.com/PraneshASP/foundry-mcp-server?tab=readme-ov-file#setup-using-npm-package +## Docker Images for MCP Servers + +Dockerfiles that package the MCP servers used by `obol-agent-web` are located in the `dockerfiles/` directory: + +- **Dockerfile.filesystem** – packages the Filesystem MCP server. +- **Dockerfile.obol** – packages the Obol MCP server. +- **Dockerfile.kubernetes** – packages the Kubernetes MCP server. +- **Dockerfile.foundry** – packages the Foundry MCP server. + +These images can be built and pushed to your own registry, for example: + +```bash +docker build -f dockerfiles/Dockerfile.obol -t /obol-mcp:latest . +``` diff --git a/obol-adk/dockerfiles/Dockerfile.filesystem b/obol-adk/dockerfiles/Dockerfile.filesystem new file mode 100644 index 00000000..f50fa831 --- /dev/null +++ b/obol-adk/dockerfiles/Dockerfile.filesystem @@ -0,0 +1,15 @@ +# Dockerfile to run the Filesystem MCP server +FROM node:lts-slim + +WORKDIR /app + +# Preinstall the server so the image has no runtime dependencies +RUN npm install -g @modelcontextprotocol/server-filesystem + +# Optional: copy documentation directory into the image +COPY ../docs /data/docs + +EXPOSE 8080 + +# Launch the server with the docs directory +CMD ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/data/docs"] diff --git a/obol-adk/dockerfiles/Dockerfile.foundry b/obol-adk/dockerfiles/Dockerfile.foundry new file mode 100644 index 00000000..3446b884 --- /dev/null +++ b/obol-adk/dockerfiles/Dockerfile.foundry @@ -0,0 +1,12 @@ +# Dockerfile to run the Foundry MCP server +FROM node:lts-slim + +WORKDIR /app + +# Install the Foundry MCP server when it becomes publicly available +# This package may still be under development +RUN npm install -g foundry-mcp-server + +EXPOSE 8080 + +CMD ["node", "/usr/local/lib/node_modules/foundry-mcp-server/dist/index.js"] diff --git a/obol-adk/dockerfiles/Dockerfile.kubernetes b/obol-adk/dockerfiles/Dockerfile.kubernetes new file mode 100644 index 00000000..60f1b434 --- /dev/null +++ b/obol-adk/dockerfiles/Dockerfile.kubernetes @@ -0,0 +1,11 @@ +# Dockerfile to run the Kubernetes MCP server +FROM node:lts-slim + +WORKDIR /app + +# Install the Kubernetes MCP server package +RUN npm install -g mcp-server-kubernetes@latest + +EXPOSE 8080 + +CMD ["mcp-server-kubernetes"] diff --git a/obol-adk/dockerfiles/Dockerfile.obol b/obol-adk/dockerfiles/Dockerfile.obol new file mode 100644 index 00000000..19c130a6 --- /dev/null +++ b/obol-adk/dockerfiles/Dockerfile.obol @@ -0,0 +1,14 @@ +# Dockerfile to run the Obol MCP server +FROM python:3.11-slim + +WORKDIR /server + +# Install uv runner +RUN pip install --no-cache-dir uvicorn uv + +# Copy server implementation (expected to be present at build time) +COPY ../obol-mcp /server + +EXPOSE 8080 + +CMD ["uv", "run", "/server/server.py"] diff --git a/obolup/obolup b/obolup/obolup old mode 100755 new mode 100644 index eac330c2..a94c296c --- a/obolup/obolup +++ b/obolup/obolup @@ -216,6 +216,47 @@ check_obolup_update() { fi } +# Ensure GOOGLE_API_KEY is available and stored in the cluster +setup_google_api_key_secret() { + if [ -z "$GOOGLE_API_KEY" ]; then + log_info "No GOOGLE_API_KEY detected." + echo "Please open https://aistudio.google.com/apikey and copy your key." + read -rp "Paste Google API key: " GOOGLE_API_KEY + fi + + if kubectl get secret google-api-key >/dev/null 2>&1; then + kubectl delete secret google-api-key >/dev/null 2>&1 || true + fi + + kubectl create secret generic google-api-key --from-literal=GOOGLE_API_KEY="$GOOGLE_API_KEY" >/dev/null 2>&1 + log_info "Google API key secret configured." +} + +# Build the obol-adk Docker image and deploy it to the Kind cluster +build_and_deploy_obol_agent() { + log_info "Building obol-agent Docker image..." + ensure docker build -t obol-agent:latest ./obol-adk + + log_info "Loading image into Kind cluster..." + ensure kind load docker-image obol-agent:latest --name "$STACK_NAME" + + log_info "Deploying obol-agent to cluster..." + if kubectl get deployment obol-agent >/dev/null 2>&1; then + kubectl set image deployment/obol-agent obol-agent=obol-agent:latest >/dev/null + else + kubectl create deployment obol-agent --image=obol-agent:latest --port=8000 >/dev/null + fi + + kubectl expose deployment obol-agent --name=obol-agent --port=8000 --type=ClusterIP --overwrite >/dev/null 2>&1 || true +} + +# Port-forward and open the obol-agent interface +open_obol_agent_interface() { + log_info "Opening obol-agent interface at http://localhost:8000..." + kubectl port-forward svc/obol-agent 8000:8000 >/dev/null 2>&1 & + xdg-open "http://localhost:8000" 2>/dev/null || open "http://localhost:8000" 2>/dev/null || log_warn "Could not open browser automatically." +} + # Launch or update the Obol Stack launch_stack() { log_info "Launching core Obol Stack services..." @@ -232,6 +273,9 @@ EOF unset KIND_EXPERIMENTAL_DOCKER_CONTAINER_EXTRA_ARGS fi + # Ensure the Google API key is available inside the cluster + setup_google_api_key_secret + # Apply base Obol Stack resources (e.g., namespaces, monitoring) #log_info "Applying Obol Stack base resources..." #kubectl apply -f https://stack.obol.org/base.yaml || log_error "Failed to apply base resources." @@ -260,6 +304,9 @@ EOF # Todo(Oisin): Blockscout segfaulting, unclear why # ensure obol install ethereum/blockscout --values ../values/blockscout.yaml + # Build and deploy obol-agent + build_and_deploy_obol_agent + # Check stack health log_info "Checking stack health..." # if ! kubectl get pods -n obol-system -o jsonpath='{.items[*].status.phase}' | grep -q "Running"; then @@ -293,6 +340,9 @@ main() { launch_stack log_info "Obol Stack is up and running!" + + # Open the obol-agent interface + open_obol_agent_interface } @@ -318,4 +368,4 @@ Docs : https://docs.obol.org/ } # Run main -main "$@" \ No newline at end of file +main "$@"