Generated by /repo-architecture skill v2.0.0

GWS MCP Architecture

MCP server providing 124 tools across 12 Google Workspace services. A single Docker deployment serves 5 authenticated Gmail accounts via FastMCP over Streamable HTTP transport. An nginx auth portal handles OAuth flows and provides a management UI. All traffic is routed through Traefik with dual-domain access (LAN .home and public .sanchezfamily.ca).

Upstream project: Fork of taylorwilsdon/google_workspace_mcp (workspace-mcp v1.9.0, MIT license). Customized with multi-account support, Docker deployment, nginx auth portal, and CLI wrapper (gw).
MCP Tools
124
Google Services
12
Authenticated Accounts
5
Containers
2
Transport
Streamable HTTP
Runtime
Python 3.11 + FastMCP

2. Runtime Architecture

Diagram A: Runtime Request Flow

HTTPS HTTPS supergateway HTTP :80 proxy :8000 REST API OAuth2 read/write Claude Code MCP Client Primary consumer Auth Portal Browser OAuth setup UI Other Agents Gemini / Codex / Qwen via supergateway bridge Traefik Reverse proxy / TLS :443 / :80 gws-portal nginx:alpine Auth UI + reverse proxy gws-mcp Python 3.11 / FastMCP / FastAPI 124 tools, 12 services, :8000 gws_creds Docker volume OAuth tokens (5 accounts) Google Workspace APIs Gmail, Drive, Calendar, Docs, ... 12 service APIs Google OAuth 2.0 accounts.google.com Token refresh + auth Legend Primary path Direct call Async / storage

Request Flow

  1. MCP client (Claude Code, Gemini, etc.) sends a tool invocation via POST /mcp over Streamable HTTP.
  2. Traefik terminates TLS (Let's Encrypt for .sanchezfamily.ca, local CA for .home) and forwards to gws-portal on port 80.
  3. gws-portal (nginx) proxies /mcp, /health, and /oauth2callback to the gws-mcp container on port 8000. Static auth portal UI is served directly.
  4. gws-mcp (FastMCP + FastAPI) resolves the target Google account from tool parameters, loads OAuth credentials from the gws_creds Docker volume, and calls the appropriate Google Workspace API.
  5. Google API responses are marshalled back through the MCP protocol to the calling agent.

Component Classification

ComponentClassificationRole
gws-mcpPrimaryFastMCP server, 124 tools across 12 Google services
gws-portalSecondarynginx reverse proxy + OAuth auth portal UI
gws_credsSecondaryDocker volume storing per-account OAuth token JSON files
TraefikAuxiliaryTLS termination, dual-domain routing (shared infra)
Google Workspace APIsExternalGmail, Drive, Calendar, Docs, Sheets, Tasks, Contacts, Forms, Slides, Chat, Search, Apps Script
Google OAuth 2.0ExternalToken exchange, refresh, consent flow

4. Storage Model

GWS MCP has no database. State is limited to OAuth credential files stored in a named Docker volume.

StoreTypeMountContents
gws_credsDocker volume/app/store_creds/Per-account OAuth token JSON files ({email}.json)

Authenticated Accounts

EmailRole
[email protected]Primary
[email protected]Personal
[email protected]Developer
[email protected]Legal
[email protected]Empiric
Warning: Running docker compose down -v deletes the credentials volume. All 5 accounts would need re-authentication via the portal. Use docker compose down (without -v) to preserve credentials.

5. Public Interfaces (MCP Tools)

HTTP Endpoints

MethodPathDescription
POST/mcpMCP Streamable HTTP endpoint (tool invocation)
GET/healthServer health + list of authenticated accounts
GET/oauth2callbackOAuth redirect handler
GET/Auth portal UI (glassmorphism setup page)

MCP Client Configuration

// Claude Code
{
  "gws-mcp": {
    "type": "sse",
    "url": "http://gws-mcp.home/mcp"
  }
}

// Other agents (Gemini, Codex, Qwen) via supergateway
{
  "command": "npx",
  "args": ["supergateway", "--streamableHttp", "http://gws-mcp.home/mcp"]
}

Gmail (15 tools)

ToolDescription
search_gmail_messagesSearch emails with Gmail query syntax
get_gmail_message_contentRead full email content by ID
get_gmail_messages_content_batchBatch read multiple emails
get_gmail_attachment_contentDownload email attachment
send_gmail_messageSend email
draft_gmail_messageCreate email draft
get_gmail_thread_contentRead full email thread
get_gmail_threads_content_batchBatch read threads
list_gmail_labelsList all labels
manage_gmail_labelCreate, update, or delete labels
list_gmail_filtersList email filters
create_gmail_filterCreate email filter
delete_gmail_filterDelete email filter
modify_gmail_message_labelsAdd/remove labels on a message
batch_modify_gmail_message_labelsBulk label modification

Google Drive (16 tools)

ToolDescription
search_drive_filesSearch files by name or content
get_drive_file_contentRead file content
get_drive_file_download_urlGet download URL
list_drive_itemsList folder contents
create_drive_fileCreate new file
import_to_google_docImport file as Google Doc
get_drive_file_permissionsList file permissions
check_drive_file_public_accessCheck public sharing status
update_drive_fileUpdate file content/metadata
get_drive_shareable_linkGenerate sharing link
share_drive_fileShare with users/groups
batch_share_drive_fileBatch share with multiple recipients
update_drive_permissionModify sharing permissions
remove_drive_permissionRemove sharing access
copy_drive_fileCopy file
transfer_drive_ownershipTransfer file ownership

Google Calendar (6 tools)

ToolDescription
list_calendarsList all calendars
get_eventsQuery calendar events
create_eventCreate calendar event
modify_eventUpdate event details
delete_eventDelete calendar event
query_freebusyCheck availability

Google Docs (15 tools)

ToolDescription
search_docsSearch documents
get_doc_contentRead document content
list_docs_in_folderList docs in Drive folder
create_docCreate new document
modify_doc_textEdit document text
find_and_replace_docFind and replace in document
insert_doc_elementsInsert content elements
insert_doc_imageInsert image into document
update_doc_headers_footersModify headers/footers
batch_update_docBatch document updates
inspect_doc_structureInspect document structure
create_table_with_dataInsert table with data
debug_table_structureDebug table structure
export_doc_to_pdfExport document as PDF
update_paragraph_styleUpdate paragraph styling

Google Sheets (10 tools)

ToolDescription
list_spreadsheetsList spreadsheets
get_spreadsheet_infoGet spreadsheet metadata
read_sheet_valuesRead cell values
modify_sheet_valuesWrite cell values
format_sheet_rangeFormat cell range
add_conditional_formattingAdd conditional format rules
update_conditional_formattingUpdate format rules
delete_conditional_formattingDelete format rules
create_spreadsheetCreate new spreadsheet
create_sheetAdd sheet tab

Google Tasks (12 tools)

ToolDescription
list_task_listsList task lists
get_task_listGet task list details
create_task_listCreate task list
update_task_listUpdate task list
delete_task_listDelete task list
list_tasksList tasks in a list
get_taskGet task details
create_taskCreate task
update_taskUpdate task
delete_taskDelete task
move_taskReorder task
clear_completed_tasksClear completed tasks

Google Contacts (15 tools)

ToolDescription
list_contactsList contacts
get_contactGet contact details
search_contactsSearch contacts
create_contactCreate contact
update_contactUpdate contact
delete_contactDelete contact
list_contact_groupsList contact groups
get_contact_groupGet group details
batch_create_contactsBatch create contacts
batch_update_contactsBatch update contacts
batch_delete_contactsBatch delete contacts
create_contact_groupCreate contact group
update_contact_groupUpdate contact group
delete_contact_groupDelete contact group
modify_contact_group_membersAdd/remove group members

Google Forms (6 tools)

ToolDescription
create_formCreate form
get_formGet form details
set_publish_settingsConfigure form publish settings
get_form_responseGet individual response
list_form_responsesList all form responses
batch_update_formBatch update form structure

Google Slides (5 tools)

ToolDescription
create_presentationCreate presentation
get_presentationGet presentation content
batch_update_presentationBatch update slides
get_pageGet slide page details
get_page_thumbnailGet slide thumbnail

Google Chat (4 tools)

ToolDescription
list_spacesList chat spaces
get_messagesGet messages in a space
send_messageSend chat message
search_messagesSearch chat messages

Google Apps Script (17 tools)

ToolDescription
list_script_projectsList script projects
get_script_projectGet project metadata
get_script_contentRead script source code
create_script_projectCreate new script project
update_script_contentUpdate script source
run_script_functionExecute a script function
create_deploymentDeploy script
list_deploymentsList deployments
update_deploymentUpdate deployment
delete_deploymentDelete deployment
list_script_processesList running processes
delete_script_projectDelete script project
list_versionsList script versions
create_versionCreate script version
get_versionGet version details
get_script_metricsGet execution metrics
generate_trigger_codeGenerate trigger boilerplate

Google Custom Search (3 tools)

ToolDescription
search_customCustom search engine query
get_search_engine_infoGet search engine config
search_custom_siterestrictSite-restricted search

6. Repository Structure

_gws-mcp/
  docker-compose.yml          # 2 services: gws-mcp + gws-portal
  nginx.conf                  # Reverse proxy config
  README.md                   # Project documentation
  portal/
    index.html                # Glassmorphism OAuth setup UI
  src/
    main.py                   # Entrypoint (CLI + MCP server)
    fastmcp_server.py         # FastMCP Cloud entrypoint
    Dockerfile                # Python 3.11-slim + uv
    pyproject.toml             # workspace-mcp v1.9.0
    auth/
      google_auth.py          # Google OAuth implementation
      credential_store.py     # Per-account token storage
      oauth_config.py         # OAuth config loader
      scopes.py               # Google API scope management
      service_decorator.py    # Auth decorator for tools
      oauth_callback_server.py# Callback handler
      (+ 6 more auth modules)
    core/
      server.py               # FastMCP server setup
      tool_registry.py        # Tool registration + filtering
      tool_tier_loader.py     # Tool tier config (complete/basic)
      tool_tiers.yaml         # Tier definitions
      config.py               # App configuration
      utils.py                # Shared utilities
      (+ 5 more core modules)
    gmail/
      gmail_tools.py          # 15 tools
    gdrive/
      drive_tools.py          # 16 tools
      drive_helpers.py
    gcalendar/
      calendar_tools.py       # 6 tools
    gdocs/
      docs_tools.py           # 15 tools
      docs_helpers.py
      docs_structure.py
      docs_tables.py
      managers/               # Document managers
    gsheets/
      sheets_tools.py         # 10 tools
      sheets_helpers.py
    gtasks/
      tasks_tools.py          # 12 tools
    gcontacts/
      contacts_tools.py       # 15 tools
    gforms/
      forms_tools.py          # 6 tools
    gslides/
      slides_tools.py         # 5 tools
    gchat/
      chat_tools.py           # 4 tools
    gappsscript/
      apps_script_tools.py    # 17 tools
    gsearch/
      search_tools.py         # 3 tools
    tests/                    # pytest test suite
    deploy/                   # Deployment configs

7. Deployment

Container Architecture

ContainerImagePortRole
gws-mcpCustom (Python 3.11-slim + uv)8000 (internal)FastMCP server with 124 tools
gws-portalnginx:alpine80 (internal)Auth portal UI + reverse proxy to gws-mcp

Docker Network

Both containers run on hosting_web (external Docker bridge shared with Traefik and all hosting services).

Volumes

VolumeMountPurpose
gws_creds/app/store_creds:rwOAuth token storage (5 account JSON files)
./portal/usr/share/nginx/html:roAuth portal static files
./nginx.conf/etc/nginx/conf.d/default.conf:ronginx reverse proxy config

Traefik Routing

DomainTargetTLS
gws-mcp.sanchezfamily.cagws-portal :80Let's Encrypt (via Cloudflare DNS challenge)
gws-mcp.homegws-portal :80Local CA wildcard cert

Environment Variables

VariableDefaultDescription
GOOGLE_CLIENT_ID(from OAuth project)Google OAuth 2.0 client ID
GOOGLE_CLIENT_SECRET(from OAuth project)Google OAuth 2.0 client secret
GOOGLE_OAUTH_REDIRECT_URIhttps://gws-mcp.sanchezfamily.ca/oauth2callbackOAuth callback URL
WORKSPACE_MCP_PORT8000MCP server bind port
WORKSPACE_MCP_HOST0.0.0.0MCP server bind address
WORKSPACE_MCP_CREDENTIALS_DIR/app/store_credsCredential storage directory
TOOL_TIERcompleteTool tier (complete or basic)
OAUTHLIB_INSECURE_TRANSPORT1Allow OAuth over HTTP (behind TLS proxy)

Secrets are stored in .env.production at the deploy directory. Google Cloud project ID: 718777906559.

Operations

# Deploy / update
cd /home/rod/_rod/_gws-mcp
docker compose up -d

# Rebuild after code changes
docker compose up -d --build

# View logs
docker compose logs -f gws-mcp
docker compose logs -f gws-portal

# Health check
curl -sk https://gws-mcp.home/health

# Stop (preserves credentials)
docker compose down

Healthcheck

The gws-mcp container has a built-in Docker healthcheck that polls http://localhost:8000/health every 30 seconds (10s timeout, 30s start period, 3 retries). Monitored by Portainer.

8. Dependencies

Python Dependencies

PackageVersionPurpose
fastmcp>=2.14.4MCP server framework (Streamable HTTP transport)
fastapi>=0.115.12HTTP API framework (health, OAuth callback)
google-api-python-client>=2.168.0Google Workspace API client
google-auth-oauthlib>=1.2.2Google OAuth 2.0 authentication
google-auth-httplib2>=0.2.0HTTP transport for Google Auth
httpx>=0.28.1Async HTTP client
pyjwt>=2.10.1JWT token handling
cryptography>=45.0.0Cryptographic operations for auth
python-dotenv>=1.1.0Environment variable loading
pyyaml>=6.0.2Tool tier config parsing
py-key-value-aio>=0.3.0Async key-value store

Infrastructure Dependencies

DependencyRoleRequired
Docker + Docker Compose v2Container runtimeYes
Traefik (shared)TLS termination, routingYes
Pi-hole DNS (shared).home domain resolutionFor LAN access
Cloudflare (shared)Public DNS + tunnelFor public access
Google Cloud ConsoleOAuth app credentialsYes
uvPython package manager (in container)Yes (build-time)

Upstream

Forked from taylorwilsdon/google_workspace_mcp (MIT license, v1.9.0). Author: Taylor Wilsdon. Customizations: multi-account support, Docker deployment with nginx portal, CLI wrapper, rod-server integration.

9. Constraints & Risks

ItemSeverityDescription
Google OAuth token expiry Medium Tokens auto-refresh, but a revoked token requires manual re-auth via the portal. No alerting for expired tokens.
Credential volume deletion High docker compose down -v destroys all 5 account credentials. No backup mechanism configured.
Google API quotas Medium Google Workspace APIs have per-user and per-project rate limits. No client-side rate limiting or retry backoff beyond what the Google client library provides.
OAuth app in "Testing" mode Low Google OAuth consent screen is in testing mode, which limits to explicitly listed test users. Production publishing requires Google review.
Single-point proxy Low nginx portal is the sole entry point. If it goes down, the MCP server is unreachable even though it may still be healthy.
OAUTHLIB_INSECURE_TRANSPORT=1 Low Required because Traefik terminates TLS and the container receives HTTP internally. Acceptable in this architecture but would be a concern if the container were directly exposed.