@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,257 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { timesheet } 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
+ * Placeholder cycle id used in the `timesheet_submit` dry-run preview
13
+ * when the caller omits `id` (auto-resolve at apply time). Apply path
14
+ * resolves the real id via {@link timesheet.resolveCurrentCycle};
15
+ * dry-run skips that prefetch and stamps this sentinel value into the
16
+ * preview's `variables.id` so the wire-shape is honest about the
17
+ * pending resolution.
18
+ */
19
+ const SUBMIT_AUTO_RESOLVE_PLACEHOLDER = "<auto-resolved-at-apply-time>";
20
+ /**
21
+ * Register the `ttctl_timesheet_*` MCP tools per the #13 spec. Tool
22
+ * names use the `ttctl_` prefix and the canonical CLI path joined
23
+ * with `_`:
24
+ *
25
+ * - `ttctl_timesheet_list`
26
+ * - `ttctl_timesheet_show`
27
+ * - `ttctl_timesheet_submit`
28
+ *
29
+ * Each tool maps 1:1 to a CLI leaf — schemas describe the same set of
30
+ * fields. Identity model:
31
+ *
32
+ * - `BillingCycle.id` — the "timesheet id" returned by
33
+ * `timesheet_list` and consumed by
34
+ * `timesheet_show` / `timesheet_submit`.
35
+ * - `JobActivityItem.id` — the "engagement id" exposed by
36
+ * `engagements_list`. Passed via
37
+ * `engagement` to scope.
38
+ *
39
+ * Submit is destructive — its tool description explicitly warns
40
+ * humans, and per #13 the CLI gates on `--confirm` / TTY interactive
41
+ * confirm. The MCP side has no analogous gate (LLM clients are
42
+ * expected to confirm with the human before invoking write tools)
43
+ * but the description and rationale are surfaced verbatim.
44
+ */
45
+ export function registerTimesheetTools(server, ctx) {
46
+ server.registerTool("ttctl_timesheet_list", {
47
+ title: "List timesheet billing cycles",
48
+ description: [
49
+ "List the signed-in user's Toptal Talent timesheet billing cycles.",
50
+ "A timesheet is a per-billing-cycle bucket of time entries that the",
51
+ "talent submits for client billing.",
52
+ "",
53
+ "Default scope: viewer-wide pending timesheets (what currently needs",
54
+ "submission). Pass `engagement` (jobActivityItem.id from",
55
+ "`engagements_list`) to scope to one engagement (returns ALL cycles for",
56
+ "that engagement, regardless of submission state).",
57
+ "",
58
+ "Example user prompts:",
59
+ ' - "Show my pending Toptal timesheets."',
60
+ ' - "What timesheets do I need to submit?"',
61
+ ' - "List all timesheets for engagement act_xyz."',
62
+ ].join("\n"),
63
+ inputSchema: {
64
+ engagement: z
65
+ .string()
66
+ .optional()
67
+ .describe("Scope to one engagement (jobActivityItem.id from `engagements_list`). Omit for viewer-wide pending."),
68
+ dryRun: DRY_RUN_FIELD,
69
+ },
70
+ }, async (args) => {
71
+ const auth = await ctx.resolveToolAuth();
72
+ if (!auth.ok)
73
+ return auth.response;
74
+ const opts = {};
75
+ if (args.engagement !== undefined)
76
+ opts.engagement = args.engagement;
77
+ if (args.dryRun === true) {
78
+ // Apply path picks PendingTimesheets (no engagement) or
79
+ // Timesheets($jobActivityItemId) (engagement scoped); mirror
80
+ // that branch in the preview so callers see the exact wire
81
+ // operation that would fire.
82
+ if (opts.engagement === undefined) {
83
+ return dryRunResponse(buildMcpDryRunPreview("PendingTimesheets", "mobile-gateway", {}, auth.token));
84
+ }
85
+ return dryRunResponse(buildMcpDryRunPreview("Timesheets", "mobile-gateway", { jobActivityItemId: opts.engagement }, auth.token));
86
+ }
87
+ try {
88
+ const items = await timesheet.list(auth.token, opts);
89
+ return successResponse(items);
90
+ }
91
+ catch (err) {
92
+ return mapTimesheetError(err);
93
+ }
94
+ });
95
+ server.registerTool("ttctl_timesheet_show", {
96
+ title: "Show one timesheet by id",
97
+ description: [
98
+ "Fetch a single timesheet's full detail by BillingCycle.id (the id",
99
+ "returned by `ttctl_timesheet_list`). Returns the cycle metadata",
100
+ "(week range, hours, submission state), the engagement+job reference,",
101
+ "the rate agreement snapshot, the comment (if any), and the per-day",
102
+ "time entries (`timesheetRecords`).",
103
+ "",
104
+ "Example user prompts:",
105
+ ' - "Show me the details of timesheet bc_abc123."',
106
+ ' - "What did I log for the May 1-15 cycle on engagement act_xyz?"',
107
+ ].join("\n"),
108
+ inputSchema: {
109
+ id: z.string().describe("Timesheet id (BillingCycle.id from `timesheet_list`)"),
110
+ dryRun: DRY_RUN_FIELD,
111
+ },
112
+ }, async (args) => {
113
+ const auth = await ctx.resolveToolAuth();
114
+ if (!auth.ok)
115
+ return auth.response;
116
+ if (args.dryRun === true) {
117
+ return dryRunResponse(buildMcpDryRunPreview("TimesheetDetails", "mobile-gateway", { id: args.id }, auth.token));
118
+ }
119
+ try {
120
+ const item = await timesheet.show(auth.token, args.id);
121
+ return successResponse(item);
122
+ }
123
+ catch (err) {
124
+ return mapTimesheetError(err);
125
+ }
126
+ });
127
+ server.registerTool("ttctl_timesheet_submit", {
128
+ title: "Submit a timesheet for billing (DESTRUCTIVE — one-way)",
129
+ description: [
130
+ "Submit a timesheet (BillingCycle.id) for billing. The submission is",
131
+ "one-way at the wire level — once submitted, the timesheet enters",
132
+ "Toptal's billing pipeline and cannot be retracted from this CLI.",
133
+ "",
134
+ "**This is a write operation**. Confirm with the user BEFORE invoking,",
135
+ "including the cycle id, week range, and hours about to be submitted.",
136
+ "",
137
+ "`id` is optional: omitted, the tool resolves the single currently-pending",
138
+ "cycle whose submission window contains 'now'. If zero or multiple",
139
+ "cycles match, the tool returns a structured error so the LLM can",
140
+ "disambiguate before retrying with an explicit id.",
141
+ "",
142
+ "Optional `engagement` (jobActivityItem.id) scopes the auto-resolve to",
143
+ "one engagement — useful when the user has multiple parallel",
144
+ "engagements with overlapping current cycles.",
145
+ "",
146
+ "**`dryRun` caveat**: when `id` is omitted AND `dryRun: true`, the preview",
147
+ "stamps the literal placeholder string `<auto-resolved-at-apply-time>`",
148
+ "into `variables.id` — the apply path's auto-resolve read is SKIPPED on",
149
+ "dry-run (no wire call). Operation name, surface, header redaction, and",
150
+ "variable shape are verbatim; only the cycle-id VALUE is deferred. Do NOT",
151
+ "treat the placeholder as a real BillingCycle id.",
152
+ "",
153
+ "Example user prompts:",
154
+ ' - "Submit my current Toptal timesheet."',
155
+ ' - "Submit timesheet bc_abc123."',
156
+ ' - "Submit my pending timesheet for engagement act_xyz."',
157
+ ].join("\n"),
158
+ inputSchema: {
159
+ id: z
160
+ .string()
161
+ .optional()
162
+ .describe("Timesheet id (BillingCycle.id) to submit. Omit for current-pending auto-resolve."),
163
+ engagement: z
164
+ .string()
165
+ .optional()
166
+ .describe("Scope auto-resolve to one engagement (jobActivityItem.id). Ignored when `id` is supplied."),
167
+ dryRun: DRY_RUN_FIELD,
168
+ },
169
+ }, async (args) => {
170
+ const auth = await ctx.resolveToolAuth();
171
+ if (!auth.ok)
172
+ return auth.response;
173
+ if (args.dryRun === true) {
174
+ // Apply path optionally pre-fetches PendingTimesheets to auto-resolve
175
+ // the cycle id when none is supplied. Dry-run SKIPS that prefetch
176
+ // (per the same "no wire call" semantics engagements.breaks.add
177
+ // applies for its engagement-id translation) and stamps a placeholder
178
+ // string into the SubmitTimesheet preview's `variables.id`. The
179
+ // wire SHAPE (operationName, surface, variables key names, redacted
180
+ // headers) is verbatim; only the cycle-id VALUE is deferred to apply.
181
+ const variables = { id: args.id ?? SUBMIT_AUTO_RESOLVE_PLACEHOLDER };
182
+ return dryRunResponse(buildMcpDryRunPreview("SubmitTimesheet", "mobile-gateway", variables, auth.token));
183
+ }
184
+ try {
185
+ let cycleId;
186
+ if (args.id !== undefined) {
187
+ cycleId = args.id;
188
+ }
189
+ else {
190
+ const resolveOpts = {};
191
+ if (args.engagement !== undefined)
192
+ resolveOpts.engagement = args.engagement;
193
+ const resolution = await timesheet.resolveCurrentCycle(auth.token, resolveOpts);
194
+ if (resolution.kind === "none") {
195
+ return errorResponse("NO_CURRENT_CYCLE", "No billing cycle is currently in its submission window.", "Run `ttctl_timesheet_list` to see what's pending, or specify an id explicitly.");
196
+ }
197
+ if (resolution.kind === "multiple") {
198
+ const lines = resolution.candidates.map((c) => {
199
+ const client = c.engagement.job.client?.fullName ?? "(no client)";
200
+ const title = c.engagement.job.title ?? "(untitled)";
201
+ return ` - ${c.id} (${client} — ${title}, ${c.startDate} → ${c.endDate})`;
202
+ });
203
+ return errorResponse("MULTIPLE_CURRENT_CYCLES", `${resolution.candidates.length.toString()} cycles match the current submission window — specify one explicitly.`, `Candidates:\n${lines.join("\n")}`);
204
+ }
205
+ cycleId = resolution.cycle.id;
206
+ }
207
+ const updated = await timesheet.submit(auth.token, cycleId);
208
+ return successResponse(updated);
209
+ }
210
+ catch (err) {
211
+ return mapTimesheetError(err);
212
+ }
213
+ });
214
+ }
215
+ function successResponse(data) {
216
+ return {
217
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
218
+ };
219
+ }
220
+ function errorResponse(code, message, recovery) {
221
+ return {
222
+ isError: true,
223
+ content: [
224
+ {
225
+ type: "text",
226
+ text: [`Error: ${message}`, "", `Recovery: ${recovery}`, "", `(Code: ${code})`].join("\n"),
227
+ },
228
+ ],
229
+ };
230
+ }
231
+ function mapTimesheetError(err) {
232
+ const typed = ttctlErrorToToolResponseOrNull(err);
233
+ if (typed !== null)
234
+ return typed;
235
+ if (err instanceof timesheet.TimesheetError) {
236
+ return errorResponse(err.code, err.message, recoveryForCode(err.code));
237
+ }
238
+ const message = err instanceof Error ? err.message : String(err);
239
+ return errorResponse("UNKNOWN", `timesheet request failed: ${message}`, "Retry; if the failure persists, file an issue.");
240
+ }
241
+ function recoveryForCode(code) {
242
+ switch (code) {
243
+ case "NOT_FOUND":
244
+ return "Verify the id (use `ttctl_timesheet_list` to discover billing-cycle ids).";
245
+ case "NO_ENGAGEMENT":
246
+ return "The activity item exists but isn't an engagement — only engagement-bearing rows have timesheets.";
247
+ case "NO_CURRENT_CYCLE":
248
+ return "No cycle is currently in its submission window. Run `ttctl_timesheet_list` to see what's pending.";
249
+ case "MULTIPLE_CURRENT_CYCLES":
250
+ return "Multiple cycles overlap — specify the cycle id explicitly via `id`.";
251
+ case "MUTATION_ERROR":
252
+ return "The server rejected the submission (often: missing required hours, deadline passed, or already submitted). Inspect the message above.";
253
+ default:
254
+ return "Adjust the tool input or retry; see the code below.";
255
+ }
256
+ }
257
+ //# sourceMappingURL=timesheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timesheet.js","sourceRoot":"","sources":["../../src/tools/timesheet.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@ttctl/mcp",
3
- "version": "0.0.0",
4
- "description": "TTCtl MCP server exposing Toptal Talent operations to AI assistants — placeholder reservation; real release in development",
3
+ "version": "0.1.0-rc.1",
4
+ "description": "TTCtl MCP server exposing Toptal Talent operations to AI assistants",
5
5
  "type": "module",
