workspace-mcp 1.1.0__py3-none-any.whl → 1.1.2__py3-none-any.whl

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.
core/comments.py CHANGED
@@ -37,100 +37,94 @@ def create_comment_tools(app_name: str, file_id_param: str):
37
37
  reply_func_name = f"reply_to_{app_name}_comment"
38
38
  resolve_func_name = f"resolve_{app_name}_comment"
39
39
 
40
- # Create read comments function
40
+ # Create functions without decorators first, then apply decorators with proper names
41
41
  if file_id_param == "document_id":
42
- @server.tool()
43
42
  @require_google_service("drive", "drive_read")
44
43
  @handle_http_errors(read_func_name)
45
44
  async def read_comments(service, user_google_email: str, document_id: str) -> str:
46
- """Read all comments from a Google Slide, Sheet or Doc."""
45
+ """Read all comments from a Google Document."""
47
46
  return await _read_comments_impl(service, app_name, document_id)
48
47
 
49
- @server.tool()
50
48
  @require_google_service("drive", "drive_file")
51
49
  @handle_http_errors(create_func_name)
52
50
  async def create_comment(service, user_google_email: str, document_id: str, comment_content: str) -> str:
53
- """Create a new comment on a Google Slide, Sheet or Doc."""
51
+ """Create a new comment on a Google Document."""
54
52
  return await _create_comment_impl(service, app_name, document_id, comment_content)
55
53
 
56
- @server.tool()
57
54
  @require_google_service("drive", "drive_file")
58
55
  @handle_http_errors(reply_func_name)
59
56
  async def reply_to_comment(service, user_google_email: str, document_id: str, comment_id: str, reply_content: str) -> str:
60
57
  """Reply to a specific comment in a Google Document."""
61
58
  return await _reply_to_comment_impl(service, app_name, document_id, comment_id, reply_content)
62
59
 
63
- @server.tool()
64
60
  @require_google_service("drive", "drive_file")
65
61
  @handle_http_errors(resolve_func_name)
66
62
  async def resolve_comment(service, user_google_email: str, document_id: str, comment_id: str) -> str:
67
- """Resolve a comment in a Google Slide, Sheet or Doc."""
63
+ """Resolve a comment in a Google Document."""
68
64
  return await _resolve_comment_impl(service, app_name, document_id, comment_id)
69
65
 
70
66
  elif file_id_param == "spreadsheet_id":
71
- @server.tool()
72
67
  @require_google_service("drive", "drive_read")
73
68
  @handle_http_errors(read_func_name)
74
69
  async def read_comments(service, user_google_email: str, spreadsheet_id: str) -> str:
75
- """Read all comments from a Google Slide, Sheet or Doc."""
70
+ """Read all comments from a Google Spreadsheet."""
76
71
  return await _read_comments_impl(service, app_name, spreadsheet_id)
77
72
 
78
- @server.tool()
79
73
  @require_google_service("drive", "drive_file")
80
74
  @handle_http_errors(create_func_name)
81
75
  async def create_comment(service, user_google_email: str, spreadsheet_id: str, comment_content: str) -> str:
82
- """Create a new comment on a Google Slide, Sheet or Doc."""
76
+ """Create a new comment on a Google Spreadsheet."""
83
77
  return await _create_comment_impl(service, app_name, spreadsheet_id, comment_content)
84
78
 
85
- @server.tool()
86
79
  @require_google_service("drive", "drive_file")
87
80
  @handle_http_errors(reply_func_name)
88
81
  async def reply_to_comment(service, user_google_email: str, spreadsheet_id: str, comment_id: str, reply_content: str) -> str:
89
- """Reply to a specific comment in a Google Slide, Sheet or Doc."""
82
+ """Reply to a specific comment in a Google Spreadsheet."""
90
83
  return await _reply_to_comment_impl(service, app_name, spreadsheet_id, comment_id, reply_content)
91
84
 
92
- @server.tool()
93
85
  @require_google_service("drive", "drive_file")
94
86
  @handle_http_errors(resolve_func_name)
95
87
  async def resolve_comment(service, user_google_email: str, spreadsheet_id: str, comment_id: str) -> str:
96
- """Resolve a comment in a Google Slide, Sheet or Doc."""
88
+ """Resolve a comment in a Google Spreadsheet."""
97
89
  return await _resolve_comment_impl(service, app_name, spreadsheet_id, comment_id)
98
90
 
99
91
  elif file_id_param == "presentation_id":
100
- @server.tool()
101
92
  @require_google_service("drive", "drive_read")
102
93
  @handle_http_errors(read_func_name)
103
94
  async def read_comments(service, user_google_email: str, presentation_id: str) -> str:
104
- """Read all comments from a Google Slide, Sheet or Doc."""
95
+ """Read all comments from a Google Presentation."""
105
96
  return await _read_comments_impl(service, app_name, presentation_id)
