workspace-mcp 1.1.9__tar.gz → 1.1.12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. {workspace_mcp-1.1.9/workspace_mcp.egg-info → workspace_mcp-1.1.12}/PKG-INFO +14 -6
  2. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/README.md +12 -4
  3. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/google_auth.py +3 -15
  4. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth_callback_server.py +4 -9
  5. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/scopes.py +0 -5
  6. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/core/server.py +6 -15
  7. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gcalendar/calendar_tools.py +19 -10
  8. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/pyproject.toml +2 -2
  9. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12/workspace_mcp.egg-info}/PKG-INFO +14 -6
  10. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/LICENSE +0 -0
  11. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/__init__.py +0 -0
  12. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/__init__.py +0 -0
  13. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/compat.py +0 -0
  14. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/config.py +0 -0
  15. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/discovery.py +0 -0
  16. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/example_config.py +0 -0
  17. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/handler.py +0 -0
  18. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/http.py +0 -0
  19. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/jwt.py +0 -0
  20. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/middleware.py +0 -0
  21. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/oauth2.py +0 -0
  22. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/sessions.py +0 -0
  23. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth21/tokens.py +0 -0
  24. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/oauth_responses.py +0 -0
  25. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/auth/service_decorator.py +0 -0
  26. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/core/__init__.py +0 -0
  27. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/core/comments.py +0 -0
  28. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/core/context.py +0 -0
  29. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/core/utils.py +0 -0
  30. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gTasks/__init__.py +0 -0
  31. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gTasks/tasks_tools.py +0 -0
  32. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gcalendar/__init__.py +0 -0
  33. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gchat/__init__.py +0 -0
  34. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gchat/chat_tools.py +0 -0
  35. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gdocs/__init__.py +0 -0
  36. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gdocs/docs_tools.py +0 -0
  37. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gdrive/__init__.py +0 -0
  38. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gdrive/drive_tools.py +0 -0
  39. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gforms/__init__.py +0 -0
  40. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gforms/forms_tools.py +0 -0
  41. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gmail/__init__.py +0 -0
  42. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gmail/gmail_tools.py +0 -0
  43. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gsheets/__init__.py +0 -0
  44. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gsheets/sheets_tools.py +0 -0
  45. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gslides/__init__.py +0 -0
  46. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/gslides/slides_tools.py +0 -0
  47. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/main.py +0 -0
  48. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/setup.cfg +0 -0
  49. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/tests/test_auth.py +0 -0
  50. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/tests/test_oauth_callback_server.py +0 -0
  51. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/workspace_mcp.egg-info/SOURCES.txt +0 -0
  52. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/workspace_mcp.egg-info/dependency_links.txt +0 -0
  53. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/workspace_mcp.egg-info/entry_points.txt +0 -0
  54. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/workspace_mcp.egg-info/requires.txt +0 -0
  55. {workspace_mcp-1.1.9 → workspace_mcp-1.1.12}/workspace_mcp.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workspace-mcp
3
- Version: 1.1.9
3
+ Version: 1.1.12
4
4
  Summary: Comprehensive, highly performant Google Workspace Streamable HTTP & SSE MCP Server for Calendar, Gmail, Docs, Sheets, Slides & Drive
5
5
  Author-email: Taylor Wilsdon <taylor@taylorwilsdon.com>
6
6
  License: MIT
@@ -27,7 +27,7 @@ Classifier: Topic :: Communications :: Chat
27
27
  Classifier: Topic :: Office/Business
28
28
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
29
29
  Classifier: Typing :: Typed
30
- Requires-Python: >=3.11
30
+ Requires-Python: >=3.10
31
31
  Description-Content-Type: text/markdown
32
32
  License-File: LICENSE
33
33
  Requires-Dist: fastapi>=0.115.12
@@ -46,7 +46,7 @@ Dynamic: license-file
46
46
  # Google Workspace MCP Server <img src="https://github.com/user-attachments/assets/b89524e4-6e6e-49e6-ba77-00d6df0c6e5c" width="80" align="right" />
47
47
 
