Content
# clockodo-mcp
A local stdio MCP server for the [Clockodo](https://www.clockodo.com) time-tracking API, built with the official .NET MCP SDK.
It pairs task-focused time-tracking tools with a generated catalog of the wider REST API (from [Clockodo's OpenAPI specification](https://docs.clockodo.com/openapi.yaml)), so an AI assistant can track time safely and still reach any other endpoint when needed.
## What it can do
- Find customers, projects, and services; start and stop clocks; manage completed time entries.
- Resolve targets by name — ambiguous matches return candidates instead of writing.
- Read the current user, absences, and entries for relative or custom date ranges.
- Explore the full REST API: `clockodo_list_operations` → `clockodo_get_operation` → `clockodo_read` / `clockodo_write`.
## Setup
You need the .NET 10 SDK (macOS or Linux).
```bash
git clone git@github.com:alainkaiser/clockodo-mcp.git
cd clockodo-mcp
dotnet publish src/Clockodo.Mcp/Clockodo.Mcp.csproj -c Release -o dist
cp .env.example .env
chmod 600 .env
```
In Clockodo, open **My data**, copy your API key, and fill in `.env`:
```bash
CLOCKODO_API_USER="you@example.com" # the email you sign in with
CLOCKODO_API_KEY="your-api-key"
CLOCKODO_EXTERNAL_APPLICATION="clockodo-mcp;technical-contact@example.com"
CLOCKODO_READ_ONLY="true"
```
Good to know:
- The API key is not your password; it inherits the permissions of its Clockodo user, so use a suitably restricted user. See Clockodo's [API documentation](https://www.clockodo.com/de-ch/api/) for details.
- `CLOCKODO_EXTERNAL_APPLICATION` is Clockodo's required client identifier in the form `application-name;technical-contact-email`.
- Optional: `CLOCKODO_ACCEPT_LANGUAGE` (`en`, `de`, or `fr`; default `en`) and `CLOCKODO_BASE_URL` (default `https://my.clockodo.com/api/`).
`scripts/run-clockodo-mcp` loads `.env` and starts the server. Values supplied by an MCP client take precedence.
## Connect an MCP client
Point your client at the wrapper script so credentials stay in `.env`.
Codex, from the repository root:
```bash
codex mcp add clockodo -- "$(pwd -P)/scripts/run-clockodo-mcp"
```
Claude Desktop, Cursor, Windsurf, and other stdio clients:
```json
{
"mcpServers": {
"clockodo": {
"command": "/absolute/path/to/clockodo-mcp/scripts/run-clockodo-mcp",
"args": []
}
}
}
```
Restart the client, then call `clockodo_server_info` to confirm catalog coverage, credentials, and the read-only state.
> This is a stdio server: the MCP client starts the process and exchanges JSON-RPC messages over stdin/stdout. Running the launcher by hand will look like it hangs — it is waiting for a client.
Clockodo also offers a separate [hosted MCP server](https://www.clockodo.com/en/integrations/mcp-server/) with its own authentication and a smaller tool set; this project runs locally and exposes the wider REST API.
## Safety
- `CLOCKODO_READ_ONLY` defaults to `true` and blocks every non-GET request. Setting it to `false` enables the full write surface — including account-level changes and irreversible deletes, not just time tracking.
- Deprecated operations and the public account-registration endpoint are hidden.
- Requests are locked to `https://my.clockodo.com/api/` with redirects disabled, so credential headers cannot be forwarded to another host. Loopback HTTP stays available for local tests.
- Destructive tools are annotated as such; have your agent confirm before `clockodo_delete_time_entry`.
## Everyday use
- Prefer `clockodo_start_clock_by_name` and `clockodo_create_time_entry_by_name`; ambiguous names return candidates without changing data.
- Use `clockodo_get_entries_by_timeframe` for `today`, `yesterday`, week, month, or custom date ranges.
- For anything else, discover the operation via the catalog tools and call `clockodo_read` or `clockodo_write`.
## Development
```bash
dotnet build ClockodoMcp.slnx
dotnet test ClockodoMcp.slnx
```
CI (GitHub Actions) restores, checks `dotnet format`, builds, and tests on every push and pull request.
To refresh the generated API catalog, run `scripts/update-clockodo-catalog.rb` and rerun the tests.
The opt-in live check calls `getUsersMeV4` only:
```bash
set -a; . ./.env; set +a
CLOCKODO_LIVE_TEST=1 dotnet test ClockodoMcp.slnx
```