106
97
 
107
- @server.tool()
108
98
  @require_google_service("drive", "drive_file")
109
99
  @handle_http_errors(create_func_name)
110
100
  async def create_comment(service, user_google_email: str, presentation_id: str, comment_content: str) -> str:
111
- """Create a new comment on a Google Slide, Sheet or Doc."""
101
+ """Create a new comment on a Google Presentation."""
112
102
  return await _create_comment_impl(service, app_name, presentation_id, comment_content)
113
103
 
114
- @server.tool()
115
104
  @require_google_service("drive", "drive_file")
116
105
  @handle_http_errors(reply_func_name)
117
106
  async def reply_to_comment(service, user_google_email: str, presentation_id: str, comment_id: str, reply_content: str) -> str:
118
- """Reply to a specific comment in a Google Slide, Sheet or Doc."""
107
+ """Reply to a specific comment in a Google Presentation."""
119
108
  return await _reply_to_comment_impl(service, app_name, presentation_id, comment_id, reply_content)
120
109
 
121
- @server.tool()
122
110
  @require_google_service("drive", "drive_file")
123
111
  @handle_http_errors(resolve_func_name)
124
112
  async def resolve_comment(service, user_google_email: str, presentation_id: str, comment_id: str) -> str:
125
- """Resolve a comment in a Google Slide, Sheet or Doc."""
113
+ """Resolve a comment in a Google Presentation."""
126
114
  return await _resolve_comment_impl(service, app_name, presentation_id, comment_id)
127
115
 
128
- # Set the proper function names for MCP registration
116
+ # Set the proper function names and register with server
129
117
  read_comments.__name__ = read_func_name
130
118
  create_comment.__name__ = create_func_name
131
119
  reply_to_comment.__name__ = reply_func_name
132
120
  resolve_comment.__name__ = resolve_func_name
133
121
 
