# ── Transport ────────────────────────────────────────────────────────── # MCP_TRANSPORT_TYPE=stdio # stdio | http (default: stdio) # MCP_HTTP_PORT=3010 # HTTP port (default: 3010) # MCP_HTTP_HOST=127.0.0.1 # HTTP host (default: 127.0.0.1) # MCP_HTTP_ENDPOINT_PATH=/mcp # HTTP endpoint path (default: /mcp) # MCP_PUBLIC_URL= # Public origin behind a TLS-terminating proxy (e.g. https://mcp.example.com) # ── Auth ────────────────────────────────────────────────────────────── # MCP_AUTH_MODE=none # none | jwt | oauth (default: none) # MCP_AUTH_SECRET_KEY= # JWT secret (required for jwt mode) # # OAuth mode (MCP_AUTH_MODE=oauth) reads granted scopes from a union of the # `scp`, `scope`, and `mcp_tool_scopes` JWT claims. Standard OIDC providers # (Authentik, Keycloak <26.5, Zitadel) compute `scope` from the client's # requested scopes in `authorization_code` flow and ignore property mappings # that try to override it. Inject per-tool scopes (`tool:NAME:read`, ...) # via the `mcp_tool_scopes` claim instead — that path isn't subject to the # OIDC restriction. If no claim-injection path exists, set # MCP_AUTH_DISABLE_SCOPE_CHECKS=true and rely on path-policy below for # access control. Bypass logs a WARNING at startup. # MCP_AUTH_DISABLE_SCOPE_CHECKS=false # ── Storage ─────────────────────────────────────────────────────────── # STORAGE_PROVIDER_TYPE=in-memory # in-memory | filesystem | supabase | cloudflare-r2 | cloudflare-kv | cloudflare-d1 # ── Session ────────────────────────────────────────────────────────── # MCP_SESSION_MODE=auto # stateless | stateful | auto (default: auto) # ── Logging ─────────────────────────────────────────────────────────── # MCP_LOG_LEVEL=info # debug | info | notice | warning | error # ── Telemetry ───────────────────────────────────────────────────────── # OTEL_ENABLED=false # Enable OpenTelemetry (default: false) # OTEL_EXPORTER_OTLP_ENDPOINT= # OTLP endpoint URL (e.g., http://localhost:4318) # ── Obsidian Local REST API ────────────────────────────────────────── # API key from Obsidian → Settings → Community Plugins → Local REST API. Required. OBSIDIAN_API_KEY= # Base URL of the Local REST API plugin. Default: http://127.0.0.1:27123. # Enable "Non-encrypted (HTTP) Server" in the plugin settings to use the default. # Use https://127.0.0.1:27124 for the always-on HTTPS port (self-signed cert; pair with OBSIDIAN_VERIFY_SSL=false). # OBSIDIAN_BASE_URL=http://127.0.0.1:27123 # Verify the TLS certificate. Default false because the plugin uses a self-signed cert. # Set to true if you've imported the cert into a trust store. # OBSIDIAN_VERIFY_SSL=false # Per-request timeout in milliseconds (default: 30000). Bump for slow searches. # OBSIDIAN_REQUEST_TIMEOUT_MS=30000 # Opt-in flag for the command-palette pair (obsidian_list_commands + # obsidian_execute_command). Off by default — Obsidian commands are opaque # and can be destructive (delete file, close vault, etc.). # OBSIDIAN_ENABLE_COMMANDS=false # ── Path policy (folder-scoped read/write) ─────────────────────────── # Optional vault-relative folder allowlists. Comma-separated; prefix-based # with implicit recursion; case-insensitive; trailing slashes normalized. # Both default unset = full vault access (current behavior). # # Reads pass when the target matches READ_PATHS, OR matches WRITE_PATHS # (write-implies-read), OR both vars are unset. # Writes pass when the target matches WRITE_PATHS, or WRITE_PATHS is unset. # # Example: read everywhere, write only in `projects/` and `scratch/` — # OBSIDIAN_WRITE_PATHS=projects/,scratch/ # # Example: read only `public/`, write only `public/inbox/` — # OBSIDIAN_READ_PATHS=public/ # OBSIDIAN_WRITE_PATHS=public/inbox/ # # OBSIDIAN_READ_PATHS= # OBSIDIAN_WRITE_PATHS= # Global read-only kill switch. When true, denies every write regardless of # OBSIDIAN_WRITE_PATHS, and suppresses the OBSIDIAN_ENABLE_COMMANDS pair # (commands can mutate). Useful for shared or public-facing deployments. # OBSIDIAN_READ_ONLY=false