6
- "main": "./index.js",
6
+ "engines": {
7
+ "node": ">=22.19.0"
8
+ },
7
9
  "license": "AGPL-3.0-only",
8
10
  "author": "Alexey Pelykh (https://github.com/alexey-pelykh)",
9
11
  "homepage": "https://github.com/alexey-pelykh/ttctl/tree/main/packages/mcp",
@@ -11,20 +13,38 @@
11
13
  "funding": "https://github.com/sponsors/alexey-pelykh",
12
14
  "repository": {
13
15
  "type": "git",
14
- "url": "git+https://github.com/alexey-pelykh/ttctl.git",
16
+ "url": "https://github.com/alexey-pelykh/ttctl.git",
15
17
  "directory": "packages/mcp"
16
18
  },
17
- "keywords": [
18
- "toptal-talent",
19
- "mcp",
20
- "placeholder"
21
- ],
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ }
24
+ },
22
25
  "files": [
23
- "index.js",
24
- "README.md",
25
- "LICENSE"
26
+ "dist"
26
27
  ],
27
28
  "publishConfig": {
28
29
  "access": "public"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^25",
33
+ "eslint": "^10.3.0",
34
+ "typescript": "~6.0.3",
35
+ "vitest": "^4.1.1"
36
+ },
37
+ "dependencies": {
38
+ "@modelcontextprotocol/sdk": "^1.28.0",
39
+ "zod": "^4.4.3",
40
+ "@ttctl/core": "^0.1.0-rc.1"
41
+ },
42
+ "scripts": {
43
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
44
+ "build": "tsc",
45
+ "typecheck": "tsc --noEmit",
46
+ "test": "vitest run --passWithNoTests",
47
+ "lint": "eslint src/",
48
+ "dev": "tsc --watch"
29
49
  }
30
- }
50
+ }
package/index.js DELETED
@@ -1,7 +0,0 @@
1
- // @ttctl/mcp placeholder — name reservation only.
2
- // The real release is in development at https://github.com/alexey-pelykh/ttctl
3
- console.log(
4
- "@ttctl/mcp: this is a placeholder reservation, not a functional release.\n" +
5
- "The real MCP server is in development. See:\n" +
6
- " https://github.com/alexey-pelykh/ttctl",
7
- );