bn-google-workspace-mcp-server
v0.0.5
Published
Stateless MCP Server for Google Workspace APIs
Maintainers
Readme
Google Workspace MCP Server
A comprehensive Model Context Protocol (MCP) server for Google Workspace services including Gmail, Drive, Calendar, Docs, Sheets, Slides, Contacts, and YouTube with OAuth2 authentication.
Features
- Gmail Operations: List labels, search messages, send emails, get message content
- Google Drive: File management, content access, and file creation
- Google Calendar: Event management and calendar operations
- Google Docs: Document creation and content access
- Google Sheets: Spreadsheet operations, data reading and creation
- Google Slides: Presentation management and creation
- Google Contacts: Contact CRUD via People API (list, search, create, update, delete)
- YouTube: Video search, ratings, playlists, subscriptions, and comments via YouTube Data API v3
- OAuth2 Authentication: Secure access via Google Access Tokens
- Stateless Architecture: Each request is independent with Bearer token authentication
- TypeScript Implementation: Built with TypeScript for type safety and maintainability
Quick Start
Installation
# Install dependencies
pnpm install
# Build the TypeScript project
pnpm run build
# Start the server
pnpm start
# Or run in development mode with auto-reload
pnpm run dev
# Run with debug logging enabled
pnpm run dev:debugDocker
# Build the Docker image
docker build -t google-workspace-mcp .
# Run the container
docker run -p 30000:30000 google-workspace-mcpThe server provides these endpoints:
POST /mcp- Main MCP endpoint for tool executionGET /health- Health check endpoint
Authentication
All requests require a Google Access Token via Authorization header:
Authorization: Bearer ya29.your-google-access-tokenSet up Google OAuth2 and obtain access tokens with appropriate scopes.
Tools
The server provides 39 tools across 8 Google services. Each tool requires Authorization: Bearer <token> header.
Gmail Tools (4)
1. gmail_list_labels
List all Gmail labels.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "gmail_list_labels",
"arguments": {}
}
}'2. gmail_search_messages
Search Gmail messages using Gmail search operators.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "2",
"method": "tools/call",
"params": {
"name": "gmail_search_messages",
"arguments": {
"query": "is:unread from:[email protected]",
"maxResults": 20
}
}
}'3. gmail_get_message_content
Get detailed information about a specific Gmail message.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "3",
"method": "tools/call",
"params": {
"name": "gmail_get_message_content",
"arguments": {
"messageId": "1234567890abcdef"
}
}
}'4. gmail_send_message
Send a Gmail message.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "4",
"method": "tools/call",
"params": {
"name": "gmail_send_message",
"arguments": {
"to": "[email protected]",
"subject": "Hello from Google Workspace MCP",
"body": "This email was sent via the MCP server!"
}
}
}'Google Drive Tools (3)
5. drive_list_files
List and search Google Drive files using Drive Query Language.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "5",
"method": "tools/call",
"params": {
"name": "drive_list_files",
"arguments": {
"query": "project",
"maxResults": 15
}
}
}'6. drive_get_file_content
Get Google Drive file content.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "6",
"method": "tools/call",
"params": {
"name": "drive_get_file_content",
"arguments": {
"fileId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
}
}
}'7. drive_create_file
Create a Google Drive file.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "7",
"method": "tools/call",
"params": {
"name": "drive_create_file",
"arguments": {
"name": "my-document.txt",
"content": "Hello, this is my new document content!",
"parentFolderId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
}
}
}'Google Calendar Tools (3)
8. calendar_list_events
List upcoming Google Calendar events.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "8",
"method": "tools/call",
"params": {
"name": "calendar_list_events",
"arguments": {
"maxResults": 25
}
}
}'9. calendar_list_calendars
List all Google Calendars.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "9",
"method": "tools/call",
"params": {
"name": "calendar_list_calendars",
"arguments": {}
}
}'10. calendar_create_event
Create a Google Calendar event.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "10",
"method": "tools/call",
"params": {
"name": "calendar_create_event",
"arguments": {
"summary": "Team Meeting",
"startTime": "2024-01-15T10:00:00-08:00",
"endTime": "2024-01-15T11:00:00-08:00"
}
}
}'Google Docs Tools (2)
11. docs_get_document
Get Google Docs document content.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "11",
"method": "tools/call",
"params": {
"name": "docs_get_document",
"arguments": {
"documentId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
}
}
}'12. docs_create_document
Create a Google Docs document.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "12",
"method": "tools/call",
"params": {
"name": "docs_create_document",
"arguments": {
"title": "My New Document",
"content": "This is the initial content of my document."
}
}
}'Google Sheets Tools (3)
13. sheets_get_spreadsheet
Get Google Sheets spreadsheet metadata.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "13",
"method": "tools/call",
"params": {
"name": "sheets_get_spreadsheet",
"arguments": {
"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
}
}
}'14. sheets_read_values
Read values from Google Sheets.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "14",
"method": "tools/call",
"params": {
"name": "sheets_read_values",
"arguments": {
"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
"range": "A1:D10"
}
}
}'15. sheets_create_spreadsheet
Create a Google Sheets spreadsheet.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "15",
"method": "tools/call",
"params": {
"name": "sheets_create_spreadsheet",
"arguments": {
"title": "My New Spreadsheet"
}
}
}'Google Slides Tools (2)
16. slides_get_presentation
Get Google Slides presentation.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "16",
"method": "tools/call",
"params": {
"name": "slides_get_presentation",
"arguments": {
"presentationId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
}
}
}'17. slides_create_presentation
Create a Google Slides presentation.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "17",
"method": "tools/call",
"params": {
"name": "slides_create_presentation",
"arguments": {
"title": "My New Presentation"
}
}
}'Google Contacts Tools (6)
18. contacts_list_contacts
List all contacts with pagination and sorting.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "29",
"method": "tools/call",
"params": {
"name": "contacts_list_contacts",
"arguments": {
"pageSize": 50
}
}
}'19. contacts_search_contacts
Search contacts by name, email, or phone number.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "30",
"method": "tools/call",
"params": {
"name": "contacts_search_contacts",
"arguments": {
"query": "John"
}
}
}'20. contacts_get_contact
Get a specific contact by resource name.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "31",
"method": "tools/call",
"params": {
"name": "contacts_get_contact",
"arguments": {
"resourceName": "people/c1234567890"
}
}
}'21. contacts_create_contact
Create a new contact with name, email, phone, organization, and notes.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "32",
"method": "tools/call",
"params": {
"name": "contacts_create_contact",
"arguments": {
"givenName": "Jane",
"familyName": "Doe",
"email": "[email protected]",
"phone": "+1-555-0100",
"organization": "Acme Inc",
"jobTitle": "Engineer"
}
}
}'22. contacts_update_contact
Update an existing contact (requires etag for optimistic concurrency).
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "33",
"method": "tools/call",
"params": {
"name": "contacts_update_contact",
"arguments": {
"resourceName": "people/c1234567890",
"etag": "%EgUBAi43...",
"jobTitle": "Senior Engineer"
}
}
}'23. contacts_delete_contact
Delete a contact.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "34",
"method": "tools/call",
"params": {
"name": "contacts_delete_contact",
"arguments": {
"resourceName": "people/c1234567890"
}
}
}'YouTube Tools (16)
24. youtube_search
Search YouTube for videos, channels, or playlists.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "35",
"method": "tools/call",
"params": {
"name": "youtube_search",
"arguments": {
"query": "MCP tutorial",
"type": "video",
"maxResults": 5
}
}
}'25. youtube_get_video_details
Get detailed information about one or more videos.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "36",
"method": "tools/call",
"params": {
"name": "youtube_get_video_details",
"arguments": {
"videoIds": "dQw4w9WgXcQ"
}
}
}'26. youtube_get_video_rating
Check if the authenticated user has liked/disliked a video.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "37",
"method": "tools/call",
"params": {
"name": "youtube_get_video_rating",
"arguments": {
"videoIds": "dQw4w9WgXcQ"
}
}
}'27. youtube_rate_video
Like, dislike, or remove rating from a video.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "38",
"method": "tools/call",
"params": {
"name": "youtube_rate_video",
"arguments": {
"videoId": "dQw4w9WgXcQ",
"rating": "like"
}
}
}'28. youtube_get_channel
Get channel information (own channel or by ID).
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "39",
"method": "tools/call",
"params": {
"name": "youtube_get_channel",
"arguments": {
"mine": true
}
}
}'29. youtube_list_subscriptions
List the authenticated user's subscriptions.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "40",
"method": "tools/call",
"params": {
"name": "youtube_list_subscriptions",
"arguments": {
"maxResults": 10
}
}
}'30. youtube_subscribe_channel
Subscribe to a YouTube channel.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "41",
"method": "tools/call",
"params": {
"name": "youtube_subscribe_channel",
"arguments": {
"channelId": "UCxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}'31. youtube_unsubscribe_channel
Unsubscribe from a YouTube channel (requires subscription ID).
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "42",
"method": "tools/call",
"params": {
"name": "youtube_unsubscribe_channel",
"arguments": {
"subscriptionId": "xxxxxxxxxxxxxxxxxxxx"
}
}
}'32. youtube_list_playlists
List playlists (own or by channel ID).
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "43",
"method": "tools/call",
"params": {
"name": "youtube_list_playlists",
"arguments": {
"mine": true
}
}
}'33. youtube_create_playlist
Create a new YouTube playlist.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "44",
"method": "tools/call",
"params": {
"name": "youtube_create_playlist",
"arguments": {
"title": "My Favorites",
"description": "A collection of my favorite videos",
"privacyStatus": "private"
}
}
}'34. youtube_list_playlist_items
List videos in a playlist.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "45",
"method": "tools/call",
"params": {
"name": "youtube_list_playlist_items",
"arguments": {
"playlistId": "PLxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}'35. youtube_add_to_playlist
Add a video to a playlist.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "46",
"method": "tools/call",
"params": {
"name": "youtube_add_to_playlist",
"arguments": {
"playlistId": "PLxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"videoId": "dQw4w9WgXcQ"
}
}
}'36. youtube_remove_from_playlist
Remove a video from a playlist (requires playlist item ID).
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "47",
"method": "tools/call",
"params": {
"name": "youtube_remove_from_playlist",
"arguments": {
"playlistItemId": "UExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxQ"
}
}
}'37. youtube_list_comments
List comments on a YouTube video.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "48",
"method": "tools/call",
"params": {
"name": "youtube_list_comments",
"arguments": {
"videoId": "dQw4w9WgXcQ",
"maxResults": 10
}
}
}'38. youtube_post_comment
Post a top-level comment on a YouTube video.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "49",
"method": "tools/call",
"params": {
"name": "youtube_post_comment",
"arguments": {
"videoId": "dQw4w9WgXcQ",
"text": "Great video!"
}
}
}'39. youtube_reply_to_comment
Reply to an existing YouTube comment.
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "50",
"method": "tools/call",
"params": {
"name": "youtube_reply_to_comment",
"arguments": {
"parentId": "UgxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxQ",
"text": "Thanks for sharing!"
}
}
}'List Available Tools
Get the complete list of available tools:
curl -X POST http://localhost:30000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer ya29.your-google-access-token" \
-d '{
"jsonrpc": "2.0",
"id": "tools-list",
"method": "tools/list",
"params": {}
}'Project Structure
google-workspace/
├── package.json # NPM configuration
├── tsconfig.json # TypeScript configuration
├── Dockerfile # Container configuration
├── tools.json # Tool definitions for MCP
├── nodemon.json # Dev mode configuration
├── src/
│ ├── index.ts # Main server entry point
│ ├── schemas.ts # Zod schemas for all tools
│ ├── tool-registry.ts # Tool registration system
│ ├── tool-loader.ts # Tool definitions loader
│ ├── debug-middleware.ts # Debug logging
│ ├── types.ts # TypeScript interfaces
│ ├── helpers.ts # Utility functions
│ ├── google-api-client.ts # Google API service factories
│ └── tools/
│ ├── index.ts # Tool exports
│ ├── gmail.ts # Gmail tools (4)
│ ├── drive.ts # Drive tools (3)
│ ├── calendar.ts # Calendar tools (3)
│ ├── docs.ts # Docs tools (2)
│ ├── sheets.ts # Sheets tools (3)
│ ├── slides.ts # Slides tools (2)
│ ├── contacts.ts # Contacts tools (6)
│ └── youtube.ts # YouTube tools (16)
└── dist/ # Compiled JavaScriptAuthentication Setup
Create Google Cloud Project:
- Go to Google Cloud Console
- Create a new project or select existing
- Enable required APIs (Gmail, Drive, Calendar, People, YouTube)
Set up OAuth2:
- Go to "Credentials" -> "Create Credentials" -> "OAuth 2.0 Client IDs"
- Configure OAuth consent screen
- Download client configuration
Required Scopes:
https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.send https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/youtube.force-sslGet Access Token:
- Use Google OAuth2 flow to obtain access tokens
- Pass tokens via
Authorization: Bearerheader
Configuration
Environment Variables
# Server Configuration
PORT=30000 # Server port (default: 30000)
DEBUG=true # Enable debug logging
# Tool Configuration
TOOLS_CONFIG_PATH=./tools.json # Custom path to tools.jsonDevelopment
Run in Development Mode
# Auto-reload on file changes
pnpm run dev
# With debug logging enabled
pnpm run dev:debugBuild for Production
pnpm run build
pnpm startError Handling
The server provides detailed error messages for common issues:
- 401: Invalid or expired Google access token
- 403: Insufficient permissions or missing scopes
- 404: Resource not found (document, file, etc.)
- 429: Rate limit exceeded
- 500: Internal server errors
License
This MCP server is licensed under the MIT License.
