workspace-mcp 1.1.4__tar.gz → 1.1.6__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.
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/PKG-INFO +62 -13
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/README.md +61 -12
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/auth/google_auth.py +6 -8
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/auth/oauth_callback_server.py +22 -8
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/core/server.py +1 -1
- workspace_mcp-1.1.6/core/utils.py +296 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gTasks/tasks_tools.py +13 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gcalendar/calendar_tools.py +7 -7
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gdocs/docs_tools.py +4 -5
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gdrive/drive_tools.py +5 -5
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gforms/forms_tools.py +22 -23
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gmail/gmail_tools.py +199 -82
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gsheets/sheets_tools.py +7 -7
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gslides/slides_tools.py +25 -25
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/pyproject.toml +1 -1
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/tests/test_oauth_callback_server.py +0 -2
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/workspace_mcp.egg-info/PKG-INFO +62 -13
- workspace_mcp-1.1.4/core/utils.py +0 -197
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/LICENSE +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/auth/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/auth/oauth_responses.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/auth/scopes.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/auth/service_decorator.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/core/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/core/comments.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/core/context.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gTasks/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gcalendar/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gchat/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gchat/chat_tools.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gdocs/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gdrive/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gforms/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gmail/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gsheets/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/gslides/__init__.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/main.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/setup.cfg +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/tests/test_auth.py +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/workspace_mcp.egg-info/SOURCES.txt +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/workspace_mcp.egg-info/dependency_links.txt +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/workspace_mcp.egg-info/entry_points.txt +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/workspace_mcp.egg-info/requires.txt +0 -0
- {workspace_mcp-1.1.4 → workspace_mcp-1.1.6}/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.
|
3
|
+
Version: 1.1.6
|
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
|
@@ -47,11 +47,11 @@ Dynamic: license-file
|
|
47
47
|
[](https://opensource.org/licenses/MIT)
|
48
48
|
[](https://www.python.org/downloads/)
|
49
49
|
[](https://pypi.org/project/workspace-mcp/)
|
50
|
-
[](https://pepy.tech/projects/workspace-mcp)
|
51
51
|
[](https://workspacemcp.com)
|
52
52
|
[](https://mseep.ai/app/eebbc4a6-0f8c-41b2-ace8-038e5516dba0)
|
53
53
|
|
54
|
-
**This is the single most feature-complete Google Workspace MCP server**
|
54
|
+
**This is the single most feature-complete Google Workspace MCP server** now with 1-click Claude installation
|
55
55
|
|
56
56
|
*Full natural language control over Google Calendar, Drive, Gmail, Docs, Sheets, Slides, Forms, Tasks, and Chat through all MCP clients, AI assistants and developer tools.*
|
57
57
|
|
@@ -79,13 +79,15 @@ Dynamic: license-file
|
|
79
79
|
---
|
80
80
|
|
81
81
|
### A quick plug for AI-Enhanced Docs
|
82
|
+
<details>
|
83
|
+
<summary>But why?</summary>
|
82
84
|
|
83
|
-
|
85
|
+
**This README was written with AI assistance, and here's why that matters**
|
84
86
|
>
|
85
|
-
> As a solo
|
87
|
+
> As a solo dev building open source tools that many never see outside use, comprehensive documentation often wouldn't happen without AI help. Using agentic dev tools like **Roo** & **Claude Code** that understand the entire codebase, AI doesn't just regurgitate generic content - it extracts real implementation details and creates accurate, specific documentation.
|
86
88
|
>
|
87
|
-
> In this case, Sonnet 4 took a pass & a human (me) verified them
|
88
|
-
|
89
|
+
> In this case, Sonnet 4 took a pass & a human (me) verified them 7/10/25.
|
90
|
+
</details>
|
89
91
|
|
90
92
|
## Overview
|
91
93
|
|
@@ -103,7 +105,7 @@ A production-ready MCP server that integrates all major Google Workspace service
|
|
103
105
|
- **📝 Google Forms**: Form creation, retrieval, publish settings, and response management
|
104
106
|
- **✓ Google Tasks**: Complete task and task list management with hierarchy, due dates, and status tracking
|
105
107
|
- **💬 Google Chat**: Space management and messaging capabilities
|
106
|
-
- **🔄
|
108
|
+
- **🔄 All Transports**: Stdio, Streamable HTTP & SSE, OpenAPI compatibility via `mcpo`
|
107
109
|
- **⚡ High Performance**: Service caching, thread-safe sessions, FastMCP integration
|
108
110
|
- **🧩 Developer Friendly**: Minimal boilerplate, automatic service injection, centralized configuration
|
109
111
|
|
@@ -111,7 +113,48 @@ A production-ready MCP server that integrates all major Google Workspace service
|
|
111
113
|
|
112
114
|
## 🚀 Quick Start
|
113
115
|
|
114
|
-
###
|
116
|
+
### 1. One-Click Claude Desktop Install (Recommended)
|
117
|
+
|
118
|
+
1. **Download:** Grab the latest `google_workspace_mcp.dxt` from the “Releases” page
|
119
|
+
2. **Install:** Double-click the file – Claude Desktop opens and prompts you to **Install**
|
120
|
+
3. **Configure:** In Claude Desktop → **Settings → Extensions → Google Workspace MCP**, paste your Google OAuth credentials
|
121
|
+
4. **Use it:** Start a new Claude chat and call any Google Workspace tool 🎉
|
122
|
+
|
123
|
+
>
|
124
|
+
**Why DXT?**
|
125
|
+
> Desktop Extensions (`.dxt`) bundle the server, dependencies, and manifest so users go from download → working MCP in **one click** – no terminal, no JSON editing, no version conflicts.
|
126
|
+
|
127
|
+
#### Required Configuration
|
128
|
+
<details>
|
129
|
+
<summary>Environment - you will configure these in Claude itself, see screenshot:</summary>
|
130
|
+
|
131
|
+
| Variable | Purpose |
|
132
|
+
|----------|---------|
|
133
|
+
| `GOOGLE_OAUTH_CLIENT_ID` | OAuth client ID from Google Cloud |
|
134
|
+
| `GOOGLE_OAUTH_CLIENT_SECRET` | OAuth client secret |
|
135
|
+
| `USER_GOOGLE_EMAIL` *(optional)* | Default email for single-user auth |
|
136
|
+
| `OAUTHLIB_INSECURE_TRANSPORT=1` | Development only (allows `http://` redirect) |
|
137
|
+
|
138
|
+
Claude Desktop stores these securely in the OS keychain; set them once in the extension pane.
|
139
|
+
</details>
|
140
|
+
|
141
|
+
<div align="center">
|
142
|
+
<video width="832" src="https://github.com/user-attachments/assets/83cca4b3-5e94-448b-acb3-6e3a27341d3a"></video>
|
143
|
+
</div>
|
144
|
+
---
|
145
|
+
|
146
|
+
### 2. Advanced / Cross-Platform Installation
|
147
|
+
|
148
|
+
If you’re developing, deploying to servers, or using another MCP-capable client, keep reading.
|
149
|
+
|
150
|
+
#### Instant CLI (uvx)
|
151
|
+
|
152
|
+
```bash
|
153
|
+
# Requires Python 3.11+ and uvx
|
154
|
+
export GOOGLE_OAUTH_CLIENT_ID="xxx"
|
155
|
+
export GOOGLE_OAUTH_CLIENT_SECRET="yyy"
|
156
|
+
uvx workspace-mcp --tools gmail drive calendar
|
157
|
+
```
|
115
158
|
|
116
159
|
> Run instantly without manual installation - you must configure OAuth credentials when using uvx. You can use either environment variables (recommended for production) or set the `GOOGLE_CLIENT_SECRET_PATH` (or legacy `GOOGLE_CLIENT_SECRETS`) environment variable to point to your `client_secret.json` file.
|
117
160
|
|
@@ -187,9 +230,10 @@ uv run main.py
|
|
187
230
|
|
188
231
|
3. **Server Configuration**:
|
189
232
|
The server's base URL and port can be customized using environment variables:
|
190
|
-
- `WORKSPACE_MCP_BASE_URI`: Sets the base URI for the server (default: http://localhost). This affects the server_url used
|
233
|
+
- `WORKSPACE_MCP_BASE_URI`: Sets the base URI for the server (default: http://localhost). This affects the `server_url` used to construct the default `OAUTH_REDIRECT_URI` if `GOOGLE_OAUTH_REDIRECT_URI` is not set.
|
191
234
|
- `WORKSPACE_MCP_PORT`: Sets the port the server listens on (default: 8000). This affects the server_url, port, and OAUTH_REDIRECT_URI.
|
192
235
|
- `USER_GOOGLE_EMAIL`: Optional default email for authentication flows. If set, the LLM won't need to specify your email when calling `start_google_auth`.
|
236
|
+
- `GOOGLE_OAUTH_REDIRECT_URI`: Sets an override for OAuth redirect specifically, must include a full address (i.e. include port if necessary). Use this if you want to run your OAuth redirect separately from the MCP. This is not recommended outside of very specific cases
|
193
237
|
|
194
238
|
### Start the Server
|
195
239
|
|
@@ -221,7 +265,8 @@ The server supports two transport modes:
|
|
221
265
|
|
222
266
|
#### Stdio Mode (Default - Recommended for Claude Desktop)
|
223
267
|
|
224
|
-
**
|
268
|
+
**Guided Setup (Recommended if not using DXT)**
|
269
|
+
|
225
270
|
```bash
|
226
271
|
python install_claude.py
|
227
272
|
```
|
@@ -266,8 +311,12 @@ After running the script, just restart Claude Desktop and you're ready to go.
|
|
266
311
|
"mcpServers": {
|
267
312
|
"google_workspace": {
|
268
313
|
"command": "uv",
|
269
|
-
"args": [
|
270
|
-
|
314
|
+
"args": [
|
315
|
+
"run",
|
316
|
+
"--directory",
|
317
|
+
"/path/to/repo/google_workspace_mcp",
|
318
|
+
"main.py"
|
319
|
+
],
|
271
320
|
"env": {
|
272
321
|
"GOOGLE_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
|
273
322
|
"GOOGLE_OAUTH_CLIENT_SECRET": "your-client-secret",
|
@@ -5,11 +5,11 @@
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
6
6
|
[](https://www.python.org/downloads/)
|
7
7
|
[](https://pypi.org/project/workspace-mcp/)
|
8
|
-
[](https://pepy.tech/projects/workspace-mcp)
|
9
9
|
[](https://workspacemcp.com)
|
10
10
|
[](https://mseep.ai/app/eebbc4a6-0f8c-41b2-ace8-038e5516dba0)
|
11
11
|
|
12
|
-
**This is the single most feature-complete Google Workspace MCP server**
|
12
|
+
**This is the single most feature-complete Google Workspace MCP server** now with 1-click Claude installation
|
13
13
|
|
14
14
|
*Full natural language control over Google Calendar, Drive, Gmail, Docs, Sheets, Slides, Forms, Tasks, and Chat through all MCP clients, AI assistants and developer tools.*
|
15
15
|
|
@@ -37,13 +37,15 @@
|
|
37
37
|
---
|
38
38
|
|
39
39
|
### A quick plug for AI-Enhanced Docs
|
40
|
+
<details>
|
41
|
+
<summary>But why?</summary>
|
40
42
|
|
41
|
-
|
43
|
+
**This README was written with AI assistance, and here's why that matters**
|
42
44
|
>
|
43
|
-
> As a solo
|
45
|
+
> As a solo dev building open source tools that many never see outside use, comprehensive documentation often wouldn't happen without AI help. Using agentic dev tools like **Roo** & **Claude Code** that understand the entire codebase, AI doesn't just regurgitate generic content - it extracts real implementation details and creates accurate, specific documentation.
|
44
46
|
>
|
45
|
-
> In this case, Sonnet 4 took a pass & a human (me) verified them
|
46
|
-
|
47
|
+
> In this case, Sonnet 4 took a pass & a human (me) verified them 7/10/25.
|
48
|
+
</details>
|
47
49
|
|
48
50
|
## Overview
|
49
51
|
|
@@ -61,7 +63,7 @@ A production-ready MCP server that integrates all major Google Workspace service
|
|
61
63
|
- **📝 Google Forms**: Form creation, retrieval, publish settings, and response management
|
62
64
|
- **✓ Google Tasks**: Complete task and task list management with hierarchy, due dates, and status tracking
|
63
65
|
- **💬 Google Chat**: Space management and messaging capabilities
|
64
|
-
- **🔄
|
66
|
+
- **🔄 All Transports**: Stdio, Streamable HTTP & SSE, OpenAPI compatibility via `mcpo`
|
65
67
|
- **⚡ High Performance**: Service caching, thread-safe sessions, FastMCP integration
|
66
68
|
- **🧩 Developer Friendly**: Minimal boilerplate, automatic service injection, centralized configuration
|
67
69
|
|
@@ -69,7 +71,48 @@ A production-ready MCP server that integrates all major Google Workspace service
|
|
69
71
|
|
70
72
|
## 🚀 Quick Start
|
71
73
|
|
72
|
-
###
|
74
|
+
### 1. One-Click Claude Desktop Install (Recommended)
|
75
|
+
|
76
|
+
1. **Download:** Grab the latest `google_workspace_mcp.dxt` from the “Releases” page
|
77
|
+
2. **Install:** Double-click the file – Claude Desktop opens and prompts you to **Install**
|
78
|
+
3. **Configure:** In Claude Desktop → **Settings → Extensions → Google Workspace MCP**, paste your Google OAuth credentials
|
79
|
+
4. **Use it:** Start a new Claude chat and call any Google Workspace tool 🎉
|
80
|
+
|
81
|
+
>
|
82
|
+
**Why DXT?**
|
83
|
+
> Desktop Extensions (`.dxt`) bundle the server, dependencies, and manifest so users go from download → working MCP in **one click** – no terminal, no JSON editing, no version conflicts.
|
84
|
+
|
85
|
+
#### Required Configuration
|
86
|
+
<details>
|
87
|
+
<summary>Environment - you will configure these in Claude itself, see screenshot:</summary>
|
88
|
+
|
89
|
+
| Variable | Purpose |
|
90
|
+
|----------|---------|
|
91
|
+
| `GOOGLE_OAUTH_CLIENT_ID` | OAuth client ID from Google Cloud |
|
92
|
+
| `GOOGLE_OAUTH_CLIENT_SECRET` | OAuth client secret |
|
93
|
+
| `USER_GOOGLE_EMAIL` *(optional)* | Default email for single-user auth |
|
94
|
+
| `OAUTHLIB_INSECURE_TRANSPORT=1` | Development only (allows `http://` redirect) |
|
95
|
+
|
96
|
+
Claude Desktop stores these securely in the OS keychain; set them once in the extension pane.
|
97
|
+
</details>
|
98
|
+
|
99
|
+
<div align="center">
|
100
|
+
<video width="832" src="https://github.com/user-attachments/assets/83cca4b3-5e94-448b-acb3-6e3a27341d3a"></video>
|
101
|
+
</div>
|
102
|
+
---
|
103
|
+
|
104
|
+
### 2. Advanced / Cross-Platform Installation
|
105
|
+
|
106
|
+
If you’re developing, deploying to servers, or using another MCP-capable client, keep reading.
|
107
|
+
|
108
|
+
#### Instant CLI (uvx)
|
109
|
+
|
110
|
+
```bash
|
111
|
+
# Requires Python 3.11+ and uvx
|
112
|
+
export GOOGLE_OAUTH_CLIENT_ID="xxx"
|
113
|
+
export GOOGLE_OAUTH_CLIENT_SECRET="yyy"
|
114
|
+
uvx workspace-mcp --tools gmail drive calendar
|
115
|
+
```
|
73
116
|
|
74
117
|
> Run instantly without manual installation - you must configure OAuth credentials when using uvx. You can use either environment variables (recommended for production) or set the `GOOGLE_CLIENT_SECRET_PATH` (or legacy `GOOGLE_CLIENT_SECRETS`) environment variable to point to your `client_secret.json` file.
|
75
118
|
|
@@ -145,9 +188,10 @@ uv run main.py
|
|
145
188
|
|
146
189
|
3. **Server Configuration**:
|
147
190
|
The server's base URL and port can be customized using environment variables:
|
148
|
-
- `WORKSPACE_MCP_BASE_URI`: Sets the base URI for the server (default: http://localhost). This affects the server_url used
|
191
|
+
- `WORKSPACE_MCP_BASE_URI`: Sets the base URI for the server (default: http://localhost). This affects the `server_url` used to construct the default `OAUTH_REDIRECT_URI` if `GOOGLE_OAUTH_REDIRECT_URI` is not set.
|
149
192
|
- `WORKSPACE_MCP_PORT`: Sets the port the server listens on (default: 8000). This affects the server_url, port, and OAUTH_REDIRECT_URI.
|
150
193
|
- `USER_GOOGLE_EMAIL`: Optional default email for authentication flows. If set, the LLM won't need to specify your email when calling `start_google_auth`.
|
194
|
+
- `GOOGLE_OAUTH_REDIRECT_URI`: Sets an override for OAuth redirect specifically, must include a full address (i.e. include port if necessary). Use this if you want to run your OAuth redirect separately from the MCP. This is not recommended outside of very specific cases
|
151
195
|
|
152
196
|
### Start the Server
|
153
197
|
|
@@ -179,7 +223,8 @@ The server supports two transport modes:
|
|
179
223
|
|
180
224
|
#### Stdio Mode (Default - Recommended for Claude Desktop)
|
181
225
|
|
182
|
-
**
|
226
|
+
**Guided Setup (Recommended if not using DXT)**
|
227
|
+
|
183
228
|
```bash
|
184
229
|
python install_claude.py
|
185
230
|
```
|
@@ -224,8 +269,12 @@ After running the script, just restart Claude Desktop and you're ready to go.
|
|
224
269
|
"mcpServers": {
|
225
270
|
"google_workspace": {
|
226
271
|
"command": "uv",
|
227
|
-
"args": [
|
228
|
-
|
272
|
+
"args": [
|
273
|
+
"run",
|
274
|
+
"--directory",
|
275
|
+
"/path/to/repo/google_workspace_mcp",
|
276
|
+
"main.py"
|
277
|
+
],
|
229
278
|
"env": {
|
230
279
|
"GOOGLE_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
|
231
280
|
"GOOGLE_OAUTH_CLIENT_SECRET": "your-client-secret",
|
@@ -1,14 +1,16 @@
|
|
1
1
|
# auth/google_auth.py
|
2
2
|
|
3
|
-
import
|
3
|
+
import asyncio
|
4
4
|
import json
|
5
|
+
import jwt
|
5
6
|
import logging
|
6
|
-
import asyncio
|
7
|
-
from typing import List, Optional, Tuple, Dict, Any, Callable
|
8
7
|
import os
|
9
8
|
|
9
|
+
from datetime import datetime
|
10
|
+
from typing import List, Optional, Tuple, Dict, Any
|
11
|
+
|
10
12
|
from google.oauth2.credentials import Credentials
|
11
|
-
from google_auth_oauthlib.flow import Flow
|
13
|
+
from google_auth_oauthlib.flow import Flow
|
12
14
|
from google.auth.transport.requests import Request
|
13
15
|
from google.auth.exceptions import RefreshError
|
14
16
|
from googleapiclient.discovery import build
|
@@ -161,8 +163,6 @@ def load_credentials_from_file(
|
|
161
163
|
expiry = None
|
162
164
|
if creds_data.get("expiry"):
|
163
165
|
try:
|
164
|
-
from datetime import datetime
|
165
|
-
|
166
166
|
expiry = datetime.fromisoformat(creds_data["expiry"])
|
167
167
|
except (ValueError, TypeError) as e:
|
168
168
|
logger.warning(
|
@@ -789,8 +789,6 @@ async def get_authenticated_google_service(
|
|
789
789
|
# Try to get email from credentials if needed for validation
|
790
790
|
if credentials and credentials.id_token:
|
791
791
|
try:
|
792
|
-
import jwt
|
793
|
-
|
794
792
|
# Decode without verification (just to get email for logging)
|
795
793
|
decoded_token = jwt.decode(
|
796
794
|
credentials.id_token, options={"verify_signature": False}
|
@@ -5,15 +5,17 @@ In streamable-http mode: Uses the existing FastAPI server
|
|
5
5
|
In stdio mode: Starts a minimal HTTP server just for OAuth callbacks
|
6
6
|
"""
|
7
7
|
|
8
|
+
import os
|
8
9
|
import asyncio
|
9
10
|
import logging
|
10
11
|
import threading
|
11
12
|
import time
|
12
|
-
from typing import Optional, Dict, Any
|
13
13
|
import socket
|
14
|
+
import uvicorn
|
14
15
|
|
15
16
|
from fastapi import FastAPI, Request
|
16
|
-
import
|
17
|
+
from typing import Optional
|
18
|
+
from urllib.parse import urlparse
|
17
19
|
|
18
20
|
from auth.google_auth import handle_auth_callback, check_client_secrets
|
19
21
|
from auth.scopes import OAUTH_STATE_TO_SESSION_ID_MAP, SCOPES
|
@@ -73,10 +75,11 @@ class MinimalOAuthServer:
|
|
73
75
|
logger.warning(f"OAuth callback: No MCP session ID found for state '{state}'. Auth will not be tied to a specific session.")
|
74
76
|
|
75
77
|
# Exchange code for credentials
|
78
|
+
redirect_uri = get_oauth_redirect_uri(port=self.port, base_uri=self.base_uri)
|
76
79
|
verified_user_id, credentials = handle_auth_callback(
|
77
80
|
scopes=SCOPES,
|
78
81
|
authorization_response=str(request.url),
|
79
|
-
redirect_uri=
|
82
|
+
redirect_uri=redirect_uri,
|
80
83
|
session_id=mcp_session_id
|
81
84
|
)
|
82
85
|
|
@@ -105,7 +108,6 @@ class MinimalOAuthServer:
|
|
105
108
|
# Check if port is available
|
106
109
|
# Extract hostname from base_uri (e.g., "http://localhost" -> "localhost")
|
107
110
|
try:
|
108
|
-
from urllib.parse import urlparse
|
109
111
|
parsed_uri = urlparse(self.base_uri)
|
110
112
|
hostname = parsed_uri.hostname or 'localhost'
|
111
113
|
except Exception:
|
@@ -179,19 +181,31 @@ class MinimalOAuthServer:
|
|
179
181
|
# Global instance for stdio mode
|
180
182
|
_minimal_oauth_server: Optional[MinimalOAuthServer] = None
|
181
183
|
|
182
|
-
def get_oauth_redirect_uri(
|
184
|
+
def get_oauth_redirect_uri(port: int = 8000, base_uri: str = "http://localhost") -> str:
|
183
185
|
"""
|
184
|
-
Get the appropriate OAuth redirect URI
|
186
|
+
Get the appropriate OAuth redirect URI.
|
187
|
+
|
188
|
+
Priority:
|
189
|
+
1. GOOGLE_OAUTH_REDIRECT_URI environment variable
|
190
|
+
2. Constructed from port and base URI
|
185
191
|
|
186
192
|
Args:
|
187
|
-
transport_mode: "stdio" or "streamable-http"
|
188
193
|
port: Port number (default 8000)
|
189
194
|
base_uri: Base URI (default "http://localhost")
|
190
195
|
|
191
196
|
Returns:
|
192
197
|
OAuth redirect URI
|
193
198
|
"""
|
194
|
-
|
199
|
+
# Highest priority: Use the environment variable if it's set
|
200
|
+
env_redirect_uri = os.getenv("GOOGLE_OAUTH_REDIRECT_URI")
|
201
|
+
if env_redirect_uri:
|
202
|
+
logger.info(f"Using redirect URI from GOOGLE_OAUTH_REDIRECT_URI: {env_redirect_uri}")
|
203
|
+
return env_redirect_uri
|
204
|
+
|
205
|
+
# Fallback to constructing the URI based on server settings
|
206
|
+
constructed_uri = f"{base_uri}:{port}/oauth2callback"
|
207
|
+
logger.info(f"Constructed redirect URI: {constructed_uri}")
|
208
|
+
return constructed_uri
|
195
209
|
|
196
210
|
def ensure_oauth_callback_available(transport_mode: str = "stdio", port: int = 8000, base_uri: str = "http://localhost") -> bool:
|
197
211
|
"""
|
@@ -82,7 +82,7 @@ def set_transport_mode(mode: str):
|
|
82
82
|
|
83
83
|
def get_oauth_redirect_uri_for_current_mode() -> str:
|
84
84
|
"""Get OAuth redirect URI based on current transport mode."""
|
85
|
-
return get_oauth_redirect_uri(
|
85
|
+
return get_oauth_redirect_uri(WORKSPACE_MCP_PORT, WORKSPACE_MCP_BASE_URI)
|
86
86
|
|
87
87
|
# Health check endpoint
|
88
88
|
@server.custom_route("/health", methods=["GET"])
|