@ttctl/mcp 0.0.0 → 0.1.0-rc.1

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.
Files changed (191) hide show
  1. package/README.md +72 -9
  2. package/dist/auth.d.ts +40 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +69 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/data-handling.d.ts +91 -0
  7. package/dist/data-handling.d.ts.map +1 -0
  8. package/dist/data-handling.js +129 -0
  9. package/dist/data-handling.js.map +1 -0
  10. package/dist/diagnostic.d.ts +262 -0
  11. package/dist/diagnostic.d.ts.map +1 -0
  12. package/dist/diagnostic.js +362 -0
  13. package/dist/diagnostic.js.map +1 -0
  14. package/dist/errors.d.ts +54 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +48 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/index.d.ts +8 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +7 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/kill-switch-hook.d.ts +67 -0
  23. package/dist/kill-switch-hook.d.ts.map +1 -0
  24. package/dist/kill-switch-hook.js +61 -0
  25. package/dist/kill-switch-hook.js.map +1 -0
  26. package/dist/server.d.ts +100 -0
  27. package/dist/server.d.ts.map +1 -0
  28. package/dist/server.js +157 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/tools/_shared.d.ts +227 -0
  31. package/dist/tools/_shared.d.ts.map +1 -0
  32. package/dist/tools/_shared.js +238 -0
  33. package/dist/tools/_shared.js.map +1 -0
  34. package/dist/tools/applications.d.ts +27 -0
  35. package/dist/tools/applications.d.ts.map +1 -0
  36. package/dist/tools/applications.js +192 -0
  37. package/dist/tools/applications.js.map +1 -0
  38. package/dist/tools/availability.d.ts +33 -0
  39. package/dist/tools/availability.d.ts.map +1 -0
  40. package/dist/tools/availability.js +272 -0
  41. package/dist/tools/availability.js.map +1 -0
  42. package/dist/tools/contracts.d.ts +29 -0
  43. package/dist/tools/contracts.d.ts.map +1 -0
  44. package/dist/tools/contracts.js +157 -0
  45. package/dist/tools/contracts.js.map +1 -0
  46. package/dist/tools/engagements.d.ts +36 -0
  47. package/dist/tools/engagements.d.ts.map +1 -0
  48. package/dist/tools/engagements.js +408 -0
  49. package/dist/tools/engagements.js.map +1 -0
  50. package/dist/tools/file-upload.d.ts +133 -0
  51. package/dist/tools/file-upload.d.ts.map +1 -0
  52. package/dist/tools/file-upload.js +247 -0
  53. package/dist/tools/file-upload.js.map +1 -0
  54. package/dist/tools/index.d.ts +28 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +131 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/jobs.d.ts +37 -0
  59. package/dist/tools/jobs.d.ts.map +1 -0
  60. package/dist/tools/jobs.js +505 -0
  61. package/dist/tools/jobs.js.map +1 -0
  62. package/dist/tools/output-schemas.d.ts +115 -0
  63. package/dist/tools/output-schemas.d.ts.map +1 -0
  64. package/dist/tools/output-schemas.js +130 -0
  65. package/dist/tools/output-schemas.js.map +1 -0
  66. package/dist/tools/payments.d.ts +36 -0
  67. package/dist/tools/payments.d.ts.map +1 -0
  68. package/dist/tools/payments.js +373 -0
  69. package/dist/tools/payments.js.map +1 -0
  70. package/dist/tools/profile/certifications.d.ts +18 -0
  71. package/dist/tools/profile/certifications.d.ts.map +1 -0
  72. package/dist/tools/profile/certifications.js +193 -0
  73. package/dist/tools/profile/certifications.js.map +1 -0
  74. package/dist/tools/profile/education.d.ts +23 -0
  75. package/dist/tools/profile/education.d.ts.map +1 -0
  76. package/dist/tools/profile/education.js +196 -0
  77. package/dist/tools/profile/education.js.map +1 -0
  78. package/dist/tools/profile/employment.d.ts +23 -0
  79. package/dist/tools/profile/employment.d.ts.map +1 -0
  80. package/dist/tools/profile/employment.js +228 -0
  81. package/dist/tools/profile/employment.js.map +1 -0
  82. package/dist/tools/profile/industries.d.ts +22 -0
  83. package/dist/tools/profile/industries.d.ts.map +1 -0
  84. package/dist/tools/profile/industries.js +168 -0
  85. package/dist/tools/profile/industries.js.map +1 -0
  86. package/dist/tools/profile/portfolio.d.ts +22 -0
  87. package/dist/tools/profile/portfolio.d.ts.map +1 -0
  88. package/dist/tools/profile/portfolio.js +341 -0
  89. package/dist/tools/profile/portfolio.js.map +1 -0
  90. package/dist/tools/profile/resume.d.ts +16 -0
  91. package/dist/tools/profile/resume.d.ts.map +1 -0
  92. package/dist/tools/profile/resume.js +107 -0
  93. package/dist/tools/profile/resume.js.map +1 -0
  94. package/dist/tools/profile/shared.d.ts +85 -0
  95. package/dist/tools/profile/shared.d.ts.map +1 -0
  96. package/dist/tools/profile/shared.js +128 -0
  97. package/dist/tools/profile/shared.js.map +1 -0
  98. package/dist/tools/profile/visas.d.ts +15 -0
  99. package/dist/tools/profile/visas.d.ts.map +1 -0
  100. package/dist/tools/profile/visas.js +170 -0
  101. package/dist/tools/profile/visas.js.map +1 -0
  102. package/dist/tools/profile_basic_photo_show.d.ts +14 -0
  103. package/dist/tools/profile_basic_photo_show.d.ts.map +1 -0
  104. package/dist/tools/profile_basic_photo_show.js +59 -0
  105. package/dist/tools/profile_basic_photo_show.js.map +1 -0
  106. package/dist/tools/profile_basic_photo_upload.d.ts +24 -0
  107. package/dist/tools/profile_basic_photo_upload.d.ts.map +1 -0
  108. package/dist/tools/profile_basic_photo_upload.js +90 -0
  109. package/dist/tools/profile_basic_photo_upload.js.map +1 -0
  110. package/dist/tools/profile_basic_show.d.ts +19 -0
  111. package/dist/tools/profile_basic_show.d.ts.map +1 -0
  112. package/dist/tools/profile_basic_show.js +64 -0
  113. package/dist/tools/profile_basic_show.js.map +1 -0
  114. package/dist/tools/profile_basic_update.d.ts +37 -0
  115. package/dist/tools/profile_basic_update.d.ts.map +1 -0
  116. package/dist/tools/profile_basic_update.js +97 -0
  117. package/dist/tools/profile_basic_update.js.map +1 -0
  118. package/dist/tools/profile_external_advanced_wizard_show.d.ts +14 -0
  119. package/dist/tools/profile_external_advanced_wizard_show.d.ts.map +1 -0
  120. package/dist/tools/profile_external_advanced_wizard_show.js +56 -0
  121. package/dist/tools/profile_external_advanced_wizard_show.js.map +1 -0
  122. package/dist/tools/profile_external_custom_requirements_set.d.ts +13 -0
  123. package/dist/tools/profile_external_custom_requirements_set.d.ts.map +1 -0
  124. package/dist/tools/profile_external_custom_requirements_set.js +75 -0
  125. package/dist/tools/profile_external_custom_requirements_set.js.map +1 -0
  126. package/dist/tools/profile_external_custom_requirements_show.d.ts +14 -0
  127. package/dist/tools/profile_external_custom_requirements_show.d.ts.map +1 -0
  128. package/dist/tools/profile_external_custom_requirements_show.js +56 -0
  129. package/dist/tools/profile_external_custom_requirements_show.js.map +1 -0
  130. package/dist/tools/profile_external_readiness.d.ts +12 -0
  131. package/dist/tools/profile_external_readiness.d.ts.map +1 -0
  132. package/dist/tools/profile_external_readiness.js +54 -0
  133. package/dist/tools/profile_external_readiness.js.map +1 -0
  134. package/dist/tools/profile_external_recommendations.d.ts +15 -0
  135. package/dist/tools/profile_external_recommendations.d.ts.map +1 -0
  136. package/dist/tools/profile_external_recommendations.js +57 -0
  137. package/dist/tools/profile_external_recommendations.js.map +1 -0
  138. package/dist/tools/profile_external_update.d.ts +14 -0
  139. package/dist/tools/profile_external_update.d.ts.map +1 -0
  140. package/dist/tools/profile_external_update.js +79 -0
  141. package/dist/tools/profile_external_update.js.map +1 -0
  142. package/dist/tools/profile_reviews_approve_item.d.ts +17 -0
  143. package/dist/tools/profile_reviews_approve_item.d.ts.map +1 -0
  144. package/dist/tools/profile_reviews_approve_item.js +77 -0
  145. package/dist/tools/profile_reviews_approve_item.js.map +1 -0
  146. package/dist/tools/profile_reviews_approve_section.d.ts +15 -0
  147. package/dist/tools/profile_reviews_approve_section.d.ts.map +1 -0
  148. package/dist/tools/profile_reviews_approve_section.js +70 -0
  149. package/dist/tools/profile_reviews_approve_section.js.map +1 -0
  150. package/dist/tools/profile_reviews_list.d.ts +16 -0
  151. package/dist/tools/profile_reviews_list.d.ts.map +1 -0
  152. package/dist/tools/profile_reviews_list.js +58 -0
  153. package/dist/tools/profile_reviews_list.js.map +1 -0
  154. package/dist/tools/profile_reviews_submit_for_review.d.ts +14 -0
  155. package/dist/tools/profile_reviews_submit_for_review.d.ts.map +1 -0
  156. package/dist/tools/profile_reviews_submit_for_review.js +56 -0
  157. package/dist/tools/profile_reviews_submit_for_review.js.map +1 -0
  158. package/dist/tools/profile_skills_add.d.ts +4 -0
  159. package/dist/tools/profile_skills_add.d.ts.map +1 -0
  160. package/dist/tools/profile_skills_add.js +52 -0
  161. package/dist/tools/profile_skills_add.js.map +1 -0
  162. package/dist/tools/profile_skills_autocomplete.d.ts +4 -0
  163. package/dist/tools/profile_skills_autocomplete.d.ts.map +1 -0
  164. package/dist/tools/profile_skills_autocomplete.js +78 -0
  165. package/dist/tools/profile_skills_autocomplete.js.map +1 -0
  166. package/dist/tools/profile_skills_list.d.ts +16 -0
  167. package/dist/tools/profile_skills_list.d.ts.map +1 -0
  168. package/dist/tools/profile_skills_list.js +65 -0
  169. package/dist/tools/profile_skills_list.js.map +1 -0
  170. package/dist/tools/profile_skills_readiness.d.ts +4 -0
  171. package/dist/tools/profile_skills_readiness.d.ts.map +1 -0
  172. package/dist/tools/profile_skills_readiness.js +53 -0
  173. package/dist/tools/profile_skills_readiness.js.map +1 -0
  174. package/dist/tools/profile_skills_remove.d.ts +4 -0
  175. package/dist/tools/profile_skills_remove.d.ts.map +1 -0
  176. package/dist/tools/profile_skills_remove.js +53 -0
  177. package/dist/tools/profile_skills_remove.js.map +1 -0
  178. package/dist/tools/profile_skills_show.d.ts +4 -0
  179. package/dist/tools/profile_skills_show.d.ts.map +1 -0
  180. package/dist/tools/profile_skills_show.js +51 -0
  181. package/dist/tools/profile_skills_show.js.map +1 -0
  182. package/dist/tools/profile_skills_update.d.ts +11 -0
  183. package/dist/tools/profile_skills_update.d.ts.map +1 -0
  184. package/dist/tools/profile_skills_update.js +97 -0
  185. package/dist/tools/profile_skills_update.js.map +1 -0
  186. package/dist/tools/timesheet.d.ts +29 -0
  187. package/dist/tools/timesheet.d.ts.map +1 -0
  188. package/dist/tools/timesheet.js +257 -0
  189. package/dist/tools/timesheet.js.map +1 -0
  190. package/package.json +33 -13
  191. package/index.js +0 -7
