webfetch-mcpo-docker

A single Docker image exposing webfetch-mcp's web_search and web_fetch tools over HTTP/OpenAPI, via mcpo.

webfetch-mcp is a stdio-only MCP server; mcpo exposes a wrapped MCP server over HTTP by spawning it as a local child process. Since that spawn happens in-process (not over the network) and webfetch-mcp has no HTTP/SSE mode of its own, both have to live in one image — that's what this repo builds.

Build

docker build -t webfetch-mcpo-docker .

Run

docker run -p 8000:8000 \
  -e MCPO_API_KEY=some-secret \
  -e SEARXNG_BASE=http://searxng.example.internal:8080 \
  webfetch-mcpo-docker

Interactive API docs: http://localhost:8000/docs (and /openapi.json). These are served without authentication even when MCPO_API_KEY is set — only the generated tool endpoints (/web_search, /web_fetch) require it, as Authorization: Bearer <MCPO_API_KEY>.

Environment variables

Variable Effect
MCPO_API_KEY If set, tool endpoints require Authorization: Bearer <value>. If unset, mcpo serves unauthenticated (its own default behavior).
MCPO_PORT Port mcpo listens on inside the container. Default 8000.
SEARXNG_BASE Passed through to webfetch-mcp; its own default (http://localhost:8080) applies if unset.
DEBUG Passed through to webfetch-mcp. "true" enables debug logging.
DETAILED_LOG Passed through to webfetch-mcp. Defaults on; set to "false" to disable its detailed log file.

No explicit plumbing is needed to get these into webfetch-mcp: mcpo builds the spawned child process's environment as the union of its own process environment and any per-server overrides, so anything set on the container's environment is inherited by the node server.mjs child automatically. (Verified against mcpo's MCPConnectionManager source, not assumed.)

Known characteristics

  • No URL filtering / SSRF protection. webfetch-mcp's web_fetch tool fetches whatever URL it's given, including private/internal addresses. This is a known, accepted characteristic of webfetch-mcp itself — out of scope for this image to fix.
  • No TLS termination. This image serves plain HTTP; put a reverse proxy or firewall in front of it if you need TLS or network restriction.
  • webfetch-mcp writes a detailed log file next to server.mjs inside the image by default (DETAILED_LOG defaults on). That directory needs to stay writable at runtime — don't run this image with a read-only root filesystem without accounting for that (e.g. a volume mount, or set DETAILED_LOG=false).

Pinned revisions

  • webfetch-mcp: pinned via ARG WEBFETCH_MCP_COMMIT in the Dockerfile, vendored from the Gitea mirror at https://code.aneur.in/mirrors/webfetch-mcp, not upstream GitHub.
  • mcpo: pinned via ARG MCPO_VERSION in the Dockerfile, installed from PyPI.

Bump either by updating the corresponding ARG default in the Dockerfile. When bumping mcpo, double check its CLI flags still match what entrypoint.sh assumes (--host, --port, --api-key, --).

CI

.gitea/workflows/docker-build.yml builds and pushes code.aneur.in/cloud/webfetch-mcpo-docker:latest on every push to main. It authenticates using the repo secrets PACKAGE_REGISTRY_USER and PACKAGE_REGISTRY_TOKEN — the default Gitea Actions token doesn't have package-registry write permission on this instance, so these must be created manually under repo Settings → Actions → Secrets, backed by a personal access token with package-write scope.

S
Description
No description provided
Readme
32 KiB
Languages
Dockerfile 72.7%
Shell 27.3%