Skip to main content
Glama

yt-toggl-mcp

A small, self-hosted MCP server for Toggl Track (API v9). It runs over stdio and exposes time tracking, projects/clients, and reporting to any MCP client.

No telemetry. The only network egress is to api.track.toggl.com. Workspace-level tokens are stripped from every response and user emails are masked.

Tools

Tool

What it does

toggl_check_auth

Verify the token; returns the (masked) user and accessible workspaces.

toggl_get_quota

Remaining API requests and reset time per organization.

toggl_list_workspaces

List accessible workspaces.

toggl_list_projects

List projects in a workspace.

toggl_list_clients

List clients in a workspace.

toggl_list_tags

List tags in a workspace.

toggl_get_current_entry

Return the running timer with elapsed seconds.

toggl_get_time_entry

Load a single entry by id.

toggl_get_time_entries

List entries for a period, an inclusive start_date/end_date range, or since/before.

toggl_create_time_entry

Create a completed entry (start + stop/duration) or a running one.

toggl_update_time_entry

Edit an existing entry; only the fields you pass are changed. A zero duration is ignored unless a stop is given.

toggl_delete_time_entry

Permanently delete an entry.

toggl_start_timer

Start a running timer with optional description, project, tags.

toggl_stop_timer

Stop the running timer (or a specific entry_id).

toggl_report

Total time for a range, grouped by project, sorted by hours.

workspace_id defaults to the configured workspace and project_id defaults to the configured project from the project settings file; explicit arguments always win. The default project is used only where it belongs: tracking in another workspace never inherits it, and with no workspaceId configured it is applied only if the resolved workspace owns that project.

period accepts today, yesterday, week, lastWeek, month, lastMonth. Ranges are interpreted in local time and end_date is inclusive at the tool boundary. since takes unix seconds and, per Toggl, also returns entries deleted since that time.

Toggl enforces a sliding-window request quota per user per organization; on 402 the error result carries quota_remaining and quota_resets_in_seconds.

toggl_report clips every entry to the requested range, so an entry crossing a boundary is neither double-counted nor dropped. It scans backward in 84-day windows and respects Toggl's historical retention boundary: if it reaches that boundary it returns incomplete: true together with incomplete_reason, rather than reporting a silently short total. Any other error is propagated.

Related MCP server: Traggo MCP

Configuration

Toggl configuration has two scopes, and each setting lives in exactly one place.

User scope — the API token. TOGGL_API_KEY, or a per-tool file under your home directory matching the other yt-* MCP servers:

~/.yt-toggl-mcp/credentials.json
{
  "apiToken": "<your token>"
}

Project scope — the tracking defaults. The server reads .yt-toggl-mcp.json from its working directory, which is the project root the MCP client launches it in. The name is fixed: there is no flag and no search up the tree, so a project either has its own Toggl defaults or has none.

{
  "workspaceId": 1234567,
  "projectId": 216478744,
  "billable": true
}

apiToken must come from one of the two sources, otherwise the server exits with a message naming the file to create. workspaceId/projectId in the user file are ignored.

File

Scope

Where

Keys

~/.yt-toggl-mcp/credentials.json

user

home directory

apiToken

.yt-toggl-mcp.json

project

repository root

workspaceId, projectId, billable

Variable

Required

Default

Purpose

TOGGL_API_KEY

no

apiToken from the credentials file

Toggl Track API token (track.toggl.com/profile).

TOGGL_CACHE_TTL

no

3600000

Metadata cache TTL in ms.

A token must come from one of the two sources, otherwise the server exits with a message naming the file to create. The toggl-setup skill (.opencode/skills/toggl-setup/SKILL.md) walks a project through creating the settings file. An apiToken key in it is rejected, because a project file may be committed by mistake while the token stays user-scoped.

A missing settings file does not stop the server: it logs a warning to stderr, the read tools keep working, and any write that would rely on the configured project fails with PROJECT_SETTINGS_MISSING instead of creating an entry with no project. A malformed file or an invalid id still stops startup.

Both keys in the project file are optional: omit workspaceId if you only have one workspace, and omit projectId if you do not want a default project.

billable is optional too, and it is what makes tracked time show as billable by default. A Toggl project's own billable setting does not propagate to the entries created in it, so without this key every new timer starts unbilled. It applies to toggl_start_timer and toggl_create_time_entry when the caller passes no billable, and only where the configured project applies; an explicit billable argument always wins. A value that is not true/false stops startup with the key named.

