Skip to content

Comprehensive, highly performant Google Workspace Streamable HTTP & SSE MCP Server with complete coverage for Calendar, Gmail, Docs, Sheets, Slides & Drive!

License

Notifications You must be signed in to change notification settings

taylorwilsdon/google_workspace_mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Google Workspace MCP Server

License: MIT Python 3.11+ UV

Connect MCP Clients, AI Assistants and more to Google Workspace services through the Model Context Protocol

See it in action:

google-calendar-mcp-demo.mov

πŸ“‘ Table of Contents


🌐 Overview

The Google Workspace MCP Server integrates Google Workspace services (Calendar, Drive, Gmail, and Docs) with AI assistants and other applications using the Model Context Protocol (MCP). This allows AI systems to access and interact with user data from Google Workspace applications securely and efficiently.


✨ Features

  • πŸ” OAuth 2.0 Authentication: Securely connects to Google APIs using user-authorized credentials with automatic token refresh and centralized authentication flow
  • πŸ“… Google Calendar Integration: Full calendar management - list calendars, fetch events, create/modify/delete events with support for all-day and timed events
  • πŸ“ Google Drive Integration: Search files, list folder contents, read file content, and create new files. Supports extraction and retrieval of .docx, .xlsx and other Microsoft Office formats natively!
  • πŸ“§ Gmail Integration: Complete email management - search messages, retrieve content, send emails, and create drafts with full support for all query syntax
  • πŸ“„ Google Docs Integration: Search for documents, read document content, list documents in folders, and create new documents right from your chat!
  • πŸ”„ Multiple Transport Options: Streamable HTTP + SSE fallback
  • πŸ”Œ mcpo Compatibility: Easily expose the server as an OpenAPI endpoint for integration with tools like Open WebUI
  • 🧩 Extensible Design: Simple structure for adding support for more Google Workspace APIs and tools
  • πŸ”„ Integrated OAuth Callback: Handles the OAuth redirect directly within the server on port 8000
  • ⚑ Thread-Safe Session Management: Robust session handling with thread-safe architecture for improved reliability

πŸš€ Quick Start

Prerequisites

  • Python 3.11+
  • uv package installer (or pip)
  • Google Cloud Project with OAuth 2.0 credentials enabled for required APIs (Calendar, Drive, Gmail, Docs)

Installation

Installing via Smithery

To install Google Workspace Integration Server for Claude Desktop automatically via Smithery:

npx -y @smithery/cli install @taylorwilsdon/google_workspace_mcp --client claude

Manual Installation

# Clone the repository (replace with your fork URL if different)
git clone https://github.com/taylorwilsdon/google_workspace_mcp.git
cd google_workspace_mcp

# Create a virtual environment and install dependencies
uv venv
source .venv/bin/activate  # On Windows use `.venv\Scripts\activate`
uv pip install -e .

Configuration

  1. Create OAuth 2.0 Credentials (Desktop application type) in the Google Cloud Console.
  2. Enable the Google Calendar API, Google Drive API, Gmail API, and Google Docs API for your project.
  3. Download the OAuth client credentials as client_secret.json and place it in the project's root directory.
  4. Add the following redirect URI to your OAuth client configuration in the Google Cloud Console. Note that http://localhost:8000 is the default base URI and port, which can be customized via environment variables (WORKSPACE_MCP_BASE_URI and WORKSPACE_MCP_PORT). If you change these, you must update the redirect URI in the Google Cloud Console accordingly.
    http://localhost:8000/oauth2callback
    
  5. ⚠️ Important: Ensure client_secret.json is added to your .gitignore file and never committed to version control.

Server Configuration

The server's base URL and port can be customized using environment variables:

  • WORKSPACE_MCP_BASE_URI: Sets the base URI for the server (default: http://localhost). This affects the server_url used for Gemini native function calling and the OAUTH_REDIRECT_URI.
  • WORKSPACE_MCP_PORT: Sets the port the server listens on (default: 8000). This affects the server_url, port, and OAUTH_REDIRECT_URI.

Example usage:

export WORKSPACE_MCP_BASE_URI="https://my-custom-domain.com"
export WORKSPACE_MCP_PORT="9000"
uv run main.py

Environment Setup

The server uses HTTP for localhost OAuth callbacks during development. Set this environment variable before running the server:

# Allow HTTP for localhost OAuth callbacks (development only!)
export OAUTHLIB_INSECURE_TRANSPORT=1

Without this, you might encounter an "OAuth 2 MUST utilize HTTPS" error during the authentication flow.

Start the Server

Choose one of the following methods to run the server:

HTTP Server Mode
python main.py
# or using uv
uv run main.py

Runs the server with an HTTP transport layer on port 8000.

Single-User Mode

Multi-user MCP is kind of a mess, so right now now everything runs best as 1:1 mapping between client snd server. That will change as soon as Claude can permform OAuth 2.1 flows, so this MCP was built eith a flag for simplified single-user environments. You can run the server in single-user mode, which bypasses session-to-OAuth mapping and uses any available credentials from the .credentials directory:

python main.py --single-user
# or using uv
uv run main.py --single-user

In single-user mode:

  • The server automatically finds and uses any valid credentials in the .credentials directory
  • No session mapping is required - the server uses the first valid credential file found
  • Useful for development, testing, or single-user deployments
  • Still requires initial OAuth authentication to create credential files

This mode is particularly helpful when you don't need multi-user session management and want simplified credential handling.

Using Docker

You can build and run the server using the provided Dockerfile.

# Build the Docker image
docker build -t google-workspace-mcp .

# Run the Docker container
# The -p flag maps the container port 8000 to the host port 8000
# The -v flag mounts the current directory to /app inside the container
# This is useful for development to pick up code changes without rebuilding
docker run -p 8000:8000 -v $(pwd):/app google-workspace-mcp

The smithery.yaml file is configured to start the server correctly within the Docker container.

Important Ports

The default ports are 8000, but can be changed via the WORKSPACE_MCP_PORT environment variable.

Service Default Port Description
OAuth Callback 8000 Handled internally by the server via the /oauth2callback route
HTTP Mode Server 8000 Default when using HTTP transport

Connecting to the Server

The server supports multiple connection methods:

Claude Desktop:

Can run anywhere and be used via mcp-remote or invoked locally with uv run main.py and using mcp-remote with localhost. Claude Desktop lacks native support for streamable HTTP or SSE.

config.json:

{
  "mcpServers": {
    "Google workspace": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8000/mcp”
      ]
    }
  }
}
Using mcpo (Recommended for OpenAPI Spec Access) With config.json (for multi-mcp mcpo usage):
  1. Install mcpo: uv pip install mcpo or pip install mcpo
  2. Create a config.json (see Integration with Open WebUI)
  3. Run mcpo pointing to your config: uvx mcpo --config config.json --port 8001
  4. The MCP server API will be available at: http://localhost:8001/google_workspace (or the name defined in config.json)
  5. OpenAPI documentation (Swagger UI) available at: http://localhost:8001/google_workspace/docs

With startup command (for single-mcp mcpo usage):

  1. Install mcpo: uv pip install mcpo or pip install mcpo
  2. Start with uvx mcpo --port 8001 --api-key "top-secret" --server-type "streamablehttp" -- http://localhost:8000/mcp
  3. The MCP server API will be available at: http://localhost:8001/openapi.json (or the name defined in config.json)
  4. OpenAPI documentation (Swagger UI) available at: http://localhost:8001/docs
HTTP Mode
  1. Start the server in HTTP mode (see Start the Server)
  2. Send MCP JSON requests directly to http://localhost:8000
  3. Useful for testing with tools like curl or custom HTTP clients
  4. Can be used to serve Claude Desktop & other MCP clients yet to integrate the new Streamable HTTP transport via mcp-remote:
  5. You can also serve in SSE fallback mode if preferred.

Integration with Open WebUI

