Skip to main content
Glama

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:

git clone <repository-url> cd toggl-mcp-custom
  1. Create virtual environment:

uv venv source .venv/bin/activate
  1. Install dependencies:

uv pip install -r requirements.txt
  1. Configure environment:

cp .env.example .env # Edit .env with your Toggl API credentials

Configuration

Create a .env file in the project root with your Toggl credentials:

TOGGL_API_TOKEN=your_api_token_here TOGGL_WORKSPACE_ID=your_workspace_id_here

Get your credentials:

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:

{ "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:

mkdir -p ~/.config/claude-code

Then add to ~/.config/claude-code/mcp.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

    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:

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:

{ "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:

{ "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:

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

# 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

-
security - not tested
-
license - not tested
-
quality - not tested

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