unraid-mcp/docs/mcp/AUTH.md
Jacob Magar 685775de25 docs: add comprehensive documentation from templates
Generate 42 documentation files across 6 subdirectories (mcp/, plugin/,
repo/, stack/, upstream/, and root) based on plugin-lab templates.
All content is real — no template placeholders — covering tools (15
action domains, 107 subactions), resources (10 live subscriptions),
elicitation flows, GraphQL integration, auth, deployment, CI/CD,
testing, and security guardrails.
2026-04-04 23:38:54 -04:00

4.1 KiB

Authentication Reference

Overview

unraid-mcp has two authentication boundaries:

  1. Inbound (client to MCP server): Bearer token authentication on HTTP transports
  2. Outbound (MCP server to Unraid): API key authentication via x-api-key header

Inbound: Bearer token (RFC 6750)

How it works

The BearerAuthMiddleware (ASGI-level) wraps the entire HTTP stack. It fires before any MCP protocol processing.

  1. Client sends Authorization: Bearer <token> header
  2. Server validates with constant-time comparison (hmac.compare_digest)
  3. Valid token: request forwarded to MCP server
  4. Invalid/missing token: 401 with WWW-Authenticate header

Token management

Auto-generation: On first HTTP startup, if no token is configured:

  1. Server generates a secrets.token_urlsafe(32) token
  2. Writes it to ~/.unraid-mcp/.env using dotenv.set_key (in-place, preserves comments)
  3. Sets file permissions to 600
  4. Removes the token from os.environ (prevents subprocess inheritance)
  5. Prints the token location to stderr

Manual generation:

openssl rand -hex 32

Set in ~/.unraid-mcp/.env:

UNRAID_MCP_BEARER_TOKEN=<your-token>

Client configuration

Claude Code plugin

The userConfig in .claude-plugin/plugin.json includes unraid_mcp_token (sensitive: true). Claude Code prompts the user for this value during plugin installation.

Direct HTTP

curl -H "Authorization: Bearer <token>" http://localhost:6970/mcp

Disabling auth

For deployments behind a trusted reverse proxy (e.g., SWAG with its own auth):

UNRAID_MCP_DISABLE_HTTP_AUTH=true

When disabled, all HTTP requests are forwarded without token validation. The server logs a warning.

Error responses

Status Condition WWW-Authenticate
401 Missing Authorization header Bearer realm="unraid-mcp"
401 Non-bearer auth scheme Bearer realm="unraid-mcp"
401 Invalid token Bearer realm="unraid-mcp", error="invalid_token"
429 Rate limit exceeded (60 failures/60s per IP) -- (includes Retry-After: 60)

Rate limiting

Per-IP failure tracking:

  • Window: 60 seconds
  • Max failures: 60 per IP before 429
  • Max IPs tracked: 10,000 (oldest evicted on overflow)
  • Log throttle: one warning per IP per 30 seconds

Well-known endpoint (RFC 9728)

GET /.well-known/oauth-protected-resource returns:

{
  "resource": "http://localhost:6970",
  "bearer_methods_supported": ["header"]
}

Empty authorization_servers tells MCP clients there is no OAuth flow -- use a pre-shared token. This endpoint is unauthenticated.

Outbound: Unraid API key

How it works

The GraphQL client in core/client.py sends requests to the Unraid API with:

x-api-key: <UNRAID_API_KEY>

Credential sources

  1. Elicitation: The health/setup subaction collects credentials interactively and writes them to ~/.unraid-mcp/.env
  2. Environment file: Loaded from the .env priority chain at startup
  3. Runtime update: apply_runtime_config() updates module globals without touching os.environ

SSL/TLS

The UNRAID_VERIFY_SSL setting controls SSL verification for outbound requests:

  • true (default): Full SSL verification
  • false: Disables verification (self-signed certs)
  • Path string: Custom CA bundle

A warning is logged when SSL verification is disabled.

Unauthenticated endpoints

Endpoint Middleware Purpose
GET /health HealthMiddleware Docker/container healthchecks
GET /.well-known/oauth-protected-resource WellKnownMiddleware MCP client OAuth discovery
GET /.well-known/oauth-protected-resource/mcp WellKnownMiddleware MCP-specific OAuth discovery

These endpoints are handled before BearerAuthMiddleware in the ASGI middleware stack.

See Also