Clockify MCP Server
by Roms504318
README.md
# Clockify MCP Server
A **scoped** Clockify MCP server for `mcp.sco-mo.com`. Exposes a fixed read/write
tool set plus a **code-defined structure scaffold** that replaces Clockify's
paid-gated project templates. The structure lives as code (`lib/structure.ts`) —
a single source of truth that's editable, re-runnable, and version-controlled.
> **v0.1 DRAFT.** The `STRUCTURE` config is a draft pending Oel's Excel
> reconciliation. The mechanism is built; **do not run `scaffoldStructure`
> against the live workspace yet** (see [Build sequence](#build-sequence)).
---
## Stack
- **Next.js App Router** route handler + [`mcp-handler`](https://www.npmjs.com/package/mcp-handler) (Vercel adapter)
- Pipeline: **GitHub → Vercel → Cloudflare**, custom domain `mcp.sco-mo.com`
- Clockify base API: `https://api.clockify.me/api/v1`
MCP endpoint (streamable-http): `https://mcp.sco-mo.com/api/mcp`
Health probe (open): `https://mcp.sco-mo.com/api/health`
---
## Environment variables
Set these in the **Vercel dashboard** (never in code, never committed):
| Var | Value | Notes |
| --- | --- | --- |
| `CLOCKIFY_API_KEY` | the raw `NDQ…` key | Sent as `X-Api-Key`. Never logged. |
| `CLOCKIFY_WORKSPACE_ID` | `69476cbc9bfb39506eedab0a` | Fixed target workspace. |
| `MCP_BEARER_TOKEN` | a strong random token | Guards the endpoint. Clients send `Authorization: Bearer <token>`. |
`.env` is git-ignored. Copy `.env.example` → `.env.local` for local dev.
If `MCP_BEARER_TOKEN` is unset the endpoint **fails closed** (401), never open.
---
## Tools — the complete scoped set (do not add to this)
**Read** — `getCurrentUser`, `listUsers`, `listTimeEntries`, `getTimeEntry`,
`listProjects`, `listClients`, `listTasks`, `listTags`
**Write** — `upsertTimeEntry`, `upsertProject`, `upsertClient`, `upsertTask`,
`upsertTag`, `archiveProject`, `archiveClient`, `deleteProject` (gated),
`deleteClient` (gated), `scaffoldStructure`, `newProjectFromShape`
### Delete discipline (the one irreversible surface)
- Clockify enforces **archive-before-delete**. `deleteProject` / `deleteClient`
verify the target is archived and refuse otherwise.
- Both require an explicit `confirm: true` argument (typed as `literal(true)`),
and are **never** called by an unattended agent — the review gate.
- Deleting a project removes it from time entries but leaves the underlying time
data intact.
### `scaffoldStructure`
Idempotent, additive-only reconcile of the workspace toward `STRUCTURE`:
creates any missing client/project/task/tag, skips what exists, never deletes.
**`dryRun` defaults to `true`** — it returns the plan without writing. Pass
`dryRun: false` to apply. Idempotency is by name.
### `newProjectFromShape`
The template replacement. Instantiates a project + its standard task list from a
shape in `STRUCTURE.shapes` (e.g. `matter`). Creates the client if a `clientName`
is given and missing.
---
## Local development
```bash
npm install
cp .env.example .env.local # fill in the three vars
npm run dev # http://localhost:3000/api/mcp
npm run typecheck
```
Smoke-test the endpoint (expects 401 without the token):
```bash
curl -s http://localhost:3000/api/health
```
---
## Deploy
1. Push to GitHub; import into Vercel (framework auto-detected as Next.js).
2. Add the three environment variables in Vercel → Settings → Environment Variables.
3. Add the domain `mcp.sco-mo.com` (Vercel → Domains); point Cloudflare DNS per
the existing pipeline.
4. Redeploy. Verify `GET /api/health` returns `config` all `true`.
---
## Build sequence
1. ✅ **Now:** server, scoped tool set, delete gate, and
`scaffoldStructure` / `newProjectFromShape` built and deployed.
2. ⛔ **Do not** run `scaffoldStructure` with `dryRun:false` against the live
workspace yet.
3. Oel sends the Excel of the existing structure. Reconcile `lib/structure.ts`
against it — Scottmoore project granularity, kill dead old-company projects,
confirm the Personal breakdown.
4. **Then** run `scaffoldStructure` to build/adjust the live workspace, and
archive/delete old-company remnants (delete gated, one `confirm` each).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues