{
  "markdown": "# clockify-mcp\n\n[![CI](https://github.com/tracegazer/clockify-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/tracegazer/clockify-mcp/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/clockify-mcp)](https://pypi.org/project/clockify-mcp/)\n[![Python](https://img.shields.io/pypi/pyversions/clockify-mcp)](https://pypi.org/project/clockify-mcp/)\n[![License: MIT](https://img.shields.io/pypi/l/clockify-mcp)](LICENSE)\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-published-0a7ea4)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.tracegazer/clockify-mcp)\n[![Smithery](https://smithery.ai/badge/tracegazer/clockify-mcp)](https://smithery.ai/servers/tracegazer/clockify-mcp)\n\n<!-- mcp-name: io.github.tracegazer/clockify-mcp -->\n\n> A [Model Context Protocol](https://modelcontextprotocol.io) server for the [Clockify](https://clockify.me) **time-tracking API**.\n\nGive your AI assistant access to your Clockify data — query workspaces, projects, and time entries, generate reports, log hours, and manage clients, invoices, and more — all through natural language.\n\n**112 tools** across 18 domains. Read-only by default, with optional write operations behind explicit opt-in.\n\n## Install in one click\n\nThe easiest way to use this server with **Claude Desktop** (and other MCPB-compatible clients) is the prebuilt bundle:\n\n**➡️ [Download `clockify-mcp.mcpb`](https://github.com/tracegazer/clockify-mcp/releases/latest/download/clockify-mcp.mcpb)** — then double-click it. Claude Desktop opens the installer, prompts for your Clockify API key, and you're done. No Python, no `npx`/`uvx`, no config files.\n\nThe `.mcpb` is attached to every [GitHub Release](https://github.com/tracegazer/clockify-mcp/releases) and mirrored on [Smithery](https://smithery.ai/). Prefer a package manager or container? See [Quick start](#quick-start) below.\n\n## What can it do?\n\n**48 read-only tools** are available today (Phase 0–8b — 18 domains). 64 write tools (create/update/delete across clients, projects, tasks, tags, time entries, holidays, expenses, and expense categories, plus time-off policy/request management, approval submit/resubmit/update, custom-field create/update/delete and project assignment, scheduling assignment management, invoice and payment management, shared-report management, and webhook create/update/delete/token) register when you set `CLOCKIFY_ACCESS_MODE=full` (or the back-compat `CLOCKIFY_ENABLE_WRITES=true`). A middle `time-tracking` mode exposes only the time-entry writes for logging hours — see [Access modes](#configuration).\n\n| Domain | Tools | Tool names |\n|--------|------:|------------|\n| **Workspaces** | 3 | `get_current_user`, `list_workspaces`, `get_workspace` |\n| **Users** | 3 | `list_users`, `get_user_member_profile`, `find_user_team_manager` |\n| **Groups** | 1 | `list_user_groups` |\n| **Clients** | 2 | `list_clients`, `get_client` |\n| **Projects** | 2 | `list_projects`, `get_project` |\n| **Tasks** | 2 | `list_tasks`, `get_task` |\n| **Tags** | 2 | `list_tags`, `get_tag` |\n| **Time entries** | 2 | `list_time_entries`, `get_time_entry` |\n| **Reports** | 6 | `generate_detailed_report`, `generate_summary_report`, `generate_weekly_report`, `generate_attendance_report`‡, `generate_expense_report`‡, `export_report` (PDF/CSV/XLSX to a file) |\n| **Shared reports** | 2 | `list_shared_reports`, `get_shared_report` |\n| **Time off**† | 5 | `list_time_off_policies`, `get_time_off_policy`, `list_time_off_balances_by_policy`, `list_time_off_balances_by_user`, `list_time_off_requests` |\n| **Holidays**† | 2 | `list_holidays`, `list_holidays_in_period` |\n| **Expenses**† | 4 | `list_expenses`, `get_expense`, `list_expense_categories`, `download_expense_receipt` |\n| **Approvals**† | 1 | `list_approval_requests` |\n| **Custom fields**† | 2 | `list_workspace_custom_fields`, `list_project_custom_fields` |\n| **Scheduling**† | 3 | `list_scheduled_assignments`, `get_project_scheduling_totals`, `get_user_scheduling_totals` |\n| **Invoices**† | 3 | `list_invoices`, `get_invoice`, `get_invoice_payments` |\n| **Webhooks**† | 3 | `list_webhooks`, `get_webhook`, `get_webhook_logs` |\n\n† **Time off**, **Holidays**, **Expenses**, **Approvals**, **Custom fields**, **Scheduling**, **Invoices**, and **Webhooks** are paid Clockify features — these tools error (HTTP 402/403/404) on plans without them.\n‡ `generate_attendance_report` and `generate_expense_report` (and `export_report` for those two types) need the workspace's attendance/Expenses add-ons; the time-based reports (detailed/summary/weekly) and shared reports work on the free plan.\n\n**Write tools** (opt-in — set `CLOCKIFY_ACCESS_MODE=full`):\n\n| Domain | Tools | Tool names |\n|--------|------:|------------|\n| **Clients** | 3 | `create_client`, `update_client`, `delete_client` |\n| **Projects** | 3 | `create_project`, `update_project`, `delete_project` |\n| **Tasks** | 3 | `create_task`, `update_task`, `delete_task` |\n| **Tags** | 3 | `create_tag`, `update_tag`, `delete_tag` |\n| **Time entries** | 7 | `create_time_entry`, `update_time_entry`, `delete_time_entry`, `duplicate_time_entry`, `bulk_update_time_entries`, `create_time_entry_for_user`, `stop_running_timer` |\n| **Shared reports** | 3 | `create_shared_report`, `update_shared_report`, `delete_shared_report` |\n| **Time off**† | 5 | `create_time_off_policy`, `create_time_off_request`, `approve_time_off_request`, `reject_time_off_request`, `withdraw_time_off_request` |\n| **Holidays**† | 3 | `create_holiday`, `update_holiday`, `delete_holiday` |\n| **Expenses**† | 7 | `create_expense`, `update_expense`, `delete_expense`, `create_expense_category`, `update_expense_category`, `delete_expense_category`, `archive_expense_category` |\n| **Approvals**† | 4 | `submit_approval_request`, `submit_approval_request_for_user`, `resubmit_approval_entries`, `update_approval_request` |\n| **Custom fields**† | 5 | `create_workspace_custom_field`, `update_workspace_custom_field`, `delete_workspace_custom_field`, `set_project_custom_field`, `remove_project_custom_field` |\n| **Scheduling**† | 5 | `create_scheduled_assignment`, `update_scheduled_assignment`, `delete_scheduled_assignment`, `publish_scheduled_assignment`, `copy_scheduled_assignment` |\n| **Invoices**† | 9 | `create_invoice`, `update_invoice`, `change_invoice_status`, `duplicate_invoice`, `delete_invoice`, `create_invoice_item`, `update_invoice_item`, `delete_invoice_item`, `create_invoice_payment` |\n| **Webhooks**† | 4 | `create_webhook`, `update_webhook`, `delete_webhook`, `generate_webhook_token` |\n\n† **Time off**, **Holidays**, **Expenses**, **Approvals**, **Custom fields**, **Scheduling**, **Invoices**, and **Webhooks** are paid Clockify features — these tools error (HTTP 402/403/404) on plans without them.\n\n`create_expense` and `update_expense` accept an optional local receipt file, uploaded via multipart.\n\n## Quick start\n\n### 1. Install\n\n```bash\npip install clockify-mcp\n```\n\nOr run without installing (requires [uv](https://docs.astral.sh/uv/)):\n\n```bash\nuvx clockify-mcp\n```\n\nOr use the container image (published to GHCR on every release):\n\n```bash\ndocker run --rm -i -e CLOCKIFY_API_KEY=your-key ghcr.io/tracegazer/clockify-mcp:latest\n```\n\n### 2. Connect to Claude Desktop\n\nAdd this to your `claude_desktop_config.json`:\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"clockify\": {\n      \"command\": \"uvx\",\n      \"args\": [\"clockify-mcp\"],\n      \"env\": {\n        \"CLOCKIFY_API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Desktop. Ask: _\"What workspaces do I have in Clockify?\"_\n\n<details>\n<summary>Using pip install instead of uvx</summary>\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"clockify\": {\n      \"command\": \"clockify-mcp\",\n      \"env\": {\n        \"CLOCKIFY_API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary>Enabling write operations</summary>\n\nBy default the server is **read-only**. Opt into writes with `CLOCKIFY_ACCESS_MODE`:\n\n| Mode | Reads | Writes |\n|------|------------|--------|\n| `read` (default) | everything | nothing |\n| `time-tracking` | everything | time-entry writes only (log & edit hours) |\n| `full` | everything | all write tools (clients, projects, invoices, …) |\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"clockify\": {\n      \"command\": \"uvx\",\n      \"args\": [\"clockify-mcp\"],\n      \"env\": {\n        \"CLOCKIFY_API_KEY\": \"your-api-key\",\n        \"CLOCKIFY_ACCESS_MODE\": \"full\"\n      }\n    }\n  }\n}\n```\n\n> **Compatibility:** the legacy `CLOCKIFY_ENABLE_WRITES=true` still works and maps to `full`.\n> If both are set, `CLOCKIFY_ACCESS_MODE` wins. In `time-tracking` mode, `duplicate`/`bulk`\n> always act on the authenticated user; for `update`/`delete` by id the assistant is told to\n> confirm before touching an entry that may belong to someone else.\n\n> **Warning:** write mode lets the connected agent create, modify, and delete real data through\n> your Clockify credential. `delete_*` tools and `withdraw_time_off_request` are irreversible.\n\n</details>\n\n### 3. Get your API key\n\nLog into Clockify → **Profile Settings** → **API** → copy your API key.\n\n## Configuration\n\nConfiguration resolves in this order (highest priority first):\n\n1. **Environment variables** (always win)\n2. **TOML config** at `~/.config/clockify-mcp/config.toml`\n\n| Env var | TOML key | Description |\n|---------|----------|-------------|\n| `CLOCKIFY_API_KEY` | `api_key` | Your Clockify API key (required) |\n| `CLOCKIFY_REGION` | `region` | `global` (default) \\| `euc1` (EU) \\| `use2` (USA) \\| `euw2` (UK) \\| `apse2` (AU) |\n| `CLOCKIFY_BASE_URL` | `base_url` | Override for subdomain workspaces, e.g. `https://acme.clockify.me` |\n| `CLOCKIFY_DEFAULT_WORKSPACE_ID` | `default_workspace_id` | Fallback workspace when a tool call omits `workspace_id` |\n| `CLOCKIFY_ACCESS_MODE` | `access_mode` | `read` (default) \\| `time-tracking` (read + log hours) \\| `full` (all writes) |\n| `CLOCKIFY_ENABLE_WRITES` | `enable_writes` | Back-compat alias: `true` = `access_mode=full`. `CLOCKIFY_ACCESS_MODE` takes precedence. |\n| `CLOCKIFY_TELEMETRY` | `telemetry_enabled` | Enable OpenTelemetry — default `false` |\n| `CLOCKIFY_TELEMETRY_DETAIL` | `telemetry_detail` | Span detail: `metadata` (default), `ids`, or `full` |\n\n**Access modes:** `read` exposes only read tools. `time-tracking` adds the time-entry write tools (create/update/delete/duplicate/bulk) for logging hours and nothing else — `duplicate`/`bulk` always act on the authenticated user, and for `update`/`delete` by id the assistant is told to confirm before touching an entry that may belong to someone else. `full` exposes all write tools. This gates which MCP tools the server registers; it is not a replacement for the API key's own permissions.\n\nSee [`config.toml.example`](config.toml.example) for a copy-paste template.\n\n```toml\n# ~/.config/clockify-mcp/config.toml\napi_key = \"your-clockify-api-key\"\n# region = \"global\"\n# default_workspace_id = \"\"\n# access_mode = \"read\"   # read | time-tracking | full\n```\n\n> **Tip:** create the config directory first: `mkdir -p ~/.config/clockify-mcp`\n\n## Running the server\n\n```bash\nclockify-mcp                       # STDIO transport (default)\nclockify-mcp --transport sse       # SSE/HTTP transport\n```\n\n> **Security note:** STDIO (the default) keeps everything local. The `sse` and `streamable-http` transports have no built-in authentication — only use them bound to loopback or behind an authenticated reverse proxy.\n\n## Notes\n\n- **Workspace scope:** Almost every Clockify operation is scoped to a workspace (`/workspaces/{workspaceId}/...`). Tools accept an optional `workspace_id`; when omitted they fall back to `CLOCKIFY_DEFAULT_WORKSPACE_ID`. If neither is set, the tool asks you to resolve one first via `list_workspaces`.\n- **Pagination:** list tools take optional `page`/`page_size` and return one page. The high-volume lists (`list_time_entries`, `list_projects`, `list_clients`, `list_tasks`, `list_tags`, `list_users`) also accept `fetch_all=true` to follow pagination and return every page concatenated (may make several API calls).\n- **Errors:** failures carry a category — `PLAN_REQUIRED`, `ACCESS_DENIED`, or `AUTH` — so the assistant knows whether to ask you to upgrade the plan, enable a module, or fix the key. See [Paid features](#paid-features--enabling-them-in-clockify).\n\n## Paid features & enabling them in Clockify\n\nMany domains are gated by **two** independent things — both must be true for the tools to work:\n\n**1. The workspace plan must include the feature.** Otherwise the API returns `402` (or a \"subscription\" message) and the server raises `ClockifyAPIError` with category `PLAN_REQUIRED`.\n\n| Feature | Minimum plan |\n|---------|--------------|\n| Reports (detailed/summary/weekly), Shared reports | Free |\n| Webhooks | Free (up to 3) — paid for more |\n| Time off, Holidays, Invoices, Approvals | Standard |\n| Expenses (incl. expense report), Custom fields, Scheduling | Pro |\n| Attendance report | Pro (attendance/time-tracking add-on) |\n\n**2. The module must be enabled in the workspace.** Even on the right plan, an admin must turn these on in Clockify → **Workspace Settings**: **Time off, Expenses, Approval, Invoicing, Scheduling**. Until enabled, the API returns `403 \"Access Denied\"` and the server raises `ClockifyAPIError` with category `ACCESS_DENIED`. (Custom fields, webhooks, and reports need no separate toggle.)\n\nWhen an operation fails, the error category says what to do:\n\n- `PLAN_REQUIRED` — upgrade the workspace plan (Standard/Pro).\n- `ACCESS_DENIED` — enable the feature in Workspace Settings, or check the API key user's role/permission.\n- `AUTH` — the API key is missing, invalid, or revoked.\n\n## Observability (optional)\n\nThe server can emit OpenTelemetry traces, metrics, and logs — completely opt-in and vendor-neutral. Export to any OTLP-compatible backend (Dynatrace, Grafana, Datadog, Jaeger, etc.). When disabled, `opentelemetry` is never imported.\n\n```bash\npip install \"clockify-mcp[telemetry]\"\n\nexport CLOCKIFY_TELEMETRY=1\n```\n\nOTLP endpoint and headers are configured via standard OpenTelemetry env vars (not in the TOML file). `CLOCKIFY_TELEMETRY_DETAIL` controls how much argument/payload data is attached (`metadata` default → `ids` → `full`); the API key is always redacted.\n\n<details>\n<summary>Dynatrace setup</summary>\n\n```bash\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"https://<your-env>.live.dynatrace.com/api/v2/otlp\"\nexport OTEL_EXPORTER_OTLP_HEADERS=\"Authorization=Api-Token <YOUR_DT_TOKEN>\"\nexport OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta\nexport OTEL_SERVICE_NAME=clockify-mcp\n```\n\nToken scopes needed: `openTelemetryTrace.ingest`, `metrics.ingest`, `logs.ingest`. Dynatrace's OTLP metrics ingest requires **delta** temporality — without that env var, metric export fails with `400 Bad Request`.\n\n</details>\n\n<details>\n<summary>Generic OTLP collector</summary>\n\n```bash\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"http://localhost:4318\"\nexport OTEL_SERVICE_NAME=clockify-mcp\n```\n\n</details>\n\n**Signals emitted:**\n\n- **Traces** — a span per MCP tool call (`execute_tool <name>`) and per Clockify API request\n- **Metrics** — `mcp.tool.duration`, `mcp.tool.errors`, and Clockify client request durations\n- **Logs** — tool errors and unexpected API response shapes, correlated to traces (OTLP only, never stdout)\n\n## Development\n\n```bash\ngit clone https://github.com/tracegazer/clockify-mcp\ncd clockify-mcp\nuv sync --extra dev\n\nCLOCKIFY_API_KEY=dummy uv run clockify-mcp --help\nuv run pytest -q\nuv run ruff check src/ tests/\n```\n\n## License\n\n[MIT](LICENSE)\n",
  "bytes": 15523,
  "sha": "19db0cd29344be55f980b4e878a09be9d7ffb9c237a479c87ac2a90da8327bd9",
  "repo_slug": "tracegazer/clockify-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_tracegazer_clockify_mcp_59275f80/readme"
}