From f5543c3513cec934fd6a7f74d3e81926dbe4a18a Mon Sep 17 00:00:00 2001 From: Robert Gambee Date: Thu, 26 Feb 2026 11:50:00 -0500 Subject: [PATCH 1/2] Allow Supabase JWT passthrough --- everyrow-mcp/src/everyrow_mcp/auth.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/everyrow-mcp/src/everyrow_mcp/auth.py b/everyrow-mcp/src/everyrow_mcp/auth.py index 04ab8712..f2a46ff4 100644 --- a/everyrow-mcp/src/everyrow_mcp/auth.py +++ b/everyrow-mcp/src/everyrow_mcp/auth.py @@ -496,8 +496,21 @@ async def exchange_authorization_code( supabase_refresh_token=authorization_code.supabase_refresh_token, ) - async def load_access_token(self, token: str) -> AccessToken | None: # noqa: ARG002 - return None + async def load_access_token(self, token: str) -> AccessToken | None: + # Accept raw Supabase JWTs directly (JWT passthrough path). + # This allows the CC app to forward the user's session JWT without an + # OAuth dance. Backward-compatible: clients using the existing OAuth + # flow continue to receive MCP-issued tokens, which are Supabase JWTs + # under the hood, so they are also accepted here. + result = await self._token_verifier.verify_token(token) + if result is None: + return None + return AccessToken( + token=result.token, + client_id=result.client_id, + scopes=["everyrow"], + expires_at=result.expires_at, + ) async def load_refresh_token( self, client: OAuthClientInformationFull, refresh_token: str From d906235fe2875348fd2ffa2b779371585339db59 Mon Sep 17 00:00:00 2001 From: Rafael Poyiadzi Date: Thu, 26 Feb 2026 18:07:28 +0000 Subject: [PATCH 2/2] Add EXTRA_ALLOWED_HOSTS env var for DNS rebinding protection Allows configuring additional allowed Host headers via a comma-separated env var, enabling cross-Docker-network access (e.g. host.docker.internal). Co-Authored-By: Claude Opus 4.6 --- everyrow-mcp/deploy/docker-compose.local.yaml | 3 ++- everyrow-mcp/src/everyrow_mcp/http_config.py | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/everyrow-mcp/deploy/docker-compose.local.yaml b/everyrow-mcp/deploy/docker-compose.local.yaml index ff66f234..c963e846 100644 --- a/everyrow-mcp/deploy/docker-compose.local.yaml +++ b/everyrow-mcp/deploy/docker-compose.local.yaml @@ -1,4 +1,4 @@ -# Local development overrides. +# Local development overrides — NOT for production use. # Usage: docker compose -f docker-compose.yaml -f docker-compose.local.yaml up services: redis: @@ -9,3 +9,4 @@ services: environment: MCP_SERVER_URL: "${MCP_SERVER_URL:-http://localhost:8000}" TRUST_PROXY_HEADERS: "${TRUST_PROXY_HEADERS:-false}" + EXTRA_ALLOWED_HOSTS: "host.docker.internal:*" # local dev only — widens DNS rebinding allowlist diff --git a/everyrow-mcp/src/everyrow_mcp/http_config.py b/everyrow-mcp/src/everyrow_mcp/http_config.py index 8a609c5d..d58ed9be 100644 --- a/everyrow-mcp/src/everyrow_mcp/http_config.py +++ b/everyrow-mcp/src/everyrow_mcp/http_config.py @@ -4,6 +4,7 @@ import contextvars import logging +import os import time as _time from urllib.parse import urlparse @@ -174,9 +175,13 @@ def _configure_mcp_auth( client_registration_options=ClientRegistrationOptions(enabled=True), ) hostname = urlparse(settings.mcp_server_url).hostname or "localhost" + allowed_hosts = [hostname] + extra = os.environ.get("EXTRA_ALLOWED_HOSTS", "") + if extra: + allowed_hosts.extend(h.strip() for h in extra.split(",") if h.strip()) mcp.settings.transport_security = TransportSecuritySettings( enable_dns_rebinding_protection=True, - allowed_hosts=[hostname], + allowed_hosts=allowed_hosts, )