Skip to main content
Glama

Toggl MCP Server

by ikido
README.md9 kB
# Toggl MCP Server A FastMCP-based Model Context Protocol (MCP) server that fetches and aggregates Toggl time tracking data with intelligent Fibery entity reference parsing and caching. ## Features - **Time Entry Aggregation**: Fetch and aggregate time entries from Toggl API - **Fibery Entity Parsing**: Automatically extract Fibery entity references from Toggl descriptions (#ID [DB] [TYPE]) - **Caching**: Smart caching with SQLite index and JSON file storage (1-hour TTL) - **Rate Limiting**: Exponential backoff handling for Toggl API rate limits - **User Filtering**: Optional filtering by single user or retrieve all workspace users - **Date Range Validation**: Enforces ISO 8601 format and max 7-day ranges per request ## Installation ### Prerequisites - Python 3.11+ - uv (package manager) ### Setup 1. Clone the repository: ```bash git clone <repository-url> cd toggl-mcp-custom ``` 2. Create virtual environment: ```bash uv venv source .venv/bin/activate ``` 3. Install dependencies: ```bash uv pip install -r requirements.txt ``` 4. Configure environment: ```bash cp .env.example .env # Edit .env with your Toggl API credentials ``` ## Configuration Create a `.env` file in the project root with your Toggl credentials: ```env TOGGL_API_TOKEN=your_api_token_here TOGGL_WORKSPACE_ID=your_workspace_id_here ``` Get your credentials: - **API Token**: Available at https://track.toggl.com/app/profile - **Workspace ID**: Available in Toggl settings or API responses ## Using with Claude Code ### Option 1: Project-Local Integration (Recommended) The easiest way is to add the MCP server to your project's `.mcp.json` file: ```json { "mcpServers": { "toggl": { "command": "/path/to/toggl-mcp-custom/.venv/bin/python", "args": ["-m", "toggl_mcp.server"], "cwd": "${workspaceRoot}" } } } ``` Replace `/path/to/toggl-mcp-custom` with the actual path to this project. Claude Code will automatically discover and use this server. The tools will be available in your conversations. ### Option 2: Global Integration To use this server across all projects, add it to your global MCP config: **macOS/Linux:** ```bash mkdir -p ~/.config/claude-code ``` Then add to `~/.config/claude-code/mcp.json`: ```json { "mcpServers": { "toggl": { "command": "/path/to/toggl-mcp-custom/.venv/bin/python", "args": ["-m", "toggl_mcp.server"], "cwd": "/path/to/toggl-mcp-custom" } } } ``` ### Using in Other Projects To add this MCP server to another project: 1. **Copy the `.mcp.json` template:** ```bash cat > /path/to/other-project/.mcp.json << 'EOF' { "mcpServers": { "toggl": { "command": "/path/to/toggl-mcp-custom/.venv/bin/python", "args": ["-m", "toggl_mcp.server"], "cwd": "/path/to/toggl-mcp-custom" } } } EOF ``` 2. **Update the paths** to point to your toggl-mcp-custom installation 3. **Restart Claude Code** - it will automatically discover the server ## Running the Server Manually If you want to run the server directly: ```bash source .venv/bin/activate python -m toggl_mcp.server ``` The server will start and expose two MCP tools: ### 1. `get_workspace_users()` Lists all users in the Toggl workspace. **Response:** ```json { "status": "success", "data": [ {"id": "12345", "email": "user@example.com", "name": "John Doe"}, {"id": "12346", "email": "jane@example.com", "name": "Jane Smith"} ], "error": null } ``` ### 2. `get_toggl_aggregated_data(start_date, end_date, user_id=None)` Fetches and aggregates time entries for a date range. **Parameters:** - `start_date` (string): ISO 8601 format (YYYY-MM-DD), e.g., "2025-10-06" - `end_date` (string): ISO 8601 format, must be >= start_date and <= start_date + 7 days - `user_id` (optional string): Filter by single user ID **Response:** ```json { "status": "success", "data": { "users": { "user@example.com": { "user_email": "user@example.com", "matched_entities": [ { "entity_database": "Scrum", "entity_type": "Task", "entity_id": "456", "description": "Design UI", "duration_hours": 7.5 } ], "unmatched_activities": [ { "description": "Team meeting", "duration_hours": 1.0 } ], "statistics": { "total_duration_hours": 8.5, "matched_duration_hours": 7.5, "unmatched_duration_hours": 1.0 } } }, "statistics": { "total_users": 1, "total_duration_hours": 8.5, "total_matched_duration_hours": 7.5, "total_unmatched_duration_hours": 1.0 } }, "error": null, "metadata": { "source": "api", "entries_fetched": 15 } } ``` ## Description Parsing The server automatically parses Toggl entry descriptions to extract Fibery entity references. **Format:** `"Description text #ID [DATABASE] [TYPE] [PROJECT]"` **Examples:** - `"Design UI #456 [Scrum] [Task] [Moneyball]"` → Matched entity - `"#123 [Dev]"` → Minimal matched entity - `"Team meeting"` → Unmatched activity **Parsing Rules:** - Extracts the rightmost `#ID` if multiple exist - Captures first 3 bracket values as DATABASE, TYPE, and PROJECT - Text before #ID becomes the description ## Architecture ### Services - **CacheService**: Manages caching with MD5 hash keys, SQLite index, and JSON file storage - **TogglService**: Handles Toggl API client with HTTP Basic Auth and rate limiting - **ParserService**: Parses descriptions to extract Fibery entity references - **AggregatorService**: Groups and aggregates time entries by user and entity ### Models - **User**: Toggl workspace user - **TimeEntry**: Raw Toggl time entry - **ParsedEntry**: Entry with extracted metadata - **UserAggregation**: Aggregated data for single user - **AggregatedData**: Complete aggregated response ## Testing Run unit tests: ```bash python -m pytest tests/ -v ``` Test coverage: - **26 unit tests** covering: - Description parsing (7 tests) - Data aggregation (5 tests) - Cache operations (5 tests) - Date validation and utilities (9 tests) ## Project Structure ``` toggl-mcp-custom/ ├── src/toggl_mcp/ │ ├── __init__.py │ ├── server.py # FastMCP server + tools │ ├── config.py # Configuration from env vars │ ├── models.py # Pydantic models │ ├── utils.py # Utility functions │ └── services/ │ ├── __init__.py │ ├── cache_service.py # SQLite + JSON caching │ ├── toggl_service.py # Toggl API client │ ├── parser_service.py # Description parsing │ └── aggregator_service.py # Data aggregation ├── tests/ │ ├── __init__.py │ ├── test_parser_service.py │ ├── test_aggregator_service.py │ ├── test_cache_service.py │ └── test_utils.py ├── cache/ # Runtime cache (auto-created) │ ├── data/ # JSON cache files │ └── index.db # SQLite index ├── requirements.txt # Python dependencies ├── .env.example # Environment template └── README.md # This file ``` ## Performance Considerations ### Rate Limiting - Toggl API limit: 3 requests per second - Exponential backoff on 429 (rate limit) responses: - Attempt 1: 60 seconds - Attempt 2: 120 seconds - Attempt 3: 240 seconds - After 3 retries: failure ### Caching - Default TTL: 1 hour - Cache keys: MD5 hash of date range + optional user_id - Storage: SQLite index + JSON files - Automatic cleanup of expired entries on retrieval ### Date Range Limits - Maximum range: 7 days per request - For larger ranges, make multiple requests and aggregate client-side - Day-by-day pagination to optimize API efficiency ## Error Handling The server returns structured error responses with error codes: - `INVALID_DATE_FORMAT` — Dates not in ISO 8601 format - `INVALID_DATE_RANGE` — end_date < start_date - `DATE_RANGE_EXCEEDS_LIMIT` — Range exceeds 7 days - `USER_NOT_FOUND` — User ID not found in workspace - `API_ERROR` — Toggl API error - `SERVICE_NOT_INITIALIZED` — Services not properly initialized - `INTERNAL_ERROR` — Server error ## Development ### Adding New Features 1. Add models to `models.py` 2. Implement service methods 3. Write unit tests in `tests/` 4. Update MCP tool in `server.py` ### Running Tests ```bash # All tests python -m pytest tests/ -v # Specific test file python -m pytest tests/test_parser_service.py -v # With coverage python -m pytest tests/ --cov=src/toggl_mcp ``` ## License MIT ## Support For issues or questions, please refer to the implementation specification in `/docs/features/1-initial-implementation/IMPLEMENTATION.md`

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ikido/toggl-mcp-custom'

If you have feedback or need assistance with the MCP directory API, please join our Discord server