Files
webfetch-mcpo-docker/README.md
T

80 lines
3.6 KiB
Markdown
Raw Normal View History

2026-09-27 07:11:57 +01:00
# webfetch-mcpo-docker
A single Docker image exposing [`webfetch-mcp`](https://code.aneur.in/mirrors/webfetch-mcp)'s
`web_search` and `web_fetch` tools over HTTP/OpenAPI, via [`mcpo`](https://github.com/open-webui/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
```sh
2026-09-27 07:11:57 +01:00
docker build -t webfetch-mcpo-docker .
```
## Run
```sh
docker run -p 8000:8000 \
-e MCPO_API_KEY=some-secret \
-e SEARXNG_BASE=http://searxng.example.internal:8080 \
2026-09-27 07:11:57 +01:00
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
2026-09-27 07:11:57 +01:00
`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.