122
+ # Register tools with the server using the proper names
123
+ server.tool()(read_comments)
124
+ server.tool()(create_comment)
125
+ server.tool()(reply_to_comment)
126
+ server.tool()(resolve_comment)
127
+
134
128
  return {
135
129
  'read_comments': read_comments,
136
130
  'create_comment': create_comment,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workspace-mcp
3
- Version: 1.1.0
3
+ Version: 1.1.2
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
@@ -79,7 +79,7 @@ Dynamic: license-file
79
79
  ### A quick plug for AI-Enhanced Docs
80
80
 
81
81
  > **This README was crafted with AI assistance, and here's why that matters**
82
- >
82
+ >
83
83
  > As a solo developer building open source tools that may only ever serve my own needs, 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.
84
84
  >
85
85
  > In this case, Sonnet 4 took a pass & a human (me) verified them 6/28/25.
@@ -217,34 +217,47 @@ docker run -p 8000:8000 -v $(pwd):/app workspace-mcp --transport streamable-http
217
217
  The server supports two transport modes:
218
218
 
219
219
  #### Stdio Mode (Default - Recommended for Claude Desktop)
220
- **Option 1: Auto-install (Recommended)**
220
+
221
+ **Easiest Setup (Recommended)**
221
222
  ```bash
222
223
  python install_claude.py
223
224
  ```
224
225
 
225
- **Option 2: Manual Configuration**
226
+ This script automatically:
227
+ - Prompts you for your Google OAuth credentials (Client ID and Secret)
228
+ - Creates the Claude Desktop config file in the correct location
229
+ - Sets up all necessary environment variables
230
+ - No manual file editing required!
231
+
232
+ After running the script, just restart Claude Desktop and you're ready to go.
233
+
234
+ **Manual Claude Configuration (Alternative)**
226
235
  1. Open Claude Desktop Settings → Developer → Edit Config
227
- 2. This creates/opens the config file at:
228
- - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
229
- - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
230
- 3. Add the server configuration:
236
+ 1. **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
237
+ 2. **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
238
+ 2. Add the server configuration:
239
+ ```json
240
+ {
241
+ "mcpServers": {
242
+ "google_workspace": {
243
+ "command": "uvx",
244
+ "args": ["workspace-mcp"],
245
+ "env": {
246
+ "GOOGLE_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
247
+ "GOOGLE_OAUTH_CLIENT_SECRET": "your-client-secret",
248
+ "OAUTHLIB_INSECURE_TRANSPORT": "1"
249
+ }
250
+ }
251
+ }
252
+ }
253
+ ```
231
254
 
232
- ```json
233
- {
234
- "mcpServers": {
235
- "google_workspace": {
236
- "command": "uvx",
237
- "args": ["workspace-mcp"],
238
- "env": {
239
- "GOOGLE_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
240
- "GOOGLE_OAUTH_CLIENT_SECRET": "your-client-secret"
241
- }
242
- }
243
- }
244
- }
245
- ```
255
+ **Get Google OAuth Credentials** (if you don't have them):
256
+ - Go to [Google Cloud Console](https://console.cloud.google.com/)
257
+ - Create a new project and enable APIs: Calendar, Drive, Gmail, Docs, Sheets, Slides, Forms, Chat
258
+ - Create OAuth 2.0 Client ID (Web application) with redirect URI: `http://localhost:8000/oauth2callback`
246
259
 
247
- **Alternative (Development Installation)**:
260
+ **Development Installation (For Contributors)**:
248
261
  ```json
249
262
  {
250
263
  "mcpServers": {
@@ -254,7 +267,8 @@ python install_claude.py
254
267
  "cwd": "/path/to/google_workspace_mcp",
255
268
  "env": {
256
269
  "GOOGLE_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
257
- "GOOGLE_OAUTH_CLIENT_SECRET": "your-client-secret"
270
+ "GOOGLE_OAUTH_CLIENT_SECRET": "your-client-secret",
271
+ "OAUTHLIB_INSECURE_TRANSPORT": "1"
258
272
  }
259
273
  }
260
274
  }
@@ -6,7 +6,7 @@ auth/oauth_responses.py,sha256=qbirSB4d7mBRKcJKqGLrJxRAPaLHqObf9t-VMAq6UKA,7020
6
6
  auth/scopes.py,sha256=kMRdFN0wLyipFkp7IitTHs-M6zhZD-oieVd7fylueBc,3320
7
7
  auth/service_decorator.py,sha256=h9bkG1O6U-p4_yT1KseBKJvueprKd4SVJe1Bj2VrdXA,15669
8
8
  core/__init__.py,sha256=AHVKdPl6v4lUFm2R-KuGuAgEmCyfxseMeLGtntMcqCs,43
9
- core/comments.py,sha256=n-S84v5N5x3LbL45vGUerERhNPYvuSlugpOboYtPGgw,11328
9
+ core/comments.py,sha256=vVfZYjH0kwqFyXcwvBx3m0Ko4WmfTJTkfD3dCQbucuc,11215
10
10
  core/context.py,sha256=zNgPXf9EO2EMs9sQkfKiywoy6sEOksVNgOrJMA_c30Y,768
11
11
  core/server.py,sha256=8A5_o6RCZ3hhsAiCszZhHiUJbVVrxJLspcvCiMmt27Q,9265
12
12
  core/utils.py,sha256=sUNPhM0xh3tqgyCZxTcoje37Et-pbNJTksybTatDyho,10127
@@ -26,9 +26,9 @@ gsheets/__init__.py,sha256=jFfhD52w_EOVw6N5guf_dIc9eP2khW_eS9UAPJg_K3k,446
26
26
  gsheets/sheets_tools.py,sha256=TVlJ-jcIvJ_sJt8xO4-sBWIshb8rabJhjTmZfzHIJsU,11898
27
27
  gslides/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  gslides/slides_tools.py,sha256=wil3XRyUMzUbpBUMqis0CW5eRuwOrP0Lp7-6WbF4QVU,10117
29
- workspace_mcp-1.1.0.dist-info/licenses/LICENSE,sha256=bB8L7rIyRy5o-WHxGgvRuY8hUTzNu4h3DTkvyV8XFJo,1070
30
- workspace_mcp-1.1.0.dist-info/METADATA,sha256=uyhkzbPiL3mgDBD2wK_CeEBVvkFaAY460yxf5wRtk-c,19406
31
- workspace_mcp-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- workspace_mcp-1.1.0.dist-info/entry_points.txt,sha256=kPiEfOTuf-ptDM0Rf2OlyrFudGW7hCZGg4MCn2Foxs4,44
33
- workspace_mcp-1.1.0.dist-info/top_level.txt,sha256=Y8mAkTitLNE2zZEJ-DbqR9R7Cs1V1MMf-UploVdOvlw,73
34
- workspace_mcp-1.1.0.dist-info/RECORD,,
29
+ workspace_mcp-1.1.2.dist-info/licenses/LICENSE,sha256=bB8L7rIyRy5o-WHxGgvRuY8hUTzNu4h3DTkvyV8XFJo,1070
30
+ workspace_mcp-1.1.2.dist-info/METADATA,sha256=n1KSe9UDDKpYJP_GnOe1rhVzHVF_2LdbUbPbN_9C9qM,20158
31
+ workspace_mcp-1.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
+ workspace_mcp-1.1.2.dist-info/entry_points.txt,sha256=kPiEfOTuf-ptDM0Rf2OlyrFudGW7hCZGg4MCn2Foxs4,44
33
+ workspace_mcp-1.1.2.dist-info/top_level.txt,sha256=Y8mAkTitLNE2zZEJ-DbqR9R7Cs1V1MMf-UploVdOvlw,73
34
+ workspace_mcp-1.1.2.dist-info/RECORD,,