@ttctl/mcp 0.0.0 → 0.1.0-rc.2

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 (195) 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 +133 -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 +129 -0
  63. package/dist/tools/output-schemas.d.ts.map +1 -0
  64. package/dist/tools/output-schemas.js +138 -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 +219 -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 +222 -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 +254 -0
  81. package/dist/tools/profile/employment.js.map +1 -0
  82. package/dist/tools/profile/industries.d.ts +30 -0
  83. package/dist/tools/profile/industries.d.ts.map +1 -0
  84. package/dist/tools/profile/industries.js +196 -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 +64 -0
  111. package/dist/tools/profile_basic_show.d.ts.map +1 -0
  112. package/dist/tools/profile_basic_show.js +108 -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_show.d.ts +15 -0
  139. package/dist/tools/profile_external_show.d.ts.map +1 -0
  140. package/dist/tools/profile_external_show.js +59 -0
  141. package/dist/tools/profile_external_show.js.map +1 -0
  142. package/dist/tools/profile_external_update.d.ts +14 -0
  143. package/dist/tools/profile_external_update.d.ts.map +1 -0
  144. package/dist/tools/profile_external_update.js +79 -0
  145. package/dist/tools/profile_external_update.js.map +1 -0
  146. package/dist/tools/profile_reviews_approve_item.d.ts +17 -0
  147. package/dist/tools/profile_reviews_approve_item.d.ts.map +1 -0
  148. package/dist/tools/profile_reviews_approve_item.js +77 -0
  149. package/dist/tools/profile_reviews_approve_item.js.map +1 -0
  150. package/dist/tools/profile_reviews_approve_section.d.ts +15 -0
  151. package/dist/tools/profile_reviews_approve_section.d.ts.map +1 -0
  152. package/dist/tools/profile_reviews_approve_section.js +70 -0
  153. package/dist/tools/profile_reviews_approve_section.js.map +1 -0
  154. package/dist/tools/profile_reviews_list.d.ts +16 -0
  155. package/dist/tools/profile_reviews_list.d.ts.map +1 -0
  156. package/dist/tools/profile_reviews_list.js +58 -0
  157. package/dist/tools/profile_reviews_list.js.map +1 -0
  158. package/dist/tools/profile_reviews_submit_for_review.d.ts +14 -0
  159. package/dist/tools/profile_reviews_submit_for_review.d.ts.map +1 -0
  160. package/dist/tools/profile_reviews_submit_for_review.js +56 -0
  161. package/dist/tools/profile_reviews_submit_for_review.js.map +1 -0
  162. package/dist/tools/profile_skills_add.d.ts +4 -0
  163. package/dist/tools/profile_skills_add.d.ts.map +1 -0
  164. package/dist/tools/profile_skills_add.js +52 -0
  165. package/dist/tools/profile_skills_add.js.map +1 -0
  166. package/dist/tools/profile_skills_autocomplete.d.ts +4 -0
  167. package/dist/tools/profile_skills_autocomplete.d.ts.map +1 -0
  168. package/dist/tools/profile_skills_autocomplete.js +78 -0
  169. package/dist/tools/profile_skills_autocomplete.js.map +1 -0
  170. package/dist/tools/profile_skills_list.d.ts +16 -0
  171. package/dist/tools/profile_skills_list.d.ts.map +1 -0
  172. package/dist/tools/profile_skills_list.js +65 -0
  173. package/dist/tools/profile_skills_list.js.map +1 -0
  174. package/dist/tools/profile_skills_readiness.d.ts +4 -0
  175. package/dist/tools/profile_skills_readiness.d.ts.map +1 -0
  176. package/dist/tools/profile_skills_readiness.js +53 -0
  177. package/dist/tools/profile_skills_readiness.js.map +1 -0
  178. package/dist/tools/profile_skills_remove.d.ts +4 -0
  179. package/dist/tools/profile_skills_remove.d.ts.map +1 -0
  180. package/dist/tools/profile_skills_remove.js +53 -0
  181. package/dist/tools/profile_skills_remove.js.map +1 -0
  182. package/dist/tools/profile_skills_show.d.ts +4 -0
  183. package/dist/tools/profile_skills_show.d.ts.map +1 -0
  184. package/dist/tools/profile_skills_show.js +51 -0
  185. package/dist/tools/profile_skills_show.js.map +1 -0
  186. package/dist/tools/profile_skills_update.d.ts +11 -0
  187. package/dist/tools/profile_skills_update.d.ts.map +1 -0
  188. package/dist/tools/profile_skills_update.js +97 -0
  189. package/dist/tools/profile_skills_update.js.map +1 -0
  190. package/dist/tools/timesheet.d.ts +29 -0
  191. package/dist/tools/timesheet.d.ts.map +1 -0
  192. package/dist/tools/timesheet.js +257 -0
  193. package/dist/tools/timesheet.js.map +1 -0
  194. package/package.json +33 -13
  195. package/index.js +0 -7
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ export declare function registerProfileSkillsAddTool(server: McpServer, ctx: ToolRegistrationContext): void;
4
+ //# sourceMappingURL=profile_skills_add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_add.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_add.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAOL,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAWtB,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CAmDlG"}
@@ -0,0 +1,52 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunResponse, genericErrorResponse, isToolErrorResponse, jsonResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_add";
8
+ const DRY_RUN_FIELD = z
9
+ .boolean()
10
+ .optional()
11
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
12
+ export function registerProfileSkillsAddTool(server, ctx) {
13
+ server.registerTool(TOOL_NAME, {
14
+ title: "Add a skill to profile",
15
+ description: [
16
+ "Add a skill to the signed-in user's profile by its catalog name (e.g., `TypeScript`, `PostgreSQL`).",
17
+ "Returns the new ProfileSkillSet with default rating/experience/visibility — configure those via `ttctl_profile_skills_update`.",
18
+ "",
19
+ "Example user prompts that should map to this tool:",
20
+ ' - "Add TypeScript to my Toptal skills."',
21
+ ' - "Add PostgreSQL as a skill on my profile."',
22
+ ].join("\n"),
23
+ inputSchema: {
24
+ name: z
25
+ .string()
26
+ .min(1)
27
+ .describe('Skill catalog name to add. The server resolves the name to a Skill id; if the name is ambiguous (e.g., "Postgres" vs "PostgreSQL"), use `ttctl_profile_skills_autocomplete` first to disambiguate.'),
28
+ dryRun: DRY_RUN_FIELD,
29
+ },
30
+ }, async (input) => {
31
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
32
+ if (isToolErrorResponse(auth))
33
+ return auth;
34
+ if (input.dryRun === true) {
35
+ return dryRunResponse(buildMcpDryRunPreview("ADD_PROFILE_SKILL_SET", "talent-profile", { input: { name: input.name.trim() } }, auth.token));
36
+ }
37
+ try {
38
+ const result = await profile.skills.add(auth.token, input.name);
39
+ return jsonResponse(result);
40
+ }
41
+ catch (err) {
42
+ const typed = ttctlErrorToToolResponseOrNull(err);
43
+ if (typed !== null)
44
+ return typed;
45
+ if (err instanceof profile.skills.SkillsError) {
46
+ return domainErrorResponse(TOOL_NAME, err);
47
+ }
48
+ return genericErrorResponse(TOOL_NAME, err);
49
+ }
50
+ });
51
+ }
52
+ //# sourceMappingURL=profile_skills_add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_add.js","sourceRoot":"","sources":["../../src/tools/profile_skills_add.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,GAEb,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,0BAA0B,CAAC;AAE7C,MAAM,aAAa,GAAG,CAAC;KACpB,OAAO,EAAE;KACT,QAAQ,EAAE;KACV,QAAQ,CACP,+JAA+J,CAChK,CAAC;AAEJ,MAAM,UAAU,4BAA4B,CAAC,MAAiB,EAAE,GAA4B;IAC1F,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE;YACX,qGAAqG;YACrG,gIAAgI;YAChI,EAAE;YACF,oDAAoD;YACpD,2CAA2C;YAC3C,gDAAgD;SACjD,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CACP,oMAAoM,CACrM;YACH,MAAM,EAAE,aAAa;SACtB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,cAAc,CACnB,qBAAqB,CACnB,uBAAuB,EACvB,gBAAgB,EAChB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,EACtC,IAAI,CAAC,KAAK,CACX,CACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAChE,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,GAAG,YAAY,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC9C,OAAO,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,oBAAoB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ export declare function registerProfileSkillsAutocompleteTool(server: McpServer, ctx: ToolRegistrationContext): void;
4
+ //# sourceMappingURL=profile_skills_autocomplete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_autocomplete.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_autocomplete.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAOL,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAWtB,wBAAgB,qCAAqC,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CA2E3G"}
@@ -0,0 +1,78 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunResponse, genericErrorResponse, isToolErrorResponse, jsonResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_autocomplete";
8
+ const DRY_RUN_FIELD = z
9
+ .boolean()
10
+ .optional()
11
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
12
+ export function registerProfileSkillsAutocompleteTool(server, ctx) {
13
+ server.registerTool(TOOL_NAME, {
14
+ title: "Search global skill catalog",
15
+ description: [
16
+ "Search the global Toptal skill catalog for entries matching `query` (suitable for disambiguating before calling `ttctl_profile_skills_add`).",
17
+ "Results are scoped to skills the talent's vertical permits and exclude any ids passed in `withoutIds` (e.g., the talent's existing skills).",
18
+ "",
19
+ "Example user prompts that should map to this tool:",
20
+ " - \"Search Toptal's catalog for 'postgres' before I add it.\"",
21
+ " - \"Find skill names matching 'java'.\"",
22
+ ].join("\n"),
23
+ inputSchema: {
24
+ query: z.string().min(1).describe("Substring to search for in skill names. Case-insensitive."),
25
+ limit: z
26
+ .number()
27
+ .int()
28
+ .min(1)
29
+ .max(50)
30
+ .optional()
31
+ .describe("Max number of suggestions to return. Defaults to 10. Range: 1-50."),
32
+ withoutIds: z
33
+ .array(z.string().min(1))
34
+ .optional()
35
+ .describe("Skill catalog ids to exclude from the results — typically the talent's existing skill catalog ids so the dropdown doesn't suggest skills already on the profile."),
36
+ dryRun: DRY_RUN_FIELD,
37
+ },
38
+ }, async (input) => {
39
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
40
+ if (isToolErrorResponse(auth))
41
+ return auth;
42
+ if (input.dryRun === true) {
43
+ return dryRunResponse(buildMcpDryRunPreview("GET_SKILLS_FOR_AUTOCOMPLETE", "talent-profile", {
44
+ profileId: profile.basic.DRY_RUN_PROFILE_ID_PLACEHOLDER,
45
+ search: input.query.trim(),
46
+ limit: input.limit ?? 10,
47
+ withoutIds: input.withoutIds ?? [],
48
+ }, auth.token));
49
+ }
50
+ try {
51
+ const profilePayload = await profile.basic.show(auth.token);
52
+ const profileId = profilePayload.viewer?.viewerRole.profileId;
53
+ if (profileId === undefined) {
54
+ return domainErrorResponse(TOOL_NAME, {
55
+ code: "NO_VIEWER",
56
+ message: "No profile id bound to this session.",
57
+ });
58
+ }
59
+ const options = {};
60
+ if (input.limit !== undefined)
61
+ options.limit = input.limit;
62
+ if (input.withoutIds !== undefined)
63
+ options.withoutIds = input.withoutIds;
64
+ const suggestions = await profile.skills.autocomplete(auth.token, profileId, input.query, options);
65
+ return jsonResponse(suggestions);
66
+ }
67
+ catch (err) {
68
+ const typed = ttctlErrorToToolResponseOrNull(err);
69
+ if (typed !== null)
70
+ return typed;
71
+ if (err instanceof profile.skills.SkillsError || err instanceof profile.basic.ProfileError) {
72
+ return domainErrorResponse(TOOL_NAME, err);
73
+ }
74
+ return genericErrorResponse(TOOL_NAME, err);
75
+ }
76
+ });
77
+ }
78
+ //# sourceMappingURL=profile_skills_autocomplete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_autocomplete.js","sourceRoot":"","sources":["../../src/tools/profile_skills_autocomplete.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,GAEb,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,mCAAmC,CAAC;AAEtD,MAAM,aAAa,GAAG,CAAC;KACpB,OAAO,EAAE;KACT,QAAQ,EAAE;KACV,QAAQ,CACP,+JAA+J,CAChK,CAAC;AAEJ,MAAM,UAAU,qCAAqC,CAAC,MAAiB,EAAE,GAA4B;IACnG,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EAAE;YACX,8IAA8I;YAC9I,6IAA6I;YAC7I,EAAE;YACF,oDAAoD;YACpD,iEAAiE;YACjE,2CAA2C;SAC5C,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,2DAA2D,CAAC;YAC9F,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,EAAE,CAAC;iBACP,QAAQ,EAAE;iBACV,QAAQ,CAAC,mEAAmE,CAAC;YAChF,UAAU,EAAE,CAAC;iBACV,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;iBACxB,QAAQ,EAAE;iBACV,QAAQ,CACP,kKAAkK,CACnK;YACH,MAAM,EAAE,aAAa;SACtB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,cAAc,CACnB,qBAAqB,CACnB,6BAA6B,EAC7B,gBAAgB,EAChB;gBACE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,8BAA8B;gBACvD,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;gBAC1B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;gBACxB,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE;aACnC,EACD,IAAI,CAAC,KAAK,CACX,CACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC;YAC9D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO,mBAAmB,CAAC,SAAS,EAAE;oBACpC,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,sCAAsC;iBAChD,CAAC,CAAC;YACL,CAAC;YACD,MAAM,OAAO,GAA8C,EAAE,CAAC;YAC9D,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3D,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;gBAAE,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YAC1E,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACnG,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,GAAG,YAAY,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,YAAY,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBAC3F,OAAO,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,oBAAoB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ /**
4
+ * Register `ttctl_profile_skills_list`. Returns every skill on the
5
+ * signed-in user's profile, with rating / experience / visibility /
6
+ * connection-count summary. Resolves the user's `profileId` internally
7
+ * via `profile.basic.show()` — no input required from the caller.
8
+ *
9
+ * Dry-run path (issue #165): accepts `dryRun?: boolean`; emits the
10
+ * uniform envelope previewing
11
+ * `getSkillSetsWithConnectionsWithConnectionsCount` against the
12
+ * talent-profile surface. `profileId` carries the placeholder because
13
+ * the apply path resolves it via a sibling profile read.
14
+ */
15
+ export declare function registerProfileSkillsListTool(server: McpServer, ctx: ToolRegistrationContext): void;
16
+ //# sourceMappingURL=profile_skills_list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_list.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_list.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAOL,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAWtB;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CAkDnG"}
@@ -0,0 +1,65 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunResponse, genericErrorResponse, isToolErrorResponse, jsonResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_list";
8
+ const DRY_RUN_FIELD = z
9
+ .boolean()
10
+ .optional()
11
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
12
+ /**
13
+ * Register `ttctl_profile_skills_list`. Returns every skill on the
14
+ * signed-in user's profile, with rating / experience / visibility /
15
+ * connection-count summary. Resolves the user's `profileId` internally
16
+ * via `profile.basic.show()` — no input required from the caller.
17
+ *
18
+ * Dry-run path (issue #165): accepts `dryRun?: boolean`; emits the
19
+ * uniform envelope previewing
20
+ * `getSkillSetsWithConnectionsWithConnectionsCount` against the
21
+ * talent-profile surface. `profileId` carries the placeholder because
22
+ * the apply path resolves it via a sibling profile read.
23
+ */
24
+ export function registerProfileSkillsListTool(server, ctx) {
25
+ server.registerTool(TOOL_NAME, {
26
+ title: "List profile skills",
27
+ description: [
28
+ "List every skill on the signed-in user's Toptal profile, with rating / experience / visibility / connection-count for each.",
29
+ "",
30
+ "Example user prompts that should map to this tool:",
31
+ ' - "What skills do I have on my Toptal profile?"',
32
+ ' - "List my Toptal skills with their ratings."',
33
+ ].join("\n"),
34
+ inputSchema: { dryRun: DRY_RUN_FIELD },
35
+ }, async (input) => {
36
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
37
+ if (isToolErrorResponse(auth))
38
+ return auth;
39
+ if (input.dryRun === true) {
40
+ return dryRunResponse(buildMcpDryRunPreview("getSkillSetsWithConnectionsWithConnectionsCount", "talent-profile", { profileId: profile.basic.DRY_RUN_PROFILE_ID_PLACEHOLDER }, auth.token));
41
+ }
42
+ try {
43
+ const profilePayload = await profile.basic.show(auth.token);
44
+ const profileId = profilePayload.viewer?.viewerRole.profileId;
45
+ if (profileId === undefined) {
46
+ return domainErrorResponse(TOOL_NAME, {
47
+ code: "NO_VIEWER",
48
+ message: "No profile id bound to this session.",
49
+ });
50
+ }
51
+ const skills = await profile.skills.list(auth.token, profileId);
52
+ return jsonResponse(skills);
53
+ }
54
+ catch (err) {
55
+ const typed = ttctlErrorToToolResponseOrNull(err);
56
+ if (typed !== null)
57
+ return typed;
58
+ if (err instanceof profile.skills.SkillsError || err instanceof profile.basic.ProfileError) {
59
+ return domainErrorResponse(TOOL_NAME, err);
60
+ }
61
+ return genericErrorResponse(TOOL_NAME, err);
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=profile_skills_list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_list.js","sourceRoot":"","sources":["../../src/tools/profile_skills_list.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,GAEb,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAE9C,MAAM,aAAa,GAAG,CAAC;KACpB,OAAO,EAAE;KACT,QAAQ,EAAE;KACV,QAAQ,CACP,+JAA+J,CAChK,CAAC;AAEJ;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAAiB,EAAE,GAA4B;IAC3F,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE;YACX,6HAA6H;YAC7H,EAAE;YACF,oDAAoD;YACpD,mDAAmD;YACnD,iDAAiD;SAClD,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE;KACvC,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,cAAc,CACnB,qBAAqB,CACnB,iDAAiD,EACjD,gBAAgB,EAChB,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,EAC3D,IAAI,CAAC,KAAK,CACX,CACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC;YAC9D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO,mBAAmB,CAAC,SAAS,EAAE;oBACpC,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,sCAAsC;iBAChD,CAAC,CAAC;YACL,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAChE,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,GAAG,YAAY,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,YAAY,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBAC3F,OAAO,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,oBAAoB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ export declare function registerProfileSkillsReadinessTool(server: McpServer, ctx: ToolRegistrationContext): void;
4
+ //# sourceMappingURL=profile_skills_readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_readiness.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_readiness.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAOL,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAWtB,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CAkDxG"}
@@ -0,0 +1,53 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunResponse, genericErrorResponse, isToolErrorResponse, jsonResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_readiness";
8
+ const DRY_RUN_FIELD = z
9
+ .boolean()
10
+ .optional()
11
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
12
+ export function registerProfileSkillsReadinessTool(server, ctx) {
13
+ server.registerTool(TOOL_NAME, {
14
+ title: "Show skill-readiness checklist",
15
+ description: [
16
+ "Fetch the signed-in user's skill-readiness checklist — the same heuristics the portal uses to gate the 'ready to apply' state on the skills section. Each boolean reflects a sub-criterion (expert proficiency count, items count, programming language present, etc.).",
17
+ "",
18
+ "Example user prompts that should map to this tool:",
19
+ ' - "Are my Toptal skills complete enough?"',
20
+ ' - "Tell me what\'s missing on my skills section."',
21
+ ].join("\n"),
22
+ inputSchema: { dryRun: DRY_RUN_FIELD },
23
+ }, async (input) => {
24
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
25
+ if (isToolErrorResponse(auth))
26
+ return auth;
27
+ if (input.dryRun === true) {
28
+ return dryRunResponse(buildMcpDryRunPreview("getSkillsReadiness", "talent-profile", { profileId: profile.basic.DRY_RUN_PROFILE_ID_PLACEHOLDER }, auth.token));
29
+ }
30
+ try {
31
+ const profilePayload = await profile.basic.show(auth.token);
32
+ const profileId = profilePayload.viewer?.viewerRole.profileId;
33
+ if (profileId === undefined) {
34
+ return domainErrorResponse(TOOL_NAME, {
35
+ code: "NO_VIEWER",
36
+ message: "No profile id bound to this session.",
37
+ });
38
+ }
39
+ const readiness = await profile.skills.readiness(auth.token, profileId);
40
+ return jsonResponse(readiness);
41
+ }
42
+ catch (err) {
43
+ const typed = ttctlErrorToToolResponseOrNull(err);
44
+ if (typed !== null)
45
+ return typed;
46
+ if (err instanceof profile.skills.SkillsError || err instanceof profile.basic.ProfileError) {
47
+ return domainErrorResponse(TOOL_NAME, err);
48
+ }
49
+ return genericErrorResponse(TOOL_NAME, err);
50
+ }
51
+ });
52
+ }
53
+ //# sourceMappingURL=profile_skills_readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_readiness.js","sourceRoot":"","sources":["../../src/tools/profile_skills_readiness.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,GAEb,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,gCAAgC,CAAC;AAEnD,MAAM,aAAa,GAAG,CAAC;KACpB,OAAO,EAAE;KACT,QAAQ,EAAE;KACV,QAAQ,CACP,+JAA+J,CAChK,CAAC;AAEJ,MAAM,UAAU,kCAAkC,CAAC,MAAiB,EAAE,GAA4B;IAChG,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,gCAAgC;QACvC,WAAW,EAAE;YACX,yQAAyQ;YACzQ,EAAE;YACF,oDAAoD;YACpD,6CAA6C;YAC7C,qDAAqD;SACtD,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE;KACvC,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,cAAc,CACnB,qBAAqB,CACnB,oBAAoB,EACpB,gBAAgB,EAChB,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,EAC3D,IAAI,CAAC,KAAK,CACX,CACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC;YAC9D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO,mBAAmB,CAAC,SAAS,EAAE;oBACpC,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,sCAAsC;iBAChD,CAAC,CAAC;YACL,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACxE,OAAO,YAAY,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,GAAG,YAAY,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,YAAY,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBAC3F,OAAO,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,oBAAoB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ export declare function registerProfileSkillsRemoveTool(server: McpServer, ctx: ToolRegistrationContext): void;
4
+ //# sourceMappingURL=profile_skills_remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_remove.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_remove.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAML,KAAK,uBAAuB,EAE7B,MAAM,cAAc,CAAC;AAWtB,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CAkDrG"}
@@ -0,0 +1,53 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunResponse, genericErrorResponse, isToolErrorResponse, textResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_remove";
8
+ const DRY_RUN_FIELD = z
9
+ .boolean()
10
+ .optional()
11
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
12
+ export function registerProfileSkillsRemoveTool(server, ctx) {
13
+ server.registerTool(TOOL_NAME, {
14
+ title: "Remove a skill from profile",
15
+ description: [
16
+ "Remove a skill from the signed-in user's profile by its `ProfileSkillSet` id (NOT the Skill catalog id).",
17
+ "Get the id from `ttctl_profile_skills_list` first if you only know the skill name.",
18
+ "Removal cascades to any connections (portfolio items, education, employment, certifications).",
19
+ "",
20
+ "Example user prompts that should map to this tool:",
21
+ ' - "Remove the TypeScript skill from my profile." (after looking up its id)',
22
+ ' - "Drop skill ss-abc123 from my profile."',
23
+ ].join("\n"),
24
+ inputSchema: {
25
+ id: z
26
+ .string()
27
+ .min(1)
28
+ .describe("ProfileSkillSet id to remove (NOT the Skill catalog id). Obtain via `ttctl_profile_skills_list`."),
29
+ dryRun: DRY_RUN_FIELD,
30
+ },
31
+ }, async (input) => {
32
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
33
+ if (isToolErrorResponse(auth))
34
+ return auth;
35
+ if (input.dryRun === true) {
36
+ return dryRunResponse(buildMcpDryRunPreview("REMOVE_PROFILE_SKILL_SET", "talent-profile", { input: { skillSetId: input.id } }, auth.token));
37
+ }
38
+ try {
39
+ await profile.skills.rm(auth.token, input.id);
40
+ return textResponse(`Removed skill ${input.id}.`);
41
+ }
42
+ catch (err) {
43
+ const typed = ttctlErrorToToolResponseOrNull(err);
44
+ if (typed !== null)
45
+ return typed;
46
+ if (err instanceof profile.skills.SkillsError) {
47
+ return domainErrorResponse(TOOL_NAME, err);
48
+ }
49
+ return genericErrorResponse(TOOL_NAME, err);
50
+ }
51
+ });
52
+ }
53
+ //# sourceMappingURL=profile_skills_remove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_remove.js","sourceRoot":"","sources":["../../src/tools/profile_skills_remove.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EAEnB,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,6BAA6B,CAAC;AAEhD,MAAM,aAAa,GAAG,CAAC;KACpB,OAAO,EAAE;KACT,QAAQ,EAAE;KACV,QAAQ,CACP,+JAA+J,CAChK,CAAC;AAEJ,MAAM,UAAU,+BAA+B,CAAC,MAAiB,EAAE,GAA4B;IAC7F,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EAAE;YACX,0GAA0G;YAC1G,oFAAoF;YACpF,+FAA+F;YAC/F,EAAE;YACF,oDAAoD;YACpD,8EAA8E;YAC9E,6CAA6C;SAC9C,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,EAAE,EAAE,CAAC;iBACF,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,kGAAkG,CAAC;YAC/G,MAAM,EAAE,aAAa;SACtB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,cAAc,CACnB,qBAAqB,CACnB,0BAA0B,EAC1B,gBAAgB,EAChB,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EACnC,IAAI,CAAC,KAAK,CACX,CACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,YAAY,CAAC,iBAAiB,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,GAAG,YAAY,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC9C,OAAO,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,oBAAoB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ export declare function registerProfileSkillsShowTool(server: McpServer, ctx: ToolRegistrationContext): void;
4
+ //# sourceMappingURL=profile_skills_show.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_show.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_show.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAOL,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAWtB,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CA2CnG"}
@@ -0,0 +1,51 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunResponse, genericErrorResponse, isToolErrorResponse, jsonResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_show";
8
+ const DRY_RUN_FIELD = z
9
+ .boolean()
10
+ .optional()
11
+ .describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
12
+ export function registerProfileSkillsShowTool(server, ctx) {
13
+ server.registerTool(TOOL_NAME, {
14
+ title: "Show a skill",
15
+ description: [
16
+ "Fetch details of a single ProfileSkillSet by id — name, rating, experience, visibility, and the count of connection edges (linked portfolio items / employment / education / certifications).",
17
+ "",
18
+ "Example user prompts that should map to this tool:",
19
+ ' - "Show me the details of my TypeScript skill on Toptal." (after looking up its id)',
20
+ ' - "What\'s the rating and connection count for skill ss-abc123?"',
21
+ ].join("\n"),
22
+ inputSchema: {
23
+ id: z
24
+ .string()
25
+ .min(1)
26
+ .describe("ProfileSkillSet id (NOT the Skill catalog id). Obtain via `ttctl_profile_skills_list`."),
27
+ dryRun: DRY_RUN_FIELD,
28
+ },
29
+ }, async (input) => {
30
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
31
+ if (isToolErrorResponse(auth))
32
+ return auth;
33
+ if (input.dryRun === true) {
34
+ return dryRunResponse(buildMcpDryRunPreview("GetSkillSetWithConnections", "talent-profile", { id: input.id }, auth.token));
35
+ }
36
+ try {
37
+ const payload = await profile.skills.show(auth.token, input.id);
38
+ return jsonResponse(payload);
39
+ }
40
+ catch (err) {
41
+ const typed = ttctlErrorToToolResponseOrNull(err);
42
+ if (typed !== null)
43
+ return typed;
44
+ if (err instanceof profile.skills.SkillsError) {
45
+ return domainErrorResponse(TOOL_NAME, err);
46
+ }
47
+ return genericErrorResponse(TOOL_NAME, err);
48
+ }
49
+ });
50
+ }
51
+ //# sourceMappingURL=profile_skills_show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_show.js","sourceRoot":"","sources":["../../src/tools/profile_skills_show.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,GAEb,MAAM,cAAc,CAAC;AAEtB,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAE9C,MAAM,aAAa,GAAG,CAAC;KACpB,OAAO,EAAE;KACT,QAAQ,EAAE;KACV,QAAQ,CACP,+JAA+J,CAChK,CAAC;AAEJ,MAAM,UAAU,6BAA6B,CAAC,MAAiB,EAAE,GAA4B;IAC3F,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE;YACX,+LAA+L;YAC/L,EAAE;YACF,oDAAoD;YACpD,uFAAuF;YACvF,oEAAoE;SACrE,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,WAAW,EAAE;YACX,EAAE,EAAE,CAAC;iBACF,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,wFAAwF,CAAC;YACrG,MAAM,EAAE,aAAa;SACtB;KACF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,mBAAmB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE3C,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,cAAc,CACnB,qBAAqB,CAAC,4BAA4B,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CACpG,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YAChE,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YACjC,IAAI,GAAG,YAAY,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC9C,OAAO,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,oBAAoB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ /**
4
+ * Multi-mutation tool: `profile.skills.set` fires one mutation per
5
+ * supplied field (rating, experience, publicity). Dry-run therefore emits
6
+ * the plural `{ previews: [...] }` envelope (via {@link dryRunMultiResponse}),
7
+ * one preview per mutation that would actually fire — order matches the
8
+ * apply path's field iteration: rating → experience → public.
9
+ */
10
+ export declare function registerProfileSkillsUpdateTool(server: McpServer, ctx: ToolRegistrationContext): void;
11
+ //# sourceMappingURL=profile_skills_update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_update.d.ts","sourceRoot":"","sources":["../../src/tools/profile_skills_update.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,EAOL,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAatB;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CAoGrG"}
@@ -0,0 +1,97 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { profile } from "@ttctl/core";
4
+ import { z } from "zod";
5
+ import { ttctlErrorToToolResponseOrNull } from "../errors.js";
6
+ import { buildMcpDryRunPreview, domainErrorResponse, dryRunMultiResponse, genericErrorResponse, isToolErrorResponse, jsonResponse, } from "./_shared.js";
7
+ const TOOL_NAME = "ttctl_profile_skills_update";
8
+ const RATING_VALUES = ["COMPETENT", "STRONG", "EXPERT", "NOVICE"];
9
+ const DRY_RUN_FIELD = z
10
+ .boolean()
11
+ .optional()
12
+ .describe("Preview the requests without executing. Returns `{ ok: true, dryRun: true, previews: [...] }` (NOTE: plural `previews` — this tool fires one mutation per supplied field, so the envelope carries an array). Default: false.");
13
+ /**
14
+ * Multi-mutation tool: `profile.skills.set` fires one mutation per
15
+ * supplied field (rating, experience, publicity). Dry-run therefore emits
16
+ * the plural `{ previews: [...] }` envelope (via {@link dryRunMultiResponse}),
17
+ * one preview per mutation that would actually fire — order matches the
18
+ * apply path's field iteration: rating → experience → public.
19
+ */
20
+ export function registerProfileSkillsUpdateTool(server, ctx) {
21
+ server.registerTool(TOOL_NAME, {
22
+ title: "Update a skill",
23
+ description: [
24
+ "Update one or more fields on an existing ProfileSkillSet — proficiency rating, years of experience, public/private visibility.",
25
+ "At least one of `rating`, `experience`, or `public` must be supplied. Multi-flag updates fire sequential mutations; partial-failure surfaces as `PARTIAL_FAILURE` listing which fields landed.",
26
+ "",
27
+ "Dry-run note: returns `{ ok: true, dryRun: true, previews: [...] }` (plural `previews`) — one preview per mutation that would actually fire, in apply-path order (rating → experience → public).",
28
+ "",
29
+ "Example user prompts that should map to this tool:",
30
+ ' - "Mark TypeScript as expert level on my profile." (after looking up its id)',
31
+ ' - "Set my Python skill to public, expert level, 60 months of experience."',
32
+ ' - "Hide my Bash skill from my public profile."',
33
+ ].join("\n"),
34
+ inputSchema: {
35
+ id: z.string().min(1).describe("ProfileSkillSet id of the skill to update (NOT the Skill catalog id)."),
36
+ rating: z
37
+ .enum(RATING_VALUES)
38
+ .optional()
39
+ .describe("Proficiency rating. One of: COMPETENT, STRONG, EXPERT, NOVICE. Optional."),
40
+ experience: z
41
+ .number()
42
+ .int()
43
+ .min(0)
44
+ .optional()
45
+ .describe("Total months of experience on this skill (integer, >= 0). E.g., 60 for 5 years. Optional."),
46
+ public: z
47
+ .boolean()
48
+ .optional()
49
+ .describe("Whether the skill is visible on the public profile. `true` = public, `false` = private. Optional."),
50
+ dryRun: DRY_RUN_FIELD,
51
+ },
52
+ }, async (input) => {
53
+ const auth = await ctx.loadTokenForTool(TOOL_NAME);
54
+ if (isToolErrorResponse(auth))
55
+ return auth;
56
+ const fields = {};
57
+ if (input.rating !== undefined)
58
+ fields.rating = input.rating;
59
+ if (input.experience !== undefined)
60
+ fields.experience = input.experience;
61
+ if (input.public !== undefined)
62
+ fields.public = input.public;
63
+ if (input.dryRun === true) {
64
+ if (Object.keys(fields).length === 0) {
65
+ return domainErrorResponse(TOOL_NAME, {
66
+ code: "VALIDATION_ERROR",
67
+ message: "At least one of `rating`, `experience`, or `public` must be supplied to preview a skills update.",
68
+ });
69
+ }
70
+ const previews = [];
71
+ if (fields.rating !== undefined) {
72
+ previews.push(buildMcpDryRunPreview("UPDATE_PROFILE_SKILL_SET_RATING", "talent-profile", { input: { skillSetId: input.id, skillSet: { rating: fields.rating } } }, auth.token));
73
+ }
74
+ if (fields.experience !== undefined) {
75
+ previews.push(buildMcpDryRunPreview("UPDATE_PROFILE_SKILL_SET_EXPERIENCE", "talent-profile", { input: { skillSetId: input.id, skillSet: { experience: fields.experience } } }, auth.token));
76
+ }
77
+ if (fields.public !== undefined) {
78
+ previews.push(buildMcpDryRunPreview("UPDATE_PROFILE_SKILL_SET_PUBLICITY", "talent-profile", { input: { skillSetId: input.id, skillSet: { public: fields.public } } }, auth.token));
79
+ }
80
+ return dryRunMultiResponse(previews);
81
+ }
82
+ try {
83
+ const result = await profile.skills.set(auth.token, input.id, fields);
84
+ return jsonResponse(result);
85
+ }
86
+ catch (err) {
87
+ const typed = ttctlErrorToToolResponseOrNull(err);
88
+ if (typed !== null)
89
+ return typed;
90
+ if (err instanceof profile.skills.SkillsError) {
91
+ return domainErrorResponse(TOOL_NAME, err);
92
+ }
93
+ return genericErrorResponse(TOOL_NAME, err);
94
+ }
95
+ });
96
+ }
97
+ //# sourceMappingURL=profile_skills_update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile_skills_update.js","sourceRoot":"","sources":["../../src/tools/profile_skills_update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolRegistrationContext } from "./_shared.js";
3
+ /**
4
+ * Register the `ttctl_timesheet_*` MCP tools per the #13 spec. Tool
5
+ * names use the `ttctl_` prefix and the canonical CLI path joined
6
+ * with `_`:
7
+ *
8
+ * - `ttctl_timesheet_list`
9
+ * - `ttctl_timesheet_show`
10
+ * - `ttctl_timesheet_submit`
11
+ *
12
+ * Each tool maps 1:1 to a CLI leaf — schemas describe the same set of
13
+ * fields. Identity model:
14
+ *
15
+ * - `BillingCycle.id` — the "timesheet id" returned by
16
+ * `timesheet_list` and consumed by
17
+ * `timesheet_show` / `timesheet_submit`.
18
+ * - `JobActivityItem.id` — the "engagement id" exposed by
19
+ * `engagements_list`. Passed via
20
+ * `engagement` to scope.
21
+ *
22
+ * Submit is destructive — its tool description explicitly warns
23
+ * humans, and per #13 the CLI gates on `--confirm` / TTY interactive
24
+ * confirm. The MCP side has no analogous gate (LLM clients are
25
+ * expected to confirm with the human before invoking write tools)
26
+ * but the description and rationale are surfaced verbatim.
27
+ */
28
+ export declare function registerTimesheetTools(server: McpServer, ctx: ToolRegistrationContext): void;
29
+ //# sourceMappingURL=timesheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timesheet.d.ts","sourceRoot":"","sources":["../../src/tools/timesheet.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,EAAyC,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAmBnG;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,uBAAuB,GAAG,IAAI,CA0L5F"}