@io_zlu/clockify-mcp
v1.0.0
Published
MCP server for managing Clockify time entries (create, list, edit, delete).
Maintainers
Readme
Clockify MCP
An MCP (Model Context Protocol) server for managing Clockify time entries. An MCP client (Claude Desktop, Claude Code, etc.) can create, review, edit, and delete time entries directly by talking to the Clockify REST API, no web app needed.
It exposes six tools.
Writing entries:
create_time_entry: creates a single billable time entry for a given date and start/end time.fill_standard_workdays: fills the standard three daily entries (07:00-11:00, 11:00-12:00, 12:00-16:00) for a list of dates, or for every weekday in a date range.update_time_entry: changes an existing entry's times, date, project, task, or description.delete_time_entry: deletes one entry on a date, or every entry on that date.
Reading entries:
list_time_entries: lists the entries in a date range with project and task names, per-day subtotals, and a grand total.check_logged_hours: reports hours logged per weekday in a date range and flags days below the expected daily total.
Workspaces, projects, and tasks are always given by name, not by id. If a name is missing or matches more than one of them, the tool returns the list of candidate options instead of changing anything, so you can call it again with a more specific name.
The two editing tools identify an entry by its date and its local start time (HH:MM), the values you can see in Clockify. If that pair does not match exactly one entry, the tool prints the entries on that day and makes no change. Run list_time_entries first to see what you are about to edit.
Environment variables
API_KEY(required): your Clockify API key.CLOCKIFY_TZ(optional): the timezone used to interpret thedate/start/endvalues, for exampleEurope/Istanbul. If not set, it defaults to the system's local timezone.
Copy .env.example to .env and fill it in, or pass these via your MCP client's env block (see below).
Install
You do not need to clone or build anything. The server is published to npm and runs with npx, which downloads and starts it on demand. Point your MCP client at npx -y @io_zlu/clockify-mcp and give it your Clockify API key in the env block.
Get your API key from Clockify: Profile Settings -> API.
Claude Code
One command registers it for every project (--scope user):
claude mcp add clockify \
--scope user \
--env API_KEY=your-clockify-key \
--env CLOCKIFY_TZ=Europe/Istanbul \
-- npx -y @io_zlu/clockify-mcpDrop --scope user to register it only for the current project (the default local scope).
Other MCP clients
Add an entry like this to your MCP client's configuration:
{
"mcpServers": {
"clockify": {
"command": "npx",
"args": ["-y", "@io_zlu/clockify-mcp"],
"env": { "API_KEY": "your-clockify-key", "CLOCKIFY_TZ": "Europe/Istanbul" }
}
}
}Installing with an AI agent
You can ask your coding agent to do the whole thing: "read the @io_zlu/clockify-mcp GitHub repo and install it." The agent should ask you for your Clockify API key, then register the server with the Claude Code command (or the JSON block) above, using npx -y @io_zlu/clockify-mcp as the command. No clone or build step is involved.
From source (development)
Only needed if you want to change the server itself.
git clone https://github.com/izerozlu/clockify-mcp.git
cd clockify-mcp
npm install
npm run build # compiles src/ to dist/server.js
npm start # runs node dist/server.js over stdioTo register a local build instead of the npm package, point the client at the built file with an absolute path, for example -- node "$(pwd)/dist/server.js".
Tool reference
Every tool takes an optional workspace (workspace name, resolved to an id internally) and
returns an error message rather than a partial write when API_KEY is not set.
create_time_entry
| Field | Required | Description |
| ------------- | -------- | -------------------------------------------------- |
| date | yes | Day of the entry, YYYY-MM-DD |
| start | yes | Start time, HH:MM (interpreted in CLOCKIFY_TZ) |
| end | yes | End time, HH:MM |
| description | no | Entry description (default empty) |
| project | no | Project name (resolved to id internally) |
| task | no | Task name within that project |
| workspace | no | Workspace name (resolved to id internally) |
fill_standard_workdays
| Field | Required | Description |
| ------------- | -------- | ------------------------------------------------ |
| startDate | no* | Start of range, YYYY-MM-DD |
| endDate | no | End of range, YYYY-MM-DD (default today) |
| dates | no* | Explicit list of YYYY-MM-DD dates (used as-is) |
| description | no | Description applied to each entry |
| project | no | Project name |
| workspace | no | Workspace name |
*Provide either startDate (a range, expanded to weekdays only) or dates.
update_time_entry
Fields you do not pass keep their current value. Passing project without task clears the
entry's task, because a task belongs to one project. Entries with no project, and entries that
are still running (no end time), are rejected unless you supply project or newEnd.
| Field | Required | Description |
| ------------- | -------- | -------------------------------------------------- |
| date | yes | Date the entry currently falls on, YYYY-MM-DD |
| start | yes | Current start time, HH:MM, identifying the entry |
| newStart | no | New start time, HH:MM |
| newEnd | no | New end time, HH:MM |
| newDate | no | Move the entry to this date, YYYY-MM-DD |
| description | no | New description |
| project | no | Move the entry to this project (by name) |
| task | no | Move the entry to this task in the target project |
| workspace | no | Workspace name |
delete_time_entry
| Field | Required | Description |
| ----------- | -------- | ----------------------------------------------- |
| date | yes | Date of the entry to delete, YYYY-MM-DD |
| start | no | Start time, HH:MM, of the one entry to delete |
| workspace | no | Workspace name |
Omitting start deletes every entry on that date. This is meant for clearing a day before
refilling it, and it cannot be undone.
list_time_entries
Read-only. Groups entries by local date and shows time range, duration, project name, task
name, and description. Still-running entries are listed as (running) and left out of totals.
| Field | Required | Description |
| ----------- | -------- | ---------------------------------------------------------- |
| startDate | no* | Range start, YYYY-MM-DD. Takes precedence over period. |
| period | no* | month or week, starting the current month or Monday |
| endDate | no | Range end, YYYY-MM-DD (default today) |
| workspace | no | Workspace name |
*Provide either startDate or period.
check_logged_hours
Read-only. Skips weekends and counts only completed entries.
| Field | Required | Description |
| --------------- | -------- | ---------------------------------------------------------- |
| startDate | no* | Range start, YYYY-MM-DD. Takes precedence over period. |
| period | no* | month or week, starting the current month or Monday |
| endDate | no | Range end, YYYY-MM-DD (default today) |
| expectedHours | no | Expected logged hours per weekday (default 8) |
| workspace | no | Workspace name |
*Provide either startDate or period.
