This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Google Calendar MCP Server - A Model Context Protocol (MCP) server providing Google Calendar integration for AI assistants. Built with TypeScript, supports both stdio and HTTP transports, with OAuth 2.0 authentication.
npm install # Install dependencies
npm run build # Build with esbuild (outputs to build/)
npm run dev # Show interactive development menu with all commands
npm run lint # TypeScript type checking (no emit)
# Testing - Quick Start
npm test # Unit tests only (no auth required)
npm run test:watch # Unit tests in watch mode
npm run dev test:integration:direct # Direct integration tests (recommended for dev)
npm run dev coverage # Generate test coverage report
# Testing - Full Suite (rarely needed, incurs LLM usage costs)
npm run dev test:integration:claude # Claude + MCP integration (requires CLAUDE_API_KEY)
npm run dev test:integration:openai # OpenAI + MCP integration (requires OPENAI_API_KEY)
npm run dev test:integration:all # All integration tests (requires all API keys)
# Authentication
npm run auth # Authenticate main account
npm run dev auth:test # Authenticate test account (for integration tests)
npm run dev account:status # Check authentication status
# Running the server
npm start # Start with stdio transport
npm run dev http # Start HTTP server on localhost:3000
npm run dev http:public # HTTP server accessible from any hostAll MCP tools follow a consistent handler pattern:
- Handler Registration: Handlers are auto-registered via
src/tools/registry.ts - Base Class: All handlers extend
BaseToolHandlerfromsrc/handlers/core/BaseToolHandler.ts - Schema Definition: Input schemas defined in
src/tools/registry.tsusing Zod - Handler Implementation: Core logic in
src/handlers/core/directory
Request Flow:
Client → Transport Layer → Schema Validation (Zod) → Handler → Google Calendar API → Response
-
Create handler class in
src/handlers/core/YourToolHandler.ts:- Extend
BaseToolHandler - Implement
runTool(args, accounts)method whereaccountsisMap<string, OAuth2Client> - Use
this.getCalendar(accounts)to get Calendar API client - Use
this.handleGoogleApiError(error)for error handling
- Extend
-
Define schema in
src/tools/registry.ts:- Add to
ToolSchemasobject with Zod schema - Add to
ToolRegistry.toolsarray with name, description, handler class
- Add to
-
Add tests:
- Unit tests in
src/tests/unit/handlers/YourToolHandler.test.ts - Integration tests in
src/tests/integration/if needed
- Unit tests in
No manual registration needed - handlers are auto-discovered by the registry system.
- OAuth 2.0 with refresh token support
- Multi-account: Supports multiple accounts with friendly nicknames (e.g.,
work,personal). Use themanage-accountstool in chat, ornpm run account auth <nickname>from CLI to add additional accounts. - Token Storage:
~/.config/google-calendar-mcp/tokens.json(platform-specific paths) - Token Validation: Automatic refresh on expiry
- Components:
src/auth/client.ts- OAuth2Client initializationsrc/auth/server.ts- Auth server for OAuth flowsrc/auth/tokenManager.ts- Token management and validation
- stdio (default): Process communication for Claude Desktop
- HTTP: RESTful API with SSE for remote deployment
- Configuration:
src/config/TransportConfig.ts - Handlers:
src/transports/stdio.tsandsrc/transports/http.ts
Unit Tests (src/tests/unit/):
- No external dependencies (mocked)
- Schema validation, error handling, datetime logic
- Run with
npm test(no setup required)
Integration Tests (src/tests/integration/):
Three types of integration tests, each with different requirements:
-
Direct Integration (most commonly used):
- File:
direct-integration.test.ts - Tests real Google Calendar API calls
- Setup Required:
# 1. Set credentials path export GOOGLE_OAUTH_CREDENTIALS=./gcp-oauth.keys.json # 2. Set test calendar (use "primary" or a specific calendar ID) export TEST_CALENDAR_ID=primary # 3. Authenticate test account npm run dev auth:test # 4. Run tests npm run dev test:integration:direct
- File:
-
LLM Integration (rarely needed):
- Files:
claude-mcp-integration.test.ts,openai-mcp-integration.test.ts - Tests end-to-end MCP protocol with AI models
- Additional Setup (beyond direct integration setup):
# For Claude tests export CLAUDE_API_KEY=sk-ant-... npm run dev test:integration:claude # For OpenAI tests export OPENAI_API_KEY=sk-... npm run dev test:integration:openai # For both npm run dev test:integration:all
⚠️ Consumes API credits and takes 2-5 minutes
- Files:
Quick Setup Summary:
# Minimal setup for development (direct integration tests only):
export GOOGLE_OAUTH_CREDENTIALS=./gcp-oauth.keys.json
export TEST_CALENDAR_ID=primary
npm run dev auth:test
npm run dev test:integration:directConflict Detection (src/services/conflict-detection/):
EventSimilarityChecker.ts- Detects scheduling conflicts, identifies duplicate events, and analyzes event overlapConflictDetectionService.ts- Main service coordinating conflict and duplicate checks- Used by
create-eventandupdate-eventhandlers
Calendar Registry (src/services/CalendarRegistry.ts):
- Calendar deduplication across multiple accounts
- Permission-based account auto-selection (read vs write)
- Calendar name-to-ID resolution with caching
Structured Responses (src/types/structured-responses.ts):
- TypeScript interfaces for consistent response formats
- All handlers return structured JSON via
createStructuredResponse()
Utilities:
src/utils/field-mask-builder.ts- Builds Google API field maskssrc/utils/event-id-validator.ts- Validates Google Calendar event IDssrc/utils/response-builder.ts- Formats MCP responsessrc/utils/datetime.ts- Timezone and datetime utilities
- Preferred Format: ISO 8601 without timezone (e.g.,
2024-01-01T10:00:00)- Uses
timeZoneparameter or calendar's default timezone
- Uses
- Also Supported: ISO 8601 with timezone (e.g.,
2024-01-01T10:00:00-08:00) - All-day Events: Date only format (e.g.,
2024-01-01) - Helper:
getCalendarTimezone()method inBaseToolHandler
list-eventsaccepts single calendar ID or JSON array:'["cal1", "cal2"]'- Batch requests handled by
BatchRequestHandler.ts - Maximum 50 calendars per request
- Modification scopes:
thisEventOnly,thisAndFollowing,all - Handled by
RecurringEventHelpers.ts - Special validation in
update-eventschema
- Use
McpErrorfrom@modelcontextprotocol/sdk/types.js BaseToolHandler.handleGoogleApiError()for consistent Google API error handling- Maps HTTP status codes to appropriate MCP error codes
All tool outputs use a structured JSON response format. Types are defined in src/types/structured-responses.ts and responses are created via createStructuredResponse() from src/utils/response-builder.ts. When adding new handlers, ensure responses conform to these structured formats.
MCP tools return errors as successful responses with error content, not as thrown exceptions. Integration tests must validate result.content[0].text for error messages, while unit tests of handlers directly can still catch thrown McpError exceptions before the MCP transport layer wraps them.
- TypeScript: Strict mode, avoid
anytypes - Formatting: Use existing patterns in handlers
- Testing: Add unit tests for all new handlers
- Error Messages: Clear, actionable error messages referencing Google Calendar concepts
- Version: v3 (
googleapispackage) - Timeout: 3 seconds per API call (configured in
BaseToolHandler) - Rate Limiting: Google Calendar API has quotas - integration tests may hit limits
- Scope Required:
https://www.googleapis.com/auth/calendar(full calendar access, superset ofcalendar.events)
- npx:
npx @cocal/google-calendar-mcp(requiresGOOGLE_OAUTH_CREDENTIALSenv var) - Docker: See
docs/docker.mdfor Docker deployment with stdio and HTTP modes - Claude Desktop Config: See README.md for local stdio configuration
Local Development (Claude Desktop):
- Use stdio mode (default)
- No server or domain required
- Direct process communication
- See README.md for setup
Key Differences:
- stdio: For Claude Desktop only, local machine
- HTTP: For testing, development, debugging (local only)