@@ -0,0 +1,157 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { contracts } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, dryRunResponse } from "./_shared.js";
7
+ const DRY_RUN_FIELD = z
8
+ .boolean()
9
+ .optional()
10
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
11
+ /**
12
+ * Register the `ttctl_contracts_*` MCP tools (#195). Two read-only tools:
13
+ *
14
+ * - `ttctl_contracts_list` — list talent-level contracts
15
+ * - `ttctl_contracts_show` — show one contract by id
16
+ *
17
+ * The `<id>` argument is the `Contract.id` from `ttctl_contracts_list`.
18
+ *
19
+ * **Domain distinction**: this group surfaces talent-level legal
20
+ * documents (Toptal Direct, Master Service Agreement) via
21
+ * `viewer.contracts` on the portal surface. Engagement-attached
22
+ * commercial agreements (rates, hours, period for one project) live
23
+ * on a different surface — use `ttctl_engagements_show <engagement-id>`.
24
+ *
25
+ * **Dry-run path** (issue #165): both tools accept `dryRun?: boolean`.
26
+ * Read-only tools build the preview at the MCP layer via
27
+ * `buildMcpDryRunPreview` — `show` previews the same `GetContracts`
28
+ * operation as `list` (the apply path fetches the list and filters
29
+ * client-side; the dry-run reflects that wire call accurately).
30
+ *
31
+ * **Per CLAUDE.md schema/contract validation rule**: `GetContracts`
32
+ * is hand-authored against the portal surface; every projected field
33
+ * is `Unknown`-typed in the SDL → INFERRED. Live E2E coverage
34
+ * (`packages/e2e/src/35-contracts.e2e.test.ts`) is mandatory pre-merge.
35
+ */
36
+ export function registerContractsTools(server, ctx) {
37
+ server.registerTool("ttctl_contracts_list", {
38
+ title: "List talent-level contracts",
39
+ description: [
40
+ "List the signed-in user's talent-level legal contracts.",
41
+ "These are top-level documents like Toptal Direct, Master Service Agreement, etc.",
42
+ "(reachable via `viewer.contracts` on the portal surface).",
43
+ "",
44
+ "For engagement-attached commercial agreements (rates, hours, period for a",
45
+ "specific project), use `ttctl_engagements_show <engagement-id>` instead —",
46
+ "those are a different domain on a different transport.",
47
+ "",
48
+ "Returns a list of contracts; each contract carries id, kind, provider,",
49
+ "status, billingType, signedAt, sentAt, isActive, verificationDeadline, title.",
50
+ "",
51
+ "Example user prompts:",
52
+ ' - "What Toptal contracts do I have?"',
53
+ ' - "Show me my Toptal legal documents."',
54
+ ' - "Is my Toptal Direct contract active?"',
55
+ ].join("\n"),
56
+ inputSchema: {
57
+ dryRun: DRY_RUN_FIELD,
58
+ },
59
+ }, async (args) => {
60
+ const auth = await ctx.resolveToolAuth();
61
+ if (!auth.ok)
62
+ return auth.response;
63
+ if (args.dryRun === true) {
64
+ return dryRunResponse(buildMcpDryRunPreview("GetContracts", "talent-profile", {}, auth.token));
65
+ }
66
+ try {
67
+ const items = await contracts.list(auth.token);
68
+ return successResponse(items);
69
+ }
70
+ catch (err) {
71
+ return mapContractsError(err);
72
+ }
73
+ });
74
+ server.registerTool("ttctl_contracts_show", {
75
+ title: "Show one talent-level contract by id",
76
+ description: [
77
+ "Fetch one talent-level contract by id (the row id from `ttctl_contracts_list`).",
78
+ "Returns the full projection: id, kind, provider, status, billingType,",
79
+ "signedAt, sentAt, isActive, verificationDeadline, title.",
80
+ "",
81
+ "The portal API does not expose a per-id contract lookup; this tool fetches",
82
+ "the full contracts list and filters client-side. Latency-conscious callers",
83
+ "querying multiple contracts should use `ttctl_contracts_list` once.",
84
+ "",
85
+ "Example user prompts:",
86
+ ' - "Show me contract ct_abc123."',
87
+ ' - "What is the status of my MSA with Toptal?"',
88
+ ].join("\n"),
89
+ inputSchema: {
90
+ id: z.string().describe("Contract id (the row id from `ttctl_contracts_list`)"),
91
+ dryRun: DRY_RUN_FIELD,
92
+ },
93
+ }, async (args) => {
94
+ const auth = await ctx.resolveToolAuth();
95
+ if (!auth.ok)
96
+ return auth.response;
97
+ if (args.dryRun === true) {
98
+ // The apply path fetches the same `GetContracts` operation as the
99
+ // list tool, then filters client-side. The preview accurately
100
+ // reflects the wire call (no per-id variable on the operation).
101
+ return dryRunResponse(buildMcpDryRunPreview("GetContracts", "talent-profile", {}, auth.token));
102
+ }
103
+ try {
104
+ const item = await contracts.show(auth.token, args.id);
105
+ return successResponse(item);
106
+ }
107
+ catch (err) {
108
+ return mapContractsError(err);
109
+ }
110
+ });
111
+ }
112
+ function successResponse(data) {
113
+ return {
114
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
115
+ };
116
+ }
117
+ function mapContractsError(err) {
118
+ const typed = ttctlErrorToToolResponseOrNull(err);
119
+ if (typed !== null)
120
+ return typed;
121
+ if (err instanceof contracts.ContractsError) {
122
+ return {
123
+ isError: true,
124
+ content: [
125
+ {
126
+ type: "text",
127
+ text: [`Error: ${err.message}`, "", recoveryForCode(err.code), "", `(Code: ${err.code})`].join("\n"),
128
+ },
129
+ ],
130
+ };
131
+ }
132
+ const message = err instanceof Error ? err.message : String(err);
133
+ return {
134
+ isError: true,
135
+ content: [
136
+ {
137
+ type: "text",
138
+ text: [
139
+ `Error: contracts request failed: ${message}`,
140
+ "",
141
+ "Recovery: Retry; if the failure persists, file an issue.",
142
+ "",
143
+ "(Code: UNKNOWN)",
144
+ ].join("\n"),
145
+ },
146
+ ],
147
+ };
148
+ }
149
+ function recoveryForCode(code) {
150
+ switch (code) {
151
+ case "NOT_FOUND":
152
+ return "Recovery: Verify the contract id (use `ttctl_contracts_list` to discover ids).";
153
+ default:
154
+ return "Recovery: Adjust the tool input or retry; see the code below.";
155
+ }
156
+ }
157
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/tools/contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ /**
4
+ * Register the `ttctl_engagements_*` MCP tools (initial #147 spec
5
+ * extended by #155 with `breaks_reschedule`). Tool names use the
6
+ * `ttctl_` prefix and the canonical CLI path joined with `_`:
7
+ *
8
+ * - `ttctl_engagements_list`
9
+ * - `ttctl_engagements_show`
10
+ * - `ttctl_engagements_stats`
11
+ * - `ttctl_engagements_breaks_list`
12
+ * - `ttctl_engagements_breaks_add`
13
+ * - `ttctl_engagements_breaks_remove`
14
+ * - `ttctl_engagements_breaks_reschedule` (#155)
15
+ *
16
+ * Each tool maps 1:1 to a CLI leaf — the schemas describe the same set
17
+ * of fields. The `<id>` argument is the `jobActivityItem.id` (the row
18
+ * id from `engagements_list`); `<break-id>` is the
19
+ * `engagementBreak.id` (the id returned by `engagements_breaks_list`).
20
+ *
21
+ * Per #147 scope amendment (2026-05-10), `allocated-hours` is NOT
22
+ * surfaced here — that scope moved to `availability` (#146) since the
23
+ * underlying mutation (`UpdateAllocatedHours`) operates on
24
+ * `viewerRole`, not per-engagement.
25
+ *
26
+ * Dry-run path (issue #165): every tool accepts `dryRun?: boolean`. The
27
+ * three read-only tools and `breaks_list` use MCP-layer preview building;
28
+ * the two break mutations are passthrough — `core.engagements.breaks.{add,remove}`
29
+ * already support `{ dryRun: true }` (#163), so the MCP layer forwards
30
+ * the flag and reformats the resulting `{ kind: "preview", preview }`
31
+ * outcome as the uniform `{ ok, dryRun, preview }` envelope. `stats`
32
+ * uses the plural `{ previews: [...] }` envelope (2 parallel
33
+ * `JobActivityItems` calls — one per status group).
34
+ */
35
+ export declare function registerEngagementsTools(server: McpServer, ctx: ToolRegistrationContext): void;
36
+ //# sourceMappingURL=engagements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engagements.d.ts","sourceRoot":"","sources":["../../src/tools/engagements.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,OAAO,EAA8D,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AASxH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CA6V9F"}
@@ -0,0 +1,408 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { engagements } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, dryRunMultiResponse, dryRunResponse } from "./_shared.js";
7
+ const DRY_RUN_FIELD = z
8
+ .boolean()
9
+ .optional()
10
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
11
+ /**
12
+ * Register the `ttctl_engagements_*` MCP tools (initial #147 spec
13
+ * extended by #155 with `breaks_reschedule`). Tool names use the
14
+ * `ttctl_` prefix and the canonical CLI path joined with `_`:
15
+ *
16
+ * - `ttctl_engagements_list`
17
+ * - `ttctl_engagements_show`
18
+ * - `ttctl_engagements_stats`
19
+ * - `ttctl_engagements_breaks_list`
20
+ * - `ttctl_engagements_breaks_add`
21
+ * - `ttctl_engagements_breaks_remove`
22
+ * - `ttctl_engagements_breaks_reschedule` (#155)
23
+ *
24
+ * Each tool maps 1:1 to a CLI leaf — the schemas describe the same set
25
+ * of fields. The `<id>` argument is the `jobActivityItem.id` (the row
26
+ * id from `engagements_list`); `<break-id>` is the
27
+ * `engagementBreak.id` (the id returned by `engagements_breaks_list`).
28
+ *
29
+ * Per #147 scope amendment (2026-05-10), `allocated-hours` is NOT
30
+ * surfaced here — that scope moved to `availability` (#146) since the
31
+ * underlying mutation (`UpdateAllocatedHours`) operates on
32
+ * `viewerRole`, not per-engagement.
33
+ *
34
+ * Dry-run path (issue #165): every tool accepts `dryRun?: boolean`. The
35
+ * three read-only tools and `breaks_list` use MCP-layer preview building;
36
+ * the two break mutations are passthrough — `core.engagements.breaks.{add,remove}`
37
+ * already support `{ dryRun: true }` (#163), so the MCP layer forwards
38
+ * the flag and reformats the resulting `{ kind: "preview", preview }`
39
+ * outcome as the uniform `{ ok, dryRun, preview }` envelope. `stats`
40
+ * uses the plural `{ previews: [...] }` envelope (2 parallel
41
+ * `JobActivityItems` calls — one per status group).
42
+ */
43
+ export function registerEngagementsTools(server, ctx) {
44
+ server.registerTool("ttctl_engagements_list", {
45
+ title: "List engagements",
46
+ description: [
47
+ "List the signed-in user's Toptal Talent engagements (active by default).",
48
+ "An engagement is an active assignment between the user and a client",
49
+ "(= what users colloquially call 'current job' or 'current contract').",
50
+ "",
51
+ "Filter via `status`:",
52
+ " - `active` (default): currently active engagements",
53
+ " - `past`: closed engagements",
54
+ " - `all`: both",
55
+ "",
56
+ "Optional `keywords` is a free-text filter (AND across multiple).",
57
+ "",
58
+ "Example user prompts:",
59
+ ' - "What are my active Toptal engagements?"',
60
+ ' - "Show me my past Toptal contracts."',
61
+ ' - "List all my Toptal jobs, current and past."',
62
+ ].join("\n"),
63
+ inputSchema: {
64
+ status: z
65
+ .enum([...engagements.ENGAGEMENT_LIST_STATUSES])
66
+ .optional()
67
+ .describe("Filter by engagement status: active (default), past, or all"),
68
+ keywords: z.array(z.string()).optional().describe("Free-text keyword filter (AND across multiple)"),
69
+ dryRun: DRY_RUN_FIELD,
70
+ },
71
+ }, async (args) => {
72
+ const auth = await ctx.resolveToolAuth();
73
+ if (!auth.ok)
74
+ return auth.response;
75
+ const opts = {};
76
+ if (args.status !== undefined)
77
+ opts.status = args.status;
78
+ if (args.keywords !== undefined)
79
+ opts.keywords = args.keywords;
80
+ if (args.dryRun === true) {
81
+ // Mirror the apply-path mapping from `--status` to
82
+ // JobActivityItemStatusGroupEnum so the preview's
83
+ // `onlyStatusGroupFilter` matches what the wire call would send.
84
+ // Apply path: core/services/engagements/index.ts `listStatusToGroups`.
85
+ const status = opts.status ?? "active";
86
+ const statusGroups = status === "active"
87
+ ? ["ACTIVE_ENGAGEMENT"]
88
+ : status === "past"
89
+ ? ["CLOSED_ENGAGEMENT"]
90
+ : ["ACTIVE_ENGAGEMENT", "CLOSED_ENGAGEMENT"];
91
+ const variables = {
92
+ keywords: opts.keywords !== undefined && opts.keywords.length > 0 ? opts.keywords : null,
93
+ onlyStatusGroupFilter: statusGroups,
94
+ };
95
+ return dryRunResponse(buildMcpDryRunPreview("JobActivityItems", "mobile-gateway", variables, auth.token));
96
+ }
97
+ try {
98
+ const items = await engagements.list(auth.token, opts);
99
+ return successResponse(items);
100
+ }
101
+ catch (err) {
102
+ return mapEngagementsError(err);
103
+ }
104
+ });
105
+ server.registerTool("ttctl_engagements_show", {
106
+ title: "Show one engagement",
107
+ description: [
108
+ "Fetch a single engagement's full detail by id (the row id from",
109
+ "`ttctl_engagements_list`, which is the underlying TalentJobActivityItem id).",
110
+ "Returns the engagement metadata (status, start/end dates, expected hours,",
111
+ "commitment), the underlying job (title, client, description, work type),",
112
+ "the current agreement (rates, commitment), earnings summary, and any",
113
+ "scheduled breaks.",
114
+ "",
115
+ "Example user prompts:",
116
+ ' - "Show me the details of engagement act_xyz."',
117
+ ' - "What is my hourly rate on engagement act_abc?"',
118
+ ' - "Are there any scheduled breaks on my current Toptal engagement?"',
119
+ ].join("\n"),
120
+ inputSchema: {
121
+ id: z.string().describe("Engagement id (the TalentJobActivityItem id from `engagements_list`)"),
122
+ dryRun: DRY_RUN_FIELD,
123
+ },
124
+ }, async (args) => {
125
+ const auth = await ctx.resolveToolAuth();
126
+ if (!auth.ok)
127
+ return auth.response;
128
+ if (args.dryRun === true) {
129
+ return dryRunResponse(buildMcpDryRunPreview("JobActivityItem", "mobile-gateway", { id: args.id }, auth.token));
130
+ }
131
+ try {
132
+ const item = await engagements.show(auth.token, args.id);
133
+ return successResponse(item);
134
+ }
135
+ catch (err) {
136
+ return mapEngagementsError(err);
137
+ }
138
+ });
139
+ server.registerTool("ttctl_engagements_stats", {
140
+ title: "Per-status engagement counts",
141
+ description: [
142
+ "Aggregate engagement counts: returns per-status totals (active, past) plus",
143
+ "the overall sum.",
144
+ "",
145
+ "Issues 2 server calls in parallel (one per engagement-bearing status group).",
146
+ "Each count is server-provided (totalCount on JobActivityList) — no",
147
+ "client-side aggregation.",
148
+ "",
149
+ "Example user prompts:",
150
+ ' - "How many Toptal engagements have I had in total?"',
151
+ ' - "Show me a breakdown of my Toptal engagements by status."',
152
+ "",
153
+ "Dry-run note: returns `{ ok: true, dryRun: true, previews: [...] }` (plural `previews`) — one `JobActivityItems` preview per engagement status group (2 total: ACTIVE_ENGAGEMENT, CLOSED_ENGAGEMENT), matching the 2 parallel calls the apply path fires.",
154
+ ].join("\n"),
155
+ inputSchema: { dryRun: DRY_RUN_FIELD },
156
+ }, async (args) => {
157
+ const auth = await ctx.resolveToolAuth();
158
+ if (!auth.ok)
159
+ return auth.response;
160
+ if (args.dryRun === true) {
161
+ const previews = engagements.ENGAGEMENT_STATUS_GROUPS.map((group) => buildMcpDryRunPreview("JobActivityItems", "mobile-gateway", { keywords: null, onlyStatusGroupFilter: [group] }, auth.token));
162
+ return dryRunMultiResponse(previews);
163
+ }
164
+ try {
165
+ const stats = await engagements.stats(auth.token);
166
+ return successResponse(stats);
167
+ }
168
+ catch (err) {
169
+ return mapEngagementsError(err);
170
+ }
171
+ });
172
+ server.registerTool("ttctl_engagements_breaks_list", {
173
+ title: "List breaks on an engagement",
174
+ description: [
175
+ "List the scheduled break windows for a specific engagement.",
176
+ "A break is a planned period when the talent will not be working on the",
177
+ "engagement (vacation, time off, etc.).",
178
+ "",
179
+ "The id parameter is the engagement id (TalentJobActivityItem id), the",
180
+ "same id used by `ttctl_engagements_show`.",
181
+ "",
182
+ "Example user prompts:",
183
+ ' - "Show me the scheduled breaks on engagement act_xyz."',
184
+ ' - "Do I have any vacations planned on my current Toptal engagement?"',
185
+ ].join("\n"),
186
+ inputSchema: {
187
+ id: z.string().describe("Engagement id (the TalentJobActivityItem id from `engagements_list`)"),
188
+ dryRun: DRY_RUN_FIELD,
189
+ },
190
+ }, async (args) => {
191
+ const auth = await ctx.resolveToolAuth();
192
+ if (!auth.ok)
193
+ return auth.response;
194
+ if (args.dryRun === true) {
195
+ return dryRunResponse(buildMcpDryRunPreview("EngagementBreaks", "mobile-gateway", { jobActivityItemId: args.id }, auth.token));
196
+ }
197
+ try {
198
+ const items = await engagements.breaks.list(auth.token, args.id);
199
+ return successResponse(items);
200
+ }
201
+ catch (err) {
202
+ return mapEngagementsError(err);
203
+ }
204
+ });
205
+ server.registerTool("ttctl_engagements_breaks_reasons_list", {
206
+ title: "List valid break reasons (catalog)",
207
+ description: [
208
+ "List the server-side catalog of valid break-reason identifiers for",
209
+ "`ttctl_engagements_breaks_add` (the `reasonIdentifier` argument).",
210
+ "",
211
+ "Reads `platformConfiguration.engagementBreakReasons` from the mobile",
212
+ "gateway. Returns an array of `{identifier, nameForRole}` sorted by",
213
+ "`identifier`. `identifier` is what the user supplies to",
214
+ "`ttctl_engagements_breaks_add`; `nameForRole` is the human-readable",
215
+ "label.",
216
+ "",
217
+ "Use this tool to discover valid `reasonIdentifier` values before",
218
+ "scheduling a break — the catalog can change over time.",
219
+ "",
220
+ "Example user prompts:",
221
+ ' - "What break reasons can I use when scheduling a Toptal engagement break?"',
222
+ ' - "List the valid --reason-id values for `ttctl engagements breaks add`."',
223
+ ].join("\n"),
224
+ inputSchema: { dryRun: DRY_RUN_FIELD },
225
+ }, async (args) => {
226
+ const auth = await ctx.resolveToolAuth();
227
+ if (!auth.ok)
228
+ return auth.response;
229
+ if (args.dryRun === true) {
230
+ return dryRunResponse(buildMcpDryRunPreview("PlatformConfiguration", "mobile-gateway", {}, auth.token));
231
+ }
232
+ try {
233
+ const items = await engagements.breaks.reasonsList(auth.token);
234
+ return successResponse(items);
235
+ }
236
+ catch (err) {
237
+ return mapEngagementsError(err);
238
+ }
239
+ });
240
+ server.registerTool("ttctl_engagements_breaks_add", {
241
+ title: "Schedule a break on an engagement",
242
+ description: [
243
+ "Schedule a new break window on an engagement.",
244
+ "",
245
+ "Required: `id` (engagement id), `startDate` (YYYY-MM-DD), `endDate`",
246
+ "(YYYY-MM-DD), `reasonIdentifier` (server-side reason key — known",
247
+ "values: `talent_on_vacation`, `client_needs_preparation`,",
248
+ "`client_on_vacation`, `other`).",
249
+ "Optional: `comment` (free-text note).",
250
+ "",
251
+ "**This is a write operation**: it modifies the user's scheduled time-off",
252
+ "on the live Toptal Talent platform. Confirm with the user before invoking.",
253
+ "",
254
+ "Example user prompts:",
255
+ ' - "Schedule a break on engagement act_xyz from June 1 to June 8."',
256
+ ' - "Add a vacation window to my current Toptal engagement next week."',
257
+ ].join("\n"),
258
+ inputSchema: {
259
+ id: z.string().describe("Engagement id (the TalentJobActivityItem id from `engagements_list`)"),
260
+ startDate: z.string().describe("Break start date (YYYY-MM-DD)"),
261
+ endDate: z.string().describe("Break end date (YYYY-MM-DD)"),
262
+ reasonIdentifier: z
263
+ .string()
264
+ .describe("Server-side reason key (known: talent_on_vacation, client_needs_preparation, client_on_vacation, other)"),
265
+ comment: z.string().optional().describe("Optional free-text comment"),
266
+ dryRun: DRY_RUN_FIELD,
267
+ },
268
+ }, async (args) => {
269
+ const auth = await ctx.resolveToolAuth();
270
+ if (!auth.ok)
271
+ return auth.response;
272
+ try {
273
+ const opts = {
274
+ startDate: args.startDate,
275
+ endDate: args.endDate,
276
+ reasonIdentifier: args.reasonIdentifier,
277
+ };
278
+ if (args.comment !== undefined)
279
+ opts.comment = args.comment;
280
+ const outcome = await engagements.breaks.add(auth.token, args.id, opts, { dryRun: args.dryRun ?? false });
281
+ if (outcome.kind === "preview")
282
+ return dryRunResponse(outcome.preview);
283
+ return successResponse(outcome.result);
284
+ }
285
+ catch (err) {
286
+ return mapEngagementsError(err);
287
+ }
288
+ });
289
+ server.registerTool("ttctl_engagements_breaks_remove", {
290
+ title: "Cancel a scheduled break",
291
+ description: [
292
+ "Cancel a previously-scheduled break by its id (the id returned by",
293
+ "`ttctl_engagements_breaks_list`).",
294
+ "",
295
+ "**This is a write operation**: it cancels a scheduled break on the live",
296
+ "Toptal Talent platform. Confirm with the user before invoking.",
297
+ "",
298
+ "Example user prompts:",
299
+ ' - "Cancel break br_abc on engagement act_xyz."',
300
+ ' - "Remove the scheduled break starting June 1 on my Toptal engagement."',
301
+ ].join("\n"),
302
+ inputSchema: {
303
+ breakId: z.string().describe("Engagement break id (the engagementBreak id from `engagements_breaks_list`)"),
304
+ dryRun: DRY_RUN_FIELD,
305
+ },
306
+ }, async (args) => {
307
+ const auth = await ctx.resolveToolAuth();
308
+ if (!auth.ok)
309
+ return auth.response;
310
+ try {
311
+ const outcome = await engagements.breaks.remove(auth.token, args.breakId, { dryRun: args.dryRun ?? false });
312
+ if (outcome.kind === "preview")
313
+ return dryRunResponse(outcome.preview);
314
+ return successResponse(outcome.result);
315
+ }
316
+ catch (err) {
317
+ return mapEngagementsError(err);
318
+ }
319
+ });
320
+ server.registerTool("ttctl_engagements_breaks_reschedule", {
321
+ title: "Reschedule a scheduled break to a new date window",
322
+ description: [
323
+ "Move an existing scheduled break to a new date window in-place, without",
324
+ "removing and re-adding it. Preserves the existing break's reason and",
325
+ "comment (the wire mutation only carries the new startDate + endDate).",
326
+ "",
327
+ "Required: `breakId` (the engagementBreak id, from `engagements_breaks_list`),",
328
+ "`startDate` (YYYY-MM-DD), `endDate` (YYYY-MM-DD).",
329
+ "",
330
+ "**This is a write operation**: it changes a scheduled break's dates on the",
331
+ "live Toptal Talent platform. Confirm with the user before invoking.",
332
+ "",
333
+ "Example user prompts:",
334
+ ' - "Reschedule break br_abc to July 1 through July 8."',
335
+ ' - "Move my scheduled vacation from June 1-8 to June 15-22."',
336
+ ' - "Push back the start of my upcoming break by a week."',
337
+ ].join("\n"),
338
+ inputSchema: {
339
+ breakId: z.string().describe("Engagement break id (the engagementBreak id from `engagements_breaks_list`)"),
340
+ startDate: z.string().describe("New break start date (YYYY-MM-DD)"),
341
+ endDate: z.string().describe("New break end date (YYYY-MM-DD)"),
342
+ dryRun: DRY_RUN_FIELD,
343
+ },
344
+ }, async (args) => {
345
+ const auth = await ctx.resolveToolAuth();
346
+ if (!auth.ok)
347
+ return auth.response;
348
+ try {
349
+ const outcome = await engagements.breaks.reschedule(auth.token, args.breakId, { startDate: args.startDate, endDate: args.endDate }, { dryRun: args.dryRun ?? false });
350
+ if (outcome.kind === "preview")
351
+ return dryRunResponse(outcome.preview);
352
+ return successResponse(outcome.result);
353
+ }
354
+ catch (err) {
355
+ return mapEngagementsError(err);
356
+ }
357
+ });
358
+ }
359
+ function successResponse(data) {
360
+ return {
361
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
362
+ };
363
+ }
364
+ function mapEngagementsError(err) {
365
+ const typed = ttctlErrorToToolResponseOrNull(err);
366
+ if (typed !== null)
367
+ return typed;
368
+ if (err instanceof engagements.EngagementsError) {
369
+ return {
370
+ isError: true,
371
+ content: [
372
+ {
373
+ type: "text",
374
+ text: [`Error: ${err.message}`, "", recoveryForCode(err.code), "", `(Code: ${err.code})`].join("\n"),
375
+ },
376
+ ],
377
+ };
378
+ }
379
+ const message = err instanceof Error ? err.message : String(err);
380
+ return {
381
+ isError: true,
382
+ content: [
383
+ {
384
+ type: "text",
385
+ text: [
386
+ `Error: engagements request failed: ${message}`,
387
+ "",
388
+ "Recovery: Retry; if the failure persists, file an issue.",
389
+ "",
390
+ "(Code: UNKNOWN)",
391
+ ].join("\n"),
392
+ },
393
+ ],
394
+ };
395
+ }
396
+ function recoveryForCode(code) {
397
+ switch (code) {
398
+ case "NOT_FOUND":
399
+ return "Recovery: Verify the engagement id (use `ttctl_engagements_list` to discover it).";
400
+ case "NO_ENGAGEMENT":
401
+ return "Recovery: This activity item is not an engagement (likely an application or interview). Use `ttctl_applications_show` instead.";
402
+ case "MUTATION_ERROR":
403
+ return "Recovery: The mutation was rejected by the server (often: overlapping break dates or validation). Check the message above and adjust the input.";
404
+ default:
405
+ return "Recovery: Adjust the tool input or retry; see the code below.";
406
+ }
407
+ }
408
+ //# sourceMappingURL=engagements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engagements.js","sourceRoot":"","sources":["../../src/tools/engagements.ts"],"names":[],"mappings":"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"}