To use this server as a tool provider within Open WebUI:

  1. Create mcpo Configuration: Create a file named config.json with the following structure to have mcpo make the streamable HTTP endpoint available as an OpenAPI spec tool.

      {
       "mcpServers": {
           "google_workspace": {
               "type": "streamablehttp",
               "url": "http://localhost:8000/mcp"
           }
       }
    }
  2. Start the mcpo Server:

    mcpo --port 8001 --config config.json --api-key "your-optional-secret-key"

    This command starts the mcpo proxy, serving your active (assuming port 8000) Google Workspace MCP on port 8001.

  3. Configure Open WebUI:

    • Navigate to your Open WebUI settings
    • Go to "Connections" -> "Tools"
    • Click "Add Tool"
    • Enter the Server URL: http://localhost:8001/google_workspace (matching the mcpo base URL and server name from config.json)
    • If you used an --api-key with mcpo, enter it as the API Key
    • Save the configuration
    • The Google Workspace tools should now be available when interacting with models in Open WebUI

First-time Authentication

When a tool requiring Google API access is called:

  • If user_google_email is provided to the tool and credentials are missing/invalid: The server automatically initiates the OAuth 2.0 flow. An authorization URL will be returned in the MCP response (or printed to the console).
  • If user_google_email is NOT provided and credentials are missing/invalid: The tool will return an error message guiding the LLM to use the centralized start_google_auth tool. The LLM should then call start_google_auth with the user's email and the appropriate service_name (e.g., "Google Calendar", "Google Docs", "Gmail", "Google Drive"). This will also return an authorization URL.

Steps for the User (once an authorization URL is obtained):

  1. Open the provided authorization URL in a web browser.
  2. Log in to the Google account and grant the requested permissions for the specified service.
  3. After authorization, Google will redirect the browser to http://localhost:8000/oauth2callback (or your configured redirect URI).
  4. The MCP server handles this callback, exchanges the authorization code for tokens, and securely stores the credentials.
  5. The LLM can then retry the original request. Subsequent calls for the same user and service should work without re-authentication until the refresh token expires or is revoked.

🧰 Available Tools

Note: The first use of any tool for a specific Google service may trigger the OAuth authentication flow if valid credentials are not already stored and user_google_email is provided to the tool. If authentication is required and user_google_email is not provided to the tool, the LLM should use the centralized start_google_auth tool (defined in core/server.py) with the user's email and the appropriate service_name.

πŸ“… Google Calendar

Source: gcalendar/calendar_tools.py

Tool Description Parameters
start_google_auth (Centralized in core/server.py) Initiates the OAuth 2.0 authentication flow for a specific Google account and service. Use this when no valid credentials are available or if a tool fails due to missing authentication and an email was not provided to it. β€’ user_google_email (required): The user's Google email address
β€’ service_name (required): The Google service name (e.g., "Google Calendar", "Google Docs", "Gmail", "Google Drive")
list_calendars Lists all calendars accessible to the authenticated user. β€’ user_google_email (optional): Used if session is not authenticated
β€’ mcp_session_id (injected automatically)
get_events Retrieves upcoming events from a specified calendar within a time range. β€’ calendar_id (optional): Calendar ID (default: primary)
β€’ time_min (optional): Start time (RFC3339 or YYYY-MM-DD)
β€’ time_max (optional): End time (RFC3339 or YYYY-MM-DD)
β€’ max_results (optional): Max number of events (default: 25)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)
create_event Creates a new calendar event. Supports all-day and timed events. β€’ summary (required): Event title
β€’ start_time (required): Start time (RFC3339 or YYYY-MM-DD)
β€’ end_time (required): End time (RFC3339 or YYYY-MM-DD)
β€’ calendar_id (optional): Calendar ID (default: primary)
β€’ description, location, attendees, timezone (optional)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)
modify_event Updates an existing event by ID. Only provided fields will be modified. β€’ event_id (required): ID of the event to modify
β€’ calendar_id (optional): Calendar ID (default: primary)
β€’ summary, start_time, end_time, description, location, attendees, timezone (optional)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)
delete_event Deletes an event by ID. β€’ event_id (required): ID of the event to delete
β€’ calendar_id (optional): Calendar ID (default: primary)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)

ℹ️ All Calendar tools support authentication via the current MCP session (mcp_session_id) or fallback to user_google_email. If neither is available and authentication is required, the tool will return an error prompting the LLM to use the centralized start_google_auth tool with the user's email and service_name="Google Calendar".

πŸ•’ Date/Time Parameters: Tools accept both full RFC3339 timestamps (e.g., 2024-05-12T10:00:00Z) and simple dates (e.g., 2024-05-12). The server automatically formats them as needed.