projectId is used only where it belongs, and is verified against the workspace before any write, so an entry never lands in the wrong project. When workspaceId is set, the project applies while tracking in that workspace and a stale id fails with INVALID_PROJECT_ID; naming another workspace_id never inherits it. Without workspaceId, the project is applied when the resolved workspace owns it and ignored when it does not; that check costs an extra request per write, and the result carries a notice when the project was skipped.

Keep .yt-toggl-mcp.json out of version control so no Toggl ids or personal tracking defaults appear in tracked repository files, and add it to each project's .gitignore.

Where the file is found

The server looks for .yt-toggl-mcp.json in its working directory, then in its parent directories up to the repository root (the nearest .git). A client that launches the server from anywhere inside the repository therefore finds the file, so no extra configuration is needed. A launch outside the repository finds nothing and the server warns.

No flag or environment variable selects another location: one repository, one .yt-toggl-mcp.json. A missing file does not break the server — reads keep working and writes that need a project default fail with PROJECT_SETTINGS_MISSING — so the first run can still authorize and pick a project. The server's instructions ask the agent to run the toggl-setup skill in that case.

Precedence, highest first:

  1. explicit tool arguments (workspace_id, project_id)

  2. .yt-toggl-mcp.json from the launch directory up to the repository root

A malformed settings file, or an id that is not a positive integer, stops the server with the path and key named. workspaceId and projectId in the user credentials file are ignored: they belong in the project settings file.

TOGGL_DEFAULT_WORKSPACE_ID was removed in 0.5.0 and --settings was removed in 0.7.0; put workspaceId and projectId in the project settings file instead.

Install

Prerequisites: Node.js >=20.19.0 and a Toggl Track API token from track.toggl.com/profile (scroll to the bottom → "Click to reveal").

npm

npx -y yt-toggl-mcp

Run it from a repository that has a .yt-toggl-mcp.json; without one the server still starts but warns, and writes that need a project default fail.

Any MCP client that speaks stdio works. The server reads its project settings from the working directory, so every config must launch it from the repository root. Generic client config:

{
  "mcpServers": {
    "yt-toggl-mcp": {
      "command": "npx",
      "args": ["-y", "yt-toggl-mcp"]
    }
  }
}

yt-toggl-mcp --help prints the credential and project settings paths, the precedence, and the environment variables; --version prints the version. Both write to stderr, since stdout carries the MCP protocol.

opencode

1. Create the credentials file

Write ~/.yt-toggl-mcp/credentials.json (Windows: C:\Users\<you>\.yt-toggl-mcp\credentials.json):

{
  "apiToken": "<your token>"
}

Alternatively set TOGGL_API_KEY in the environment to supply the token.

2. Register the server

Add this to ~/.config/opencode/opencode.jsonc (Windows: C:\Users\<you>\.config\opencode\opencode.jsonc) under the existing mcp key. <repo> is the repository whose .yt-toggl-mcp.json the server should read:

{
  "mcp": {
    "yt-toggl-mcp": {
      "type": "local",
      "command": ["npx", "-y", "yt-toggl-mcp"]
    }
  }
}

No environment block is needed: the server reads its own credentials file, like yt-gmail-mcp and yt-zoho-mcp.

3. Let the setup run

The server's instructions tell the agent to run the toggl-setup skill when this repository has no .yt-toggl-mcp.json. It checks the token, guides authorization if needed, lists the workspaces and projects, asks which project this repository should use, writes the file, and adds it to .gitignore.

The server finds the file by walking up from its launch directory to the repository root, so one global yt-toggl-mcp entry covers every repository.

4. Restart opencode

Config is read once at startup and is not hot-reloaded, so the server only loads after a restart.

5. Verify

Ask opencode to call toggl_check_auth. It should return your (masked) account and workspace list. A quick win after that: ask "what am I currently tracking?".

Development

npm install
npm run build
npm run lint
npm test

npm test runs the Vitest suite with HTTP mocked, so no token or live calls are needed.

The server runs from src in development (npm run dev, npm test). dist is only for the published bin: npm install compiles it through the prepare script, and npm run build does the same on demand.

node dist/index.js runs the built server locally — it reads the same credentials and project settings files described above, so run it from the project root. npm run dev watches the source with tsx instead of building.

License

MIT © yentsun — see LICENSE.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers