@studiometa/productive-mcp 0.8.1 → 0.8.3
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/dist/handlers/bookings.d.ts.map +1 -1
- package/dist/handlers/comments.d.ts.map +1 -1
- package/dist/handlers/companies.d.ts.map +1 -1
- package/dist/handlers/deals.d.ts.map +1 -1
- package/dist/handlers/help.d.ts.map +1 -1
- package/dist/handlers/index.d.ts.map +1 -1
- package/dist/handlers/people.d.ts.map +1 -1
- package/dist/handlers/projects.d.ts.map +1 -1
- package/dist/handlers/tasks.d.ts.map +1 -1
- package/dist/handlers/time.d.ts.map +1 -1
- package/dist/handlers/timers.d.ts.map +1 -1
- package/dist/handlers/types.d.ts +2 -0
- package/dist/handlers/types.d.ts.map +1 -1
- package/dist/handlers.js +1 -1
- package/dist/hints.d.ts +60 -0
- package/dist/hints.d.ts.map +1 -0
- package/dist/http.js +2 -2
- package/dist/{index-D743zTS1.js → index-CZpVCEu4.js} +528 -24
- package/dist/index-CZpVCEu4.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/schema.d.ts +23 -18
- package/dist/schema.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/stdio.js +1 -1
- package/dist/{version-C5cU9Q70.js → version-TuExzSYT.js} +2 -2
- package/dist/{version-C5cU9Q70.js.map → version-TuExzSYT.js.map} +1 -1
- package/package.json +6 -6
- package/skills/SKILL.md +165 -2
- package/dist/index-D743zTS1.js.map +0 -1
|
@@ -190,6 +190,364 @@ function formatListResponse(data, formatter, meta, options) {
|
|
|
190
190
|
});
|
|
191
191
|
return result;
|
|
192
192
|
}
|
|
193
|
+
function getTaskHints(taskId, serviceId) {
|
|
194
|
+
const hints = {
|
|
195
|
+
related_resources: [
|
|
196
|
+
{
|
|
197
|
+
resource: "comments",
|
|
198
|
+
description: "Get comments on this task",
|
|
199
|
+
example: {
|
|
200
|
+
resource: "comments",
|
|
201
|
+
action: "list",
|
|
202
|
+
filter: { task_id: taskId }
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
resource: "time",
|
|
207
|
+
description: "Get time entries logged on this task",
|
|
208
|
+
example: {
|
|
209
|
+
resource: "time",
|
|
210
|
+
action: "list",
|
|
211
|
+
filter: { task_id: taskId }
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
resource: "tasks",
|
|
216
|
+
description: "Get subtasks of this task",
|
|
217
|
+
example: {
|
|
218
|
+
resource: "tasks",
|
|
219
|
+
action: "list",
|
|
220
|
+
filter: { parent_task_id: taskId }
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
],
|
|
224
|
+
common_actions: [
|
|
225
|
+
{
|
|
226
|
+
action: "Add a comment",
|
|
227
|
+
example: {
|
|
228
|
+
resource: "comments",
|
|
229
|
+
action: "create",
|
|
230
|
+
task_id: taskId,
|
|
231
|
+
body: "<your comment>"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
};
|
|
236
|
+
if (serviceId) {
|
|
237
|
+
hints.common_actions.push({
|
|
238
|
+
action: "Log time on this task",
|
|
239
|
+
example: {
|
|
240
|
+
resource: "time",
|
|
241
|
+
action: "create",
|
|
242
|
+
service_id: serviceId,
|
|
243
|
+
task_id: taskId,
|
|
244
|
+
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
245
|
+
time: 60,
|
|
246
|
+
note: "<description of work>"
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return hints;
|
|
251
|
+
}
|
|
252
|
+
function getProjectHints(projectId) {
|
|
253
|
+
return {
|
|
254
|
+
related_resources: [
|
|
255
|
+
{
|
|
256
|
+
resource: "tasks",
|
|
257
|
+
description: "Get tasks in this project",
|
|
258
|
+
example: {
|
|
259
|
+
resource: "tasks",
|
|
260
|
+
action: "list",
|
|
261
|
+
filter: { project_id: projectId }
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
resource: "services",
|
|
266
|
+
description: "Get services (budget lines) for this project",
|
|
267
|
+
example: {
|
|
268
|
+
resource: "services",
|
|
269
|
+
action: "list",
|
|
270
|
+
filter: { project_id: projectId }
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
resource: "time",
|
|
275
|
+
description: "Get time entries for this project",
|
|
276
|
+
example: {
|
|
277
|
+
resource: "time",
|
|
278
|
+
action: "list",
|
|
279
|
+
filter: { project_id: projectId }
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
resource: "comments",
|
|
284
|
+
description: "Get comments on this project",
|
|
285
|
+
example: {
|
|
286
|
+
resource: "comments",
|
|
287
|
+
action: "list",
|
|
288
|
+
filter: { project_id: projectId }
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
resource: "deals",
|
|
293
|
+
description: "Get deals/budgets for this project",
|
|
294
|
+
example: {
|
|
295
|
+
resource: "deals",
|
|
296
|
+
action: "list",
|
|
297
|
+
filter: { project_id: projectId }
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
],
|
|
301
|
+
common_actions: [
|
|
302
|
+
{
|
|
303
|
+
action: "Create a task",
|
|
304
|
+
example: {
|
|
305
|
+
resource: "tasks",
|
|
306
|
+
action: "create",
|
|
307
|
+
project_id: projectId,
|
|
308
|
+
task_list_id: "<task_list_id>",
|
|
309
|
+
title: "<task title>"
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function getDealHints(dealId) {
|
|
316
|
+
return {
|
|
317
|
+
related_resources: [
|
|
318
|
+
{
|
|
319
|
+
resource: "comments",
|
|
320
|
+
description: "Get comments on this deal/budget",
|
|
321
|
+
example: {
|
|
322
|
+
resource: "comments",
|
|
323
|
+
action: "list",
|
|
324
|
+
filter: { deal_id: dealId }
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
resource: "services",
|
|
329
|
+
description: "Get services (budget lines) for this deal",
|
|
330
|
+
example: {
|
|
331
|
+
resource: "services",
|
|
332
|
+
action: "list",
|
|
333
|
+
filter: { deal_id: dealId }
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
resource: "time",
|
|
338
|
+
description: "Get time entries for this deal/budget",
|
|
339
|
+
example: {
|
|
340
|
+
resource: "time",
|
|
341
|
+
action: "list",
|
|
342
|
+
filter: { deal_id: dealId }
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
resource: "bookings",
|
|
347
|
+
description: "Get resource bookings for this deal",
|
|
348
|
+
example: {
|
|
349
|
+
resource: "bookings",
|
|
350
|
+
action: "list",
|
|
351
|
+
filter: { deal_id: dealId }
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
],
|
|
355
|
+
common_actions: [
|
|
356
|
+
{
|
|
357
|
+
action: "Add a comment",
|
|
358
|
+
example: {
|
|
359
|
+
resource: "comments",
|
|
360
|
+
action: "create",
|
|
361
|
+
deal_id: dealId,
|
|
362
|
+
body: "<your comment>"
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function getPersonHints(personId) {
|
|
369
|
+
return {
|
|
370
|
+
related_resources: [
|
|
371
|
+
{
|
|
372
|
+
resource: "tasks",
|
|
373
|
+
description: "Get tasks assigned to this person",
|
|
374
|
+
example: {
|
|
375
|
+
resource: "tasks",
|
|
376
|
+
action: "list",
|
|
377
|
+
filter: { assignee_id: personId }
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
resource: "time",
|
|
382
|
+
description: "Get time entries by this person",
|
|
383
|
+
example: {
|
|
384
|
+
resource: "time",
|
|
385
|
+
action: "list",
|
|
386
|
+
filter: { person_id: personId }
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
resource: "bookings",
|
|
391
|
+
description: "Get bookings for this person",
|
|
392
|
+
example: {
|
|
393
|
+
resource: "bookings",
|
|
394
|
+
action: "list",
|
|
395
|
+
filter: { person_id: personId }
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
resource: "timers",
|
|
400
|
+
description: "Get active timers for this person",
|
|
401
|
+
example: {
|
|
402
|
+
resource: "timers",
|
|
403
|
+
action: "list",
|
|
404
|
+
filter: { person_id: personId }
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function getCompanyHints(companyId) {
|
|
411
|
+
return {
|
|
412
|
+
related_resources: [
|
|
413
|
+
{
|
|
414
|
+
resource: "projects",
|
|
415
|
+
description: "Get projects for this company",
|
|
416
|
+
example: {
|
|
417
|
+
resource: "projects",
|
|
418
|
+
action: "list",
|
|
419
|
+
filter: { company_id: companyId }
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
resource: "deals",
|
|
424
|
+
description: "Get deals for this company",
|
|
425
|
+
example: {
|
|
426
|
+
resource: "deals",
|
|
427
|
+
action: "list",
|
|
428
|
+
filter: { company_id: companyId }
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
resource: "tasks",
|
|
433
|
+
description: "Get tasks for this company",
|
|
434
|
+
example: {
|
|
435
|
+
resource: "tasks",
|
|
436
|
+
action: "list",
|
|
437
|
+
filter: { company_id: companyId }
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
resource: "people",
|
|
442
|
+
description: "Get contacts at this company",
|
|
443
|
+
example: {
|
|
444
|
+
resource: "people",
|
|
445
|
+
action: "list",
|
|
446
|
+
filter: { company_id: companyId }
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
]
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function getTimeEntryHints(timeEntryId, taskId, serviceId) {
|
|
453
|
+
const hints = {
|
|
454
|
+
related_resources: [],
|
|
455
|
+
common_actions: [
|
|
456
|
+
{
|
|
457
|
+
action: "Update this time entry",
|
|
458
|
+
example: {
|
|
459
|
+
resource: "time",
|
|
460
|
+
action: "update",
|
|
461
|
+
id: timeEntryId,
|
|
462
|
+
time: 120,
|
|
463
|
+
note: "<updated note>"
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
]
|
|
467
|
+
};
|
|
468
|
+
if (serviceId) {
|
|
469
|
+
hints.related_resources.push({
|
|
470
|
+
resource: "services",
|
|
471
|
+
description: "Get the associated service",
|
|
472
|
+
example: {
|
|
473
|
+
resource: "services",
|
|
474
|
+
action: "get",
|
|
475
|
+
id: serviceId
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
return hints;
|
|
480
|
+
}
|
|
481
|
+
function getCommentHints(_commentId, commentableType, commentableId) {
|
|
482
|
+
const hints = {
|
|
483
|
+
related_resources: []
|
|
484
|
+
};
|
|
485
|
+
if (commentableType && commentableId) {
|
|
486
|
+
const resourceMap = {
|
|
487
|
+
task: "tasks",
|
|
488
|
+
deal: "deals",
|
|
489
|
+
project: "projects",
|
|
490
|
+
company: "companies"
|
|
491
|
+
};
|
|
492
|
+
const resource = resourceMap[commentableType];
|
|
493
|
+
if (resource) {
|
|
494
|
+
hints.related_resources.push({
|
|
495
|
+
resource,
|
|
496
|
+
description: `Get the ${commentableType} this comment is on`,
|
|
497
|
+
example: {
|
|
498
|
+
resource,
|
|
499
|
+
action: "get",
|
|
500
|
+
id: commentableId
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return hints;
|
|
506
|
+
}
|
|
507
|
+
function getBookingHints(bookingId, personId) {
|
|
508
|
+
const hints = {
|
|
509
|
+
related_resources: [],
|
|
510
|
+
common_actions: [
|
|
511
|
+
{
|
|
512
|
+
action: "Update this booking",
|
|
513
|
+
example: {
|
|
514
|
+
resource: "bookings",
|
|
515
|
+
action: "update",
|
|
516
|
+
id: bookingId,
|
|
517
|
+
time: 480
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
]
|
|
521
|
+
};
|
|
522
|
+
if (personId) {
|
|
523
|
+
hints.related_resources.push({
|
|
524
|
+
resource: "people",
|
|
525
|
+
description: "Get the person this booking is for",
|
|
526
|
+
example: {
|
|
527
|
+
resource: "people",
|
|
528
|
+
action: "get",
|
|
529
|
+
id: personId
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
return hints;
|
|
534
|
+
}
|
|
535
|
+
function getTimerHints(timerId, serviceId) {
|
|
536
|
+
const hints = {
|
|
537
|
+
common_actions: [
|
|
538
|
+
{
|
|
539
|
+
action: "Stop this timer",
|
|
540
|
+
example: {
|
|
541
|
+
resource: "timers",
|
|
542
|
+
action: "stop",
|
|
543
|
+
id: timerId
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
],
|
|
547
|
+
related_resources: []
|
|
548
|
+
};
|
|
549
|
+
return hints;
|
|
550
|
+
}
|
|
193
551
|
function jsonResult(data) {
|
|
194
552
|
return {
|
|
195
553
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
@@ -233,7 +591,18 @@ async function handleBookings(action, args, ctx) {
|
|
|
233
591
|
if (action === "get") {
|
|
234
592
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
235
593
|
const result = await api.getBooking(id, { include });
|
|
236
|
-
|
|
594
|
+
const formatted = formatBooking(result.data, {
|
|
595
|
+
...formatOptions,
|
|
596
|
+
included: result.included
|
|
597
|
+
});
|
|
598
|
+
if (ctx.includeHints !== false) {
|
|
599
|
+
const personId = result.data.relationships?.person?.data?.id;
|
|
600
|
+
return jsonResult({
|
|
601
|
+
...formatted,
|
|
602
|
+
_hints: getBookingHints(id, personId)
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
return jsonResult(formatted);
|
|
237
606
|
}
|
|
238
607
|
if (action === "create") {
|
|
239
608
|
if (!person_id || !started_on || !ended_on) {
|
|
@@ -285,7 +654,26 @@ async function handleComments(action, args, ctx) {
|
|
|
285
654
|
if (action === "get") {
|
|
286
655
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
287
656
|
const result = await api.getComment(id, { include });
|
|
288
|
-
|
|
657
|
+
const formatted = formatComment(result.data, {
|
|
658
|
+
...formatOptions,
|
|
659
|
+
included: result.included
|
|
660
|
+
});
|
|
661
|
+
if (ctx.includeHints !== false) {
|
|
662
|
+
const commentableType = result.data.attributes?.commentable_type;
|
|
663
|
+
let commentableId;
|
|
664
|
+
if (commentableType === "task") {
|
|
665
|
+
commentableId = result.data.relationships?.task?.data?.id;
|
|
666
|
+
} else if (commentableType === "deal") {
|
|
667
|
+
commentableId = result.data.relationships?.deal?.data?.id;
|
|
668
|
+
} else if (commentableType === "company") {
|
|
669
|
+
commentableId = result.data.relationships?.company?.data?.id;
|
|
670
|
+
}
|
|
671
|
+
return jsonResult({
|
|
672
|
+
...formatted,
|
|
673
|
+
_hints: getCommentHints(id, commentableType, commentableId)
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
return jsonResult(formatted);
|
|
289
677
|
}
|
|
290
678
|
if (action === "create") {
|
|
291
679
|
if (!body) return inputErrorResult(ErrorMessages.missingRequiredFields("comment", ["body"]));
|
|
@@ -325,7 +713,14 @@ async function handleCompanies(action, args, ctx) {
|
|
|
325
713
|
if (action === "get") {
|
|
326
714
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
327
715
|
const result = await api.getCompany(id);
|
|
328
|
-
|
|
716
|
+
const formatted = formatCompany(result.data, formatOptions);
|
|
717
|
+
if (ctx.includeHints !== false) {
|
|
718
|
+
return jsonResult({
|
|
719
|
+
...formatted,
|
|
720
|
+
_hints: getCompanyHints(id)
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
return jsonResult(formatted);
|
|
329
724
|
}
|
|
330
725
|
if (action === "create") {
|
|
331
726
|
if (!name) return inputErrorResult(ErrorMessages.missingRequiredFields("company", ["name"]));
|
|
@@ -355,7 +750,14 @@ async function handleDeals(action, args, ctx) {
|
|
|
355
750
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
356
751
|
const include = userInclude?.length ? [.../* @__PURE__ */ new Set([...DEFAULT_DEAL_INCLUDE_GET, ...userInclude])] : DEFAULT_DEAL_INCLUDE_GET;
|
|
357
752
|
const result = await api.getDeal(id, { include });
|
|
358
|
-
|
|
753
|
+
const formatted = formatDeal(result.data, { ...formatOptions, included: result.included });
|
|
754
|
+
if (ctx.includeHints !== false) {
|
|
755
|
+
return jsonResult({
|
|
756
|
+
...formatted,
|
|
757
|
+
_hints: getDealHints(id)
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
return jsonResult(formatted);
|
|
359
761
|
}
|
|
360
762
|
if (action === "create") {
|
|
361
763
|
if (!name || !company_id) {
|
|
@@ -397,9 +799,11 @@ const RESOURCE_HELP = {
|
|
|
397
799
|
},
|
|
398
800
|
filters: {
|
|
399
801
|
query: "Text search on project name",
|
|
400
|
-
|
|
802
|
+
project_type: "Filter by project type: 1=internal, 2=client",
|
|
401
803
|
company_id: "Filter by company",
|
|
402
|
-
|
|
804
|
+
responsible_id: "Filter by project manager",
|
|
805
|
+
person_id: "Filter by team member",
|
|
806
|
+
status: "Filter by status: 1=active, 2=archived"
|
|
403
807
|
},
|
|
404
808
|
fields: {
|
|
405
809
|
id: "Unique project identifier",
|
|
@@ -434,9 +838,18 @@ const RESOURCE_HELP = {
|
|
|
434
838
|
filters: {
|
|
435
839
|
query: "Text search on task title",
|
|
436
840
|
project_id: "Filter by project",
|
|
841
|
+
company_id: "Filter by company",
|
|
437
842
|
assignee_id: "Filter by assigned person",
|
|
438
|
-
|
|
439
|
-
|
|
843
|
+
creator_id: "Filter by task creator",
|
|
844
|
+
status: 'Filter by status: 1=open, 2=closed (or "open", "closed", "all")',
|
|
845
|
+
task_list_id: "Filter by task list",
|
|
846
|
+
board_id: "Filter by board",
|
|
847
|
+
workflow_status_id: "Filter by workflow status (kanban column)",
|
|
848
|
+
parent_task_id: "Filter by parent task (for subtasks)",
|
|
849
|
+
overdue_status: "Filter by overdue: 1=not overdue, 2=overdue",
|
|
850
|
+
due_date_on: "Filter by exact due date (YYYY-MM-DD)",
|
|
851
|
+
due_date_before: "Filter by due date before (YYYY-MM-DD)",
|
|
852
|
+
due_date_after: "Filter by due date after (YYYY-MM-DD)"
|
|
440
853
|
},
|
|
441
854
|
includes: [
|
|
442
855
|
"project",
|
|
@@ -501,11 +914,18 @@ const RESOURCE_HELP = {
|
|
|
501
914
|
update: "Update an existing time entry"
|
|
502
915
|
},
|
|
503
916
|
filters: {
|
|
504
|
-
person_id:
|
|
917
|
+
person_id: 'Filter by person (use "me" for current user)',
|
|
505
918
|
service_id: "Filter by service",
|
|
506
919
|
project_id: "Filter by project",
|
|
920
|
+
task_id: "Filter by task",
|
|
921
|
+
company_id: "Filter by company",
|
|
922
|
+
deal_id: "Filter by deal",
|
|
923
|
+
budget_id: "Filter by budget",
|
|
507
924
|
after: "Filter entries after date (YYYY-MM-DD)",
|
|
508
|
-
before: "Filter entries before date (YYYY-MM-DD)"
|
|
925
|
+
before: "Filter entries before date (YYYY-MM-DD)",
|
|
926
|
+
status: "Filter by approval status: 1=approved, 2=unapproved, 3=rejected",
|
|
927
|
+
billing_type_id: "Filter by billing type: 1=fixed, 2=actuals, 3=non_billable",
|
|
928
|
+
invoicing_status: "Filter by invoicing: 1=not_invoiced, 2=drafted, 3=finalized"
|
|
509
929
|
},
|
|
510
930
|
fields: {
|
|
511
931
|
id: "Unique time entry identifier",
|
|
@@ -545,7 +965,12 @@ const RESOURCE_HELP = {
|
|
|
545
965
|
},
|
|
546
966
|
filters: {
|
|
547
967
|
project_id: "Filter by project",
|
|
548
|
-
deal_id: "Filter by deal"
|
|
968
|
+
deal_id: "Filter by deal",
|
|
969
|
+
task_id: "Filter by task",
|
|
970
|
+
person_id: "Filter by person (trackable by)",
|
|
971
|
+
budget_status: "Filter by budget status: 1=open, 2=delivered",
|
|
972
|
+
billing_type: "Filter by billing type: 1=fixed, 2=actuals, 3=none",
|
|
973
|
+
time_tracking_enabled: "Filter by time tracking: true/false"
|
|
549
974
|
},
|
|
550
975
|
fields: {
|
|
551
976
|
id: "Unique service identifier",
|
|
@@ -569,7 +994,12 @@ const RESOURCE_HELP = {
|
|
|
569
994
|
},
|
|
570
995
|
filters: {
|
|
571
996
|
query: "Text search on name or email",
|
|
572
|
-
status: "Filter by status
|
|
997
|
+
status: "Filter by status: 1=active, 2=deactivated",
|
|
998
|
+
person_type: "Filter by type: 1=user, 2=contact, 3=placeholder",
|
|
999
|
+
company_id: "Filter by company",
|
|
1000
|
+
project_id: "Filter by project",
|
|
1001
|
+
role_id: "Filter by role",
|
|
1002
|
+
team: "Filter by team name"
|
|
573
1003
|
},
|
|
574
1004
|
fields: {
|
|
575
1005
|
id: "Unique person identifier",
|
|
@@ -632,7 +1062,10 @@ const RESOURCE_HELP = {
|
|
|
632
1062
|
},
|
|
633
1063
|
filters: {
|
|
634
1064
|
task_id: "Filter by task",
|
|
635
|
-
deal_id: "Filter by deal"
|
|
1065
|
+
deal_id: "Filter by deal",
|
|
1066
|
+
project_id: "Filter by project",
|
|
1067
|
+
page_id: "Filter by page",
|
|
1068
|
+
discussion_id: "Filter by discussion"
|
|
636
1069
|
},
|
|
637
1070
|
includes: ["creator", "task", "deal"],
|
|
638
1071
|
fields: {
|
|
@@ -659,6 +1092,10 @@ const RESOURCE_HELP = {
|
|
|
659
1092
|
start: "Start a new timer (requires service_id or time_entry_id)",
|
|
660
1093
|
stop: "Stop an active timer by ID"
|
|
661
1094
|
},
|
|
1095
|
+
filters: {
|
|
1096
|
+
person_id: "Filter by person",
|
|
1097
|
+
time_entry_id: "Filter by time entry"
|
|
1098
|
+
},
|
|
662
1099
|
fields: {
|
|
663
1100
|
id: "Unique timer identifier",
|
|
664
1101
|
started_at: "When the timer started (ISO 8601)",
|
|
@@ -684,7 +1121,12 @@ const RESOURCE_HELP = {
|
|
|
684
1121
|
filters: {
|
|
685
1122
|
query: "Text search on deal name",
|
|
686
1123
|
company_id: "Filter by company",
|
|
687
|
-
|
|
1124
|
+
project_id: "Filter by project",
|
|
1125
|
+
responsible_id: "Filter by responsible person",
|
|
1126
|
+
pipeline_id: "Filter by pipeline",
|
|
1127
|
+
stage_status_id: "Filter by stage: 1=open, 2=won, 3=lost",
|
|
1128
|
+
type: "Filter by type: 1=deal, 2=budget",
|
|
1129
|
+
budget_status: "Filter by budget status: 1=open, 2=closed"
|
|
688
1130
|
},
|
|
689
1131
|
includes: ["company", "deal_status", "responsible", "project"],
|
|
690
1132
|
fields: {
|
|
@@ -716,8 +1158,13 @@ const RESOURCE_HELP = {
|
|
|
716
1158
|
filters: {
|
|
717
1159
|
person_id: "Filter by person",
|
|
718
1160
|
service_id: "Filter by service",
|
|
1161
|
+
project_id: "Filter by project",
|
|
1162
|
+
company_id: "Filter by company",
|
|
1163
|
+
event_id: "Filter by event",
|
|
719
1164
|
after: "Filter bookings after date (YYYY-MM-DD)",
|
|
720
|
-
before: "Filter bookings before date (YYYY-MM-DD)"
|
|
1165
|
+
before: "Filter bookings before date (YYYY-MM-DD)",
|
|
1166
|
+
booking_type: "Filter by type: event (absence) or service (budget)",
|
|
1167
|
+
draft: "Filter by tentative status: true/false"
|
|
721
1168
|
},
|
|
722
1169
|
includes: ["person", "service", "event"],
|
|
723
1170
|
fields: {
|
|
@@ -808,12 +1255,26 @@ async function handlePeople(action, args, ctx, credentials) {
|
|
|
808
1255
|
if (action === "get") {
|
|
809
1256
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
810
1257
|
const result = await api.getPerson(id);
|
|
811
|
-
|
|
1258
|
+
const formatted = formatPerson(result.data, formatOptions);
|
|
1259
|
+
if (ctx.includeHints !== false) {
|
|
1260
|
+
return jsonResult({
|
|
1261
|
+
...formatted,
|
|
1262
|
+
_hints: getPersonHints(id)
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
return jsonResult(formatted);
|
|
812
1266
|
}
|
|
813
1267
|
if (action === "me") {
|
|
814
1268
|
if (credentials.userId) {
|
|
815
1269
|
const result = await api.getPerson(credentials.userId);
|
|
816
|
-
|
|
1270
|
+
const formatted = formatPerson(result.data, formatOptions);
|
|
1271
|
+
if (ctx.includeHints !== false) {
|
|
1272
|
+
return jsonResult({
|
|
1273
|
+
...formatted,
|
|
1274
|
+
_hints: getPersonHints(credentials.userId)
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
return jsonResult(formatted);
|
|
817
1278
|
}
|
|
818
1279
|
return jsonResult({
|
|
819
1280
|
message: "User ID not configured. Set userId in credentials to use this action.",
|
|
@@ -834,7 +1295,14 @@ async function handleProjects(action, args, ctx) {
|
|
|
834
1295
|
if (action === "get") {
|
|
835
1296
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
836
1297
|
const result = await api.getProject(id);
|
|
837
|
-
|
|
1298
|
+
const formatted = formatProject(result.data, formatOptions);
|
|
1299
|
+
if (ctx.includeHints !== false) {
|
|
1300
|
+
return jsonResult({
|
|
1301
|
+
...formatted,
|
|
1302
|
+
_hints: getProjectHints(id)
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
return jsonResult(formatted);
|
|
838
1306
|
}
|
|
839
1307
|
if (action === "list") {
|
|
840
1308
|
const result = await api.getProjects({ filter, page, perPage });
|
|
@@ -980,7 +1448,15 @@ async function handleTasks(action, args, ctx) {
|
|
|
980
1448
|
if (action === "get") {
|
|
981
1449
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
982
1450
|
const result = await api.getTask(id, { include });
|
|
983
|
-
|
|
1451
|
+
const formatted = formatTask(result.data, { ...formatOptions, included: result.included });
|
|
1452
|
+
if (ctx.includeHints !== false) {
|
|
1453
|
+
const serviceId = result.data.relationships?.service?.data?.id;
|
|
1454
|
+
return jsonResult({
|
|
1455
|
+
...formatted,
|
|
1456
|
+
_hints: getTaskHints(id, serviceId)
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
return jsonResult(formatted);
|
|
984
1460
|
}
|
|
985
1461
|
if (action === "create") {
|
|
986
1462
|
if (!title || !project_id || !task_list_id) {
|
|
@@ -1024,7 +1500,15 @@ async function handleTime(action, args, ctx) {
|
|
|
1024
1500
|
if (action === "get") {
|
|
1025
1501
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
1026
1502
|
const result = await api.getTimeEntry(id);
|
|
1027
|
-
|
|
1503
|
+
const formatted = formatTimeEntry(result.data, formatOptions);
|
|
1504
|
+
if (ctx.includeHints !== false) {
|
|
1505
|
+
const serviceId = result.data.relationships?.service?.data?.id;
|
|
1506
|
+
return jsonResult({
|
|
1507
|
+
...formatted,
|
|
1508
|
+
_hints: getTimeEntryHints(id, void 0, serviceId)
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
return jsonResult(formatted);
|
|
1028
1512
|
}
|
|
1029
1513
|
if (action === "create") {
|
|
1030
1514
|
if (!person_id || !service_id || !time || !date) {
|
|
@@ -1069,7 +1553,14 @@ async function handleTimers(action, args, ctx) {
|
|
|
1069
1553
|
if (action === "get") {
|
|
1070
1554
|
if (!id) return inputErrorResult(ErrorMessages.missingId("get"));
|
|
1071
1555
|
const result = await api.getTimer(id, { include });
|
|
1072
|
-
|
|
1556
|
+
const formatted = formatTimer(result.data);
|
|
1557
|
+
if (ctx.includeHints !== false) {
|
|
1558
|
+
return jsonResult({
|
|
1559
|
+
...formatted,
|
|
1560
|
+
_hints: getTimerHints(id)
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
return jsonResult(formatted);
|
|
1073
1564
|
}
|
|
1074
1565
|
if (action === "start" || action === "create") {
|
|
1075
1566
|
if (!service_id && !time_entry_id) {
|
|
@@ -1112,7 +1603,18 @@ async function executeToolWithCredentials(name, args, credentials) {
|
|
|
1112
1603
|
if (name !== "productive") {
|
|
1113
1604
|
return errorResult(`Unknown tool: ${name}`);
|
|
1114
1605
|
}
|
|
1115
|
-
const {
|
|
1606
|
+
const {
|
|
1607
|
+
resource,
|
|
1608
|
+
action,
|
|
1609
|
+
filter,
|
|
1610
|
+
page,
|
|
1611
|
+
per_page,
|
|
1612
|
+
compact,
|
|
1613
|
+
include,
|
|
1614
|
+
query,
|
|
1615
|
+
no_hints,
|
|
1616
|
+
...restArgs
|
|
1617
|
+
} = args;
|
|
1116
1618
|
const isCompact = compact ?? action !== "get";
|
|
1117
1619
|
const formatOptions = { compact: isCompact };
|
|
1118
1620
|
let stringFilter = toStringFilter(filter);
|
|
@@ -1120,13 +1622,15 @@ async function executeToolWithCredentials(name, args, credentials) {
|
|
|
1120
1622
|
if (query) {
|
|
1121
1623
|
stringFilter = { ...stringFilter, query };
|
|
1122
1624
|
}
|
|
1625
|
+
const includeHints = no_hints !== true && action === "get" && !isCompact;
|
|
1123
1626
|
const ctx = {
|
|
1124
1627
|
api,
|
|
1125
1628
|
formatOptions,
|
|
1126
1629
|
filter: stringFilter,
|
|
1127
1630
|
page,
|
|
1128
1631
|
perPage,
|
|
1129
|
-
include
|
|
1632
|
+
include,
|
|
1633
|
+
includeHints
|
|
1130
1634
|
};
|
|
1131
1635
|
try {
|
|
1132
1636
|
if (action === "help") {
|
|
@@ -1174,4 +1678,4 @@ async function executeToolWithCredentials(name, args, credentials) {
|
|
|
1174
1678
|
export {
|
|
1175
1679
|
executeToolWithCredentials as e
|
|
1176
1680
|
};
|
|
1177
|
-
//# sourceMappingURL=index-
|
|
1681
|
+
//# sourceMappingURL=index-CZpVCEu4.js.map
|