Merge pull request #164 from shawnzhu/schema-modifier

remove user_google_email parameter for multi-user mode
This commit is contained in:
Taylor Wilsdon
2025-08-14 11:12:16 -04:00
committed by GitHub
4 changed files with 81 additions and 41 deletions

View File

@@ -97,7 +97,7 @@ A production-ready MCP server that integrates all major Google Workspace service
| `USER_GOOGLE_EMAIL` *(optional)* | Default email for single-user auth |
| `GOOGLE_PSE_API_KEY` *(optional)* | API key for Google Custom Search - see [Custom Search Setup](#google-custom-search-setup) |
| `GOOGLE_PSE_ENGINE_ID` *(optional)* | Programmable Search Engine ID for Custom Search |
| `MCP_ENABLE_OAUTH21` *(optional)* | Set to `true` to enable OAuth 2.1 support (requires streamable-http transport) |
| `MCP_ENABLE_OAUTH21` *(optional)* | Set to `true` to enable OAuth 2.1 support (requires streamable-http transport & will remove user_google_email from tool docstrings) |
| `OAUTHLIB_INSECURE_TRANSPORT=1` | Development only (allows `http://` redirect) |
Claude Desktop stores these securely in the OS keychain; set them once in the extension pane.

View File

@@ -1,5 +1,6 @@
import inspect
import logging
import re
from functools import wraps
from typing import Dict, List, Optional, Any, Callable, Union, Tuple
@@ -237,6 +238,39 @@ async def get_authenticated_google_service_oauth21(
logger = logging.getLogger(__name__)
def _remove_user_email_arg_from_docstring(docstring: str) -> str:
"""
Remove user_google_email parameter documentation from docstring.
Args:
docstring: The original function docstring
Returns:
Modified docstring with user_google_email parameter removed
"""
if not docstring:
return docstring
# Pattern to match user_google_email parameter documentation
# Handles various formats like:
# - user_google_email (str): The user's Google email address. Required.
# - user_google_email: Description
# - user_google_email (str) - Description
patterns = [
r'^\s*user_google_email\s*\([^)]*\)\s*:\s*[^\n]*\.?\s*(?:Required\.?)?\s*\n',
r'^\s*user_google_email\s*:\s*[^\n]*\n',
r'^\s*user_google_email\s*\([^)]*\)\s*-\s*[^\n]*\n',
]
modified_docstring = docstring
for pattern in patterns:
modified_docstring = re.sub(pattern, '', modified_docstring, flags=re.MULTILINE)
# Clean up any sequence of 3 or more newlines that might have been created
modified_docstring = re.sub(r'\n{3,}', '\n\n', modified_docstring)
return modified_docstring
# Service configuration mapping
SERVICE_CONFIGS = {
"gmail": {"service": "gmail", "version": "v1"},
@@ -485,6 +519,13 @@ def require_google_service(
# Set the wrapper's signature to the one without 'service'
wrapper.__signature__ = wrapper_sig
# Conditionally modify docstring to remove user_google_email parameter documentation
if is_oauth21_enabled():
logger.debug('OAuth 2.1 mode enabled, removing user_google_email from docstring')
if func.__doc__:
wrapper.__doc__ = _remove_user_email_arg_from_docstring(func.__doc__)
return wrapper
return decorator

View File

@@ -774,7 +774,6 @@ async def inspect_doc_structure(
CRITICAL FOR TABLE OPERATIONS:
ALWAYS call this BEFORE creating tables to get a safe insertion index.
Look for "total_length" in the output - use values less than this for insertion.
WHAT THE OUTPUT SHOWS:
- total_elements: Number of document elements

View File

@@ -208,9 +208,9 @@ def main():
# Check port availability before starting HTTP server
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(1.0) # Prevent hanging on bind
s.bind(("0.0.0.0", port))
except OSError:
s.bind((socket.gethostbyname(""), port))
except OSError as e:
safe_print(f"Socket error: {e}")
safe_print(f"❌ Port {port} is already in use. Cannot start HTTP server.")
sys.exit(1)