clokio-mcp 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -3
- package/dist/tools/attendance.js +83 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ acting. An explicit code on a tool call always takes precedence.
|
|
|
64
64
|
Optional: set `CLOKIO_TOOLSETS` to register only the tool groups you need, e.g.
|
|
65
65
|
`CLOKIO_TOOLSETS=tasks`. This cuts the per-session tool-list cost - a
|
|
66
66
|
task-focused session drops from 98 tools to 32. Optional groups are `tasks`,
|
|
67
|
-
`employees`, `attendance` (which includes leave and time
|
|
67
|
+
`employees`, `attendance` (which includes leave, time entries and logging time), `docs` and
|
|
68
68
|
`tickets`;
|
|
69
69
|
combine them with commas. If your key cannot open documents (no acts-as
|
|
70
70
|
employee and no explicit docs scopes), leaving `docs` out saves 33 tools it
|
|
@@ -74,7 +74,7 @@ through it.
|
|
|
74
74
|
|
|
75
75
|
## Tools
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
102 tools across seven areas. Read-only tools carry the MCP `readOnlyHint`; writes
|
|
78
78
|
are marked mutating (deletes are `destructive`).
|
|
79
79
|
|
|
80
80
|
| Area | Tools |
|
|
@@ -83,7 +83,7 @@ are marked mutating (deletes are `destructive`).
|
|
|
83
83
|
| **Projects & clients** | list projects, project statuses, project custom fields, project contacts, get client, add client contact |
|
|
84
84
|
| **Reference** | task statuses, task labels, locations, list webhooks (read-only), whoami |
|
|
85
85
|
| **Employees** | list (name search), lookup by PIN, task-stats, inbox (mentions, new assignments, others' status changes), create, set status |
|
|
86
|
-
| **Attendance** | daily, range, per-employee, monthly summary, clock in/out, break start/end, time entries, leaves, leave balances |
|
|
86
|
+
| **Attendance** | daily, range, per-employee, monthly summary, clock in/out, break start/end, time entries, leaves, leave balances, **log time on a task**, start / stop / read the timer (see [Logging time](#logging-time)) |
|
|
87
87
|
| **Documents** (see [Documents](#documents) for who a key acts as) | list, tree, search, get (Markdown / HTML / JSON), create, replace content, update meta, move, archive, restore, delete, templates + create from template, members (by `employee_code`) and teams (list/add/update/remove, shareable teams), public share link, comments (list/add/resolve/reopen), versions (list/get/restore), attachments (list/upload/download) |
|
|
88
88
|
| **Tickets** (see [Tickets](#tickets)) | list (filters + cursor), get (with its newest messages; internal notes labelled, everything the customer wrote wrapped as untrusted), more messages, **reply to the customer** (fresh `Idempotency-Key` per call, `destructive`), internal note (with mentions), update state / assignee, add / remove one label, contacts list / get / update, inboxes, ticket labels, saved replies |
|
|
89
89
|
|
|
@@ -117,6 +117,28 @@ are marked mutating (deletes are `destructive`).
|
|
|
117
117
|
returns every occurrence of one series.
|
|
118
118
|
- An API key sees **public custom fields only**.
|
|
119
119
|
|
|
120
|
+
## Logging time
|
|
121
|
+
|
|
122
|
+
`clokio_log_time`, `clokio_start_timer`, `clokio_stop_timer` and
|
|
123
|
+
`clokio_get_active_timer` (0.21.0) call `/api/v1/time-entries` and
|
|
124
|
+
`/api/v1/timer/*`. The time is **always the key's acting person's** (its
|
|
125
|
+
"acts as" employee, else the person who issued it); no tool takes an
|
|
126
|
+
employee and the server refuses one.
|
|
127
|
+
|
|
128
|
+
- **Scopes:** `time_entries:write` for the three writes, `time_entries:read`
|
|
129
|
+
for the running timer. `time_entries:write` must be ticked on the key
|
|
130
|
+
explicitly: full access (`*`) never grants it.
|
|
131
|
+
- `clokio_log_time` takes `task_id` and EITHER `date` + `start` + `end`,
|
|
132
|
+
`date` + `start` + `duration_minutes`, or `duration_minutes` alone (the
|
|
133
|
+
entry then ends now). Times are local to that person. At most 12 hours per
|
|
134
|
+
entry; nothing may start or end more than 10 minutes in the future; an
|
|
135
|
+
overlap with another time entry of the same person (their running timer and
|
|
136
|
+
an overnight entry from the day before included) is refused.
|
|
137
|
+
- `clokio_start_timer` is refused while a timer runs; `force: true` stops it
|
|
138
|
+
and starts the new one. `clokio_stop_timer` is refused when nothing runs.
|
|
139
|
+
- The task must be visible to that person, on an active project of your
|
|
140
|
+
organisation; a board another organisation shared with you is refused.
|
|
141
|
+
|
|
120
142
|
## Documents
|
|
121
143
|
|
|
122
144
|
The Docs tools call `/api/v1/docs...` with the same `CLOKIO_API_KEY` as
|
package/dist/tools/attendance.js
CHANGED
|
@@ -183,6 +183,89 @@ export function registerAttendanceTools(server, config) {
|
|
|
183
183
|
},
|
|
184
184
|
}),
|
|
185
185
|
});
|
|
186
|
+
// Logging time (backend task #5775). The time is ALWAYS the key's acting
|
|
187
|
+
// person's: none of these tools takes an employee, and the server refuses
|
|
188
|
+
// one in the body. Scope time_entries:write is explicit-only ("*" never
|
|
189
|
+
// grants it).
|
|
190
|
+
const actingPerson = "The time is ALWAYS recorded for the API key's ACTING person (its \"acts as\" employee, else the person who issued it), " +
|
|
191
|
+
'never for anyone else; there is no way to log time for another employee. ' +
|
|
192
|
+
'Needs the time_entries:write scope, ticked explicitly on the key: full access ("*") does NOT grant it.';
|
|
193
|
+
const taskRule = 'The task must be one that person can view in your organisation, on an active project; a board another organisation ' +
|
|
194
|
+
'shared with you is refused (404).';
|
|
195
|
+
registerTool(server, config, {
|
|
196
|
+
name: 'clokio_log_time',
|
|
197
|
+
description: 'Log a finished time entry on a task. ' + actingPerson + ' ' +
|
|
198
|
+
'Times are local to that person (their location timezone, else UTC). Give EITHER date + start + end ' +
|
|
199
|
+
'(an end at or before start runs past midnight), OR date + start + duration_minutes, OR duration_minutes alone ' +
|
|
200
|
+
'(the entry then ENDS NOW and started that many minutes ago; date must be today or omitted). ' +
|
|
201
|
+
'At most 12 hours (720 minutes) per entry; nothing may start or end more than 10 minutes in the future; ' +
|
|
202
|
+
'an entry overlapping another time entry of the same person (including their running timer, and an overnight entry from the day before) is refused. ' +
|
|
203
|
+
'A duration counts real minutes across a DST change. ' + taskRule + ' ' +
|
|
204
|
+
"The project's billable flag is inherited and the description defaults to the task title.",
|
|
205
|
+
schema: {
|
|
206
|
+
task_id: z.number().int().positive(),
|
|
207
|
+
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'date must be YYYY-MM-DD').optional()
|
|
208
|
+
.describe('YYYY-MM-DD, the day the entry STARTS. Required with start'),
|
|
209
|
+
start: z.string().regex(/^\d{2}:\d{2}$/, 'start must be HH:MM').optional().describe('HH:MM, local time'),
|
|
210
|
+
end: z.string().regex(/^\d{2}:\d{2}$/, 'end must be HH:MM').optional()
|
|
211
|
+
.describe('HH:MM, local time. Give end OR duration_minutes, not both'),
|
|
212
|
+
duration_minutes: z.number().int().min(1).max(720).optional(),
|
|
213
|
+
description: z.string().max(255).optional(),
|
|
214
|
+
},
|
|
215
|
+
mutates: true,
|
|
216
|
+
handler: (args, cfg) => {
|
|
217
|
+
if ((args.end === undefined) === (args.duration_minutes === undefined)) {
|
|
218
|
+
throw new Error('Give exactly one of end or duration_minutes.');
|
|
219
|
+
}
|
|
220
|
+
if (args.start !== undefined && args.date === undefined) {
|
|
221
|
+
throw new Error('date is required with start.');
|
|
222
|
+
}
|
|
223
|
+
if (args.end !== undefined && args.start === undefined) {
|
|
224
|
+
throw new Error('start is required with end.');
|
|
225
|
+
}
|
|
226
|
+
return request(cfg, '/time-entries', {
|
|
227
|
+
method: 'POST',
|
|
228
|
+
body: {
|
|
229
|
+
task_id: args.task_id,
|
|
230
|
+
date: args.date,
|
|
231
|
+
start: args.start,
|
|
232
|
+
end: args.end,
|
|
233
|
+
duration_minutes: args.duration_minutes,
|
|
234
|
+
description: args.description,
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
registerTool(server, config, {
|
|
240
|
+
name: 'clokio_start_timer',
|
|
241
|
+
description: "Start a running timer on a task. " + actingPerson + ' ' + taskRule + ' ' +
|
|
242
|
+
'If a timer is already running the call is refused (409) and the running entry is returned; ' +
|
|
243
|
+
'pass force: true to stop that timer and start this one. The description defaults to the task title.',
|
|
244
|
+
schema: {
|
|
245
|
+
task_id: z.number().int().positive(),
|
|
246
|
+
description: z.string().max(255).optional(),
|
|
247
|
+
force: z.boolean().optional().describe('Stop a running timer first instead of being refused'),
|
|
248
|
+
},
|
|
249
|
+
mutates: true,
|
|
250
|
+
handler: (args, cfg) => request(cfg, '/timer/start', {
|
|
251
|
+
method: 'POST',
|
|
252
|
+
body: { task_id: args.task_id, description: args.description, force: args.force },
|
|
253
|
+
}),
|
|
254
|
+
});
|
|
255
|
+
registerTool(server, config, {
|
|
256
|
+
name: 'clokio_stop_timer',
|
|
257
|
+
description: "Stop the running timer of the API key's ACTING person (never anyone else's) and return the entry with its hours. " +
|
|
258
|
+
'Refused (409) when nothing is running. Needs time_entries:write (not granted by "*").',
|
|
259
|
+
schema: {},
|
|
260
|
+
mutates: true,
|
|
261
|
+
handler: (_args, cfg) => request(cfg, '/timer/stop', { method: 'POST' }),
|
|
262
|
+
});
|
|
263
|
+
registerTool(server, config, {
|
|
264
|
+
name: 'clokio_get_active_timer',
|
|
265
|
+
description: "The running timer of the API key's ACTING person, or entry: null when none runs. Needs time_entries:read.",
|
|
266
|
+
schema: {},
|
|
267
|
+
handler: (_args, cfg) => request(cfg, '/timer/active'),
|
|
268
|
+
});
|
|
186
269
|
registerTool(server, config, {
|
|
187
270
|
name: 'clokio_list_leaves',
|
|
188
271
|
description: 'Leave requests in a date range. from and to are both REQUIRED (YYYY-MM-DD, to >= from). ' +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clokio-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for Clokio - manage tasks, projects, clients, employees, attendance and documents from Claude and any MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|