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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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
16 changes: 15 additions & 1 deletion obol-adk/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
- 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 <registry>/obol-mcp:latest .
```
15 changes: 15 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.filesystem
Original file line numberDiff line numberDiff line change
@@ -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"]
12 changes: 12 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.foundry
Original file line numberDiff line numberDiff line change
@@ -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"]
11 changes: 11 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.kubernetes
Original file line numberDiff line numberDiff line change
@@ -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"]
14 changes: 14 additions & 0 deletions obol-adk/dockerfiles/Dockerfile.obol
Original file line numberDiff line numberDiff line change
@@ -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"]
52 changes: 51 additions & 1 deletion obolup/obolup
100755 → 100644
Original file line numberDiff line numberDiff line change
Expand Up@@ -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..."
Expand All@@ -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."
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -293,6 +340,9 @@ main() {
launch_stack

log_info "Obol Stack is up and running!"

# Open the obol-agent interface
open_obol_agent_interface
}


Expand All@@ -318,4 +368,4 @@ Docs : https://docs.obol.org/
}

# Run main
main "$@"
main "$@"