refactor to centralize, move to desktop type
This commit is contained in:
@@ -2,57 +2,34 @@
|
||||
Shared configuration for Google Workspace MCP server.
|
||||
This module holds configuration values that need to be shared across modules
|
||||
to avoid circular imports.
|
||||
|
||||
NOTE: OAuth configuration has been moved to auth.oauth_config for centralization.
|
||||
This module now imports from there for backward compatibility.
|
||||
"""
|
||||
|
||||
import os
|
||||
from auth.oauth_config import (
|
||||
get_oauth_base_url,
|
||||
get_oauth_redirect_uri,
|
||||
set_transport_mode,
|
||||
get_transport_mode,
|
||||
is_oauth21_enabled
|
||||
)
|
||||
|
||||
# Server configuration
|
||||
WORKSPACE_MCP_PORT = int(os.getenv("PORT", os.getenv("WORKSPACE_MCP_PORT", 8000)))
|
||||
WORKSPACE_MCP_BASE_URI = os.getenv("WORKSPACE_MCP_BASE_URI", "http://localhost")
|
||||
|
||||
# Disable USER_GOOGLE_EMAIL in OAuth 2.1 multi-user mode
|
||||
_oauth21_enabled = os.getenv("MCP_ENABLE_OAUTH21", "false").lower() == "true"
|
||||
USER_GOOGLE_EMAIL = None if _oauth21_enabled else os.getenv("USER_GOOGLE_EMAIL", None)
|
||||
USER_GOOGLE_EMAIL = None if is_oauth21_enabled() else os.getenv("USER_GOOGLE_EMAIL", None)
|
||||
|
||||
# Transport mode (will be set by main.py)
|
||||
_current_transport_mode = "stdio" # Default to stdio
|
||||
|
||||
|
||||
def set_transport_mode(mode: str):
|
||||
"""Set the current transport mode for OAuth callback handling."""
|
||||
global _current_transport_mode
|
||||
_current_transport_mode = mode
|
||||
|
||||
|
||||
def get_transport_mode() -> str:
|
||||
"""Get the current transport mode."""
|
||||
return _current_transport_mode
|
||||
|
||||
|
||||
# OAuth Configuration
|
||||
# Determine base URL and redirect URI once at startup
|
||||
_OAUTH_REDIRECT_URI = os.getenv("GOOGLE_OAUTH_REDIRECT_URI")
|
||||
if _OAUTH_REDIRECT_URI:
|
||||
# Extract base URL from the redirect URI (remove the /oauth2callback path)
|
||||
_OAUTH_BASE_URL = _OAUTH_REDIRECT_URI.removesuffix("/oauth2callback")
|
||||
else:
|
||||
# Construct from base URI and port if not explicitly set
|
||||
_OAUTH_BASE_URL = f"{WORKSPACE_MCP_BASE_URI}:{WORKSPACE_MCP_PORT}"
|
||||
_OAUTH_REDIRECT_URI = f"{_OAUTH_BASE_URL}/oauth2callback"
|
||||
|
||||
def get_oauth_base_url() -> str:
|
||||
"""Get OAuth base URL for constructing OAuth endpoints.
|
||||
|
||||
Returns the base URL (without paths) for OAuth endpoints,
|
||||
respecting GOOGLE_OAUTH_REDIRECT_URI for reverse proxy scenarios.
|
||||
"""
|
||||
return _OAUTH_BASE_URL
|
||||
|
||||
def get_oauth_redirect_uri() -> str:
|
||||
"""Get OAuth redirect URI based on current configuration.
|
||||
|
||||
Returns the redirect URI configured at startup, either from
|
||||
GOOGLE_OAUTH_REDIRECT_URI environment variable or constructed
|
||||
from WORKSPACE_MCP_BASE_URI and WORKSPACE_MCP_PORT.
|
||||
"""
|
||||
return _OAUTH_REDIRECT_URI
|
||||
# Re-export OAuth functions for backward compatibility
|
||||
__all__ = [
|
||||
'WORKSPACE_MCP_PORT',
|
||||
'WORKSPACE_MCP_BASE_URI',
|
||||
'USER_GOOGLE_EMAIL',
|
||||
'get_oauth_base_url',
|
||||
'get_oauth_redirect_uri',
|
||||
'set_transport_mode',
|
||||
'get_transport_mode'
|
||||
]
|
||||
@@ -50,15 +50,15 @@ class SecureFastMCP(FastMCP):
|
||||
def streamable_http_app(self) -> "Starlette":
|
||||
"""Override to add secure middleware stack for OAuth 2.1."""
|
||||
app = super().streamable_http_app()
|
||||
|
||||
|
||||
# Add middleware in order (first added = outermost layer)
|
||||
# 1. CORS Security - handles CORS with proper origin validation
|
||||
app.user_middleware.insert(0, cors_security_middleware)
|
||||
# 2. VS Code Path Normalization - rewrites VS Code paths transparently
|
||||
# 2. VS Code Path Normalization - rewrites VS Code paths transparently
|
||||
app.user_middleware.insert(1, vscode_middleware)
|
||||
# 3. Session Management - extracts session info for MCP context
|
||||
app.user_middleware.insert(2, session_middleware)
|
||||
|
||||
|
||||
# Rebuild middleware stack
|
||||
app.middleware_stack = app.build_middleware_stack()
|
||||
logger.info("Added secure middleware stack: CORS Security, VS Code Compatibility, Session Management")
|
||||
@@ -66,7 +66,7 @@ class SecureFastMCP(FastMCP):
|
||||
|
||||
# --- Server Instance ---
|
||||
server = SecureFastMCP(
|
||||
name="google_workspace",
|
||||
name="google_workspace",
|
||||
auth=None,
|
||||
)
|
||||
|
||||
@@ -86,32 +86,38 @@ def configure_server_for_http():
|
||||
This must be called BEFORE server.run().
|
||||
"""
|
||||
global _auth_provider
|
||||
|
||||
transport_mode = get_transport_mode()
|
||||
|
||||
if transport_mode != "streamable-http":
|
||||
return
|
||||
|
||||
oauth21_enabled = os.getenv("MCP_ENABLE_OAUTH21", "false").lower() == "true"
|
||||
# Use centralized OAuth configuration
|
||||
from auth.oauth_config import get_oauth_config
|
||||
config = get_oauth_config()
|
||||
|
||||
# Check if OAuth 2.1 is enabled via centralized config
|
||||
oauth21_enabled = config.is_oauth21_enabled()
|
||||
|
||||
if oauth21_enabled:
|
||||
if not os.getenv("GOOGLE_OAUTH_CLIENT_ID"):
|
||||
logger.warning("⚠️ OAuth 2.1 enabled but GOOGLE_OAUTH_CLIENT_ID not set")
|
||||
if not config.is_configured():
|
||||
logger.warning("⚠️ OAuth 2.1 enabled but OAuth credentials not configured")
|
||||
return
|
||||
|
||||
if GOOGLE_REMOTE_AUTH_AVAILABLE:
|
||||
logger.info("🔐 OAuth 2.1 enabled")
|
||||
logger.info("🔐 OAuth 2.1 enabled with automatic OAuth 2.0 fallback for legacy clients")
|
||||
try:
|
||||
_auth_provider = GoogleRemoteAuthProvider()
|
||||
server.auth = _auth_provider
|
||||
set_auth_provider(_auth_provider)
|
||||
from auth.oauth21_integration import enable_oauth21
|
||||
enable_oauth21()
|
||||
enable_oauth21() # This is now just a logging call
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to initialize GoogleRemoteAuthProvider: {e}", exc_info=True)
|
||||
else:
|
||||
logger.error("OAuth 2.1 is enabled, but GoogleRemoteAuthProvider is not available.")
|
||||
else:
|
||||
logger.info("OAuth 2.1 is DISABLED. Server will use legacy tool-based authentication.")
|
||||
logger.info("OAuth 2.0 mode - Server will use legacy authentication.")
|
||||
server.auth = None
|
||||
|
||||
def get_auth_provider() -> Optional[Union[GoogleWorkspaceAuthProvider, GoogleRemoteAuthProvider]]:
|
||||
@@ -223,7 +229,7 @@ if os.getenv("MCP_ENABLE_OAUTH21", "false").lower() == "true" and not GOOGLE_REM
|
||||
handle_oauth_client_config,
|
||||
handle_oauth_register
|
||||
)
|
||||
|
||||
|
||||
server.custom_route("/.well-known/oauth-protected-resource", methods=["GET", "OPTIONS"])(handle_oauth_protected_resource)
|
||||
server.custom_route("/.well-known/oauth-authorization-server", methods=["GET", "OPTIONS"])(handle_oauth_authorization_server)
|
||||
server.custom_route("/.well-known/oauth-client", methods=["GET", "OPTIONS"])(handle_oauth_client_config)
|
||||
|
||||
Reference in New Issue
Block a user