Hard-coding DOCKER_NETWORK=jakenet causes docker compose up to fail for new
users who haven't pre-created that external network. Default to empty so the
container uses only the default bridge network unless explicitly configured.
- .codex-plugin/plugin.json: add interface.displayName field required by
lint-plugin.sh validation check
- .env.example: fix dotenv-linter key ordering across all variable groups
(MCP settings, safety flags, Docker vars all now alphabetically sorted)
- hooks/scripts/sync-env.sh: scope lock file to CLAUDE_PLUGIN_ROOT instead
of global /tmp/ to avoid cross-repo lock contention
- entrypoint.sh: only require UNRAID_MCP_BEARER_TOKEN when transport is
not stdio and HTTP auth is not disabled (fixes false startup failures)
- docker-compose.yaml: use fixed network key `unraid-mcp-external` with
`name: ${DOCKER_NETWORK:-unraid-mcp-external}` to avoid compose errors
when DOCKER_NETWORK differs from the declared network name
- docker-compose.yaml: make healthcheck transport-aware — skip HTTP probe
when UNRAID_MCP_TRANSPORT=stdio to prevent false unhealthy status
- docs/unraid.subdomain.conf: fix proxy_pass port from 3000 to 6970
- .codex-plugin/plugin.json: fix MCP URL port from 3000 to 6970
- .env.example: reorder UNRAID_API_KEY before UNRAID_API_URL (alpha);
correct UNRAID_MCP_BEARER_TOKEN comment — required conditionally not always
- hooks/scripts/ensure-ignore-files.sh: write .gitignore atomically via
temp file + mv to prevent truncation on interrupted rewrite
- hooks/scripts/sync-env.sh: chmod 600 .env immediately after touch,
before any early-exit paths that could leave secrets world-readable
- sync-env.sh: replace sed with awk for safe value replacement, add flock
on /tmp/unraid-sync-env.lock, remove auto-token-generation (fail with
clear error if UNRAID_MCP_BEARER_TOKEN not set)
- ensure-ignore-files.sh: rename from ensure-gitignore.sh, add --check mode
that exits non-zero without modifying file (for CI/pre-commit use)
- hooks.json: update both references to new ensure-ignore-files.sh name
- docker-compose.yaml: add user PUID/PGID, external network, deploy.resources
limits (1024M/1cpu), wget healthcheck, start_period=30s
- Dockerfile: install wget, use wget healthcheck, start_period=30s,
add entrypoint.sh, ENTRYPOINT points to /entrypoint.sh
- entrypoint.sh: env validation (UNRAID_API_URL, UNRAID_API_KEY,
UNRAID_MCP_BEARER_TOKEN) with exec for signal forwarding
- .env.example: add PUID, PGID, DOCKER_NETWORK, UNRAID_MCP_ALLOW_DESTRUCTIVE,
UNRAID_MCP_ALLOW_YOLO; fix UNRAID_MCP_BEARER_TOKEN key name
- BearerAuthMiddleware: pure ASGI __call__ pattern (no BaseHTTPMiddleware overhead),
pre-encoded token bytes, pre-built 401/429 bodies, per-IP rate limiting
(60 failures/60s → 429), log throttling (30s/IP), RFC 6750 compliant headers
- Token lifecycle: auto-generate secrets.token_urlsafe(32) on first HTTP startup,
write to ~/.unraid-mcp/.env via dotenv.set_key, print once to STDERR,
pop from os.environ after storing in module global
- Startup guard: sys.exit(1) if HTTP + no token + DISABLE_HTTP_AUTH not set
- Escape hatch: UNRAID_MCP_DISABLE_HTTP_AUTH=true for gateway-delegated auth
- Default transport: stdio → streamable-http (breaking change)
- 23 new tests covering pass-through, 401/429, RFC 6750 headers, rate limiting,
token generation, startup guard
BREAKING CHANGE: default transport is now streamable-http; stdio users must set
UNRAID_MCP_TRANSPORT=stdio (Claude Desktop plugin unaffected — plugin.json hardcodes stdio)
Add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, UNRAID_MCP_BASE_URL, and
UNRAID_MCP_JWT_SIGNING_KEY env vars to settings.py, along with the
is_google_auth_configured() predicate and three new keys in
get_config_summary(). TDD: 4 tests written red-first, all passing green.
- Remove array_status, system_info, notifications_overview, and parity_status resources
- Keep only logs_stream resource (unraid://logs/stream) which is working properly
- Update README.md with current resource documentation and modern docker compose syntax
- Fix import path issues that were causing subscription errors
- Update environment configuration examples
- Clean up subscription manager to only include working log streaming
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>