diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index a4f5d6e1..c9dc9728 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -61,3 +61,60 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max + + verify-public-access: + name: Verify Anonymous GHCR Pull Access + runs-on: ubuntu-latest + needs: publish + if: needs.publish.result == 'success' + timeout-minutes: 10 + steps: + - name: Verify anonymous manifest access (with retry) + run: | + set -euo pipefail + image="ghcr.io/gleanwork/local-mcp-server:latest" + attempts=18 + sleep_seconds=10 + success=0 + + for attempt in $(seq 1 "${attempts}"); do + if docker manifest inspect "${image}" >/dev/null 2>&1; then + success=1 + echo "Anonymous manifest access verified for ${image}" + break + fi + + echo "Attempt ${attempt}/${attempts}: ${image} not anonymously available yet" + sleep "${sleep_seconds}" + done + + if [[ "${success}" -ne 1 ]]; then + echo "::error title=Anonymous GHCR pull failed::Unable to pull ${image} without authentication. Set GitHub Packages visibility to Public for ghcr.io/gleanwork/local-mcp-server." + exit 1 + fi + + - name: Pull and smoke test image anonymously + run: | + set -euo pipefail + image="ghcr.io/gleanwork/local-mcp-server:latest" + + docker pull "${image}" + docker run --rm --entrypoint node "${image}" --version + + init_payload='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"gh-actions","version":"1.0"}}}' + printf '%s\n' "${init_payload}" | docker run --rm -i "${image}" > /tmp/mcp-init.txt 2>&1 & + docker_pid=$! + sleep 3 + + if kill -0 "${docker_pid}" 2>/dev/null; then + kill "${docker_pid}" 2>/dev/null || true + wait "${docker_pid}" 2>/dev/null || true + fi + + if grep -q '"result"' /tmp/mcp-init.txt; then + echo "MCP initialize handshake succeeded" + else + echo "::error title=Docker runtime smoke test failed::MCP initialize response missing from container output" + cat /tmp/mcp-init.txt + exit 1 + fi diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 1925c669..f393dfe2 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -1,3 +1,33 @@ # Troubleshooting This guide helps you diagnose and resolve common issues with the Glean MCP Server. + +## Docker image pull fails with `denied` / `403 Forbidden` + +If `docker pull ghcr.io/gleanwork/local-mcp-server:latest` fails with a permissions error: + +1. Authenticate to GitHub Container Registry: + +```bash +# Token must include read:packages +echo "$GITHUB_TOKEN" | docker login ghcr.io -u "$GITHUB_USERNAME" --password-stdin +``` + +2. Retry the pull: + +```bash +docker pull ghcr.io/gleanwork/local-mcp-server:latest +``` + +3. If the image was just published, wait a few minutes for GHCR propagation and retry. + +4. If access is still blocked, build from source as a fallback: + +```bash +docker build -t glean/local-mcp-server:local . +``` + +5. If the issue persists, open a GitHub issue and include: + +- the exact `docker pull` command +- the full error output diff --git a/packages/local-mcp-server/README.md b/packages/local-mcp-server/README.md index 2401c9dc..ffbb42ac 100644 --- a/packages/local-mcp-server/README.md +++ b/packages/local-mcp-server/README.md @@ -82,6 +82,20 @@ Multi-architecture Docker images are published to GitHub Container Registry and docker pull ghcr.io/gleanwork/local-mcp-server:latest ``` +If you see `denied` / `403 Forbidden` when pulling from GHCR, authenticate first: + +```bash +# Token must include read:packages +echo "$GITHUB_TOKEN" | docker login ghcr.io -u "$GITHUB_USERNAME" --password-stdin +docker pull ghcr.io/gleanwork/local-mcp-server:latest +``` + +If GHCR access is blocked in your environment, you can build locally: + +```bash +docker build -t glean/local-mcp-server:local . +``` + ### MCP Client Configuration Configure your MCP client to use the Docker image. Most MCP clients support passing environment variables via the `env` block: @@ -148,6 +162,12 @@ If your MCP client doesn't pass the `env` block to Docker, use `-e` flags in the - Verify your `GLEAN_API_TOKEN` is valid - Check your `GLEAN_INSTANCE` matches your Glean deployment +**`docker pull` returns `denied` or `403 Forbidden`:** + +- Authenticate to `ghcr.io` with a token that has `read:packages` +- Retry pull with the same image/tag +- If this persists, open an issue with your exact pull command and error output + **MCP client can't connect:** - Verify Docker is installed and running