kimai-timelog-mcp
# kimai-timelog-mcp
[](https://github.com/Alpha101Code/kimai-timelog-mcp/actions/workflows/ci.yml)
An MCP server that lets Claude (or any MCP-capable LLM client) read and write your
Kimai timesheets. You say *"log 9 to 12:30 on the portal revamp, fixing the login
redirect"* and the entry appears in Kimai.
Every request is made as **you** — it uses your personal Kimai API token, so it can
only see and change what your Kimai account is allowed to.
---
## 1. Get a Kimai API token
1. Open Kimai → click your name (top right) → **My profile** → **API access** tab.
2. Create a token, give it a name like `claude`, and **copy it immediately** — Kimai
shows it exactly once.
## 2. Install
You need [uv](https://docs.astral.sh/uv/) (recommended) or Python 3.10+.
```bash
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
```
Then either:
**A. From a shared folder / git repo (what colleagues will do)**
```bash
uvx --from git+https://github.com/Alpha101Code/kimai-timelog-mcp kimai-mcp --check
```
**B. From a local copy**
```bash
cd /path/to/kimai-timelog-mcp
uv run kimai-mcp --check
```
`--check` verifies the URL and token and prints your visible projects. Set the two
environment variables first:
```bash
export KIMAI_URL=https://timesheet-sd.maccs.mu
export KIMAI_API_TOKEN=your-token-here
```
## 3. Wire it into your client
### Claude Desktop
Settings → Developer → **Edit Config**, then add:
```json
{
"mcpServers": {
"kimai": {
"command": "uvx",
"args": ["--from", "git+https://github.com/Alpha101Code/kimai-timelog-mcp", "kimai-mcp"],
"env": {
"KIMAI_URL": "https://timesheet-sd.maccs.mu",
"KIMAI_API_TOKEN": "your-token-here"
}
}
}
}
```
Restart Claude Desktop. On Windows use `uvx.exe` if `uvx` is not found on PATH.
### Claude Code
```bash
claude mcp add kimai \
--env KIMAI_URL=https://timesheet-sd.maccs.mu \
--env KIMAI_API_TOKEN=your-token-here \
-- uvx --from git+https://github.com/Alpha101Code/kimai-timelog-mcp kimai-mcp
```
### Cursor / Windsurf / Cline / Zed
Same JSON shape as Claude Desktop, in that client's MCP config file
(`~/.cursor/mcp.json` for Cursor).
### Anything else
It is a standard **stdio** MCP server. Command: `kimai-mcp`. Config: the two
environment variables above.
---
## Tools
| Tool | What it does |
|---|---|
| `whoami` | Who the token belongs to, their timezone, today's date |
| `list_projects` | Projects you can book against, searchable by name |
| `list_activities` | Activities valid for a project (project-specific + global) |
| `list_customers` | Customers you can see |
| `list_tags` | Tag names configured in Kimai |
| `list_timesheets` | Your entries for a date range, with totals |
| `recent_entries` | Your most recent project/activity/description combos |
| `summarize_time` | Hours totalled by project, activity or day |
| `log_time` | Write a finished entry |
| `start_timer` | Start a running entry |
| `active_timers` | What is currently running |
| `stop_timer` | Stop the running entry |
| `restart_timer` | Clone an old entry as a new running one |
| `update_timesheet` | Change an existing entry |
| `delete_timesheet` | Delete an entry (requires an explicit confirm) |
### Design choices worth knowing
- **Names, not IDs.** `project: "Portal Revamp"` works; so does a unique partial
like `"portal"`. Ambiguous names come back as an error listing the candidates,
which the model can put to you as a question.
- **Loose time input.** `date`: `today`, `yesterday`, `monday`, `3 days ago`,
`2026-08-24`, `25/08/2026`. `start`/`end`: `09:00`, `9am`, `5.30pm`, `0930`.
`duration`: `1h30m`, `90m`, `1.5h`, `1:30`.
- **Your timezone.** Kimai reports the token owner's timezone; everything is
resolved against that, not the server's clock.
- **No invented hours.** `log_time` needs start+end, start+duration, or duration —
if none is given it returns an error telling the model to ask you rather than
guessing.
- **Delete is two-step.** The first call returns what *would* be deleted; only a
second call with `confirm: true` removes it.
## Example prompts
```
Log 9:00–12:30 today on Portal Revamp, development, "fixed the login redirect".
What did I log this week? Break it down by project.
Same as yesterday afternoon, but for today.
Start a timer on Internal Tools / Admin.
I forgot Monday — 4 hours on Mobile App, release testing.
Move entry 512 to start at 10:15 instead.
```
## Rolling it out to colleagues
Everyone needs three things: `uv` installed, their own Kimai token, and the config
block above. Nothing is shared between users — no server to run, no central token.
If you later want a single hosted server instead of a per-machine install, the tool
layer stays as-is; only the transport in `__main__.py` changes.
## Security
- The token is a **password equivalent**. It lives in your client's config file on
your own machine — do not commit it, do not paste it into a shared doc.
- Give tokens an expiry date in Kimai and rotate them.
- The server talks only to `KIMAI_URL`. It has no other network access, no
filesystem access, and no shell.
- If your Kimai is internal-only, this must run on a machine that can reach it
(VPN or office network).
## Development
```
src/kimai_mcp/
client.py Kimai REST client — auth, errors, name→id resolution, caching
timeutil.py parsing for human dates, times and durations
server.py the MCP tools
__main__.py stdio entrypoint + --check
tests/
mock_kimai.py a stand-in Kimai instance
test_e2e.py drives the real server over stdio against it
```
Run the suite (no Kimai instance needed):
```bash
uv run --with mcp --with httpx python tests/test_e2e.py
```
### Compatibility
Works with both major versions of the Python MCP SDK: `mcp` 1.x (`FastMCP`) and
2.x (`MCPServer`). The server picks the right one at import time, and anticipated
failures subclass the SDK's `ToolError` so the message reaches the model instead of
a generic "error executing tool". The suite is run against both in CI.
The distribution is named `kimai-timelog-mcp` (matching the repo); the command it
installs is `kimai-mcp`.
Built against the Kimai 2 REST API (`/api`, `Authorization: Bearer <token>`).
Endpoint reference: https://www.kimai.org/documentation/rest-api.html and your own
instance's `/api/doc`.
TDQS
Scored across 15 tools
Each tool targets a distinct operation: reference data listing, timesheet queries, entry creation, timer control, editing, deletion, and reporting. Even similar tools like list_timesheets and recent_entries are clearly differentiated by what they return.
The set mostly follows a clear list_ for read-only collections and verb_noun for actions, such as log_time and stop_timer. Minor deviations like active_timers, recent_entries, and whoami break the pattern slightly but remain understandable.
At 15 tools, the server covers discovery, logging, timer lifecycle, modifications, deletion, and reporting without feeling bloated. Each tool contributes a meaningful piece of the time-logging workflow.
The toolset supports a full time-logging lifecycle: lookup reference data, check existing entries, log time, start and stop timers, restart entries, update or delete entries, and summarize hours. It also includes helpful context tools like whoami and recent_entries; admin CRUD for projects or customers is outside the apparent purpose.