48
48
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
49
- [![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
49
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
50
50
  [![PyPI](https://img.shields.io/pypi/v/workspace-mcp.svg)](https://pypi.org/project/workspace-mcp/)
51
51
  [![PyPI Downloads](https://static.pepy.tech/badge/workspace-mcp/month)](https://pepy.tech/projects/workspace-mcp)
52
52
  [![Website](https://img.shields.io/badge/Website-workspacemcp.com-green.svg)](https://workspacemcp.com)
@@ -151,7 +151,7 @@ If you’re developing, deploying to servers, or using another MCP-capable clien
151
151
  #### Instant CLI (uvx)
152
152
 
153
153
  ```bash
154
- # Requires Python 3.11+ and uvx
154
+ # Requires Python 3.10+ and uvx
155
155
  export GOOGLE_OAUTH_CLIENT_ID="xxx"
156
156
  export GOOGLE_OAUTH_CLIENT_SECRET="yyy"
157
157
  uvx workspace-mcp --tools gmail drive calendar
@@ -174,7 +174,7 @@ uvx workspace-mcp --tools gmail drive calendar tasks
174
174
  uvx workspace-mcp --transport streamable-http
175
175
  ```
176
176
 
177
- *Requires Python 3.11+ and [uvx](https://github.com/astral-sh/uv). The package is available on [PyPI](https://pypi.org/project/workspace-mcp).*
177
+ *Requires Python 3.10+ and [uvx](https://github.com/astral-sh/uv). The package is available on [PyPI](https://pypi.org/project/workspace-mcp).*
178
178
 
179
179
  ### Development Installation
180
180
 
@@ -188,7 +188,7 @@ uv run main.py
188
188
 
189
189
  ### Prerequisites
190
190
 
191
- - **Python 3.11+**
191
+ - **Python 3.10+**
192
192
  - **[uvx](https://github.com/astral-sh/uv)** (for instant installation) or [uv](https://github.com/astral-sh/uv) (for development)
193
193
  - **Google Cloud Project** with OAuth 2.0 credentials
194
194
 
@@ -524,6 +524,14 @@ async def your_new_tool(service, param1: str, param2: int = 10):
524
524
 
525
525
  To use this server as a tool provider within Open WebUI:
526
526
 
527
+ ### Instant Start (No Config Needed)
528
+ Just copy and paste the below, set your values and you're off!
529
+ ```bash
530
+ GOOGLE_OAUTH_CLIENT_ID="your_client_id" GOOGLE_OAUTH_CLIENT_SECRET="your_client_secret" uvx mcpo --port 8000 --api-key "top-secret" -- uvx workspace-mcp
531
+ ```
532
+
533
+ Otherwise:
534
+
527
535
  ### 1. Create MCPO Configuration
528
536
 
529
537
  Create a file named `config.json` with the following structure to have `mcpo` make the streamable HTTP endpoint available as an OpenAPI spec tool:
@@ -3,7 +3,7 @@
3
3
  # Google Workspace MCP Server <img src="https://github.com/user-attachments/assets/b89524e4-6e6e-49e6-ba77-00d6df0c6e5c" width="80" align="right" />
4
4
 
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
- [![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
6
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
7
7
  [![PyPI](https://img.shields.io/pypi/v/workspace-mcp.svg)](https://pypi.org/project/workspace-mcp/)
8
8
  [![PyPI Downloads](https://static.pepy.tech/badge/workspace-mcp/month)](https://pepy.tech/projects/workspace-mcp)
9
9
  [![Website](https://img.shields.io/badge/Website-workspacemcp.com-green.svg)](https://workspacemcp.com)
@@ -108,7 +108,7 @@ If you’re developing, deploying to servers, or using another MCP-capable clien
108
108
  #### Instant CLI (uvx)
109
109
 
110
110
  ```bash
111
- # Requires Python 3.11+ and uvx
111
+ # Requires Python 3.10+ and uvx
112
112
  export GOOGLE_OAUTH_CLIENT_ID="xxx"
113
113
  export GOOGLE_OAUTH_CLIENT_SECRET="yyy"
114
114
  uvx workspace-mcp --tools gmail drive calendar
@@ -131,7 +131,7 @@ uvx workspace-mcp --tools gmail drive calendar tasks
131
131
  uvx workspace-mcp --transport streamable-http
132
132
  ```
133
133
 
134
- *Requires Python 3.11+ and [uvx](https://github.com/astral-sh/uv). The package is available on [PyPI](https://pypi.org/project/workspace-mcp).*
134
+ *Requires Python 3.10+ and [uvx](https://github.com/astral-sh/uv). The package is available on [PyPI](https://pypi.org/project/workspace-mcp).*
135
135
 
136
136
  ### Development Installation
137
137
 
@@ -145,7 +145,7 @@ uv run main.py
145
145
 
146
146
  ### Prerequisites
147
147
 
148
- - **Python 3.11+**
148
+ - **Python 3.10+**
149
149
  - **[uvx](https://github.com/astral-sh/uv)** (for instant installation) or [uv](https://github.com/astral-sh/uv) (for development)
150
150
  - **Google Cloud Project** with OAuth 2.0 credentials
151
151
 
@@ -481,6 +481,14 @@ async def your_new_tool(service, param1: str, param2: int = 10):
481
481
 
482
482
  To use this server as a tool provider within Open WebUI:
483
483
 
484
+ ### Instant Start (No Config Needed)
485
+ Just copy and paste the below, set your values and you're off!
486
+ ```bash
487
+ GOOGLE_OAUTH_CLIENT_ID="your_client_id" GOOGLE_OAUTH_CLIENT_SECRET="your_client_secret" uvx mcpo --port 8000 --api-key "top-secret" -- uvx workspace-mcp
488
+ ```
489
+
490
+ Otherwise:
491
+
484
492
  ### 1. Create MCPO Configuration
485
493
 
486
494
  Create a file named `config.json` with the following structure to have `mcpo` make the streamable HTTP endpoint available as an OpenAPI spec tool:
@@ -15,7 +15,7 @@ from google.auth.transport.requests import Request
15
15
  from google.auth.exceptions import RefreshError
16
16
  from googleapiclient.discovery import build
17
17
  from googleapiclient.errors import HttpError
18
- from auth.scopes import OAUTH_STATE_TO_SESSION_ID_MAP, SCOPES
18
+ from auth.scopes import SCOPES
19
19
 
20
20
  # Configure logging
21
21
  logging.basicConfig(level=logging.INFO)
@@ -346,7 +346,6 @@ def create_oauth_flow(
346
346
 
347
347
 
348
348
  async def start_auth_flow(
349
- mcp_session_id: Optional[str],
350
349
  user_google_email: Optional[str],
351
350
  service_name: str, # e.g., "Google Calendar", "Gmail" for user messages
352
351
  redirect_uri: str, # Added redirect_uri as a required parameter
@@ -355,7 +354,6 @@ async def start_auth_flow(
355
354
  Initiates the Google OAuth flow and returns an actionable message for the user.
356
355
 
357
356
  Args:
358
- mcp_session_id: The active MCP session ID.
359
357
  user_google_email: The user's specified Google email, if provided.
360
358
  service_name: The name of the Google service requiring auth (for user messages).
361
359
  redirect_uri: The URI Google will redirect to after authorization.
@@ -378,7 +376,7 @@ async def start_auth_flow(
378
376
  )
379
377
 
380
378
  logger.info(
381
- f"[start_auth_flow] Initiating auth for {user_display_name} (session: {mcp_session_id}) with global SCOPES."
379
+ f"[start_auth_flow] Initiating auth for {user_display_name} with global SCOPES."
382
380
  )
383
381
 
384
382
  try:
@@ -391,11 +389,6 @@ async def start_auth_flow(
391
389
  os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
392
390
 
393
391
  oauth_state = os.urandom(16).hex()
394
- if mcp_session_id:
395
- OAUTH_STATE_TO_SESSION_ID_MAP[oauth_state] = mcp_session_id
396
- logger.info(
397
- f"[start_auth_flow] Stored mcp_session_id '{mcp_session_id}' for oauth_state '{oauth_state}'."
398
- )
399
392
 
400
393
  flow = create_oauth_flow(
401
394
  scopes=SCOPES, # Use global SCOPES
@@ -417,11 +410,7 @@ async def start_auth_flow(
417
410
  "**LLM, after presenting the link, instruct the user as follows:**",
418
411
  "1. Click the link and complete the authorization in their browser.",
419
412
  ]
420
- session_info_for_llm = (
421
- f" (this will link to your current session {mcp_session_id})"
422
- if mcp_session_id
423
- else ""
424
- )
413
+ session_info_for_llm = ""
425
414
 
426
415
  if not initial_email_provided:
427
416
  message_lines.extend(
@@ -773,7 +762,6 @@ async def get_authenticated_google_service(
773
762
 
774
763
  # Generate auth URL and raise exception with it
775
764
  auth_response = await start_auth_flow(
776
- mcp_session_id=None, # Session ID not available in service layer
777
765
  user_google_email=user_google_email,
778
766
  service_name=f"Google {service_name.title()}",
779
767
  redirect_uri=redirect_uri,
@@ -18,7 +18,7 @@ from typing import Optional
18
18
  from urllib.parse import urlparse
19
19
 
20
20
  from auth.google_auth import handle_auth_callback, check_client_secrets
21
- from auth.scopes import OAUTH_STATE_TO_SESSION_ID_MAP, SCOPES
21
+ from auth.scopes import SCOPES
22
22
  from auth.oauth_responses import create_error_response, create_success_response, create_server_error_response
23
23
 
24
24
  logger = logging.getLogger(__name__)
@@ -68,11 +68,7 @@ class MinimalOAuthServer:
68
68
 
69
69
  logger.info(f"OAuth callback: Received code (state: {state}). Attempting to exchange for tokens.")
70
70
 
71
- mcp_session_id: Optional[str] = OAUTH_STATE_TO_SESSION_ID_MAP.pop(state, None)
72
- if mcp_session_id:
73
- logger.info(f"OAuth callback: Retrieved MCP session ID '{mcp_session_id}' for state '{state}'.")
74
- else:
75
- logger.warning(f"OAuth callback: No MCP session ID found for state '{state}'. Auth will not be tied to a specific session.")
71
+ # Session ID tracking removed - not needed
76
72
 
77
73
  # Exchange code for credentials
78
74
  redirect_uri = get_oauth_redirect_uri(port=self.port, base_uri=self.base_uri)
@@ -80,11 +76,10 @@ class MinimalOAuthServer:
80
76
  scopes=SCOPES,
81
77
  authorization_response=str(request.url),
82
78
  redirect_uri=redirect_uri,
83
- session_id=mcp_session_id
79
+ session_id=None
84
80
  )
85
81
 
86
- log_session_part = f" (linked to session: {mcp_session_id})" if mcp_session_id else ""
87
- logger.info(f"OAuth callback: Successfully authenticated user: {verified_user_id} (state: {state}){log_session_part}.")
82
+ logger.info(f"OAuth callback: Successfully authenticated user: {verified_user_id} (state: {state}).")
88
83
 
89
84
  # Return success page using shared template
90
85
  return create_success_response(verified_user_id)
@@ -5,14 +5,9 @@ This module centralizes OAuth scope definitions for Google Workspace integration
5
5
  Separated from service_decorator.py to avoid circular imports.
6
6
  """
7
7
  import logging
8
- from typing import Dict
9
8
 
10
9
  logger = logging.getLogger(__name__)
11
10
 
12
- # Temporary map to associate OAuth state with MCP session ID
13
- # This should ideally be a more robust cache in a production system (e.g., Redis)
14
- OAUTH_STATE_TO_SESSION_ID_MAP: Dict[str, str] = {}
15
-
16
11
  # Individual OAuth Scope Constants
17
12
  USERINFO_EMAIL_SCOPE = 'https://www.googleapis.com/auth/userinfo.email'
18
13
  OPENID_SCOPE = 'openid'
@@ -16,7 +16,6 @@ from auth.oauth_responses import create_error_response, create_success_response,
16
16
 
17
17
  # Import shared configuration
18
18
  from auth.scopes import (
19
- OAUTH_STATE_TO_SESSION_ID_MAP,
20
19
  SCOPES,
21
20
  USERINFO_EMAIL_SCOPE, # noqa: F401
22
21
  OPENID_SCOPE, # noqa: F401
@@ -129,11 +128,7 @@ async def oauth2_callback(request: Request) -> HTMLResponse:
129
128
 
130
129
  logger.info(f"OAuth callback: Received code (state: {state}). Attempting to exchange for tokens.")
131
130
 
132
- mcp_session_id: Optional[str] = OAUTH_STATE_TO_SESSION_ID_MAP.pop(state, None)
133
- if mcp_session_id:
134
- logger.info(f"OAuth callback: Retrieved MCP session ID '{mcp_session_id}' for state '{state}'.")
135
- else:
136
- logger.warning(f"OAuth callback: No MCP session ID found for state '{state}'. Auth will not be tied to a specific session directly via this callback.")
131
+ # Session ID tracking removed - not needed
137
132
 
138
133
  # Exchange code for credentials. handle_auth_callback will save them.
139
134
  # The user_id returned here is the Google-verified email.
@@ -141,11 +136,10 @@ async def oauth2_callback(request: Request) -> HTMLResponse:
141
136
  scopes=SCOPES, # Ensure all necessary scopes are requested
142
137
  authorization_response=str(request.url),
143
138
  redirect_uri=get_oauth_redirect_uri_for_current_mode(),
144
- session_id=mcp_session_id # Pass session_id if available
139
+ session_id=None # Session ID tracking removed
145
140
  )
146
141
 
147
- log_session_part = f" (linked to session: {mcp_session_id})" if mcp_session_id else ""
148
- logger.info(f"OAuth callback: Successfully authenticated user: {verified_user_id} (state: {state}){log_session_part}.")
142
+ logger.info(f"OAuth callback: Successfully authenticated user: {verified_user_id} (state: {state}).")
149
143
 
150
144
  # Return success page using shared template
151
145
  return create_success_response(verified_user_id)
@@ -159,14 +153,13 @@ async def oauth2_callback(request: Request) -> HTMLResponse:
159
153
  @server.tool()
160
154
  async def start_google_auth(
161
155
  service_name: str,
162
- user_google_email: str = USER_GOOGLE_EMAIL,
163
- mcp_session_id: Optional[str] = Header(None, alias="Mcp-Session-Id")
156
+ user_google_email: str = USER_GOOGLE_EMAIL
164
157
  ) -> str:
165
158
  """
166
159
  Initiates the Google OAuth 2.0 authentication flow for the specified user email and service.
167
160
  This is the primary method to establish credentials when no valid session exists or when targeting a specific account for a particular service.
168
161
  It generates an authorization URL that the LLM must present to the user.
169
- The authentication attempt is linked to the current MCP session via `mcp_session_id`.
162
+ This initiates a new authentication flow for the specified user and service.
170
163
 
171
164
  LLM Guidance:
172
165
  - Use this tool when you need to authenticate a user for a specific Google service (e.g., "Google Calendar", "Google Docs", "Gmail", "Google Drive")
@@ -182,7 +175,6 @@ async def start_google_auth(
182
175
  Args:
183
176
  user_google_email (str): The user's full Google email address (e.g., 'example@gmail.com'). This is REQUIRED.
184
177
  service_name (str): The name of the Google service for which authentication is being requested (e.g., "Google Calendar", "Google Docs"). This is REQUIRED.
185
- mcp_session_id (Optional[str]): The active MCP session ID (automatically injected by FastMCP from the Mcp-Session-Id header). Links the OAuth flow state to the session.
186
178
 
187
179
  Returns:
188
180
  str: A detailed message for the LLM with the authorization URL and instructions to guide the user through the authentication process.
@@ -197,7 +189,7 @@ async def start_google_auth(
197
189
  logger.error(f"[start_google_auth] {error_msg}")
198
190
  raise Exception(error_msg)
199
191
 
200
- logger.info(f"Tool 'start_google_auth' invoked for user_google_email: '{user_google_email}', service: '{service_name}', session: '{mcp_session_id}'.")
192
+ logger.info(f"Tool 'start_google_auth' invoked for user_google_email: '{user_google_email}', service: '{service_name}'.")
201
193
 
202
194
  # Ensure OAuth callback is available for current transport mode
203
195
  redirect_uri = get_oauth_redirect_uri_for_current_mode()
@@ -205,7 +197,6 @@ async def start_google_auth(
205
197
  raise Exception("Failed to start OAuth callback server. Please try again.")
206
198
 
207
199
  auth_result = await start_auth_flow(
208
- mcp_session_id=mcp_session_id,
209
200
  user_google_email=user_google_email,
210
201
  service_name=service_name,
211
202
  redirect_uri=redirect_uri
@@ -122,9 +122,11 @@ async def get_events(
122
122
  time_min: Optional[str] = None,
123
123
  time_max: Optional[str] = None,
124
124
  max_results: int = 25,
125
+ query: Optional[str] = None,
125
126
  ) -> str:
126
127
  """
127
128
  Retrieves a list of events from a specified Google Calendar within a given time range.
129
+ You can also search for events by keyword by supplying the optional "query" param.
128
130
 
129
131
  Args:
130
132
  user_google_email (str): The user's Google email address. Required.
@@ -132,12 +134,13 @@ async def get_events(
132
134
  time_min (Optional[str]): The start of the time range (inclusive) in RFC3339 format (e.g., '2024-05-12T10:00:00Z' or '2024-05-12'). If omitted, defaults to the current time.
133
135
  time_max (Optional[str]): The end of the time range (exclusive) in RFC3339 format. If omitted, events starting from `time_min` onwards are considered (up to `max_results`).
134
136
  max_results (int): The maximum number of events to return. Defaults to 25.
137
+ query (Optional[str]): A keyword to search for within event fields (summary, description, location).
135
138
 
136
139
  Returns:
137
140
  str: A formatted list of events (summary, start and end times, link) within the specified range.
138
141
  """
139
142
  logger.info(
140
- f"[get_events] Raw time parameters - time_min: '{time_min}', time_max: '{time_max}'"
143
+ f"[get_events] Raw time parameters - time_min: '{time_min}', time_max: '{time_max}', query: '{query}'"
141
144
  )
142
145
 
143
146
  # Ensure time_min and time_max are correctly formatted for the API
@@ -161,19 +164,25 @@ async def get_events(
161
164
  )
162
165
 
163
166
  logger.info(
164
- f"[get_events] Final API parameters - calendarId: '{calendar_id}', timeMin: '{effective_time_min}', timeMax: '{effective_time_max}', maxResults: {max_results}"
167
+ f"[get_events] Final API parameters - calendarId: '{calendar_id}', timeMin: '{effective_time_min}', timeMax: '{effective_time_max}', maxResults: {max_results}, query: '{query}'"
165
168
  )
166
169
 
170
+ # Build the request parameters dynamically
171
+ request_params = {
172
+ "calendarId": calendar_id,
173
+ "timeMin": effective_time_min,
174
+ "timeMax": effective_time_max,
175
+ "maxResults": max_results,
176
+ "singleEvents": True,
177
+ "orderBy": "startTime",
178
+ }
179
+
180
+ if query:
181
+ request_params["q"] = query
182
+
167
183
  events_result = await asyncio.to_thread(
168
184
  lambda: service.events()
169
- .list(
170
- calendarId=calendar_id,
171
- timeMin=effective_time_min,
172
- timeMax=effective_time_max,
173
- maxResults=max_results,
174
- singleEvents=True,
175
- orderBy="startTime",
176
- )
185
+ .list(**request_params)
177
186
  .execute()
178
187
  )
179
188
  items = events_result.get("items", [])
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "workspace-mcp"
7
- version = "1.1.9"
7
+ version = "1.1.12"
8
8
  description = "Comprehensive, highly performant Google Workspace Streamable HTTP & SSE MCP Server for Calendar, Gmail, Docs, Sheets, Slides & Drive"
9
9
  readme = "README.md"
10
10
  keywords = [ "mcp", "google", "workspace", "llm", "ai", "claude", "model", "context", "protocol", "server"]
11
- requires-python = ">=3.11"
11
+ requires-python = ">=3.10"
12
12
  dependencies = [
13
13
  "fastapi>=0.115.12",
14
14
  "fastmcp>=2.3.3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workspace-mcp
3
- Version: 1.1.9
3
+ Version: 1.1.12
4
4
  Summary: Comprehensive, highly performant Google Workspace Streamable HTTP & SSE MCP Server for Calendar, Gmail, Docs, Sheets, Slides & Drive
5
5
  Author-email: Taylor Wilsdon <taylor@taylorwilsdon.com>
6
6
  License: MIT
@@ -27,7 +27,7 @@ Classifier: Topic :: Communications :: Chat
27
27
  Classifier: Topic :: Office/Business
28
28
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
29
29
  Classifier: Typing :: Typed
30
- Requires-Python: >=3.11
30
+ Requires-Python: >=3.10
31
31
  Description-Content-Type: text/markdown
32
32
  License-File: LICENSE
33
33
  Requires-Dist: fastapi>=0.115.12
@@ -46,7 +46,7 @@ Dynamic: license-file
46
46
  # Google Workspace MCP Server <img src="https://github.com/user-attachments/assets/b89524e4-6e6e-49e6-ba77-00d6df0c6e5c" width="80" align="right" />
47
47
 
48
48
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
49
- [![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
49
+ [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
50
50
  [![PyPI](https://img.shields.io/pypi/v/workspace-mcp.svg)](https://pypi.org/project/workspace-mcp/)
51
51
  [![PyPI Downloads](https://static.pepy.tech/badge/workspace-mcp/month)](https://pepy.tech/projects/workspace-mcp)
52
52
  [![Website](https://img.shields.io/badge/Website-workspacemcp.com-green.svg)](https://workspacemcp.com)
@@ -151,7 +151,7 @@ If you’re developing, deploying to servers, or using another MCP-capable clien
151
151
  #### Instant CLI (uvx)
152
152
 
153
153
  ```bash
154
- # Requires Python 3.11+ and uvx
154
+ # Requires Python 3.10+ and uvx
155
155
  export GOOGLE_OAUTH_CLIENT_ID="xxx"
156
156
  export GOOGLE_OAUTH_CLIENT_SECRET="yyy"
157
157
  uvx workspace-mcp --tools gmail drive calendar
@@ -174,7 +174,7 @@ uvx workspace-mcp --tools gmail drive calendar tasks
174
174
  uvx workspace-mcp --transport streamable-http
175
175
  ```
176
176
 
177
- *Requires Python 3.11+ and [uvx](https://github.com/astral-sh/uv). The package is available on [PyPI](https://pypi.org/project/workspace-mcp).*
177
+ *Requires Python 3.10+ and [uvx](https://github.com/astral-sh/uv). The package is available on [PyPI](https://pypi.org/project/workspace-mcp).*
178
178
 
179
179
  ### Development Installation
180
180
 
@@ -188,7 +188,7 @@ uv run main.py
188
188
 
189
189
  ### Prerequisites
190
190
 
191
- - **Python 3.11+**
191
+ - **Python 3.10+**
192
192
  - **[uvx](https://github.com/astral-sh/uv)** (for instant installation) or [uv](https://github.com/astral-sh/uv) (for development)
193
193
  - **Google Cloud Project** with OAuth 2.0 credentials
194
194
 
@@ -524,6 +524,14 @@ async def your_new_tool(service, param1: str, param2: int = 10):
524
524
 
525
525
  To use this server as a tool provider within Open WebUI:
526
526
 
527
+ ### Instant Start (No Config Needed)
528
+ Just copy and paste the below, set your values and you're off!
529
+ ```bash
530
+ GOOGLE_OAUTH_CLIENT_ID="your_client_id" GOOGLE_OAUTH_CLIENT_SECRET="your_client_secret" uvx mcpo --port 8000 --api-key "top-secret" -- uvx workspace-mcp
531
+ ```
532
+
533
+ Otherwise:
534
+
527
535
  ### 1. Create MCPO Configuration
528
536
 
529
537
  Create a file named `config.json` with the following structure to have `mcpo` make the streamable HTTP endpoint available as an OpenAPI spec tool:
File without changes
File without changes
File without changes