πŸ“ Google Drive

Source: gdrive/drive_tools.py

Tool Description Parameters
search_drive_files Searches for files and folders across the user's Drive β€’ query (required): Search query string (e.g., name contains 'report')
β€’ max_results (optional): Maximum number of files to return
get_drive_file_content Retrieves the content of a specific file β€’ file_id (required): The ID of the file
β€’ mime_type (optional): Specify the desired export format
list_drive_items Lists files and folders within a specific folder or the root β€’ folder_id (optional): The ID of the folder to list (defaults to root)
β€’ max_results (optional): Maximum number of items to return
create_drive_file Creates a new file in Google Drive β€’ name (required): The desired name for the new file
β€’ content (required): The text content to write into the file
β€’ folder_id (optional): The ID of the parent folder
β€’ mime_type (optional): The MIME type of the file (defaults to text/plain)

Query Syntax: For Google Drive search queries, see Drive Search Query Syntax

πŸ“§ Gmail

Source: gmail/gmail_tools.py

Tool Description Parameters
search_gmail_messages Search email messages using standard Gmail search operators (from, subject, etc). β€’ query (required): Search string (e.g., "from:foo subject:bar is:unread")
β€’ user_google_email (optional)
β€’ page_size (optional, default: 10)
β€’ mcp_session_id (injected automatically)
get_gmail_message_content Get subject, sender, and plain text body of an email by message ID. β€’ message_id (required)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)
send_gmail_message Send a plain text email using the user's Gmail account. β€’ to (required): Recipient email address
β€’ subject (required)
β€’ body (required)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)
draft_gmail_message Create a draft email in the user's Gmail account. β€’ subject (required): Email subject
β€’ body (required): Email body (plain text)
β€’ to (optional): Recipient email address
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)

Query Syntax: For Gmail search queries, see Gmail Search Query Syntax

πŸ“ Google Docs

Source: gdocs/docs_tools.py

Tool Description Parameters
search_docs Search for Google Docs by name (using Drive API). β€’ query (required): Text to search for in Doc names
β€’ user_google_email (optional)
β€’ page_size (optional, default: 10)
β€’ mcp_session_id (injected automatically)
get_doc_content Retrieve the plain text content of a Google Doc by its document ID. β€’ document_id (required)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)
list_docs_in_folder List all Google Docs inside a given Drive folder (by folder ID, default = root). β€’ folder_id (optional, default: 'root')
β€’ user_google_email (optional)
β€’ page_size (optional, default: 100)
β€’ mcp_session_id (injected automatically)
create_doc Create a new Google Doc, optionally with initial content. β€’ title (required): Name for the doc
β€’ content (optional, default: empty)
β€’ user_google_email (optional)
β€’ mcp_session_id (injected automatically)

πŸ› οΈ Development

Project Structure

google_workspace_mcp/
β”œβ”€β”€ .venv/             # Virtual environment (created by uv)
β”œβ”€β”€ auth/              # OAuth handling logic (google_auth.py, oauth_manager.py)
β”œβ”€β”€ core/              # Core MCP server logic (server.py)
β”œβ”€β”€ gcalendar/         # Google Calendar tools (calendar_tools.py)
β”œβ”€β”€ gdocs/             # Google Docs tools (docs_tools.py)
β”œβ”€β”€ gdrive/            # Google Drive tools (drive_tools.py)
β”œβ”€β”€ gmail/             # Gmail tools (gmail_tools.py)
β”œβ”€β”€ .gitignore         # Git ignore file
β”œβ”€β”€ client_secret.json # Google OAuth Credentials (DO NOT COMMIT)
β”œβ”€β”€ config.json        # Example mcpo configuration
β”œβ”€β”€ main.py            # Main server entry point (imports tools)
β”œβ”€β”€ mcp_server_debug.log # Log file for debugging
β”œβ”€β”€ pyproject.toml     # Project metadata and dependencies (for uv/pip)
β”œβ”€β”€ README.md          # This file
β”œβ”€β”€ uv.lock            # uv lock file

Port Handling for OAuth

The server cleverly handles the OAuth 2.0 redirect URI (/oauth2callback) without needing a separate web server framework:

  • It utilizes the built-in HTTP server capabilities of the underlying MCP library when run in HTTP mode or via mcpo
  • A custom MCP route is registered specifically for /oauth2callback on port 8000
  • When Google redirects the user back after authorization, the MCP server intercepts the request on this route
  • The auth module extracts the authorization code and completes the token exchange
  • This requires OAUTHLIB_INSECURE_TRANSPORT=1 to be set when running locally, as the callback uses http://localhost

Debugging

Log File

Check mcp_server_debug.log for detailed logs, including authentication steps and API calls. Enable debug logging if needed.

OAuth Issues
  • Verify client_secret.json is correct and present
  • Ensure the correct redirect URI (http://localhost:8000/oauth2callback) is configured in Google Cloud Console
  • Confirm the necessary APIs (Calendar, Drive, Gmail) are enabled in your Google Cloud project
  • Check that OAUTHLIB_INSECURE_TRANSPORT=1 is set in the environment where the server process runs
  • Look for specific error messages during the browser-based OAuth flow
Tool Errors

Check the server logs for tracebacks or error messages returned from the Google APIs.

Adding New Tools

  1. Choose or create the appropriate module (e.g., gdocs/gdocs_tools.py)
  2. Import necessary libraries (Google API client library, etc.)
  3. Define an async function for your tool logic. Use type hints for parameters
  4. Decorate the function with @server.tool("your_tool_name")
  5. Inside the function, get authenticated credentials:
from auth.google_auth import get_credentials, CONFIG_CLIENT_SECRETS_PATH
# ...
credentials = await asyncio.to_thread(
    get_credentials,
    user_google_email=your_user_email_variable, # Optional, can be None if session_id is primary
    required_scopes=YOUR_SPECIFIC_SCOPES_LIST,  # e.g., [CALENDAR_READONLY_SCOPE]
    client_secrets_path=CONFIG_CLIENT_SECRETS_PATH,
    session_id=your_mcp_session_id_variable    # Usually injected via Header
)
if not credentials or not credentials.valid:
    # Handle missing/invalid credentials, possibly by calling start_auth_flow
    # from auth.google_auth (which is what service-specific start_auth tools do)
    pass
  1. Build the Google API service client: service = build('drive', 'v3', credentials=credentials)
  2. Implement the logic to call the Google API
  3. Handle potential errors gracefully
  4. Return the results as a JSON-serializable dictionary or list
  5. Import the tool function in main.py so it gets registered with the server
  6. Define necessary service-specific scope constants in your tool's module
  7. Update pyproject.toml if new dependencies are required

Scope Management: The global SCOPES list in config/google_config.py is used for the initial OAuth consent screen. Individual tools should request the minimal required_scopes they need when calling get_credentials.


πŸ”’ Security Notes

  • client_secret.json: This file contains sensitive credentials. NEVER commit it to version control. Ensure it's listed in your .gitignore file. Store it securely.

  • User Tokens: Authenticated user credentials (refresh tokens) are stored locally in files like credentials-<user_id_hash>.json. Protect these files as they grant access to the user's Google account data. Ensure they are also in .gitignore.

  • OAuth Callback Security: The use of http://localhost for the OAuth callback is standard for installed applications during development but requires OAUTHLIB_INSECURE_TRANSPORT=1. For production deployments outside of localhost, you MUST use HTTPS for the callback URI and configure it accordingly in Google Cloud Console.

  • mcpo Security: If using mcpo to expose the server over the network, consider:

    • Using the --api-key option for basic authentication
    • Running mcpo behind a reverse proxy (like Nginx or Caddy) to handle HTTPS termination, proper logging, and more robust authentication
    • Binding mcpo only to trusted network interfaces if exposing it beyond localhost
  • Scope Management: The server requests specific OAuth scopes (permissions) for Calendar, Drive, and Gmail. Users grant access based on these scopes during the initial authentication. Do not request broader scopes than necessary for the implemented tools.


Screenshots:

image image

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Comprehensive, highly performant Google Workspace Streamable HTTP & SSE MCP Server with complete coverage for Calendar, Gmail, Docs, Sheets, Slides & Drive!

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 6