@daghis/teamcity-mcp 0.1.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 (1133) hide show
  1. package/.commitlintrc.js +3 -0
  2. package/.eslintignore +16 -0
  3. package/.eslintrc.js +166 -0
  4. package/.github/settings.yml +7 -0
  5. package/.github/workflows/ci.yml +111 -0
  6. package/.github/workflows/codeql.yml +35 -0
  7. package/.github/workflows/commitlint.yml +20 -0
  8. package/.github/workflows/publish.yml +47 -0
  9. package/.github/workflows/release-please.yml +21 -0
  10. package/.nvmrc +1 -0
  11. package/.prettierignore +22 -0
  12. package/.prettierrc +28 -0
  13. package/AGENTS.md +68 -0
  14. package/ARCHITECTURE.md +66 -0
  15. package/CHANGELOG.md +8 -0
  16. package/CONTRIBUTING.md +68 -0
  17. package/LICENSE +22 -0
  18. package/README.md +256 -0
  19. package/TODO.md +80 -0
  20. package/dist/index.js +42216 -0
  21. package/dist/index.js.map +7 -0
  22. package/dist/src/api-client.d.ts +51 -0
  23. package/dist/src/api-client.d.ts.map +1 -0
  24. package/dist/src/config/index.d.ts +41 -0
  25. package/dist/src/config/index.d.ts.map +1 -0
  26. package/dist/src/errors/index.d.ts +2 -0
  27. package/dist/src/errors/index.d.ts.map +1 -0
  28. package/dist/src/formatters/build-step-formatter.d.ts +5 -0
  29. package/dist/src/formatters/build-step-formatter.d.ts.map +1 -0
  30. package/dist/src/formatters/trigger-formatter.d.ts +4 -0
  31. package/dist/src/formatters/trigger-formatter.d.ts.map +1 -0
  32. package/dist/src/index.d.ts +3 -0
  33. package/dist/src/index.d.ts.map +1 -0
  34. package/dist/src/middleware/error.d.ts +56 -0
  35. package/dist/src/middleware/error.d.ts.map +1 -0
  36. package/dist/src/middleware/global-error-handler.d.ts +22 -0
  37. package/dist/src/middleware/global-error-handler.d.ts.map +1 -0
  38. package/dist/src/middleware/index.d.ts +2 -0
  39. package/dist/src/middleware/index.d.ts.map +1 -0
  40. package/dist/src/server.d.ts +4 -0
  41. package/dist/src/server.d.ts.map +1 -0
  42. package/dist/src/swagger/index.d.ts +43 -0
  43. package/dist/src/swagger/index.d.ts.map +1 -0
  44. package/dist/src/swagger/swagger-cache.d.ts +23 -0
  45. package/dist/src/swagger/swagger-cache.d.ts.map +1 -0
  46. package/dist/src/swagger/swagger-fetcher.d.ts +24 -0
  47. package/dist/src/swagger/swagger-fetcher.d.ts.map +1 -0
  48. package/dist/src/swagger/swagger-validator.d.ts +17 -0
  49. package/dist/src/swagger/swagger-validator.d.ts.map +1 -0
  50. package/dist/src/teamcity/api-types.d.ts +224 -0
  51. package/dist/src/teamcity/api-types.d.ts.map +1 -0
  52. package/dist/src/teamcity/artifact-manager.d.ts +52 -0
  53. package/dist/src/teamcity/artifact-manager.d.ts.map +1 -0
  54. package/dist/src/teamcity/auth.d.ts +22 -0
  55. package/dist/src/teamcity/auth.d.ts.map +1 -0
  56. package/dist/src/teamcity/branch-discovery-manager.d.ts +39 -0
  57. package/dist/src/teamcity/branch-discovery-manager.d.ts.map +1 -0
  58. package/dist/src/teamcity/branch-filtering-service.d.ts +62 -0
  59. package/dist/src/teamcity/branch-filtering-service.d.ts.map +1 -0
  60. package/dist/src/teamcity/branch-specification-parser.d.ts +33 -0
  61. package/dist/src/teamcity/branch-specification-parser.d.ts.map +1 -0
  62. package/dist/src/teamcity/build-config-manager.d.ts +75 -0
  63. package/dist/src/teamcity/build-config-manager.d.ts.map +1 -0
  64. package/dist/src/teamcity/build-config-navigator.d.ts +89 -0
  65. package/dist/src/teamcity/build-config-navigator.d.ts.map +1 -0
  66. package/dist/src/teamcity/build-configuration-clone-manager.d.ts +49 -0
  67. package/dist/src/teamcity/build-configuration-clone-manager.d.ts.map +1 -0
  68. package/dist/src/teamcity/build-configuration-manager.d.ts +82 -0
  69. package/dist/src/teamcity/build-configuration-manager.d.ts.map +1 -0
  70. package/dist/src/teamcity/build-configuration-resolver.d.ts +95 -0
  71. package/dist/src/teamcity/build-configuration-resolver.d.ts.map +1 -0
  72. package/dist/src/teamcity/build-configuration-update-manager.d.ts +76 -0
  73. package/dist/src/teamcity/build-configuration-update-manager.d.ts.map +1 -0
  74. package/dist/src/teamcity/build-list-manager.d.ts +62 -0
  75. package/dist/src/teamcity/build-list-manager.d.ts.map +1 -0
  76. package/dist/src/teamcity/build-parameters-manager.d.ts +143 -0
  77. package/dist/src/teamcity/build-parameters-manager.d.ts.map +1 -0
  78. package/dist/src/teamcity/build-progress-tracker.d.ts +49 -0
  79. package/dist/src/teamcity/build-progress-tracker.d.ts.map +1 -0
  80. package/dist/src/teamcity/build-query-builder.d.ts +27 -0
  81. package/dist/src/teamcity/build-query-builder.d.ts.map +1 -0
  82. package/dist/src/teamcity/build-queue-manager.d.ts +102 -0
  83. package/dist/src/teamcity/build-queue-manager.d.ts.map +1 -0
  84. package/dist/src/teamcity/build-results-manager.d.ts +87 -0
  85. package/dist/src/teamcity/build-results-manager.d.ts.map +1 -0
  86. package/dist/src/teamcity/build-status-manager.d.ts +65 -0
  87. package/dist/src/teamcity/build-status-manager.d.ts.map +1 -0
  88. package/dist/src/teamcity/build-step-manager.d.ts +65 -0
  89. package/dist/src/teamcity/build-step-manager.d.ts.map +1 -0
  90. package/dist/src/teamcity/build-trigger-manager.d.ts +108 -0
  91. package/dist/src/teamcity/build-trigger-manager.d.ts.map +1 -0
  92. package/dist/src/teamcity/circuit-breaker.d.ts +47 -0
  93. package/dist/src/teamcity/circuit-breaker.d.ts.map +1 -0
  94. package/dist/src/teamcity/client-adapter.d.ts +12 -0
  95. package/dist/src/teamcity/client-adapter.d.ts.map +1 -0
  96. package/dist/src/teamcity/client.d.ts +49 -0
  97. package/dist/src/teamcity/client.d.ts.map +1 -0
  98. package/dist/src/teamcity/config.d.ts +41 -0
  99. package/dist/src/teamcity/config.d.ts.map +1 -0
  100. package/dist/src/teamcity/configuration-branch-matcher.d.ts +37 -0
  101. package/dist/src/teamcity/configuration-branch-matcher.d.ts.map +1 -0
  102. package/dist/src/teamcity/errors.d.ts +79 -0
  103. package/dist/src/teamcity/errors.d.ts.map +1 -0
  104. package/dist/src/teamcity/index.d.ts +48 -0
  105. package/dist/src/teamcity/index.d.ts.map +1 -0
  106. package/dist/src/teamcity/pagination.d.ts +32 -0
  107. package/dist/src/teamcity/pagination.d.ts.map +1 -0
  108. package/dist/src/teamcity/project-list-manager.d.ts +19 -0
  109. package/dist/src/teamcity/project-list-manager.d.ts.map +1 -0
  110. package/dist/src/teamcity/project-manager.d.ts +73 -0
  111. package/dist/src/teamcity/project-manager.d.ts.map +1 -0
  112. package/dist/src/teamcity/project-navigator.d.ts +100 -0
  113. package/dist/src/teamcity/project-navigator.d.ts.map +1 -0
  114. package/dist/src/teamcity/test-problem-reporter.d.ts +60 -0
  115. package/dist/src/teamcity/test-problem-reporter.d.ts.map +1 -0
  116. package/dist/src/teamcity/types/api-responses.d.ts +235 -0
  117. package/dist/src/teamcity/types/api-responses.d.ts.map +1 -0
  118. package/dist/src/teamcity-client/api/agent-api.d.ts +97 -0
  119. package/dist/src/teamcity-client/api/agent-api.d.ts.map +1 -0
  120. package/dist/src/teamcity-client/api/agent-pool-api.d.ts +92 -0
  121. package/dist/src/teamcity-client/api/agent-pool-api.d.ts.map +1 -0
  122. package/dist/src/teamcity-client/api/agent-type-api.d.ts +20 -0
  123. package/dist/src/teamcity-client/api/agent-type-api.d.ts.map +1 -0
  124. package/dist/src/teamcity-client/api/audit-api.d.ts +26 -0
  125. package/dist/src/teamcity-client/api/audit-api.d.ts.map +1 -0
  126. package/dist/src/teamcity-client/api/avatar-api.d.ts +34 -0
  127. package/dist/src/teamcity-client/api/avatar-api.d.ts.map +1 -0
  128. package/dist/src/teamcity-client/api/build-api.d.ts +315 -0
  129. package/dist/src/teamcity-client/api/build-api.d.ts.map +1 -0
  130. package/dist/src/teamcity-client/api/build-queue-api.d.ts +90 -0
  131. package/dist/src/teamcity-client/api/build-queue-api.d.ts.map +1 -0
  132. package/dist/src/teamcity-client/api/build-type-api.d.ts +585 -0
  133. package/dist/src/teamcity-client/api/build-type-api.d.ts.map +1 -0
  134. package/dist/src/teamcity-client/api/change-api.d.ts +71 -0
  135. package/dist/src/teamcity-client/api/change-api.d.ts.map +1 -0
  136. package/dist/src/teamcity-client/api/cloud-instance-api.d.ts +70 -0
  137. package/dist/src/teamcity-client/api/cloud-instance-api.d.ts.map +1 -0
  138. package/dist/src/teamcity-client/api/deployment-dashboard-api.d.ts +64 -0
  139. package/dist/src/teamcity-client/api/deployment-dashboard-api.d.ts.map +1 -0
  140. package/dist/src/teamcity-client/api/global-server-settings-api.d.ts +25 -0
  141. package/dist/src/teamcity-client/api/global-server-settings-api.d.ts.map +1 -0
  142. package/dist/src/teamcity-client/api/group-api.d.ts +99 -0
  143. package/dist/src/teamcity-client/api/group-api.d.ts.map +1 -0
  144. package/dist/src/teamcity-client/api/health-api.d.ts +38 -0
  145. package/dist/src/teamcity-client/api/health-api.d.ts.map +1 -0
  146. package/dist/src/teamcity-client/api/investigation-api.d.ts +46 -0
  147. package/dist/src/teamcity-client/api/investigation-api.d.ts.map +1 -0
  148. package/dist/src/teamcity-client/api/mute-api.d.ts +46 -0
  149. package/dist/src/teamcity-client/api/mute-api.d.ts.map +1 -0
  150. package/dist/src/teamcity-client/api/node-api.d.ts +49 -0
  151. package/dist/src/teamcity-client/api/node-api.d.ts.map +1 -0
  152. package/dist/src/teamcity-client/api/problem-api.d.ts +26 -0
  153. package/dist/src/teamcity-client/api/problem-api.d.ts.map +1 -0
  154. package/dist/src/teamcity-client/api/problem-occurrence-api.d.ts +26 -0
  155. package/dist/src/teamcity-client/api/problem-occurrence-api.d.ts.map +1 -0
  156. package/dist/src/teamcity-client/api/project-api.d.ts +271 -0
  157. package/dist/src/teamcity-client/api/project-api.d.ts.map +1 -0
  158. package/dist/src/teamcity-client/api/role-api.d.ts +56 -0
  159. package/dist/src/teamcity-client/api/role-api.d.ts.map +1 -0
  160. package/dist/src/teamcity-client/api/root-api.d.ts +35 -0
  161. package/dist/src/teamcity-client/api/root-api.d.ts.map +1 -0
  162. package/dist/src/teamcity-client/api/server-api.d.ts +112 -0
  163. package/dist/src/teamcity-client/api/server-api.d.ts.map +1 -0
  164. package/dist/src/teamcity-client/api/server-authentication-settings-api.d.ts +25 -0
  165. package/dist/src/teamcity-client/api/server-authentication-settings-api.d.ts.map +1 -0
  166. package/dist/src/teamcity-client/api/test-api.d.ts +26 -0
  167. package/dist/src/teamcity-client/api/test-api.d.ts.map +1 -0
  168. package/dist/src/teamcity-client/api/test-occurrence-api.d.ts +26 -0
  169. package/dist/src/teamcity-client/api/test-occurrence-api.d.ts.map +1 -0
  170. package/dist/src/teamcity-client/api/user-api.d.ts +164 -0
  171. package/dist/src/teamcity-client/api/user-api.d.ts.map +1 -0
  172. package/dist/src/teamcity-client/api/vcs-root-api.d.ts +88 -0
  173. package/dist/src/teamcity-client/api/vcs-root-api.d.ts.map +1 -0
  174. package/dist/src/teamcity-client/api/vcs-root-instance-api.d.ts +104 -0
  175. package/dist/src/teamcity-client/api/vcs-root-instance-api.d.ts.map +1 -0
  176. package/dist/src/teamcity-client/api/versioned-settings-api.d.ts +94 -0
  177. package/dist/src/teamcity-client/api/versioned-settings-api.d.ts.map +1 -0
  178. package/dist/src/teamcity-client/api.d.ts +31 -0
  179. package/dist/src/teamcity-client/api.d.ts.map +1 -0
  180. package/dist/src/teamcity-client/base.d.ts +32 -0
  181. package/dist/src/teamcity-client/base.d.ts.map +1 -0
  182. package/dist/src/teamcity-client/common.d.ts +14 -0
  183. package/dist/src/teamcity-client/common.d.ts.map +1 -0
  184. package/dist/src/teamcity-client/configuration.d.ts +23 -0
  185. package/dist/src/teamcity-client/configuration.d.ts.map +1 -0
  186. package/dist/src/teamcity-client/index.d.ts +4 -0
  187. package/dist/src/teamcity-client/index.d.ts.map +1 -0
  188. package/dist/src/teamcity-client/models/agent-locator.d.ts +34 -0
  189. package/dist/src/teamcity-client/models/agent-locator.d.ts.map +1 -0
  190. package/dist/src/teamcity-client/models/agent-pool-locator.d.ts +10 -0
  191. package/dist/src/teamcity-client/models/agent-pool-locator.d.ts.map +1 -0
  192. package/dist/src/teamcity-client/models/agent-pool.d.ts +16 -0
  193. package/dist/src/teamcity-client/models/agent-pool.d.ts.map +1 -0
  194. package/dist/src/teamcity-client/models/agent-pools.d.ts +9 -0
  195. package/dist/src/teamcity-client/models/agent-pools.d.ts.map +1 -0
  196. package/dist/src/teamcity-client/models/agent-requirement.d.ts +11 -0
  197. package/dist/src/teamcity-client/models/agent-requirement.d.ts.map +1 -0
  198. package/dist/src/teamcity-client/models/agent-requirements.d.ts +6 -0
  199. package/dist/src/teamcity-client/models/agent-requirements.d.ts.map +1 -0
  200. package/dist/src/teamcity-client/models/agent-type-locator.d.ts +8 -0
  201. package/dist/src/teamcity-client/models/agent-type-locator.d.ts.map +1 -0
  202. package/dist/src/teamcity-client/models/agent-type.d.ts +14 -0
  203. package/dist/src/teamcity-client/models/agent-type.d.ts.map +1 -0
  204. package/dist/src/teamcity-client/models/agent-types.d.ts +9 -0
  205. package/dist/src/teamcity-client/models/agent-types.d.ts.map +1 -0
  206. package/dist/src/teamcity-client/models/agent.d.ts +59 -0
  207. package/dist/src/teamcity-client/models/agent.d.ts.map +1 -0
  208. package/dist/src/teamcity-client/models/agents.d.ts +9 -0
  209. package/dist/src/teamcity-client/models/agents.d.ts.map +1 -0
  210. package/dist/src/teamcity-client/models/approvable-build.d.ts +6 -0
  211. package/dist/src/teamcity-client/models/approvable-build.d.ts.map +1 -0
  212. package/dist/src/teamcity-client/models/approval-info.d.ts +24 -0
  213. package/dist/src/teamcity-client/models/approval-info.d.ts.map +1 -0
  214. package/dist/src/teamcity-client/models/artifact-dependencies.d.ts +7 -0
  215. package/dist/src/teamcity-client/models/artifact-dependencies.d.ts.map +1 -0
  216. package/dist/src/teamcity-client/models/artifact-dependency.d.ts +13 -0
  217. package/dist/src/teamcity-client/models/artifact-dependency.d.ts.map +1 -0
  218. package/dist/src/teamcity-client/models/artifact-download-info.d.ts +5 -0
  219. package/dist/src/teamcity-client/models/artifact-download-info.d.ts.map +1 -0
  220. package/dist/src/teamcity-client/models/audit-action.d.ts +6 -0
  221. package/dist/src/teamcity-client/models/audit-action.d.ts.map +1 -0
  222. package/dist/src/teamcity-client/models/audit-event.d.ts +12 -0
  223. package/dist/src/teamcity-client/models/audit-event.d.ts.map +1 -0
  224. package/dist/src/teamcity-client/models/audit-events.d.ts +9 -0
  225. package/dist/src/teamcity-client/models/audit-events.d.ts.map +1 -0
  226. package/dist/src/teamcity-client/models/audit-locator.d.ts +245 -0
  227. package/dist/src/teamcity-client/models/audit-locator.d.ts.map +1 -0
  228. package/dist/src/teamcity-client/models/auth-module.d.ts +6 -0
  229. package/dist/src/teamcity-client/models/auth-module.d.ts.map +1 -0
  230. package/dist/src/teamcity-client/models/auth-modules.d.ts +5 -0
  231. package/dist/src/teamcity-client/models/auth-modules.d.ts.map +1 -0
  232. package/dist/src/teamcity-client/models/authorization-tokens-requirements.d.ts +5 -0
  233. package/dist/src/teamcity-client/models/authorization-tokens-requirements.d.ts.map +1 -0
  234. package/dist/src/teamcity-client/models/authorized-info.d.ts +6 -0
  235. package/dist/src/teamcity-client/models/authorized-info.d.ts.map +1 -0
  236. package/dist/src/teamcity-client/models/branch-locator.d.ts +40 -0
  237. package/dist/src/teamcity-client/models/branch-locator.d.ts.map +1 -0
  238. package/dist/src/teamcity-client/models/branch-version.d.ts +13 -0
  239. package/dist/src/teamcity-client/models/branch-version.d.ts.map +1 -0
  240. package/dist/src/teamcity-client/models/branch.d.ts +12 -0
  241. package/dist/src/teamcity-client/models/branch.d.ts.map +1 -0
  242. package/dist/src/teamcity-client/models/branches.d.ts +7 -0
  243. package/dist/src/teamcity-client/models/branches.d.ts.map +1 -0
  244. package/dist/src/teamcity-client/models/build-cancel-request.d.ts +5 -0
  245. package/dist/src/teamcity-client/models/build-cancel-request.d.ts.map +1 -0
  246. package/dist/src/teamcity-client/models/build-change.d.ts +6 -0
  247. package/dist/src/teamcity-client/models/build-change.d.ts.map +1 -0
  248. package/dist/src/teamcity-client/models/build-changes.d.ts +6 -0
  249. package/dist/src/teamcity-client/models/build-changes.d.ts.map +1 -0
  250. package/dist/src/teamcity-client/models/build-executor.d.ts +4 -0
  251. package/dist/src/teamcity-client/models/build-executor.d.ts.map +1 -0
  252. package/dist/src/teamcity-client/models/build-locator.d.ts +69 -0
  253. package/dist/src/teamcity-client/models/build-locator.d.ts.map +1 -0
  254. package/dist/src/teamcity-client/models/build-queue-locator.d.ts +14 -0
  255. package/dist/src/teamcity-client/models/build-queue-locator.d.ts.map +1 -0
  256. package/dist/src/teamcity-client/models/build-status-update.d.ts +5 -0
  257. package/dist/src/teamcity-client/models/build-status-update.d.ts.map +1 -0
  258. package/dist/src/teamcity-client/models/build-trigger-customization.d.ts +7 -0
  259. package/dist/src/teamcity-client/models/build-trigger-customization.d.ts.map +1 -0
  260. package/dist/src/teamcity-client/models/build-triggering-options.d.ts +12 -0
  261. package/dist/src/teamcity-client/models/build-triggering-options.d.ts.map +1 -0
  262. package/dist/src/teamcity-client/models/build-type-locator.d.ts +18 -0
  263. package/dist/src/teamcity-client/models/build-type-locator.d.ts.map +1 -0
  264. package/dist/src/teamcity-client/models/build-type.d.ts +64 -0
  265. package/dist/src/teamcity-client/models/build-type.d.ts.map +1 -0
  266. package/dist/src/teamcity-client/models/build-types.d.ts +9 -0
  267. package/dist/src/teamcity-client/models/build-types.d.ts.map +1 -0
  268. package/dist/src/teamcity-client/models/build.d.ts +127 -0
  269. package/dist/src/teamcity-client/models/build.d.ts.map +1 -0
  270. package/dist/src/teamcity-client/models/builds-with-reason.d.ts +6 -0
  271. package/dist/src/teamcity-client/models/builds-with-reason.d.ts.map +1 -0
  272. package/dist/src/teamcity-client/models/builds.d.ts +9 -0
  273. package/dist/src/teamcity-client/models/builds.d.ts.map +1 -0
  274. package/dist/src/teamcity-client/models/change-locator.d.ts +21 -0
  275. package/dist/src/teamcity-client/models/change-locator.d.ts.map +1 -0
  276. package/dist/src/teamcity-client/models/change-status.d.ts +19 -0
  277. package/dist/src/teamcity-client/models/change-status.d.ts.map +1 -0
  278. package/dist/src/teamcity-client/models/change.d.ts +35 -0
  279. package/dist/src/teamcity-client/models/change.d.ts.map +1 -0
  280. package/dist/src/teamcity-client/models/changes.d.ts +9 -0
  281. package/dist/src/teamcity-client/models/changes.d.ts.map +1 -0
  282. package/dist/src/teamcity-client/models/cleanup.d.ts +9 -0
  283. package/dist/src/teamcity-client/models/cleanup.d.ts.map +1 -0
  284. package/dist/src/teamcity-client/models/cloud-error.d.ts +5 -0
  285. package/dist/src/teamcity-client/models/cloud-error.d.ts.map +1 -0
  286. package/dist/src/teamcity-client/models/cloud-image-locator.d.ts +17 -0
  287. package/dist/src/teamcity-client/models/cloud-image-locator.d.ts.map +1 -0
  288. package/dist/src/teamcity-client/models/cloud-image.d.ts +18 -0
  289. package/dist/src/teamcity-client/models/cloud-image.d.ts.map +1 -0
  290. package/dist/src/teamcity-client/models/cloud-images.d.ts +9 -0
  291. package/dist/src/teamcity-client/models/cloud-images.d.ts.map +1 -0
  292. package/dist/src/teamcity-client/models/cloud-instance-locator.d.ts +13 -0
  293. package/dist/src/teamcity-client/models/cloud-instance-locator.d.ts.map +1 -0
  294. package/dist/src/teamcity-client/models/cloud-instance.d.ts +16 -0
  295. package/dist/src/teamcity-client/models/cloud-instance.d.ts.map +1 -0
  296. package/dist/src/teamcity-client/models/cloud-instances.d.ts +9 -0
  297. package/dist/src/teamcity-client/models/cloud-instances.d.ts.map +1 -0
  298. package/dist/src/teamcity-client/models/cloud-profile-locator.d.ts +13 -0
  299. package/dist/src/teamcity-client/models/cloud-profile-locator.d.ts.map +1 -0
  300. package/dist/src/teamcity-client/models/cloud-profile.d.ts +13 -0
  301. package/dist/src/teamcity-client/models/cloud-profile.d.ts.map +1 -0
  302. package/dist/src/teamcity-client/models/cloud-profiles.d.ts +9 -0
  303. package/dist/src/teamcity-client/models/cloud-profiles.d.ts.map +1 -0
  304. package/dist/src/teamcity-client/models/comment.d.ts +7 -0
  305. package/dist/src/teamcity-client/models/comment.d.ts.map +1 -0
  306. package/dist/src/teamcity-client/models/commiter.d.ts +6 -0
  307. package/dist/src/teamcity-client/models/commiter.d.ts.map +1 -0
  308. package/dist/src/teamcity-client/models/compatibilities.d.ts +6 -0
  309. package/dist/src/teamcity-client/models/compatibilities.d.ts.map +1 -0
  310. package/dist/src/teamcity-client/models/compatibility-policy.d.ts +6 -0
  311. package/dist/src/teamcity-client/models/compatibility-policy.d.ts.map +1 -0
  312. package/dist/src/teamcity-client/models/compatibility.d.ts +10 -0
  313. package/dist/src/teamcity-client/models/compatibility.d.ts.map +1 -0
  314. package/dist/src/teamcity-client/models/composite-approval-rule.d.ts +10 -0
  315. package/dist/src/teamcity-client/models/composite-approval-rule.d.ts.map +1 -0
  316. package/dist/src/teamcity-client/models/composite-approvals.d.ts +6 -0
  317. package/dist/src/teamcity-client/models/composite-approvals.d.ts.map +1 -0
  318. package/dist/src/teamcity-client/models/cron.d.ts +8 -0
  319. package/dist/src/teamcity-client/models/cron.d.ts.map +1 -0
  320. package/dist/src/teamcity-client/models/customizations.d.ts +15 -0
  321. package/dist/src/teamcity-client/models/customizations.d.ts.map +1 -0
  322. package/dist/src/teamcity-client/models/daily.d.ts +5 -0
  323. package/dist/src/teamcity-client/models/daily.d.ts.map +1 -0
  324. package/dist/src/teamcity-client/models/datas.d.ts +6 -0
  325. package/dist/src/teamcity-client/models/datas.d.ts.map +1 -0
  326. package/dist/src/teamcity-client/models/deployment-dashboard-locator.d.ts +9 -0
  327. package/dist/src/teamcity-client/models/deployment-dashboard-locator.d.ts.map +1 -0
  328. package/dist/src/teamcity-client/models/deployment-dashboard.d.ts +9 -0
  329. package/dist/src/teamcity-client/models/deployment-dashboard.d.ts.map +1 -0
  330. package/dist/src/teamcity-client/models/deployment-dashboards.d.ts +9 -0
  331. package/dist/src/teamcity-client/models/deployment-dashboards.d.ts.map +1 -0
  332. package/dist/src/teamcity-client/models/deployment-history.d.ts +6 -0
  333. package/dist/src/teamcity-client/models/deployment-history.d.ts.map +1 -0
  334. package/dist/src/teamcity-client/models/deployment-instance-locator.d.ts +16 -0
  335. package/dist/src/teamcity-client/models/deployment-instance-locator.d.ts.map +1 -0
  336. package/dist/src/teamcity-client/models/deployment-instance.d.ts +20 -0
  337. package/dist/src/teamcity-client/models/deployment-instance.d.ts.map +1 -0
  338. package/dist/src/teamcity-client/models/deployment-instances.d.ts +9 -0
  339. package/dist/src/teamcity-client/models/deployment-instances.d.ts.map +1 -0
  340. package/dist/src/teamcity-client/models/deployment-state-entries.d.ts +8 -0
  341. package/dist/src/teamcity-client/models/deployment-state-entries.d.ts.map +1 -0
  342. package/dist/src/teamcity-client/models/deployment-state-entry.d.ts +16 -0
  343. package/dist/src/teamcity-client/models/deployment-state-entry.d.ts.map +1 -0
  344. package/dist/src/teamcity-client/models/disabled-responsibilities.d.ts +6 -0
  345. package/dist/src/teamcity-client/models/disabled-responsibilities.d.ts.map +1 -0
  346. package/dist/src/teamcity-client/models/download-info.d.ts +8 -0
  347. package/dist/src/teamcity-client/models/download-info.d.ts.map +1 -0
  348. package/dist/src/teamcity-client/models/downloaded-artifacts.d.ts +7 -0
  349. package/dist/src/teamcity-client/models/downloaded-artifacts.d.ts.map +1 -0
  350. package/dist/src/teamcity-client/models/effective-responsibilities.d.ts +6 -0
  351. package/dist/src/teamcity-client/models/effective-responsibilities.d.ts.map +1 -0
  352. package/dist/src/teamcity-client/models/enabled-info.d.ts +7 -0
  353. package/dist/src/teamcity-client/models/enabled-info.d.ts.map +1 -0
  354. package/dist/src/teamcity-client/models/enabled-responsibilities.d.ts +6 -0
  355. package/dist/src/teamcity-client/models/enabled-responsibilities.d.ts.map +1 -0
  356. package/dist/src/teamcity-client/models/entries.d.ts +6 -0
  357. package/dist/src/teamcity-client/models/entries.d.ts.map +1 -0
  358. package/dist/src/teamcity-client/models/entry.d.ts +5 -0
  359. package/dist/src/teamcity-client/models/entry.d.ts.map +1 -0
  360. package/dist/src/teamcity-client/models/environment.d.ts +5 -0
  361. package/dist/src/teamcity-client/models/environment.d.ts.map +1 -0
  362. package/dist/src/teamcity-client/models/feature.d.ts +11 -0
  363. package/dist/src/teamcity-client/models/feature.d.ts.map +1 -0
  364. package/dist/src/teamcity-client/models/features.d.ts +6 -0
  365. package/dist/src/teamcity-client/models/features.d.ts.map +1 -0
  366. package/dist/src/teamcity-client/models/file-change.d.ts +10 -0
  367. package/dist/src/teamcity-client/models/file-change.d.ts.map +1 -0
  368. package/dist/src/teamcity-client/models/file-changes.d.ts +6 -0
  369. package/dist/src/teamcity-client/models/file-changes.d.ts.map +1 -0
  370. package/dist/src/teamcity-client/models/files.d.ts +6 -0
  371. package/dist/src/teamcity-client/models/files.d.ts.map +1 -0
  372. package/dist/src/teamcity-client/models/group-approval-rule.d.ts +8 -0
  373. package/dist/src/teamcity-client/models/group-approval-rule.d.ts.map +1 -0
  374. package/dist/src/teamcity-client/models/group-approvals.d.ts +6 -0
  375. package/dist/src/teamcity-client/models/group-approvals.d.ts.map +1 -0
  376. package/dist/src/teamcity-client/models/group.d.ts +16 -0
  377. package/dist/src/teamcity-client/models/group.d.ts.map +1 -0
  378. package/dist/src/teamcity-client/models/groups.d.ts +6 -0
  379. package/dist/src/teamcity-client/models/groups.d.ts.map +1 -0
  380. package/dist/src/teamcity-client/models/health-categories.d.ts +9 -0
  381. package/dist/src/teamcity-client/models/health-categories.d.ts.map +1 -0
  382. package/dist/src/teamcity-client/models/health-category.d.ts +7 -0
  383. package/dist/src/teamcity-client/models/health-category.d.ts.map +1 -0
  384. package/dist/src/teamcity-client/models/health-item.d.ts +13 -0
  385. package/dist/src/teamcity-client/models/health-item.d.ts.map +1 -0
  386. package/dist/src/teamcity-client/models/health-status-items.d.ts +9 -0
  387. package/dist/src/teamcity-client/models/health-status-items.d.ts.map +1 -0
  388. package/dist/src/teamcity-client/models/href.d.ts +4 -0
  389. package/dist/src/teamcity-client/models/href.d.ts.map +1 -0
  390. package/dist/src/teamcity-client/models/index.d.ts +230 -0
  391. package/dist/src/teamcity-client/models/index.d.ts.map +1 -0
  392. package/dist/src/teamcity-client/models/investigation-locator.d.ts +35 -0
  393. package/dist/src/teamcity-client/models/investigation-locator.d.ts.map +1 -0
  394. package/dist/src/teamcity-client/models/investigation.d.ts +24 -0
  395. package/dist/src/teamcity-client/models/investigation.d.ts.map +1 -0
  396. package/dist/src/teamcity-client/models/investigations.d.ts +9 -0
  397. package/dist/src/teamcity-client/models/investigations.d.ts.map +1 -0
  398. package/dist/src/teamcity-client/models/issue-usage.d.ts +7 -0
  399. package/dist/src/teamcity-client/models/issue-usage.d.ts.map +1 -0
  400. package/dist/src/teamcity-client/models/issue.d.ts +5 -0
  401. package/dist/src/teamcity-client/models/issue.d.ts.map +1 -0
  402. package/dist/src/teamcity-client/models/issues-usages.d.ts +7 -0
  403. package/dist/src/teamcity-client/models/issues-usages.d.ts.map +1 -0
  404. package/dist/src/teamcity-client/models/issues.d.ts +5 -0
  405. package/dist/src/teamcity-client/models/issues.d.ts.map +1 -0
  406. package/dist/src/teamcity-client/models/items.d.ts +4 -0
  407. package/dist/src/teamcity-client/models/items.d.ts.map +1 -0
  408. package/dist/src/teamcity-client/models/labeled-value.d.ts +5 -0
  409. package/dist/src/teamcity-client/models/labeled-value.d.ts.map +1 -0
  410. package/dist/src/teamcity-client/models/license-key.d.ts +29 -0
  411. package/dist/src/teamcity-client/models/license-key.d.ts.map +1 -0
  412. package/dist/src/teamcity-client/models/license-keys.d.ts +7 -0
  413. package/dist/src/teamcity-client/models/license-keys.d.ts.map +1 -0
  414. package/dist/src/teamcity-client/models/licensing-data.d.ts +26 -0
  415. package/dist/src/teamcity-client/models/licensing-data.d.ts.map +1 -0
  416. package/dist/src/teamcity-client/models/link.d.ts +6 -0
  417. package/dist/src/teamcity-client/models/link.d.ts.map +1 -0
  418. package/dist/src/teamcity-client/models/links.d.ts +6 -0
  419. package/dist/src/teamcity-client/models/links.d.ts.map +1 -0
  420. package/dist/src/teamcity-client/models/matrix-build-feature-descriptor.d.ts +8 -0
  421. package/dist/src/teamcity-client/models/matrix-build-feature-descriptor.d.ts.map +1 -0
  422. package/dist/src/teamcity-client/models/matrix-configuration.d.ts +9 -0
  423. package/dist/src/teamcity-client/models/matrix-configuration.d.ts.map +1 -0
  424. package/dist/src/teamcity-client/models/matrix-dependencies.d.ts +6 -0
  425. package/dist/src/teamcity-client/models/matrix-dependencies.d.ts.map +1 -0
  426. package/dist/src/teamcity-client/models/matrix-dependency.d.ts +7 -0
  427. package/dist/src/teamcity-client/models/matrix-dependency.d.ts.map +1 -0
  428. package/dist/src/teamcity-client/models/matrix-parameter-descriptor.d.ts +7 -0
  429. package/dist/src/teamcity-client/models/matrix-parameter-descriptor.d.ts.map +1 -0
  430. package/dist/src/teamcity-client/models/meta-data.d.ts +6 -0
  431. package/dist/src/teamcity-client/models/meta-data.d.ts.map +1 -0
  432. package/dist/src/teamcity-client/models/metric-tag.d.ts +5 -0
  433. package/dist/src/teamcity-client/models/metric-tag.d.ts.map +1 -0
  434. package/dist/src/teamcity-client/models/metric-tags.d.ts +6 -0
  435. package/dist/src/teamcity-client/models/metric-tags.d.ts.map +1 -0
  436. package/dist/src/teamcity-client/models/metric-value.d.ts +7 -0
  437. package/dist/src/teamcity-client/models/metric-value.d.ts.map +1 -0
  438. package/dist/src/teamcity-client/models/metric-values.d.ts +6 -0
  439. package/dist/src/teamcity-client/models/metric-values.d.ts.map +1 -0
  440. package/dist/src/teamcity-client/models/metric.d.ts +10 -0
  441. package/dist/src/teamcity-client/models/metric.d.ts.map +1 -0
  442. package/dist/src/teamcity-client/models/metrics.d.ts +6 -0
  443. package/dist/src/teamcity-client/models/metrics.d.ts.map +1 -0
  444. package/dist/src/teamcity-client/models/model-file.d.ts +13 -0
  445. package/dist/src/teamcity-client/models/model-file.d.ts.map +1 -0
  446. package/dist/src/teamcity-client/models/multiple-operation-result.d.ts +7 -0
  447. package/dist/src/teamcity-client/models/multiple-operation-result.d.ts.map +1 -0
  448. package/dist/src/teamcity-client/models/mute-locator.d.ts +26 -0
  449. package/dist/src/teamcity-client/models/mute-locator.d.ts.map +1 -0
  450. package/dist/src/teamcity-client/models/mute.d.ts +13 -0
  451. package/dist/src/teamcity-client/models/mute.d.ts.map +1 -0
  452. package/dist/src/teamcity-client/models/mutes.d.ts +9 -0
  453. package/dist/src/teamcity-client/models/mutes.d.ts.map +1 -0
  454. package/dist/src/teamcity-client/models/new-build-type-description.d.ts +13 -0
  455. package/dist/src/teamcity-client/models/new-build-type-description.d.ts.map +1 -0
  456. package/dist/src/teamcity-client/models/new-project-description.d.ts +15 -0
  457. package/dist/src/teamcity-client/models/new-project-description.d.ts.map +1 -0
  458. package/dist/src/teamcity-client/models/node.d.ts +21 -0
  459. package/dist/src/teamcity-client/models/node.d.ts.map +1 -0
  460. package/dist/src/teamcity-client/models/nodes.d.ts +6 -0
  461. package/dist/src/teamcity-client/models/nodes.d.ts.map +1 -0
  462. package/dist/src/teamcity-client/models/operation-result.d.ts +6 -0
  463. package/dist/src/teamcity-client/models/operation-result.d.ts.map +1 -0
  464. package/dist/src/teamcity-client/models/parsed-test-name.d.ts +10 -0
  465. package/dist/src/teamcity-client/models/parsed-test-name.d.ts.map +1 -0
  466. package/dist/src/teamcity-client/models/permission-assignment.d.ts +8 -0
  467. package/dist/src/teamcity-client/models/permission-assignment.d.ts.map +1 -0
  468. package/dist/src/teamcity-client/models/permission-assignments.d.ts +6 -0
  469. package/dist/src/teamcity-client/models/permission-assignments.d.ts.map +1 -0
  470. package/dist/src/teamcity-client/models/permission-restriction.d.ts +8 -0
  471. package/dist/src/teamcity-client/models/permission-restriction.d.ts.map +1 -0
  472. package/dist/src/teamcity-client/models/permission-restrictions.d.ts +6 -0
  473. package/dist/src/teamcity-client/models/permission-restrictions.d.ts.map +1 -0
  474. package/dist/src/teamcity-client/models/permission.d.ts +6 -0
  475. package/dist/src/teamcity-client/models/permission.d.ts.map +1 -0
  476. package/dist/src/teamcity-client/models/permissions.d.ts +6 -0
  477. package/dist/src/teamcity-client/models/permissions.d.ts.map +1 -0
  478. package/dist/src/teamcity-client/models/pin-info.d.ts +6 -0
  479. package/dist/src/teamcity-client/models/pin-info.d.ts.map +1 -0
  480. package/dist/src/teamcity-client/models/plugin.d.ts +9 -0
  481. package/dist/src/teamcity-client/models/plugin.d.ts.map +1 -0
  482. package/dist/src/teamcity-client/models/plugins.d.ts +6 -0
  483. package/dist/src/teamcity-client/models/plugins.d.ts.map +1 -0
  484. package/dist/src/teamcity-client/models/problem-locator.d.ts +15 -0
  485. package/dist/src/teamcity-client/models/problem-locator.d.ts.map +1 -0
  486. package/dist/src/teamcity-client/models/problem-occurrence-locator.d.ts +16 -0
  487. package/dist/src/teamcity-client/models/problem-occurrence-locator.d.ts.map +1 -0
  488. package/dist/src/teamcity-client/models/problem-occurrence.d.ts +20 -0
  489. package/dist/src/teamcity-client/models/problem-occurrence.d.ts.map +1 -0
  490. package/dist/src/teamcity-client/models/problem-occurrences.d.ts +14 -0
  491. package/dist/src/teamcity-client/models/problem-occurrences.d.ts.map +1 -0
  492. package/dist/src/teamcity-client/models/problem-scope.d.ts +9 -0
  493. package/dist/src/teamcity-client/models/problem-scope.d.ts.map +1 -0
  494. package/dist/src/teamcity-client/models/problem-target.d.ts +8 -0
  495. package/dist/src/teamcity-client/models/problem-target.d.ts.map +1 -0
  496. package/dist/src/teamcity-client/models/problem.d.ts +15 -0
  497. package/dist/src/teamcity-client/models/problem.d.ts.map +1 -0
  498. package/dist/src/teamcity-client/models/problems.d.ts +8 -0
  499. package/dist/src/teamcity-client/models/problems.d.ts.map +1 -0
  500. package/dist/src/teamcity-client/models/progress-info.d.ts +13 -0
  501. package/dist/src/teamcity-client/models/progress-info.d.ts.map +1 -0
  502. package/dist/src/teamcity-client/models/project-feature.d.ts +11 -0
  503. package/dist/src/teamcity-client/models/project-feature.d.ts.map +1 -0
  504. package/dist/src/teamcity-client/models/project-features.d.ts +7 -0
  505. package/dist/src/teamcity-client/models/project-features.d.ts.map +1 -0
  506. package/dist/src/teamcity-client/models/project-locator.d.ts +20 -0
  507. package/dist/src/teamcity-client/models/project-locator.d.ts.map +1 -0
  508. package/dist/src/teamcity-client/models/project.d.ts +39 -0
  509. package/dist/src/teamcity-client/models/project.d.ts.map +1 -0
  510. package/dist/src/teamcity-client/models/projects.d.ts +9 -0
  511. package/dist/src/teamcity-client/models/projects.d.ts.map +1 -0
  512. package/dist/src/teamcity-client/models/properties.d.ts +7 -0
  513. package/dist/src/teamcity-client/models/properties.d.ts.map +1 -0
  514. package/dist/src/teamcity-client/models/property.d.ts +8 -0
  515. package/dist/src/teamcity-client/models/property.d.ts.map +1 -0
  516. package/dist/src/teamcity-client/models/related-entities.d.ts +6 -0
  517. package/dist/src/teamcity-client/models/related-entities.d.ts.map +1 -0
  518. package/dist/src/teamcity-client/models/related-entity.d.ts +29 -0
  519. package/dist/src/teamcity-client/models/related-entity.d.ts.map +1 -0
  520. package/dist/src/teamcity-client/models/related.d.ts +5 -0
  521. package/dist/src/teamcity-client/models/related.d.ts.map +1 -0
  522. package/dist/src/teamcity-client/models/repository-state.d.ts +7 -0
  523. package/dist/src/teamcity-client/models/repository-state.d.ts.map +1 -0
  524. package/dist/src/teamcity-client/models/requirements.d.ts +4 -0
  525. package/dist/src/teamcity-client/models/requirements.d.ts.map +1 -0
  526. package/dist/src/teamcity-client/models/resolution.d.ts +11 -0
  527. package/dist/src/teamcity-client/models/resolution.d.ts.map +1 -0
  528. package/dist/src/teamcity-client/models/responsibility.d.ts +5 -0
  529. package/dist/src/teamcity-client/models/responsibility.d.ts.map +1 -0
  530. package/dist/src/teamcity-client/models/revision.d.ts +9 -0
  531. package/dist/src/teamcity-client/models/revision.d.ts.map +1 -0
  532. package/dist/src/teamcity-client/models/revisions.d.ts +7 -0
  533. package/dist/src/teamcity-client/models/revisions.d.ts.map +1 -0
  534. package/dist/src/teamcity-client/models/role.d.ts +6 -0
  535. package/dist/src/teamcity-client/models/role.d.ts.map +1 -0
  536. package/dist/src/teamcity-client/models/roles.d.ts +5 -0
  537. package/dist/src/teamcity-client/models/roles.d.ts.map +1 -0
  538. package/dist/src/teamcity-client/models/server-auth-settings.d.ts +12 -0
  539. package/dist/src/teamcity-client/models/server-auth-settings.d.ts.map +1 -0
  540. package/dist/src/teamcity-client/models/server-global-settings.d.ts +15 -0
  541. package/dist/src/teamcity-client/models/server-global-settings.d.ts.map +1 -0
  542. package/dist/src/teamcity-client/models/server.d.ts +26 -0
  543. package/dist/src/teamcity-client/models/server.d.ts.map +1 -0
  544. package/dist/src/teamcity-client/models/snapshot-dependencies.d.ts +6 -0
  545. package/dist/src/teamcity-client/models/snapshot-dependencies.d.ts.map +1 -0
  546. package/dist/src/teamcity-client/models/snapshot-dependency-link.d.ts +8 -0
  547. package/dist/src/teamcity-client/models/snapshot-dependency-link.d.ts.map +1 -0
  548. package/dist/src/teamcity-client/models/snapshot-dependency.d.ts +13 -0
  549. package/dist/src/teamcity-client/models/snapshot-dependency.d.ts.map +1 -0
  550. package/dist/src/teamcity-client/models/state-field.d.ts +5 -0
  551. package/dist/src/teamcity-client/models/state-field.d.ts.map +1 -0
  552. package/dist/src/teamcity-client/models/step.d.ts +12 -0
  553. package/dist/src/teamcity-client/models/step.d.ts.map +1 -0
  554. package/dist/src/teamcity-client/models/steps.d.ts +6 -0
  555. package/dist/src/teamcity-client/models/steps.d.ts.map +1 -0
  556. package/dist/src/teamcity-client/models/tag-locator.d.ts +6 -0
  557. package/dist/src/teamcity-client/models/tag-locator.d.ts.map +1 -0
  558. package/dist/src/teamcity-client/models/tag.d.ts +7 -0
  559. package/dist/src/teamcity-client/models/tag.d.ts.map +1 -0
  560. package/dist/src/teamcity-client/models/tags.d.ts +6 -0
  561. package/dist/src/teamcity-client/models/tags.d.ts.map +1 -0
  562. package/dist/src/teamcity-client/models/team-city-node-locator.d.ts +6 -0
  563. package/dist/src/teamcity-client/models/team-city-node-locator.d.ts.map +1 -0
  564. package/dist/src/teamcity-client/models/test-counters.d.ts +10 -0
  565. package/dist/src/teamcity-client/models/test-counters.d.ts.map +1 -0
  566. package/dist/src/teamcity-client/models/test-locator.d.ts +14 -0
  567. package/dist/src/teamcity-client/models/test-locator.d.ts.map +1 -0
  568. package/dist/src/teamcity-client/models/test-occurrence-locator.d.ts +31 -0
  569. package/dist/src/teamcity-client/models/test-occurrence-locator.d.ts.map +1 -0
  570. package/dist/src/teamcity-client/models/test-occurrence.d.ts +37 -0
  571. package/dist/src/teamcity-client/models/test-occurrence.d.ts.map +1 -0
  572. package/dist/src/teamcity-client/models/test-occurrences.d.ts +16 -0
  573. package/dist/src/teamcity-client/models/test-occurrences.d.ts.map +1 -0
  574. package/dist/src/teamcity-client/models/test-run-metadata.d.ts +6 -0
  575. package/dist/src/teamcity-client/models/test-run-metadata.d.ts.map +1 -0
  576. package/dist/src/teamcity-client/models/tests.d.ts +10 -0
  577. package/dist/src/teamcity-client/models/tests.d.ts.map +1 -0
  578. package/dist/src/teamcity-client/models/token.d.ts +9 -0
  579. package/dist/src/teamcity-client/models/token.d.ts.map +1 -0
  580. package/dist/src/teamcity-client/models/tokens.d.ts +6 -0
  581. package/dist/src/teamcity-client/models/tokens.d.ts.map +1 -0
  582. package/dist/src/teamcity-client/models/trigger.d.ts +13 -0
  583. package/dist/src/teamcity-client/models/trigger.d.ts.map +1 -0
  584. package/dist/src/teamcity-client/models/triggered-by.d.ts +16 -0
  585. package/dist/src/teamcity-client/models/triggered-by.d.ts.map +1 -0
  586. package/dist/src/teamcity-client/models/triggers.d.ts +6 -0
  587. package/dist/src/teamcity-client/models/triggers.d.ts.map +1 -0
  588. package/dist/src/teamcity-client/models/type.d.ts +4 -0
  589. package/dist/src/teamcity-client/models/type.d.ts.map +1 -0
  590. package/dist/src/teamcity-client/models/typed-value-set.d.ts +10 -0
  591. package/dist/src/teamcity-client/models/typed-value-set.d.ts.map +1 -0
  592. package/dist/src/teamcity-client/models/typed-value-sets.d.ts +6 -0
  593. package/dist/src/teamcity-client/models/typed-value-sets.d.ts.map +1 -0
  594. package/dist/src/teamcity-client/models/typed-value.d.ts +6 -0
  595. package/dist/src/teamcity-client/models/typed-value.d.ts.map +1 -0
  596. package/dist/src/teamcity-client/models/user-approval-rule.d.ts +6 -0
  597. package/dist/src/teamcity-client/models/user-approval-rule.d.ts.map +1 -0
  598. package/dist/src/teamcity-client/models/user-approvals.d.ts +6 -0
  599. package/dist/src/teamcity-client/models/user-approvals.d.ts.map +1 -0
  600. package/dist/src/teamcity-client/models/user-avatars.d.ts +10 -0
  601. package/dist/src/teamcity-client/models/user-avatars.d.ts.map +1 -0
  602. package/dist/src/teamcity-client/models/user-group-locator.d.ts +6 -0
  603. package/dist/src/teamcity-client/models/user-group-locator.d.ts.map +1 -0
  604. package/dist/src/teamcity-client/models/user-locator.d.ts +15 -0
  605. package/dist/src/teamcity-client/models/user-locator.d.ts.map +1 -0
  606. package/dist/src/teamcity-client/models/user.d.ts +22 -0
  607. package/dist/src/teamcity-client/models/user.d.ts.map +1 -0
  608. package/dist/src/teamcity-client/models/users.d.ts +6 -0
  609. package/dist/src/teamcity-client/models/users.d.ts.map +1 -0
  610. package/dist/src/teamcity-client/models/vcs-check-status.d.ts +6 -0
  611. package/dist/src/teamcity-client/models/vcs-check-status.d.ts.map +1 -0
  612. package/dist/src/teamcity-client/models/vcs-label.d.ts +18 -0
  613. package/dist/src/teamcity-client/models/vcs-label.d.ts.map +1 -0
  614. package/dist/src/teamcity-client/models/vcs-labels.d.ts +6 -0
  615. package/dist/src/teamcity-client/models/vcs-labels.d.ts.map +1 -0
  616. package/dist/src/teamcity-client/models/vcs-root-entries.d.ts +6 -0
  617. package/dist/src/teamcity-client/models/vcs-root-entries.d.ts.map +1 -0
  618. package/dist/src/teamcity-client/models/vcs-root-entry.d.ts +8 -0
  619. package/dist/src/teamcity-client/models/vcs-root-entry.d.ts.map +1 -0
  620. package/dist/src/teamcity-client/models/vcs-root-instance-locator.d.ts +38 -0
  621. package/dist/src/teamcity-client/models/vcs-root-instance-locator.d.ts.map +1 -0
  622. package/dist/src/teamcity-client/models/vcs-root-instance.d.ts +24 -0
  623. package/dist/src/teamcity-client/models/vcs-root-instance.d.ts.map +1 -0
  624. package/dist/src/teamcity-client/models/vcs-root-instances.d.ts +9 -0
  625. package/dist/src/teamcity-client/models/vcs-root-instances.d.ts.map +1 -0
  626. package/dist/src/teamcity-client/models/vcs-root-locator.d.ts +37 -0
  627. package/dist/src/teamcity-client/models/vcs-root-locator.d.ts.map +1 -0
  628. package/dist/src/teamcity-client/models/vcs-root.d.ts +20 -0
  629. package/dist/src/teamcity-client/models/vcs-root.d.ts.map +1 -0
  630. package/dist/src/teamcity-client/models/vcs-roots.d.ts +9 -0
  631. package/dist/src/teamcity-client/models/vcs-roots.d.ts.map +1 -0
  632. package/dist/src/teamcity-client/models/vcs-status.d.ts +6 -0
  633. package/dist/src/teamcity-client/models/vcs-status.d.ts.map +1 -0
  634. package/dist/src/teamcity-client/models/versioned-settings-config.d.ts +31 -0
  635. package/dist/src/teamcity-client/models/versioned-settings-config.d.ts.map +1 -0
  636. package/dist/src/teamcity-client/models/versioned-settings-context-parameter.d.ts +5 -0
  637. package/dist/src/teamcity-client/models/versioned-settings-context-parameter.d.ts.map +1 -0
  638. package/dist/src/teamcity-client/models/versioned-settings-context-parameters.d.ts +5 -0
  639. package/dist/src/teamcity-client/models/versioned-settings-context-parameters.d.ts.map +1 -0
  640. package/dist/src/teamcity-client/models/versioned-settings-error.d.ts +7 -0
  641. package/dist/src/teamcity-client/models/versioned-settings-error.d.ts.map +1 -0
  642. package/dist/src/teamcity-client/models/versioned-settings-status.d.ts +15 -0
  643. package/dist/src/teamcity-client/models/versioned-settings-status.d.ts.map +1 -0
  644. package/dist/src/teamcity-client/models/versioned-settings-token.d.ts +6 -0
  645. package/dist/src/teamcity-client/models/versioned-settings-token.d.ts.map +1 -0
  646. package/dist/src/teamcity-client/models/versioned-settings-tokens.d.ts +5 -0
  647. package/dist/src/teamcity-client/models/versioned-settings-tokens.d.ts.map +1 -0
  648. package/dist/src/tools/index.d.ts +2 -0
  649. package/dist/src/tools/index.d.ts.map +1 -0
  650. package/dist/src/tools.d.ts +22 -0
  651. package/dist/src/tools.d.ts.map +1 -0
  652. package/dist/src/types/config.d.ts +129 -0
  653. package/dist/src/types/config.d.ts.map +1 -0
  654. package/dist/src/types/index.d.ts +116 -0
  655. package/dist/src/types/index.d.ts.map +1 -0
  656. package/dist/src/types/mcp.d.ts +68 -0
  657. package/dist/src/types/mcp.d.ts.map +1 -0
  658. package/dist/src/types/project.d.ts +56 -0
  659. package/dist/src/types/project.d.ts.map +1 -0
  660. package/dist/src/types/teamcity.d.ts +258 -0
  661. package/dist/src/types/teamcity.d.ts.map +1 -0
  662. package/dist/src/utils/async/index.d.ts +90 -0
  663. package/dist/src/utils/async/index.d.ts.map +1 -0
  664. package/dist/src/utils/error-logger.d.ts +34 -0
  665. package/dist/src/utils/error-logger.d.ts.map +1 -0
  666. package/dist/src/utils/index.d.ts +23 -0
  667. package/dist/src/utils/index.d.ts.map +1 -0
  668. package/dist/src/utils/logger/index.d.ts +73 -0
  669. package/dist/src/utils/logger/index.d.ts.map +1 -0
  670. package/dist/src/utils/logger.d.ts +11 -0
  671. package/dist/src/utils/logger.d.ts.map +1 -0
  672. package/dist/src/utils/lru-cache.d.ts +20 -0
  673. package/dist/src/utils/lru-cache.d.ts.map +1 -0
  674. package/dist/src/utils/mcp.d.ts +18 -0
  675. package/dist/src/utils/mcp.d.ts.map +1 -0
  676. package/dist/src/utils/validation.d.ts +61 -0
  677. package/dist/src/utils/validation.d.ts.map +1 -0
  678. package/docs/TEAMCITY_MCP_TOOLS_GUIDE.md +1076 -0
  679. package/docs/mcp-tools-mode-matrix.md +68 -0
  680. package/docs/mcp-tools-reference.md +203 -0
  681. package/examples/list-build-configs-usage.ts +276 -0
  682. package/jest.ci.config.js +14 -0
  683. package/jest.config.js +108 -0
  684. package/jest.setup.js +24 -0
  685. package/openapi-generator-config.json +27 -0
  686. package/openapitools.json +7 -0
  687. package/package.json +101 -0
  688. package/scripts/build.cjs +87 -0
  689. package/scripts/debug-fetch-log.ts +52 -0
  690. package/scripts/emit-coverage-stats.js +42 -0
  691. package/scripts/fetch-swagger-spec.ts +140 -0
  692. package/scripts/interact.sh +23 -0
  693. package/scripts/print-builds.ts +21 -0
  694. package/scripts/verify-integration-env.cjs +29 -0
  695. package/src/api-client.ts +307 -0
  696. package/src/config/index.ts +286 -0
  697. package/src/errors/index.ts +25 -0
  698. package/src/formatters/build-step-formatter.ts +178 -0
  699. package/src/formatters/trigger-formatter.ts +207 -0
  700. package/src/index.ts +61 -0
  701. package/src/middleware/error.test.ts +274 -0
  702. package/src/middleware/error.ts +314 -0
  703. package/src/middleware/global-error-handler.test.ts +239 -0
  704. package/src/middleware/global-error-handler.ts +203 -0
  705. package/src/middleware/index.ts +5 -0
  706. package/src/server.ts +126 -0
  707. package/src/swagger/index.ts +220 -0
  708. package/src/swagger/swagger-cache.ts +220 -0
  709. package/src/swagger/swagger-fetcher.ts +126 -0
  710. package/src/swagger/swagger-validator.ts +212 -0
  711. package/src/teamcity/api-types.ts +387 -0
  712. package/src/teamcity/artifact-manager.ts +362 -0
  713. package/src/teamcity/auth.ts +215 -0
  714. package/src/teamcity/branch-discovery-manager.ts +311 -0
  715. package/src/teamcity/branch-filtering-service.ts +369 -0
  716. package/src/teamcity/branch-specification-parser.ts +238 -0
  717. package/src/teamcity/build-config-manager.ts +458 -0
  718. package/src/teamcity/build-config-navigator.ts +589 -0
  719. package/src/teamcity/build-configuration-clone-manager.ts +501 -0
  720. package/src/teamcity/build-configuration-manager.ts +447 -0
  721. package/src/teamcity/build-configuration-resolver.ts +725 -0
  722. package/src/teamcity/build-configuration-update-manager.ts +610 -0
  723. package/src/teamcity/build-list-manager.ts +313 -0
  724. package/src/teamcity/build-parameters-manager.ts +875 -0
  725. package/src/teamcity/build-progress-tracker.ts +514 -0
  726. package/src/teamcity/build-query-builder.ts +325 -0
  727. package/src/teamcity/build-queue-manager.ts +622 -0
  728. package/src/teamcity/build-results-manager.ts +589 -0
  729. package/src/teamcity/build-status-manager.ts +564 -0
  730. package/src/teamcity/build-step-manager.ts +508 -0
  731. package/src/teamcity/build-trigger-manager.ts +1083 -0
  732. package/src/teamcity/circuit-breaker.ts +219 -0
  733. package/src/teamcity/client-adapter.ts +35 -0
  734. package/src/teamcity/client.ts +269 -0
  735. package/src/teamcity/config.ts +188 -0
  736. package/src/teamcity/configuration-branch-matcher.ts +327 -0
  737. package/src/teamcity/errors.ts +351 -0
  738. package/src/teamcity/index.ts +266 -0
  739. package/src/teamcity/pagination.ts +209 -0
  740. package/src/teamcity/project-list-manager.ts +267 -0
  741. package/src/teamcity/project-manager.ts +493 -0
  742. package/src/teamcity/project-navigator.ts +664 -0
  743. package/src/teamcity/test-problem-reporter.ts +423 -0
  744. package/src/teamcity/types/api-responses.ts +314 -0
  745. package/src/teamcity-client/.openapi-generator/FILES +274 -0
  746. package/src/teamcity-client/.openapi-generator/VERSION +1 -0
  747. package/src/teamcity-client/.openapi-generator-ignore +23 -0
  748. package/src/teamcity-client/README.md +50 -0
  749. package/src/teamcity-client/api/agent-api.ts +2046 -0
  750. package/src/teamcity-client/api/agent-pool-api.ts +1877 -0
  751. package/src/teamcity-client/api/agent-type-api.ts +213 -0
  752. package/src/teamcity-client/api/audit-api.ts +341 -0
  753. package/src/teamcity-client/api/avatar-api.ts +569 -0
  754. package/src/teamcity-client/api/build-api.ts +7726 -0
  755. package/src/teamcity-client/api/build-queue-api.ts +1922 -0
  756. package/src/teamcity-client/api/build-type-api.ts +15502 -0
  757. package/src/teamcity-client/api/change-api.ts +1311 -0
  758. package/src/teamcity-client/api/cloud-instance-api.ts +1289 -0
  759. package/src/teamcity-client/api/deployment-dashboard-api.ts +1295 -0
  760. package/src/teamcity-client/api/global-server-settings-api.ts +286 -0
  761. package/src/teamcity-client/api/group-api.ts +2084 -0
  762. package/src/teamcity-client/api/health-api.ts +566 -0
  763. package/src/teamcity-client/api/investigation-api.ts +856 -0
  764. package/src/teamcity-client/api/mute-api.ts +824 -0
  765. package/src/teamcity-client/api/node-api.ts +877 -0
  766. package/src/teamcity-client/api/problem-api.ts +337 -0
  767. package/src/teamcity-client/api/problem-occurrence-api.ts +349 -0
  768. package/src/teamcity-client/api/project-api.ts +6511 -0
  769. package/src/teamcity-client/api/role-api.ts +1062 -0
  770. package/src/teamcity-client/api/root-api.ts +439 -0
  771. package/src/teamcity-client/api/server-api.ts +2306 -0
  772. package/src/teamcity-client/api/server-authentication-settings-api.ts +289 -0
  773. package/src/teamcity-client/api/test-api.ts +329 -0
  774. package/src/teamcity-client/api/test-occurrence-api.ts +340 -0
  775. package/src/teamcity-client/api/user-api.ts +3644 -0
  776. package/src/teamcity-client/api/vcs-root-api.ts +1837 -0
  777. package/src/teamcity-client/api/vcs-root-instance-api.ts +2479 -0
  778. package/src/teamcity-client/api/versioned-settings-api.ts +2025 -0
  779. package/src/teamcity-client/api.ts +44 -0
  780. package/src/teamcity-client/base.ts +91 -0
  781. package/src/teamcity-client/common.ts +197 -0
  782. package/src/teamcity-client/configuration.ts +130 -0
  783. package/src/teamcity-client/git_push.sh +57 -0
  784. package/src/teamcity-client/index.ts +17 -0
  785. package/src/teamcity-client/models/agent-locator.ts +124 -0
  786. package/src/teamcity-client/models/agent-pool-locator.ts +63 -0
  787. package/src/teamcity-client/models/agent-pool.ts +87 -0
  788. package/src/teamcity-client/models/agent-pools.ts +54 -0
  789. package/src/teamcity-client/models/agent-requirement.ts +66 -0
  790. package/src/teamcity-client/models/agent-requirements.ts +36 -0
  791. package/src/teamcity-client/models/agent-type-locator.ts +51 -0
  792. package/src/teamcity-client/models/agent-type.ts +81 -0
  793. package/src/teamcity-client/models/agent-types.ts +54 -0
  794. package/src/teamcity-client/models/agent.ts +295 -0
  795. package/src/teamcity-client/models/agents.ts +54 -0
  796. package/src/teamcity-client/models/approvable-build.ts +39 -0
  797. package/src/teamcity-client/models/approval-info.ts +100 -0
  798. package/src/teamcity-client/models/artifact-dependencies.ts +42 -0
  799. package/src/teamcity-client/models/artifact-dependency.ts +75 -0
  800. package/src/teamcity-client/models/artifact-download-info.ts +33 -0
  801. package/src/teamcity-client/models/audit-action.ts +39 -0
  802. package/src/teamcity-client/models/audit-event.ts +66 -0
  803. package/src/teamcity-client/models/audit-events.ts +54 -0
  804. package/src/teamcity-client/models/audit-locator.ts +315 -0
  805. package/src/teamcity-client/models/auth-module.ts +36 -0
  806. package/src/teamcity-client/models/auth-modules.ts +30 -0
  807. package/src/teamcity-client/models/authorization-tokens-requirements.ts +33 -0
  808. package/src/teamcity-client/models/authorized-info.ts +36 -0
  809. package/src/teamcity-client/models/branch-locator.ts +117 -0
  810. package/src/teamcity-client/models/branch-version.ts +78 -0
  811. package/src/teamcity-client/models/branch.ts +72 -0
  812. package/src/teamcity-client/models/branches.ts +42 -0
  813. package/src/teamcity-client/models/build-cancel-request.ts +33 -0
  814. package/src/teamcity-client/models/build-change.ts +36 -0
  815. package/src/teamcity-client/models/build-changes.ts +36 -0
  816. package/src/teamcity-client/models/build-executor.ts +27 -0
  817. package/src/teamcity-client/models/build-locator.ts +277 -0
  818. package/src/teamcity-client/models/build-queue-locator.ts +87 -0
  819. package/src/teamcity-client/models/build-status-update.ts +33 -0
  820. package/src/teamcity-client/models/build-trigger-customization.ts +42 -0
  821. package/src/teamcity-client/models/build-triggering-options.ts +72 -0
  822. package/src/teamcity-client/models/build-type-locator.ts +111 -0
  823. package/src/teamcity-client/models/build-type.ts +305 -0
  824. package/src/teamcity-client/models/build-types.ts +54 -0
  825. package/src/teamcity-client/models/build.ts +631 -0
  826. package/src/teamcity-client/models/builds-with-reason.ts +36 -0
  827. package/src/teamcity-client/models/builds.ts +54 -0
  828. package/src/teamcity-client/models/change-locator.ts +129 -0
  829. package/src/teamcity-client/models/change-status.ts +114 -0
  830. package/src/teamcity-client/models/change.ts +186 -0
  831. package/src/teamcity-client/models/changes.ts +54 -0
  832. package/src/teamcity-client/models/cleanup.ts +51 -0
  833. package/src/teamcity-client/models/cloud-error.ts +33 -0
  834. package/src/teamcity-client/models/cloud-image-locator.ts +105 -0
  835. package/src/teamcity-client/models/cloud-image.ts +102 -0
  836. package/src/teamcity-client/models/cloud-images.ts +54 -0
  837. package/src/teamcity-client/models/cloud-instance-locator.ts +81 -0
  838. package/src/teamcity-client/models/cloud-instance.ts +90 -0
  839. package/src/teamcity-client/models/cloud-instances.ts +54 -0
  840. package/src/teamcity-client/models/cloud-profile-locator.ts +81 -0
  841. package/src/teamcity-client/models/cloud-profile.ts +72 -0
  842. package/src/teamcity-client/models/cloud-profiles.ts +54 -0
  843. package/src/teamcity-client/models/comment.ts +42 -0
  844. package/src/teamcity-client/models/commiter.ts +36 -0
  845. package/src/teamcity-client/models/compatibilities.ts +36 -0
  846. package/src/teamcity-client/models/compatibility-policy.ts +36 -0
  847. package/src/teamcity-client/models/compatibility.ts +54 -0
  848. package/src/teamcity-client/models/composite-approval-rule.ts +54 -0
  849. package/src/teamcity-client/models/composite-approvals.ts +36 -0
  850. package/src/teamcity-client/models/cron.ts +51 -0
  851. package/src/teamcity-client/models/customizations.ts +45 -0
  852. package/src/teamcity-client/models/daily.ts +33 -0
  853. package/src/teamcity-client/models/datas.ts +36 -0
  854. package/src/teamcity-client/models/deployment-dashboard-locator.ts +57 -0
  855. package/src/teamcity-client/models/deployment-dashboard.ts +51 -0
  856. package/src/teamcity-client/models/deployment-dashboards.ts +54 -0
  857. package/src/teamcity-client/models/deployment-history.ts +36 -0
  858. package/src/teamcity-client/models/deployment-instance-locator.ts +62 -0
  859. package/src/teamcity-client/models/deployment-instance.ts +68 -0
  860. package/src/teamcity-client/models/deployment-instances.ts +54 -0
  861. package/src/teamcity-client/models/deployment-state-entries.ts +45 -0
  862. package/src/teamcity-client/models/deployment-state-entry.ts +59 -0
  863. package/src/teamcity-client/models/disabled-responsibilities.ts +36 -0
  864. package/src/teamcity-client/models/download-info.ts +45 -0
  865. package/src/teamcity-client/models/downloaded-artifacts.ts +42 -0
  866. package/src/teamcity-client/models/effective-responsibilities.ts +36 -0
  867. package/src/teamcity-client/models/enabled-info.ts +42 -0
  868. package/src/teamcity-client/models/enabled-responsibilities.ts +36 -0
  869. package/src/teamcity-client/models/entries.ts +36 -0
  870. package/src/teamcity-client/models/entry.ts +33 -0
  871. package/src/teamcity-client/models/environment.ts +33 -0
  872. package/src/teamcity-client/models/feature.ts +66 -0
  873. package/src/teamcity-client/models/features.ts +36 -0
  874. package/src/teamcity-client/models/file-change.ts +63 -0
  875. package/src/teamcity-client/models/file-changes.ts +36 -0
  876. package/src/teamcity-client/models/files.ts +39 -0
  877. package/src/teamcity-client/models/group-approval-rule.ts +45 -0
  878. package/src/teamcity-client/models/group-approvals.ts +36 -0
  879. package/src/teamcity-client/models/group.ts +87 -0
  880. package/src/teamcity-client/models/groups.ts +36 -0
  881. package/src/teamcity-client/models/health-categories.ts +54 -0
  882. package/src/teamcity-client/models/health-category.ts +45 -0
  883. package/src/teamcity-client/models/health-item.ts +51 -0
  884. package/src/teamcity-client/models/health-status-items.ts +54 -0
  885. package/src/teamcity-client/models/href.ts +27 -0
  886. package/src/teamcity-client/models/index.ts +229 -0
  887. package/src/teamcity-client/models/investigation-locator.ts +125 -0
  888. package/src/teamcity-client/models/investigation.ts +100 -0
  889. package/src/teamcity-client/models/investigations.ts +54 -0
  890. package/src/teamcity-client/models/issue-usage.ts +39 -0
  891. package/src/teamcity-client/models/issue.ts +33 -0
  892. package/src/teamcity-client/models/issues-usages.ts +42 -0
  893. package/src/teamcity-client/models/issues.ts +30 -0
  894. package/src/teamcity-client/models/items.ts +27 -0
  895. package/src/teamcity-client/models/labeled-value.ts +33 -0
  896. package/src/teamcity-client/models/license-key.ts +134 -0
  897. package/src/teamcity-client/models/license-keys.ts +42 -0
  898. package/src/teamcity-client/models/licensing-data.ts +114 -0
  899. package/src/teamcity-client/models/link.ts +39 -0
  900. package/src/teamcity-client/models/links.ts +36 -0
  901. package/src/teamcity-client/models/matrix-build-feature-descriptor.ts +48 -0
  902. package/src/teamcity-client/models/matrix-configuration.ts +51 -0
  903. package/src/teamcity-client/models/matrix-dependencies.ts +36 -0
  904. package/src/teamcity-client/models/matrix-dependency.ts +39 -0
  905. package/src/teamcity-client/models/matrix-parameter-descriptor.ts +42 -0
  906. package/src/teamcity-client/models/meta-data.ts +36 -0
  907. package/src/teamcity-client/models/metric-tag.ts +33 -0
  908. package/src/teamcity-client/models/metric-tags.ts +36 -0
  909. package/src/teamcity-client/models/metric-value.ts +42 -0
  910. package/src/teamcity-client/models/metric-values.ts +36 -0
  911. package/src/teamcity-client/models/metric.ts +57 -0
  912. package/src/teamcity-client/models/metrics.ts +36 -0
  913. package/src/teamcity-client/models/model-file.ts +75 -0
  914. package/src/teamcity-client/models/multiple-operation-result.ts +42 -0
  915. package/src/teamcity-client/models/mute-locator.ts +108 -0
  916. package/src/teamcity-client/models/mute.ts +69 -0
  917. package/src/teamcity-client/models/mutes.ts +54 -0
  918. package/src/teamcity-client/models/new-build-type-description.ts +75 -0
  919. package/src/teamcity-client/models/new-project-description.ts +87 -0
  920. package/src/teamcity-client/models/node.ts +87 -0
  921. package/src/teamcity-client/models/nodes.ts +36 -0
  922. package/src/teamcity-client/models/operation-result.ts +36 -0
  923. package/src/teamcity-client/models/parsed-test-name.ts +63 -0
  924. package/src/teamcity-client/models/permission-assignment.ts +45 -0
  925. package/src/teamcity-client/models/permission-assignments.ts +36 -0
  926. package/src/teamcity-client/models/permission-restriction.ts +45 -0
  927. package/src/teamcity-client/models/permission-restrictions.ts +36 -0
  928. package/src/teamcity-client/models/permission.ts +39 -0
  929. package/src/teamcity-client/models/permissions.ts +36 -0
  930. package/src/teamcity-client/models/pin-info.ts +36 -0
  931. package/src/teamcity-client/models/plugin.ts +54 -0
  932. package/src/teamcity-client/models/plugins.ts +36 -0
  933. package/src/teamcity-client/models/problem-locator.ts +93 -0
  934. package/src/teamcity-client/models/problem-occurrence-locator.ts +99 -0
  935. package/src/teamcity-client/models/problem-occurrence.ts +114 -0
  936. package/src/teamcity-client/models/problem-occurrences.ts +84 -0
  937. package/src/teamcity-client/models/problem-scope.ts +48 -0
  938. package/src/teamcity-client/models/problem-target.ts +45 -0
  939. package/src/teamcity-client/models/problem.ts +84 -0
  940. package/src/teamcity-client/models/problems.ts +48 -0
  941. package/src/teamcity-client/models/progress-info.ts +78 -0
  942. package/src/teamcity-client/models/project-feature.ts +66 -0
  943. package/src/teamcity-client/models/project-features.ts +42 -0
  944. package/src/teamcity-client/models/project-locator.ts +123 -0
  945. package/src/teamcity-client/models/project.ts +207 -0
  946. package/src/teamcity-client/models/projects.ts +54 -0
  947. package/src/teamcity-client/models/properties.ts +42 -0
  948. package/src/teamcity-client/models/property.ts +48 -0
  949. package/src/teamcity-client/models/related-entities.ts +36 -0
  950. package/src/teamcity-client/models/related-entity.ts +144 -0
  951. package/src/teamcity-client/models/related.ts +30 -0
  952. package/src/teamcity-client/models/repository-state.ts +42 -0
  953. package/src/teamcity-client/models/requirements.ts +27 -0
  954. package/src/teamcity-client/models/resolution.ts +41 -0
  955. package/src/teamcity-client/models/responsibility.ts +33 -0
  956. package/src/teamcity-client/models/revision.ts +54 -0
  957. package/src/teamcity-client/models/revisions.ts +42 -0
  958. package/src/teamcity-client/models/role.ts +39 -0
  959. package/src/teamcity-client/models/roles.ts +30 -0
  960. package/src/teamcity-client/models/server-auth-settings.ts +72 -0
  961. package/src/teamcity-client/models/server-global-settings.ts +93 -0
  962. package/src/teamcity-client/models/server.ts +156 -0
  963. package/src/teamcity-client/models/snapshot-dependencies.ts +36 -0
  964. package/src/teamcity-client/models/snapshot-dependency-link.ts +45 -0
  965. package/src/teamcity-client/models/snapshot-dependency.ts +75 -0
  966. package/src/teamcity-client/models/state-field.ts +33 -0
  967. package/src/teamcity-client/models/step.ts +72 -0
  968. package/src/teamcity-client/models/steps.ts +36 -0
  969. package/src/teamcity-client/models/tag-locator.ts +39 -0
  970. package/src/teamcity-client/models/tag.ts +42 -0
  971. package/src/teamcity-client/models/tags.ts +36 -0
  972. package/src/teamcity-client/models/team-city-node-locator.ts +39 -0
  973. package/src/teamcity-client/models/test-counters.ts +63 -0
  974. package/src/teamcity-client/models/test-locator.ts +87 -0
  975. package/src/teamcity-client/models/test-occurrence-locator.ts +147 -0
  976. package/src/teamcity-client/models/test-occurrence.ts +173 -0
  977. package/src/teamcity-client/models/test-occurrences.ts +93 -0
  978. package/src/teamcity-client/models/test-run-metadata.ts +36 -0
  979. package/src/teamcity-client/models/tests.ts +57 -0
  980. package/src/teamcity-client/models/token.ts +54 -0
  981. package/src/teamcity-client/models/tokens.ts +36 -0
  982. package/src/teamcity-client/models/trigger.ts +75 -0
  983. package/src/teamcity-client/models/triggered-by.ts +87 -0
  984. package/src/teamcity-client/models/triggers.ts +36 -0
  985. package/src/teamcity-client/models/type.ts +27 -0
  986. package/src/teamcity-client/models/typed-value-set.ts +60 -0
  987. package/src/teamcity-client/models/typed-value-sets.ts +36 -0
  988. package/src/teamcity-client/models/typed-value.ts +39 -0
  989. package/src/teamcity-client/models/user-approval-rule.ts +36 -0
  990. package/src/teamcity-client/models/user-approvals.ts +36 -0
  991. package/src/teamcity-client/models/user-avatars.ts +63 -0
  992. package/src/teamcity-client/models/user-group-locator.ts +39 -0
  993. package/src/teamcity-client/models/user-locator.ts +93 -0
  994. package/src/teamcity-client/models/user.ts +123 -0
  995. package/src/teamcity-client/models/users.ts +36 -0
  996. package/src/teamcity-client/models/vcs-check-status.ts +39 -0
  997. package/src/teamcity-client/models/vcs-label.ts +65 -0
  998. package/src/teamcity-client/models/vcs-labels.ts +36 -0
  999. package/src/teamcity-client/models/vcs-root-entries.ts +36 -0
  1000. package/src/teamcity-client/models/vcs-root-entry.ts +48 -0
  1001. package/src/teamcity-client/models/vcs-root-instance-locator.ts +124 -0
  1002. package/src/teamcity-client/models/vcs-root-instance.ts +132 -0
  1003. package/src/teamcity-client/models/vcs-root-instances.ts +54 -0
  1004. package/src/teamcity-client/models/vcs-root-locator.ts +118 -0
  1005. package/src/teamcity-client/models/vcs-root.ts +111 -0
  1006. package/src/teamcity-client/models/vcs-roots.ts +54 -0
  1007. package/src/teamcity-client/models/vcs-status.ts +36 -0
  1008. package/src/teamcity-client/models/versioned-settings-config.ts +111 -0
  1009. package/src/teamcity-client/models/versioned-settings-context-parameter.ts +33 -0
  1010. package/src/teamcity-client/models/versioned-settings-context-parameters.ts +30 -0
  1011. package/src/teamcity-client/models/versioned-settings-error.ts +45 -0
  1012. package/src/teamcity-client/models/versioned-settings-status.ts +68 -0
  1013. package/src/teamcity-client/models/versioned-settings-token.ts +39 -0
  1014. package/src/teamcity-client/models/versioned-settings-tokens.ts +30 -0
  1015. package/src/teamcity-client/package.json +33 -0
  1016. package/src/teamcity-client/tsconfig.esm.json +7 -0
  1017. package/src/teamcity-client/tsconfig.json +13 -0
  1018. package/src/teamcity-client-types.d.ts +27 -0
  1019. package/src/tools/index.ts +2 -0
  1020. package/src/tools.ts +2890 -0
  1021. package/src/types/config.ts +140 -0
  1022. package/src/types/index.ts +171 -0
  1023. package/src/types/mcp.ts +80 -0
  1024. package/src/types/project.ts +128 -0
  1025. package/src/types/teamcity.ts +289 -0
  1026. package/src/utils/async/index.test.ts +664 -0
  1027. package/src/utils/async/index.ts +578 -0
  1028. package/src/utils/error-logger.test.ts +173 -0
  1029. package/src/utils/error-logger.ts +145 -0
  1030. package/src/utils/index.ts +88 -0
  1031. package/src/utils/logger/index.test.ts +271 -0
  1032. package/src/utils/logger/index.ts +441 -0
  1033. package/src/utils/logger.ts +49 -0
  1034. package/src/utils/lru-cache.ts +105 -0
  1035. package/src/utils/mcp.ts +84 -0
  1036. package/src/utils/validation.ts +284 -0
  1037. package/tests/__mocks__/@modelcontextprotocol/sdk/server/index.js +31 -0
  1038. package/tests/__mocks__/@modelcontextprotocol/sdk/server/stdio.js +12 -0
  1039. package/tests/__mocks__/@modelcontextprotocol/sdk/types.js +16 -0
  1040. package/tests/development-tooling.test.ts +207 -0
  1041. package/tests/e2e/cleanup.ts +68 -0
  1042. package/tests/e2e/index.ts +166 -0
  1043. package/tests/e2e/mcp-client.ts +73 -0
  1044. package/tests/e2e/setup-playground.ts +67 -0
  1045. package/tests/integration/branches-and-queue-scenario.test.ts +108 -0
  1046. package/tests/integration/build-config-clone-update-scenario.test.ts +80 -0
  1047. package/tests/integration/build-results-and-logs-scenario.test.ts +136 -0
  1048. package/tests/integration/dev-tools-list.test.ts +103 -0
  1049. package/tests/integration/e2e-scenario.test.ts +147 -0
  1050. package/tests/integration/lib/mcp-runner.ts +59 -0
  1051. package/tests/integration/parameters-scenario.test.ts +85 -0
  1052. package/tests/integration/pause-configs-scenario.test.ts +74 -0
  1053. package/tests/integration/queue-maintenance-scenario.test.ts +132 -0
  1054. package/tests/integration/server-health-scenario.test.ts +59 -0
  1055. package/tests/integration/triggers-scenario.test.ts +80 -0
  1056. package/tests/integration/vcs-scenario.test.ts +78 -0
  1057. package/tests/jest.test.js +122 -0
  1058. package/tests/mcp-server.test.ts +378 -0
  1059. package/tests/setup.test.js +97 -0
  1060. package/tests/setup.ts +88 -0
  1061. package/tests/swagger/swagger-fetcher.test.ts +619 -0
  1062. package/tests/teamcity/auth.test.ts +276 -0
  1063. package/tests/teamcity/circuit-breaker.test.ts +304 -0
  1064. package/tests/teamcity/errors.test.ts +221 -0
  1065. package/tests/test-utils/mock-logger.ts +15 -0
  1066. package/tests/test-utils/mock-teamcity-client.ts +403 -0
  1067. package/tests/testing-infrastructure.test.ts +209 -0
  1068. package/tests/tooling.test.js +118 -0
  1069. package/tests/types/shims.d.ts +20 -0
  1070. package/tests/types/tool-results.ts +68 -0
  1071. package/tests/typescript.test.js +108 -0
  1072. package/tests/unit/mcp/server-lifecycle.test.ts +301 -0
  1073. package/tests/unit/middleware/error.test.ts +283 -0
  1074. package/tests/unit/server.test.ts +102 -0
  1075. package/tests/unit/swagger/swagger-manager.test.ts +89 -0
  1076. package/tests/unit/teamcity/artifact-manager.test.ts +450 -0
  1077. package/tests/unit/teamcity/branch-discovery-manager.test.ts +561 -0
  1078. package/tests/unit/teamcity/branch-filtering-service.test.ts +481 -0
  1079. package/tests/unit/teamcity/branch-specification-parser.test.ts +443 -0
  1080. package/tests/unit/teamcity/build-config-navigator-more.test.ts +245 -0
  1081. package/tests/unit/teamcity/build-config-navigator.test.ts +1452 -0
  1082. package/tests/unit/teamcity/build-configuration-manager.test.ts +750 -0
  1083. package/tests/unit/teamcity/build-configuration-resolver.test.ts +659 -0
  1084. package/tests/unit/teamcity/build-list-manager.test.ts +574 -0
  1085. package/tests/unit/teamcity/build-parameters-manager.test.ts +712 -0
  1086. package/tests/unit/teamcity/build-progress-tracker.test.ts +1030 -0
  1087. package/tests/unit/teamcity/build-query-builder.test.ts +311 -0
  1088. package/tests/unit/teamcity/build-queue-manager.test.ts +879 -0
  1089. package/tests/unit/teamcity/build-results-manager.test.ts +630 -0
  1090. package/tests/unit/teamcity/build-status-manager.test.ts +640 -0
  1091. package/tests/unit/teamcity/build-step-manager.test.ts +886 -0
  1092. package/tests/unit/teamcity/build-trigger-manager.test.ts +1052 -0
  1093. package/tests/unit/teamcity/configuration-branch-matcher.test.ts +692 -0
  1094. package/tests/unit/teamcity/pagination.test.ts +118 -0
  1095. package/tests/unit/teamcity/project-list-manager.test.ts +118 -0
  1096. package/tests/unit/teamcity/project-manager-branches.test.ts +176 -0
  1097. package/tests/unit/teamcity/project-manager-more.test.ts +90 -0
  1098. package/tests/unit/teamcity/project-manager.test.ts +189 -0
  1099. package/tests/unit/teamcity/project-navigator-branches.test.ts +168 -0
  1100. package/tests/unit/teamcity/project-navigator-more.test.ts +58 -0
  1101. package/tests/unit/teamcity/project-navigator.test.ts +791 -0
  1102. package/tests/unit/teamcity/test-problem-reporter-trend-patterns.test.ts +80 -0
  1103. package/tests/unit/teamcity/test-problem-reporter.test.ts +551 -0
  1104. package/tests/unit/tools/agent-vcs-admin.test.ts +121 -0
  1105. package/tests/unit/tools/availability-and-queue.test.ts +118 -0
  1106. package/tests/unit/tools/branches-vcs-agents.test.ts +119 -0
  1107. package/tests/unit/tools/build-actions-and-status.test.ts +125 -0
  1108. package/tests/unit/tools/bulk-surface-coverage.test.ts +116 -0
  1109. package/tests/unit/tools/compatibility-lookups.test.ts +150 -0
  1110. package/tests/unit/tools/fetch-build-log-ambiguity.test.ts +70 -0
  1111. package/tests/unit/tools/fetch-build-log-by-number.test.ts +66 -0
  1112. package/tests/unit/tools/fetch-build-log-pagination.test.ts +73 -0
  1113. package/tests/unit/tools/fetch-build-log-tail.test.ts +33 -0
  1114. package/tests/unit/tools/get-status-and-results.test.ts +67 -0
  1115. package/tests/unit/tools/list-branches-and-parameters.test.ts +36 -0
  1116. package/tests/unit/tools/list-build-configs-pagination.test.ts +39 -0
  1117. package/tests/unit/tools/list-builds-pagination.test.ts +45 -0
  1118. package/tests/unit/tools/list-pagination-all.test.ts +259 -0
  1119. package/tests/unit/tools/list-projects-pagination.test.ts +39 -0
  1120. package/tests/unit/tools/parameters-and-steps-triggers.test.ts +176 -0
  1121. package/tests/unit/tools/project-build-crud.test.ts +110 -0
  1122. package/tests/unit/tools/project-hierarchy.test.ts +46 -0
  1123. package/tests/unit/tools/queue-maintenance.test.ts +130 -0
  1124. package/tests/unit/tools/server-health-and-metrics.test.ts +134 -0
  1125. package/tests/unit/tools/simple-getters.test.ts +88 -0
  1126. package/tests/unit/tools/update_project_settings.test.ts +64 -0
  1127. package/tests/unit/utils/lru-cache.test.ts +77 -0
  1128. package/tests/unit/utils/mcp.test.ts +82 -0
  1129. package/tests/unit/utils/runTool.test.ts +38 -0
  1130. package/tests/unit/utils/validation.test.ts +168 -0
  1131. package/tsconfig.build.json +28 -0
  1132. package/tsconfig.json +60 -0
  1133. package/tsconfig.lint.json +13 -0
package/src/tools.ts ADDED
@@ -0,0 +1,2890 @@
1
+ /**
2
+ * Static Tool Definitions for TeamCity MCP Server
3
+ * Simple, direct tool implementations without complex abstractions
4
+ */
5
+ import { z } from 'zod';
6
+
7
+ import { getMCPMode as getMCPModeFromConfig } from '@/config';
8
+ import { BuildResultsManager } from '@/teamcity/build-results-manager';
9
+ import { createAdapterFromTeamCityAPI } from '@/teamcity/client-adapter';
10
+ import { createPaginatedFetcher, fetchAllPages } from '@/teamcity/pagination';
11
+ import { debug } from '@/utils/logger';
12
+ import { json, runTool } from '@/utils/mcp';
13
+
14
+ import { TeamCityAPI } from './api-client';
15
+
16
+ // Tool response type
17
+ export interface ToolResponse {
18
+ content?: Array<{ type: string; text: string }>;
19
+ error?: string;
20
+ success?: boolean;
21
+ data?: unknown;
22
+ }
23
+
24
+ // Tool definition - handlers use unknown but are cast internally
25
+ export interface ToolDefinition {
26
+ name: string;
27
+ description: string;
28
+ inputSchema: unknown;
29
+ handler: (args: unknown) => Promise<ToolResponse>;
30
+ mode?: 'dev' | 'full'; // If not specified, available in both modes
31
+ }
32
+
33
+ // Specific argument types are intentionally scoped to the handlers that use them.
34
+ // Zod validates at runtime; these interfaces keep compile-time safety and clean linting.
35
+ interface DeleteProjectArgs {
36
+ projectId: string;
37
+ }
38
+ interface CreateBuildConfigArgs {
39
+ projectId: string;
40
+ name: string;
41
+ id: string;
42
+ description?: string;
43
+ }
44
+ interface CloneBuildConfigArgs {
45
+ sourceBuildTypeId: string;
46
+ name: string;
47
+ id: string;
48
+ projectId?: string;
49
+ }
50
+ interface UpdateBuildConfigArgs {
51
+ buildTypeId: string;
52
+ name?: string;
53
+ description?: string;
54
+ paused?: boolean;
55
+ artifactRules?: string;
56
+ }
57
+ interface AddParameterArgs {
58
+ buildTypeId: string;
59
+ name: string;
60
+ value: string;
61
+ }
62
+ interface UpdateParameterArgs {
63
+ buildTypeId: string;
64
+ name: string;
65
+ value: string;
66
+ }
67
+ interface DeleteParameterArgs {
68
+ buildTypeId: string;
69
+ name: string;
70
+ }
71
+ interface CreateVCSRootArgs {
72
+ projectId: string;
73
+ name: string;
74
+ id: string;
75
+ vcsName: string;
76
+ url: string;
77
+ branch?: string;
78
+ }
79
+ interface AuthorizeAgentArgs {
80
+ agentId: string;
81
+ authorize: boolean;
82
+ }
83
+ interface AssignAgentToPoolArgs {
84
+ agentId: string;
85
+ poolId: string;
86
+ }
87
+ interface ManageBuildStepsArgs {
88
+ buildTypeId: string;
89
+ action: 'add' | 'update' | 'delete';
90
+ stepId?: string;
91
+ name?: string;
92
+ type?: string;
93
+ properties?: Record<string, unknown>;
94
+ }
95
+ interface ManageBuildTriggersArgs {
96
+ buildTypeId: string;
97
+ action: 'add' | 'delete';
98
+ triggerId?: string;
99
+ type?: string;
100
+ properties?: Record<string, unknown>;
101
+ }
102
+
103
+ /**
104
+ * Get the current MCP mode from environment
105
+ */
106
+ export function getMCPMode(): 'dev' | 'full' {
107
+ return getMCPModeFromConfig();
108
+ }
109
+
110
+ /**
111
+ * Developer tools (dev mode) - Read-only operations for developers
112
+ */
113
+ const DEV_TOOLS: ToolDefinition[] = [
114
+ // === Basic Tools ===
115
+ {
116
+ name: 'ping',
117
+ description: 'Test MCP server connectivity',
118
+ inputSchema: {
119
+ type: 'object',
120
+ properties: {
121
+ message: { type: 'string', description: 'Optional message to echo back' },
122
+ },
123
+ },
124
+ handler: async (args: unknown) => {
125
+ const typedArgs = args as { message?: string };
126
+ return {
127
+ content: [
128
+ {
129
+ type: 'text',
130
+ text: `pong${typedArgs.message ? `: ${typedArgs.message}` : ''}`,
131
+ },
132
+ ],
133
+ };
134
+ },
135
+ },
136
+
137
+ // === Project Tools ===
138
+ {
139
+ name: 'list_projects',
140
+ description: 'List TeamCity projects (supports pagination)',
141
+ inputSchema: {
142
+ type: 'object',
143
+ properties: {
144
+ locator: { type: 'string', description: 'Optional locator to filter projects' },
145
+ parentProjectId: { type: 'string', description: 'Filter by parent project ID' },
146
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
147
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
148
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
149
+ fields: {
150
+ type: 'string',
151
+ description: 'Optional fields selector for server-side projection',
152
+ },
153
+ },
154
+ },
155
+ handler: async (args: unknown) => {
156
+ const schema = z.object({
157
+ locator: z.string().min(1).optional(),
158
+ parentProjectId: z.string().min(1).optional(),
159
+ pageSize: z.number().int().min(1).max(1000).optional(),
160
+ maxPages: z.number().int().min(1).max(1000).optional(),
161
+ all: z.boolean().optional(),
162
+ fields: z.string().min(1).optional(),
163
+ });
164
+ return runTool(
165
+ 'list_projects',
166
+ schema,
167
+ async (typed) => {
168
+ const api = TeamCityAPI.getInstance();
169
+ const baseParts: string[] = [];
170
+ if (typed.locator) baseParts.push(typed.locator);
171
+ if (typed.parentProjectId) baseParts.push(`parent:(id:${typed.parentProjectId})`);
172
+
173
+ const pageSize = typed.pageSize ?? 100;
174
+
175
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
176
+ const parts = [...baseParts];
177
+ if (typeof count === 'number') parts.push(`count:${count}`);
178
+ if (typeof start === 'number') parts.push(`start:${start}`);
179
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
180
+ return api.projects.getAllProjects(locator as string | undefined, typed.fields);
181
+ };
182
+
183
+ const fetcher = createPaginatedFetcher(
184
+ baseFetch,
185
+ (response: unknown) => {
186
+ const data = response as { project?: unknown[]; count?: number };
187
+ return Array.isArray(data.project) ? (data.project as unknown[]) : [];
188
+ },
189
+ (response: unknown) => {
190
+ const data = response as { count?: number };
191
+ return typeof data.count === 'number' ? data.count : undefined;
192
+ }
193
+ );
194
+
195
+ if (typed.all) {
196
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
197
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
198
+ }
199
+
200
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
201
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
202
+ },
203
+ args
204
+ );
205
+ },
206
+ },
207
+
208
+ {
209
+ name: 'get_project',
210
+ description: 'Get details of a specific project',
211
+ inputSchema: {
212
+ type: 'object',
213
+ properties: {
214
+ projectId: { type: 'string', description: 'Project ID' },
215
+ },
216
+ required: ['projectId'],
217
+ },
218
+ handler: async (args: unknown) => {
219
+ const schema = z.object({ projectId: z.string().min(1) });
220
+ return runTool(
221
+ 'get_project',
222
+ schema,
223
+ async (typed) => {
224
+ const api = TeamCityAPI.getInstance();
225
+ const project = await api.getProject(typed.projectId);
226
+ return json(project);
227
+ },
228
+ args
229
+ );
230
+ },
231
+ },
232
+
233
+ // === Build Tools ===
234
+ {
235
+ name: 'list_builds',
236
+ description: 'List TeamCity builds (supports pagination)',
237
+ inputSchema: {
238
+ type: 'object',
239
+ properties: {
240
+ locator: { type: 'string', description: 'Optional build locator to filter builds' },
241
+ projectId: { type: 'string', description: 'Filter by project ID' },
242
+ buildTypeId: { type: 'string', description: 'Filter by build type ID' },
243
+ status: {
244
+ type: 'string',
245
+ enum: ['SUCCESS', 'FAILURE', 'ERROR'],
246
+ description: 'Filter by status',
247
+ },
248
+ count: { type: 'number', description: 'Deprecated: use pageSize', default: 10 },
249
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
250
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
251
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
252
+ fields: {
253
+ type: 'string',
254
+ description: 'Optional fields selector for server-side projection',
255
+ },
256
+ },
257
+ },
258
+ handler: async (args: unknown) => {
259
+ const schema = z.object({
260
+ locator: z.string().min(1).optional(),
261
+ projectId: z.string().min(1).optional(),
262
+ buildTypeId: z.string().min(1).optional(),
263
+ status: z.enum(['SUCCESS', 'FAILURE', 'ERROR']).optional(),
264
+ count: z.number().int().min(1).max(1000).default(10).optional(),
265
+ pageSize: z.number().int().min(1).max(1000).optional(),
266
+ maxPages: z.number().int().min(1).max(1000).optional(),
267
+ all: z.boolean().optional(),
268
+ fields: z.string().min(1).optional(),
269
+ });
270
+
271
+ return runTool(
272
+ 'list_builds',
273
+ schema,
274
+ async (typed) => {
275
+ const api = TeamCityAPI.getInstance();
276
+ // Build shared filter parts
277
+ const baseParts: string[] = [];
278
+ if (typed.locator) baseParts.push(typed.locator);
279
+ if (typed.projectId) baseParts.push(`project:(id:${typed.projectId})`);
280
+ if (typed.buildTypeId) baseParts.push(`buildType:(id:${typed.buildTypeId})`);
281
+ if (typed.status) baseParts.push(`status:${typed.status}`);
282
+
283
+ const pageSize = typed.pageSize ?? typed.count ?? 100;
284
+
285
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
286
+ const parts = [...baseParts];
287
+ if (typeof count === 'number') parts.push(`count:${count}`);
288
+ if (typeof start === 'number') parts.push(`start:${start}`);
289
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
290
+ // Use the generated client directly to retain nextHref/prevHref in response.data
291
+ return api.builds.getAllBuilds(locator as string | undefined, typed.fields);
292
+ };
293
+
294
+ const fetcher = createPaginatedFetcher(
295
+ baseFetch,
296
+ (response: unknown) => {
297
+ const data = response as { build?: unknown[]; count?: number };
298
+ return Array.isArray(data.build) ? (data.build as unknown[]) : [];
299
+ },
300
+ (response: unknown) => {
301
+ const data = response as { count?: number };
302
+ return typeof data.count === 'number' ? data.count : undefined;
303
+ }
304
+ );
305
+
306
+ if (typed.all) {
307
+ const items = await fetchAllPages(fetcher, {
308
+ pageSize,
309
+ maxPages: typed.maxPages,
310
+ });
311
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
312
+ }
313
+
314
+ // Single page
315
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
316
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
317
+ },
318
+ args
319
+ );
320
+ },
321
+ },
322
+
323
+ {
324
+ name: 'get_build',
325
+ description: 'Get details of a specific build',
326
+ inputSchema: {
327
+ type: 'object',
328
+ properties: {
329
+ buildId: { type: 'string', description: 'Build ID' },
330
+ },
331
+ required: ['buildId'],
332
+ },
333
+ handler: async (args: unknown) => {
334
+ const schema = z.object({ buildId: z.string().min(1) });
335
+ return runTool(
336
+ 'get_build',
337
+ schema,
338
+ async (typed) => {
339
+ const api = TeamCityAPI.getInstance();
340
+ const build = await api.getBuild(typed.buildId);
341
+ return json(build);
342
+ },
343
+ args
344
+ );
345
+ },
346
+ },
347
+
348
+ {
349
+ name: 'trigger_build',
350
+ description: 'Trigger a new build',
351
+ inputSchema: {
352
+ type: 'object',
353
+ properties: {
354
+ buildTypeId: { type: 'string', description: 'Build type ID to trigger' },
355
+ branchName: { type: 'string', description: 'Branch to build (optional)' },
356
+ comment: { type: 'string', description: 'Build comment (optional)' },
357
+ },
358
+ required: ['buildTypeId'],
359
+ },
360
+ handler: async (args: unknown) => {
361
+ const schema = z.object({
362
+ buildTypeId: z.string().min(1),
363
+ branchName: z.string().min(1).max(255).optional(),
364
+ comment: z.string().max(500).optional(),
365
+ });
366
+
367
+ return runTool(
368
+ 'trigger_build',
369
+ schema,
370
+ async (typed) => {
371
+ const api = TeamCityAPI.getInstance();
372
+ try {
373
+ const build = await api.triggerBuild(
374
+ typed.buildTypeId,
375
+ typed.branchName,
376
+ typed.comment
377
+ );
378
+ return json({
379
+ success: true,
380
+ action: 'trigger_build',
381
+ buildId: String(build.id ?? ''),
382
+ state: (build.state as string) ?? undefined,
383
+ status: (build.status as string) ?? undefined,
384
+ });
385
+ } catch (e) {
386
+ // Fallback to XML body in case server rejects JSON body
387
+ const branchPart = typed.branchName
388
+ ? `<branchName>${typed.branchName}</branchName>`
389
+ : '';
390
+ const commentPart = typed.comment
391
+ ? `<comment><text>${typed.comment.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</text></comment>`
392
+ : '';
393
+ const xml = `<?xml version="1.0" encoding="UTF-8"?><build><buildType id="${typed.buildTypeId}"/>${branchPart}${commentPart}</build>`;
394
+ const response = await api.buildQueue.addBuildToQueue(false, xml as unknown as never, {
395
+ headers: { 'Content-Type': 'application/xml', Accept: 'application/json' },
396
+ });
397
+ const build = response.data as { id?: number; state?: string; status?: string };
398
+ return json({
399
+ success: true,
400
+ action: 'trigger_build',
401
+ buildId: String(build.id ?? ''),
402
+ state: (build.state as string) ?? undefined,
403
+ status: (build.status as string) ?? undefined,
404
+ });
405
+ }
406
+ },
407
+ args
408
+ );
409
+ },
410
+ },
411
+
412
+ {
413
+ name: 'cancel_queued_build',
414
+ description: 'Cancel a queued build by ID',
415
+ inputSchema: {
416
+ type: 'object',
417
+ properties: {
418
+ buildId: { type: 'string', description: 'Queued build ID' },
419
+ },
420
+ required: ['buildId'],
421
+ },
422
+ handler: async (args: unknown) => {
423
+ const schema = z.object({ buildId: z.string().min(1) });
424
+ return runTool(
425
+ 'cancel_queued_build',
426
+ schema,
427
+ async (typed) => {
428
+ const api = TeamCityAPI.getInstance();
429
+ await api.buildQueue.deleteQueuedBuild(typed.buildId);
430
+ return json({ success: true, action: 'cancel_queued_build', buildId: typed.buildId });
431
+ },
432
+ args
433
+ );
434
+ },
435
+ // Available in dev and full modes (developer convenience)
436
+ },
437
+
438
+ {
439
+ name: 'get_build_status',
440
+ description: 'Get build status with optional test/problem and queue context details',
441
+ inputSchema: {
442
+ type: 'object',
443
+ properties: {
444
+ buildId: { type: 'string', description: 'Build ID' },
445
+ includeTests: { type: 'boolean', description: 'Include test summary' },
446
+ includeProblems: { type: 'boolean', description: 'Include build problems' },
447
+ includeQueueTotals: {
448
+ type: 'boolean',
449
+ description: 'Include total queued count (extra API call when queued)',
450
+ },
451
+ includeQueueReason: {
452
+ type: 'boolean',
453
+ description: 'Include waitReason for the queued item (extra API call when queued)',
454
+ },
455
+ },
456
+ required: ['buildId'],
457
+ },
458
+ handler: async (args: unknown) => {
459
+ const schema = z.object({
460
+ buildId: z.string().min(1),
461
+ includeTests: z.boolean().optional(),
462
+ includeProblems: z.boolean().optional(),
463
+ includeQueueTotals: z.boolean().optional(),
464
+ includeQueueReason: z.boolean().optional(),
465
+ });
466
+ return runTool(
467
+ 'get_build_status',
468
+ schema,
469
+ async (typed) => {
470
+ const api = TeamCityAPI.getInstance();
471
+ const statusManager = new (
472
+ await import('@/teamcity/build-status-manager')
473
+ ).BuildStatusManager(createAdapterFromTeamCityAPI(api));
474
+ const result = await statusManager.getBuildStatus({
475
+ buildId: typed.buildId,
476
+ includeTests: typed.includeTests,
477
+ includeProblems: typed.includeProblems,
478
+ });
479
+
480
+ if (result.state === 'queued') {
481
+ const enrich: { totalQueued?: number; waitReason?: string; canMoveToTop?: boolean } =
482
+ {};
483
+ // Derive canMoveToTop without extra call
484
+ if (typeof result.queuePosition === 'number') {
485
+ enrich.canMoveToTop = result.queuePosition > 1;
486
+ }
487
+
488
+ if (typed.includeQueueTotals) {
489
+ try {
490
+ const countResp = await api.buildQueue.getAllQueuedBuilds(undefined, 'count');
491
+ enrich.totalQueued = (countResp.data as { count?: number }).count;
492
+ } catch {
493
+ /* ignore */
494
+ }
495
+ }
496
+ if (typed.includeQueueReason) {
497
+ try {
498
+ const qb = await api.buildQueue.getQueuedBuild(typed.buildId);
499
+ enrich.waitReason = (qb.data as { waitReason?: string }).waitReason;
500
+ } catch {
501
+ /* ignore */
502
+ }
503
+ }
504
+ return json({ ...result, ...enrich });
505
+ }
506
+
507
+ return json(result);
508
+ },
509
+ args
510
+ );
511
+ },
512
+ },
513
+
514
+ {
515
+ name: 'fetch_build_log',
516
+ description: 'Fetch build log with pagination (by lines)',
517
+ inputSchema: {
518
+ type: 'object',
519
+ properties: {
520
+ buildId: { type: 'string', description: 'Build ID (TeamCity internal id)' },
521
+ buildNumber: {
522
+ type: 'string',
523
+ description:
524
+ 'Human build number (e.g., 54). If provided, optionally include buildTypeId to disambiguate.',
525
+ },
526
+ buildTypeId: {
527
+ type: 'string',
528
+ description: 'Optional build type ID to disambiguate buildNumber',
529
+ },
530
+ page: { type: 'number', description: '1-based page number' },
531
+ pageSize: { type: 'number', description: 'Lines per page (default 500)' },
532
+ startLine: { type: 'number', description: '0-based start line (overrides page)' },
533
+ lineCount: { type: 'number', description: 'Max lines to return (overrides pageSize)' },
534
+ tail: { type: 'boolean', description: 'Tail mode: return last N lines' },
535
+ },
536
+ required: [],
537
+ },
538
+ handler: async (args: unknown) => {
539
+ const schema = z
540
+ .object({
541
+ buildId: z.string().min(1).optional(),
542
+ buildNumber: z.union([z.string().min(1), z.number().int().min(0)]).optional(),
543
+ buildTypeId: z.string().min(1).optional(),
544
+ page: z.number().int().min(1).optional(),
545
+ pageSize: z.number().int().min(1).max(5000).optional(),
546
+ startLine: z.number().int().min(0).optional(),
547
+ lineCount: z.number().int().min(1).max(5000).optional(),
548
+ tail: z.boolean().optional(),
549
+ })
550
+ .refine((v) => Boolean(v.buildId) || Boolean(v.buildNumber), {
551
+ message: 'Provide either buildId or buildNumber',
552
+ });
553
+
554
+ return runTool(
555
+ 'fetch_build_log',
556
+ schema,
557
+ async (typed) => {
558
+ const api = TeamCityAPI.getInstance();
559
+
560
+ // Resolve effective buildId from buildId or buildNumber (+ optional buildTypeId)
561
+ let effectiveBuildId: string | undefined;
562
+ if (typed.buildId) {
563
+ effectiveBuildId = typed.buildId;
564
+ } else {
565
+ const numberStr = String(typed.buildNumber);
566
+ const baseLocatorParts: string[] = [];
567
+ if (typed.buildTypeId) baseLocatorParts.push(`buildType:(id:${typed.buildTypeId})`);
568
+ // Include non-default branches so build numbers on PR branches resolve
569
+ baseLocatorParts.push('branch:default:any');
570
+ baseLocatorParts.push(`number:${numberStr}`);
571
+ // Limit result set to avoid huge payloads
572
+ baseLocatorParts.push('count:10');
573
+ const locator = baseLocatorParts.join(',');
574
+ const resp = (await api.listBuilds(locator)) as {
575
+ build?: Array<{ id?: number; buildTypeId?: string }>;
576
+ };
577
+ const builds = Array.isArray(resp.build) ? resp.build : [];
578
+ if (builds.length === 0) {
579
+ // Fallback: if buildTypeId is provided, fetch recent builds for that configuration and match by number
580
+ if (typed.buildTypeId) {
581
+ const recent = (await api.listBuilds(
582
+ `buildType:(id:${typed.buildTypeId}),branch:default:any,count:100`
583
+ )) as { build?: Array<{ id?: number; number?: string }> };
584
+ const items = Array.isArray(recent.build) ? recent.build : [];
585
+ const match = items.find((b) => String(b.number) === numberStr);
586
+ if (match?.id != null) {
587
+ effectiveBuildId = String(match.id);
588
+ } else {
589
+ throw new Error(
590
+ `No build found with number ${numberStr} for buildTypeId ${typed.buildTypeId}`
591
+ );
592
+ }
593
+ } else {
594
+ throw new Error(
595
+ `No build found with number ${numberStr}${typed.buildTypeId ? ` for buildTypeId ${typed.buildTypeId}` : ''}`
596
+ );
597
+ }
598
+ }
599
+ if (!effectiveBuildId && !typed.buildTypeId && builds.length > 1) {
600
+ throw new Error(
601
+ `Multiple builds match number ${numberStr}. Provide buildTypeId to disambiguate.`
602
+ );
603
+ }
604
+ if (!effectiveBuildId) {
605
+ const found = builds[0];
606
+ if (!found?.id) {
607
+ throw new Error('Resolved build has no id');
608
+ }
609
+ effectiveBuildId = String(found.id);
610
+ }
611
+ }
612
+ if (!effectiveBuildId) {
613
+ throw new Error('Failed to resolve buildId from inputs');
614
+ }
615
+
616
+ // Tail mode: return last N lines regardless of provided paging params
617
+ if (typed.tail) {
618
+ const count = typed.lineCount ?? typed.pageSize ?? 500;
619
+ const full = await api.getBuildLog(effectiveBuildId);
620
+ const allLines = full.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n');
621
+ if (allLines.length > 0 && allLines[allLines.length - 1] === '') allLines.pop();
622
+ const total = allLines.length;
623
+ const start = Math.max(0, total - count);
624
+ const lines = allLines.slice(start);
625
+
626
+ return json({
627
+ lines,
628
+ meta: {
629
+ buildId: effectiveBuildId,
630
+ buildNumber:
631
+ typeof typed.buildNumber !== 'undefined' ? String(typed.buildNumber) : undefined,
632
+ buildTypeId: typed.buildTypeId,
633
+ mode: 'tail',
634
+ pageSize: count,
635
+ startLine: start,
636
+ hasMore: start > 0,
637
+ totalLines: total,
638
+ },
639
+ });
640
+ }
641
+
642
+ const effectivePageSize = typed.lineCount ?? typed.pageSize ?? 500;
643
+ const startLine =
644
+ typeof typed.startLine === 'number'
645
+ ? typed.startLine
646
+ : ((typed.page ?? 1) - 1) * effectivePageSize;
647
+
648
+ const chunk = await api.getBuildLogChunk(effectiveBuildId, {
649
+ startLine,
650
+ lineCount: effectivePageSize,
651
+ });
652
+
653
+ const page = Math.floor(startLine / effectivePageSize) + 1;
654
+ const hasMore = chunk.nextStartLine !== undefined;
655
+
656
+ return json({
657
+ lines: chunk.lines,
658
+ meta: {
659
+ buildId: effectiveBuildId,
660
+ buildNumber:
661
+ typeof typed.buildNumber !== 'undefined' ? String(typed.buildNumber) : undefined,
662
+ buildTypeId: typed.buildTypeId,
663
+ page,
664
+ pageSize: effectivePageSize,
665
+ startLine: chunk.startLine,
666
+ nextPage: hasMore ? page + 1 : undefined,
667
+ prevPage: page > 1 ? page - 1 : undefined,
668
+ hasMore,
669
+ totalLines: chunk.totalLines,
670
+ nextStartLine: chunk.nextStartLine,
671
+ },
672
+ });
673
+ },
674
+ args
675
+ );
676
+ },
677
+ },
678
+
679
+ // === Build Configuration Tools ===
680
+ {
681
+ name: 'list_build_configs',
682
+ description: 'List build configurations (supports pagination)',
683
+ inputSchema: {
684
+ type: 'object',
685
+ properties: {
686
+ locator: { type: 'string', description: 'Optional build type locator to filter' },
687
+ projectId: { type: 'string', description: 'Filter by project ID' },
688
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
689
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
690
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
691
+ fields: {
692
+ type: 'string',
693
+ description: 'Optional fields selector for server-side projection',
694
+ },
695
+ },
696
+ },
697
+ handler: async (args: unknown) => {
698
+ const schema = z.object({
699
+ locator: z.string().min(1).optional(),
700
+ projectId: z.string().min(1).optional(),
701
+ pageSize: z.number().int().min(1).max(1000).optional(),
702
+ maxPages: z.number().int().min(1).max(1000).optional(),
703
+ all: z.boolean().optional(),
704
+ fields: z.string().min(1).optional(),
705
+ });
706
+ return runTool(
707
+ 'list_build_configs',
708
+ schema,
709
+ async (typed) => {
710
+ const api = TeamCityAPI.getInstance();
711
+ const baseParts: string[] = [];
712
+ if (typed.locator) baseParts.push(typed.locator);
713
+ if (typed.projectId) baseParts.push(`affectedProject:(id:${typed.projectId})`);
714
+
715
+ const pageSize = typed.pageSize ?? 100;
716
+
717
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
718
+ const parts = [...baseParts];
719
+ if (typeof count === 'number') parts.push(`count:${count}`);
720
+ if (typeof start === 'number') parts.push(`start:${start}`);
721
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
722
+ return api.buildTypes.getAllBuildTypes(locator as string | undefined, typed.fields);
723
+ };
724
+
725
+ const fetcher = createPaginatedFetcher(
726
+ baseFetch,
727
+ (response: unknown) => {
728
+ const data = response as { buildType?: unknown[]; count?: number };
729
+ return Array.isArray(data.buildType) ? (data.buildType as unknown[]) : [];
730
+ },
731
+ (response: unknown) => {
732
+ const data = response as { count?: number };
733
+ return typeof data.count === 'number' ? data.count : undefined;
734
+ }
735
+ );
736
+
737
+ if (typed.all) {
738
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
739
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
740
+ }
741
+
742
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
743
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
744
+ },
745
+ args
746
+ );
747
+ },
748
+ },
749
+
750
+ {
751
+ name: 'get_build_config',
752
+ description: 'Get details of a build configuration',
753
+ inputSchema: {
754
+ type: 'object',
755
+ properties: {
756
+ buildTypeId: { type: 'string', description: 'Build type ID' },
757
+ },
758
+ required: ['buildTypeId'],
759
+ },
760
+ handler: async (args: unknown) => {
761
+ const schema = z.object({ buildTypeId: z.string().min(1) });
762
+ return runTool(
763
+ 'get_build_config',
764
+ schema,
765
+ async (typed) => {
766
+ const api = TeamCityAPI.getInstance();
767
+ const buildType = await api.getBuildType(typed.buildTypeId);
768
+ return json(buildType);
769
+ },
770
+ args
771
+ );
772
+ },
773
+ },
774
+
775
+ // === Test Tools ===
776
+ {
777
+ name: 'list_test_failures',
778
+ description: 'List test failures for a build (supports pagination)',
779
+ inputSchema: {
780
+ type: 'object',
781
+ properties: {
782
+ buildId: { type: 'string', description: 'Build ID' },
783
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
784
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
785
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
786
+ fields: {
787
+ type: 'string',
788
+ description: 'Optional fields selector for server-side projection',
789
+ },
790
+ },
791
+ required: ['buildId'],
792
+ },
793
+ handler: async (args: unknown) => {
794
+ const schema = z.object({
795
+ buildId: z.string().min(1),
796
+ pageSize: z.number().int().min(1).max(1000).optional(),
797
+ maxPages: z.number().int().min(1).max(1000).optional(),
798
+ all: z.boolean().optional(),
799
+ fields: z.string().min(1).optional(),
800
+ });
801
+ return runTool(
802
+ 'list_test_failures',
803
+ schema,
804
+ async (typed) => {
805
+ const api = TeamCityAPI.getInstance();
806
+ const pageSize = typed.pageSize ?? 100;
807
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
808
+ const parts: string[] = [`build:(id:${typed.buildId})`, 'status:FAILURE'];
809
+ if (typeof count === 'number') parts.push(`count:${count}`);
810
+ if (typeof start === 'number') parts.push(`start:${start}`);
811
+ const locator = parts.join(',');
812
+ return api.tests.getAllTestOccurrences(locator as string, typed.fields);
813
+ };
814
+
815
+ const fetcher = createPaginatedFetcher(
816
+ baseFetch,
817
+ (response: unknown) => {
818
+ const data = response as { testOccurrence?: unknown[]; count?: number };
819
+ return Array.isArray(data.testOccurrence) ? (data.testOccurrence as unknown[]) : [];
820
+ },
821
+ (response: unknown) => {
822
+ const data = response as { count?: number };
823
+ return typeof data.count === 'number' ? data.count : undefined;
824
+ }
825
+ );
826
+
827
+ if (typed.all) {
828
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
829
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
830
+ }
831
+
832
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
833
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
834
+ },
835
+ args
836
+ );
837
+ },
838
+ },
839
+
840
+ // === VCS Tools ===
841
+ {
842
+ name: 'list_vcs_roots',
843
+ description: 'List VCS roots (supports pagination)',
844
+ inputSchema: {
845
+ type: 'object',
846
+ properties: {
847
+ projectId: { type: 'string', description: 'Filter by project ID' },
848
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
849
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
850
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
851
+ fields: {
852
+ type: 'string',
853
+ description: 'Optional fields selector for server-side projection',
854
+ },
855
+ },
856
+ },
857
+ handler: async (args: unknown) => {
858
+ const schema = z.object({
859
+ projectId: z.string().min(1).optional(),
860
+ pageSize: z.number().int().min(1).max(1000).optional(),
861
+ maxPages: z.number().int().min(1).max(1000).optional(),
862
+ all: z.boolean().optional(),
863
+ fields: z.string().min(1).optional(),
864
+ });
865
+ return runTool(
866
+ 'list_vcs_roots',
867
+ schema,
868
+ async (typed) => {
869
+ const api = TeamCityAPI.getInstance();
870
+ const baseParts: string[] = [];
871
+ if (typed.projectId) baseParts.push(`affectedProject:(id:${typed.projectId})`);
872
+
873
+ const pageSize = typed.pageSize ?? 100;
874
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
875
+ const parts = [...baseParts];
876
+ if (typeof count === 'number') parts.push(`count:${count}`);
877
+ if (typeof start === 'number') parts.push(`start:${start}`);
878
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
879
+ return api.vcsRoots.getAllVcsRoots(locator as string | undefined, typed.fields);
880
+ };
881
+
882
+ const fetcher = createPaginatedFetcher(
883
+ baseFetch,
884
+ (response: unknown) => {
885
+ const data = response as { ['vcs-root']?: unknown[]; count?: number };
886
+ return Array.isArray(data['vcs-root']) ? (data['vcs-root'] as unknown[]) : [];
887
+ },
888
+ (response: unknown) => {
889
+ const data = response as { count?: number };
890
+ return typeof data.count === 'number' ? data.count : undefined;
891
+ }
892
+ );
893
+
894
+ if (typed.all) {
895
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
896
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
897
+ }
898
+
899
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
900
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
901
+ },
902
+ args
903
+ );
904
+ },
905
+ },
906
+
907
+ {
908
+ name: 'get_vcs_root',
909
+ description: 'Get details of a VCS root (including properties)',
910
+ inputSchema: {
911
+ type: 'object',
912
+ properties: {
913
+ id: { type: 'string', description: 'VCS root ID' },
914
+ },
915
+ required: ['id'],
916
+ },
917
+ handler: async (args: unknown) => {
918
+ const schema = z.object({ id: z.string().min(1) });
919
+ return runTool(
920
+ 'get_vcs_root',
921
+ schema,
922
+ async (typed) => {
923
+ const api = TeamCityAPI.getInstance();
924
+ const listing = await api.vcsRoots.getAllVcsRoots(`id:${typed.id}`);
925
+ const rootEntry = (listing.data as { vcsRoot?: unknown[] }).vcsRoot?.[0] as
926
+ | { id?: string; name?: string; href?: string }
927
+ | undefined;
928
+ const props = await api.vcsRoots.getAllVcsRootProperties(typed.id);
929
+ return json({
930
+ id: rootEntry?.id ?? typed.id,
931
+ name: rootEntry?.name,
932
+ href: rootEntry?.href,
933
+ properties: props.data,
934
+ });
935
+ },
936
+ args
937
+ );
938
+ },
939
+ },
940
+
941
+ // === Queue (read-only) ===
942
+ {
943
+ name: 'list_queued_builds',
944
+ description: 'List queued builds (supports TeamCity queue locator + pagination)',
945
+ inputSchema: {
946
+ type: 'object',
947
+ properties: {
948
+ locator: {
949
+ type: 'string',
950
+ description: 'Queue locator filter (e.g., project:(id:MyProj))',
951
+ },
952
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
953
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
954
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
955
+ fields: {
956
+ type: 'string',
957
+ description: 'Optional fields selector for server-side projection',
958
+ },
959
+ },
960
+ },
961
+ handler: async (args: unknown) => {
962
+ const schema = z.object({
963
+ locator: z.string().min(1).optional(),
964
+ pageSize: z.number().int().min(1).max(1000).optional(),
965
+ maxPages: z.number().int().min(1).max(1000).optional(),
966
+ all: z.boolean().optional(),
967
+ fields: z.string().min(1).optional(),
968
+ });
969
+ return runTool(
970
+ 'list_queued_builds',
971
+ schema,
972
+ async (typed) => {
973
+ const api = TeamCityAPI.getInstance();
974
+ const baseParts: string[] = [];
975
+ if (typed.locator) baseParts.push(typed.locator);
976
+ const pageSize = typed.pageSize ?? 100;
977
+
978
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
979
+ const parts = [...baseParts];
980
+ if (typeof count === 'number') parts.push(`count:${count}`);
981
+ if (typeof start === 'number') parts.push(`start:${start}`);
982
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
983
+ return api.buildQueue.getAllQueuedBuilds(locator as string | undefined, typed.fields);
984
+ };
985
+
986
+ const fetcher = createPaginatedFetcher(
987
+ baseFetch,
988
+ (response: unknown) => {
989
+ const data = response as { build?: unknown[]; count?: number };
990
+ return Array.isArray(data.build) ? (data.build as unknown[]) : [];
991
+ },
992
+ (response: unknown) => {
993
+ const data = response as { count?: number };
994
+ return typeof data.count === 'number' ? data.count : undefined;
995
+ }
996
+ );
997
+
998
+ if (typed.all) {
999
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
1000
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
1001
+ }
1002
+
1003
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
1004
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
1005
+ },
1006
+ args
1007
+ );
1008
+ },
1009
+ },
1010
+
1011
+ // === Server Health & Metrics (read-only) ===
1012
+ {
1013
+ name: 'get_server_metrics',
1014
+ description: 'Fetch server metrics (CPU/memory/disk/load) if available',
1015
+ inputSchema: { type: 'object', properties: {} },
1016
+ handler: async (_args: unknown) => {
1017
+ const api = TeamCityAPI.getInstance();
1018
+ const metrics = await api.server.getAllMetrics();
1019
+ return json(metrics.data);
1020
+ },
1021
+ mode: 'full',
1022
+ },
1023
+ {
1024
+ name: 'get_server_info',
1025
+ description: 'Get TeamCity server info (version, build number, state)',
1026
+ inputSchema: { type: 'object', properties: {} },
1027
+ handler: async (_args: unknown) => {
1028
+ const api = TeamCityAPI.getInstance();
1029
+ const info = await api.server.getServerInfo();
1030
+ return json(info.data);
1031
+ },
1032
+ },
1033
+ {
1034
+ name: 'list_server_health_items',
1035
+ description: 'List server health items (warnings/errors) for readiness checks',
1036
+ inputSchema: {
1037
+ type: 'object',
1038
+ properties: {
1039
+ locator: { type: 'string', description: 'Optional health item locator filter' },
1040
+ },
1041
+ },
1042
+ handler: async (args: unknown) => {
1043
+ const schema = z.object({ locator: z.string().min(1).optional() });
1044
+ return runTool(
1045
+ 'list_server_health_items',
1046
+ schema,
1047
+ async (typed) => {
1048
+ const api = TeamCityAPI.getInstance();
1049
+ const response = await api.health.getHealthItems(typed.locator);
1050
+ return json(response.data);
1051
+ },
1052
+ args
1053
+ );
1054
+ },
1055
+ mode: 'full',
1056
+ },
1057
+ {
1058
+ name: 'get_server_health_item',
1059
+ description: 'Get a single server health item by locator',
1060
+ inputSchema: {
1061
+ type: 'object',
1062
+ properties: { locator: { type: 'string', description: 'Health item locator' } },
1063
+ required: ['locator'],
1064
+ },
1065
+ handler: async (args: unknown) => {
1066
+ const schema = z.object({ locator: z.string().min(1) });
1067
+ return runTool(
1068
+ 'get_server_health_item',
1069
+ schema,
1070
+ async (typed) => {
1071
+ const api = TeamCityAPI.getInstance();
1072
+ const response = await api.health.getSingleHealthItem(typed.locator);
1073
+ return json(response.data);
1074
+ },
1075
+ args
1076
+ );
1077
+ },
1078
+ mode: 'full',
1079
+ },
1080
+
1081
+ // === Availability Policy Guard (read-only) ===
1082
+ {
1083
+ name: 'check_availability_guard',
1084
+ description:
1085
+ 'Evaluate server health; returns ok=false if critical health items found (severity ERROR)',
1086
+ inputSchema: {
1087
+ type: 'object',
1088
+ properties: {
1089
+ failOnWarning: {
1090
+ type: 'boolean',
1091
+ description: 'Treat warnings as failures (default false)',
1092
+ },
1093
+ },
1094
+ },
1095
+ handler: async (args: unknown) => {
1096
+ const schema = z.object({ failOnWarning: z.boolean().optional() });
1097
+ return runTool(
1098
+ 'check_availability_guard',
1099
+ schema,
1100
+ async (typed) => {
1101
+ const api = TeamCityAPI.getInstance();
1102
+ const resp = await api.health.getHealthItems();
1103
+ const items = (resp.data?.healthItem ?? []) as Array<{
1104
+ severity?: 'ERROR' | 'WARNING' | 'INFO' | string;
1105
+ id?: string;
1106
+ category?: string;
1107
+ additionalData?: unknown;
1108
+ href?: string;
1109
+ text?: string;
1110
+ }>;
1111
+ const critical = items.filter((i) => i.severity === 'ERROR');
1112
+ const warnings = items.filter((i) => i.severity === 'WARNING');
1113
+ const ok = critical.length === 0 && (!typed.failOnWarning || warnings.length === 0);
1114
+ return json({ ok, criticalCount: critical.length, warningCount: warnings.length, items });
1115
+ },
1116
+ args
1117
+ );
1118
+ },
1119
+ },
1120
+
1121
+ // === Agent Compatibility (read-only lookups) ===
1122
+ {
1123
+ name: 'get_compatible_build_types_for_agent',
1124
+ description: 'Get build types compatible with the specified agent',
1125
+ inputSchema: {
1126
+ type: 'object',
1127
+ properties: { agentId: { type: 'string', description: 'Agent ID' } },
1128
+ required: ['agentId'],
1129
+ },
1130
+ handler: async (args: unknown) => {
1131
+ const schema = z.object({ agentId: z.string().min(1) });
1132
+ return runTool(
1133
+ 'get_compatible_build_types_for_agent',
1134
+ schema,
1135
+ async (typed) => {
1136
+ const api = TeamCityAPI.getInstance();
1137
+ const resp = await api.agents.getCompatibleBuildTypes(typed.agentId);
1138
+ return json(resp.data);
1139
+ },
1140
+ args
1141
+ );
1142
+ },
1143
+ },
1144
+ {
1145
+ name: 'get_incompatible_build_types_for_agent',
1146
+ description: 'Get build types incompatible with the specified agent',
1147
+ inputSchema: {
1148
+ type: 'object',
1149
+ properties: { agentId: { type: 'string', description: 'Agent ID' } },
1150
+ required: ['agentId'],
1151
+ },
1152
+ handler: async (args: unknown) => {
1153
+ const schema = z.object({ agentId: z.string().min(1) });
1154
+ return runTool(
1155
+ 'get_incompatible_build_types_for_agent',
1156
+ schema,
1157
+ async (typed) => {
1158
+ const api = TeamCityAPI.getInstance();
1159
+ const resp = await api.agents.getIncompatibleBuildTypes(typed.agentId);
1160
+ return json(resp.data);
1161
+ },
1162
+ args
1163
+ );
1164
+ },
1165
+ },
1166
+ {
1167
+ name: 'get_agent_enabled_info',
1168
+ description: 'Get the enabled/disabled state for an agent, including comment and switch time',
1169
+ inputSchema: {
1170
+ type: 'object',
1171
+ properties: { agentId: { type: 'string', description: 'Agent ID' } },
1172
+ required: ['agentId'],
1173
+ },
1174
+ handler: async (args: unknown) => {
1175
+ const schema = z.object({ agentId: z.string().min(1) });
1176
+ return runTool(
1177
+ 'get_agent_enabled_info',
1178
+ schema,
1179
+ async (typed) => {
1180
+ const api = TeamCityAPI.getInstance();
1181
+ const resp = await api.agents.getEnabledInfo(typed.agentId);
1182
+ return json(resp.data);
1183
+ },
1184
+ args
1185
+ );
1186
+ },
1187
+ },
1188
+ {
1189
+ name: 'get_compatible_agents_for_build_type',
1190
+ description: 'List agents compatible with a build type (optionally filter enabled only)',
1191
+ inputSchema: {
1192
+ type: 'object',
1193
+ properties: {
1194
+ buildTypeId: { type: 'string', description: 'Build type ID' },
1195
+ includeDisabled: {
1196
+ type: 'boolean',
1197
+ description: 'Include disabled agents (default false)',
1198
+ },
1199
+ },
1200
+ required: ['buildTypeId'],
1201
+ },
1202
+ handler: async (args: unknown) => {
1203
+ const schema = z.object({
1204
+ buildTypeId: z.string().min(1),
1205
+ includeDisabled: z.boolean().optional(),
1206
+ });
1207
+ return runTool(
1208
+ 'get_compatible_agents_for_build_type',
1209
+ schema,
1210
+ async (typed) => {
1211
+ const api = TeamCityAPI.getInstance();
1212
+ const filters = [`compatible:(buildType:${typed.buildTypeId})`];
1213
+ if (!typed.includeDisabled) filters.push('enabled:true');
1214
+ const locator = filters.join(',');
1215
+ const resp = await api.agents.getAllAgents(locator);
1216
+ return json(resp.data);
1217
+ },
1218
+ args
1219
+ );
1220
+ },
1221
+ },
1222
+ {
1223
+ name: 'count_compatible_agents_for_build_type',
1224
+ description: 'Return only the count of enabled compatible agents for a build type',
1225
+ inputSchema: {
1226
+ type: 'object',
1227
+ properties: {
1228
+ buildTypeId: { type: 'string', description: 'Build type ID' },
1229
+ includeDisabled: {
1230
+ type: 'boolean',
1231
+ description: 'Include disabled agents (default false)',
1232
+ },
1233
+ },
1234
+ required: ['buildTypeId'],
1235
+ },
1236
+ handler: async (args: unknown) => {
1237
+ const schema = z.object({
1238
+ buildTypeId: z.string().min(1),
1239
+ includeDisabled: z.boolean().optional(),
1240
+ });
1241
+ return runTool(
1242
+ 'count_compatible_agents_for_build_type',
1243
+ schema,
1244
+ async (typed) => {
1245
+ const api = TeamCityAPI.getInstance();
1246
+ const parts = [`compatible:(buildType:${typed.buildTypeId})`];
1247
+ if (!typed.includeDisabled) parts.push('enabled:true');
1248
+ const locator = parts.join(',');
1249
+ const resp = await api.agents.getAllAgents(locator, 'count');
1250
+ const count = (resp.data as { count?: number }).count ?? 0;
1251
+ return json({ count });
1252
+ },
1253
+ args
1254
+ );
1255
+ },
1256
+ },
1257
+ {
1258
+ name: 'get_compatible_agents_for_queued_build',
1259
+ description:
1260
+ 'List agents compatible with a queued/running build by buildId (optionally filter enabled only)',
1261
+ inputSchema: {
1262
+ type: 'object',
1263
+ properties: {
1264
+ buildId: { type: 'string', description: 'Build ID' },
1265
+ includeDisabled: {
1266
+ type: 'boolean',
1267
+ description: 'Include disabled agents (default false)',
1268
+ },
1269
+ },
1270
+ required: ['buildId'],
1271
+ },
1272
+ handler: async (args: unknown) => {
1273
+ const schema = z.object({
1274
+ buildId: z.string().min(1),
1275
+ includeDisabled: z.boolean().optional(),
1276
+ });
1277
+ return runTool(
1278
+ 'get_compatible_agents_for_queued_build',
1279
+ schema,
1280
+ async (typed) => {
1281
+ const api = TeamCityAPI.getInstance();
1282
+ const build = await api.getBuild(typed.buildId);
1283
+ const buildTypeId = (build as { buildTypeId?: string }).buildTypeId;
1284
+ if (!buildTypeId) return json({ items: [], count: 0, note: 'Build type ID not found' });
1285
+ const parts = [`compatible:(buildType:${buildTypeId})`];
1286
+ if (!typed.includeDisabled) parts.push('enabled:true');
1287
+ const locator = parts.join(',');
1288
+ const resp = await api.agents.getAllAgents(locator);
1289
+ return json(resp.data);
1290
+ },
1291
+ args
1292
+ );
1293
+ },
1294
+ },
1295
+ {
1296
+ name: 'check_teamcity_connection',
1297
+ description: 'Check connectivity to TeamCity server and basic readiness',
1298
+ inputSchema: { type: 'object', properties: {} },
1299
+ handler: async (_args: unknown) => {
1300
+ const ok = await TeamCityAPI.getInstance().testConnection();
1301
+ return json({ ok });
1302
+ },
1303
+ },
1304
+
1305
+ // === Agent Tools ===
1306
+ {
1307
+ name: 'list_agents',
1308
+ description: 'List build agents (supports pagination)',
1309
+ inputSchema: {
1310
+ type: 'object',
1311
+ properties: {
1312
+ locator: { type: 'string', description: 'Optional agent locator to filter' },
1313
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
1314
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
1315
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
1316
+ fields: {
1317
+ type: 'string',
1318
+ description: 'Optional fields selector for server-side projection',
1319
+ },
1320
+ },
1321
+ },
1322
+ handler: async (args: unknown) => {
1323
+ const schema = z.object({
1324
+ locator: z.string().min(1).optional(),
1325
+ pageSize: z.number().int().min(1).max(1000).optional(),
1326
+ maxPages: z.number().int().min(1).max(1000).optional(),
1327
+ all: z.boolean().optional(),
1328
+ fields: z.string().min(1).optional(),
1329
+ });
1330
+ return runTool(
1331
+ 'list_agents',
1332
+ schema,
1333
+ async (typed) => {
1334
+ const api = TeamCityAPI.getInstance();
1335
+ const pageSize = typed.pageSize ?? 100;
1336
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
1337
+ const parts: string[] = [];
1338
+ if (typed.locator) parts.push(typed.locator);
1339
+ if (typeof count === 'number') parts.push(`count:${count}`);
1340
+ if (typeof start === 'number') parts.push(`start:${start}`);
1341
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
1342
+ return api.agents.getAllAgents(locator as string | undefined, typed.fields);
1343
+ };
1344
+
1345
+ const fetcher = createPaginatedFetcher(
1346
+ baseFetch,
1347
+ (response: unknown) => {
1348
+ const data = response as { agent?: unknown[]; count?: number };
1349
+ return Array.isArray(data.agent) ? (data.agent as unknown[]) : [];
1350
+ },
1351
+ (response: unknown) => {
1352
+ const data = response as { count?: number };
1353
+ return typeof data.count === 'number' ? data.count : undefined;
1354
+ }
1355
+ );
1356
+
1357
+ if (typed.all) {
1358
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
1359
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
1360
+ }
1361
+
1362
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
1363
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
1364
+ },
1365
+ args
1366
+ );
1367
+ },
1368
+ },
1369
+
1370
+ {
1371
+ name: 'list_agent_pools',
1372
+ description: 'List agent pools (supports pagination)',
1373
+ inputSchema: {
1374
+ type: 'object',
1375
+ properties: {
1376
+ pageSize: { type: 'number', description: 'Items per page (default 100)' },
1377
+ maxPages: { type: 'number', description: 'Max pages to fetch (when all=true)' },
1378
+ all: { type: 'boolean', description: 'Fetch all pages up to maxPages' },
1379
+ fields: {
1380
+ type: 'string',
1381
+ description: 'Optional fields selector for server-side projection',
1382
+ },
1383
+ },
1384
+ },
1385
+ handler: async (args: unknown) => {
1386
+ const schema = z.object({
1387
+ pageSize: z.number().int().min(1).max(1000).optional(),
1388
+ maxPages: z.number().int().min(1).max(1000).optional(),
1389
+ all: z.boolean().optional(),
1390
+ fields: z.string().min(1).optional(),
1391
+ });
1392
+ return runTool(
1393
+ 'list_agent_pools',
1394
+ schema,
1395
+ async (typed) => {
1396
+ const api = TeamCityAPI.getInstance();
1397
+ const pageSize = typed.pageSize ?? 100;
1398
+ const baseFetch = async ({ count, start }: { count?: number; start?: number }) => {
1399
+ const parts: string[] = [];
1400
+ if (typeof count === 'number') parts.push(`count:${count}`);
1401
+ if (typeof start === 'number') parts.push(`start:${start}`);
1402
+ const locator = parts.length > 0 ? parts.join(',') : undefined;
1403
+ return api.agentPools.getAllAgentPools(locator as string | undefined, typed.fields);
1404
+ };
1405
+
1406
+ const fetcher = createPaginatedFetcher(
1407
+ baseFetch,
1408
+ (response: unknown) => {
1409
+ const data = response as { agentPool?: unknown[]; count?: number };
1410
+ return Array.isArray(data.agentPool) ? (data.agentPool as unknown[]) : [];
1411
+ },
1412
+ (response: unknown) => {
1413
+ const data = response as { count?: number };
1414
+ return typeof data.count === 'number' ? data.count : undefined;
1415
+ }
1416
+ );
1417
+
1418
+ if (typed.all) {
1419
+ const items = await fetchAllPages(fetcher, { pageSize, maxPages: typed.maxPages });
1420
+ return json({ items, pagination: { mode: 'all', pageSize, fetched: items.length } });
1421
+ }
1422
+
1423
+ const firstPage = await fetcher({ count: pageSize, start: 0 });
1424
+ return json({ items: firstPage.items, pagination: { page: 1, pageSize } });
1425
+ },
1426
+ args
1427
+ );
1428
+ },
1429
+ },
1430
+
1431
+ // === Additional Tools from Complex Implementation ===
1432
+
1433
+ // Build Analysis Tools
1434
+ {
1435
+ name: 'get_build_results',
1436
+ description:
1437
+ 'Get detailed results of a build including tests, artifacts, changes, and statistics',
1438
+ inputSchema: {
1439
+ type: 'object',
1440
+ properties: {
1441
+ buildId: { type: 'string', description: 'Build ID' },
1442
+ includeArtifacts: {
1443
+ type: 'boolean',
1444
+ description: 'Include artifacts listing and metadata',
1445
+ },
1446
+ includeStatistics: { type: 'boolean', description: 'Include build statistics' },
1447
+ includeChanges: { type: 'boolean', description: 'Include VCS changes' },
1448
+ includeDependencies: { type: 'boolean', description: 'Include dependency builds' },
1449
+ artifactFilter: { type: 'string', description: 'Filter artifacts by name/path pattern' },
1450
+ maxArtifactSize: {
1451
+ type: 'number',
1452
+ description: 'Max artifact content size (bytes) when inlining',
1453
+ },
1454
+ },
1455
+ required: ['buildId'],
1456
+ },
1457
+ handler: async (args: unknown) => {
1458
+ const schema = z.object({
1459
+ buildId: z.string().min(1),
1460
+ includeArtifacts: z.boolean().optional(),
1461
+ includeStatistics: z.boolean().optional(),
1462
+ includeChanges: z.boolean().optional(),
1463
+ includeDependencies: z.boolean().optional(),
1464
+ artifactFilter: z.string().min(1).optional(),
1465
+ maxArtifactSize: z.number().int().min(1).optional(),
1466
+ });
1467
+
1468
+ return runTool(
1469
+ 'get_build_results',
1470
+ schema,
1471
+ async (typed) => {
1472
+ // Use the manager for rich results via the unified TeamCityAPI adapter.
1473
+ const api = TeamCityAPI.getInstance();
1474
+ const manager = new BuildResultsManager(createAdapterFromTeamCityAPI(api));
1475
+ const result = await manager.getBuildResults(typed.buildId, {
1476
+ includeArtifacts: typed.includeArtifacts,
1477
+ includeStatistics: typed.includeStatistics,
1478
+ includeChanges: typed.includeChanges,
1479
+ includeDependencies: typed.includeDependencies,
1480
+ artifactFilter: typed.artifactFilter,
1481
+ maxArtifactSize: typed.maxArtifactSize,
1482
+ });
1483
+ return json(result);
1484
+ },
1485
+ args
1486
+ );
1487
+ },
1488
+ },
1489
+
1490
+ {
1491
+ name: 'get_test_details',
1492
+ description: 'Get detailed information about test failures',
1493
+ inputSchema: {
1494
+ type: 'object',
1495
+ properties: {
1496
+ buildId: { type: 'string', description: 'Build ID' },
1497
+ testNameId: { type: 'string', description: 'Test name ID (optional)' },
1498
+ },
1499
+ required: ['buildId'],
1500
+ },
1501
+ handler: async (args: unknown) => {
1502
+ const schema = z.object({
1503
+ buildId: z.string().min(1),
1504
+ testNameId: z.string().min(1).optional(),
1505
+ });
1506
+ return runTool(
1507
+ 'get_test_details',
1508
+ schema,
1509
+ async (typed) => {
1510
+ const api = TeamCityAPI.getInstance();
1511
+ let locator = `build:(id:${typed.buildId})`;
1512
+ if (typed.testNameId) locator += `,test:(id:${typed.testNameId})`;
1513
+ const response = await api.tests.getAllTestOccurrences(locator);
1514
+ return json(response.data);
1515
+ },
1516
+ args
1517
+ );
1518
+ },
1519
+ },
1520
+
1521
+ {
1522
+ name: 'analyze_build_problems',
1523
+ description: 'Analyze and report build problems and failures',
1524
+ inputSchema: {
1525
+ type: 'object',
1526
+ properties: {
1527
+ buildId: { type: 'string', description: 'Build ID to analyze' },
1528
+ },
1529
+ required: ['buildId'],
1530
+ },
1531
+ handler: async (args: unknown) => {
1532
+ const schema = z.object({ buildId: z.string().min(1) });
1533
+ return runTool(
1534
+ 'analyze_build_problems',
1535
+ schema,
1536
+ async (typed) => {
1537
+ const api = TeamCityAPI.getInstance();
1538
+ const build = await api.getBuild(typed.buildId);
1539
+ const problems = await api.builds.getBuildProblems(typed.buildId);
1540
+ const failures = await api.listTestFailures(typed.buildId);
1541
+ return json({
1542
+ buildStatus: build.status,
1543
+ statusText: build.statusText,
1544
+ problems: problems.data,
1545
+ testFailures: failures,
1546
+ });
1547
+ },
1548
+ args
1549
+ );
1550
+ },
1551
+ },
1552
+
1553
+ {
1554
+ name: 'list_branches',
1555
+ description: 'List branches for a project or build configuration',
1556
+ inputSchema: {
1557
+ type: 'object',
1558
+ properties: {
1559
+ projectId: { type: 'string', description: 'Project ID' },
1560
+ buildTypeId: { type: 'string', description: 'Build type ID' },
1561
+ },
1562
+ },
1563
+ handler: async (args: unknown) => {
1564
+ const schema = z
1565
+ .object({
1566
+ projectId: z.string().min(1).optional(),
1567
+ buildTypeId: z.string().min(1).optional(),
1568
+ })
1569
+ .refine((v) => Boolean(v.projectId ?? v.buildTypeId), {
1570
+ message: 'Either projectId or buildTypeId is required',
1571
+ path: ['projectId'],
1572
+ });
1573
+ return runTool(
1574
+ 'list_branches',
1575
+ schema,
1576
+ async (typed) => {
1577
+ const api = TeamCityAPI.getInstance();
1578
+ const locator = typed.buildTypeId
1579
+ ? `buildType:(id:${typed.buildTypeId})`
1580
+ : `project:(id:${typed.projectId})`;
1581
+
1582
+ const builds = (await api.listBuilds(`${locator},count:100}`)) as {
1583
+ build?: Array<{ branchName?: string | null }>; // minimal shape used
1584
+ };
1585
+ const items = Array.isArray(builds.build) ? builds.build : [];
1586
+ const branchNames = items
1587
+ .map((b) => b.branchName)
1588
+ .filter((n): n is string => typeof n === 'string' && n.length > 0);
1589
+ const branches = new Set(branchNames);
1590
+ return json({ branches: Array.from(branches), count: branches.size });
1591
+ },
1592
+ args
1593
+ );
1594
+ },
1595
+ },
1596
+
1597
+ {
1598
+ name: 'list_parameters',
1599
+ description: 'List parameters for a build configuration',
1600
+ inputSchema: {
1601
+ type: 'object',
1602
+ properties: {
1603
+ buildTypeId: { type: 'string', description: 'Build type ID' },
1604
+ },
1605
+ required: ['buildTypeId'],
1606
+ },
1607
+ handler: async (args: unknown) => {
1608
+ const schema = z.object({ buildTypeId: z.string().min(1) });
1609
+ return runTool(
1610
+ 'list_parameters',
1611
+ schema,
1612
+ async (typed) => {
1613
+ const api = TeamCityAPI.getInstance();
1614
+ const buildType = await api.getBuildType(typed.buildTypeId);
1615
+ return json({
1616
+ parameters: buildType.parameters?.property ?? [],
1617
+ count: buildType.parameters?.property?.length ?? 0,
1618
+ });
1619
+ },
1620
+ args
1621
+ );
1622
+ },
1623
+ },
1624
+
1625
+ {
1626
+ name: 'list_project_hierarchy',
1627
+ description: 'List project hierarchy showing parent-child relationships',
1628
+ inputSchema: {
1629
+ type: 'object',
1630
+ properties: {
1631
+ rootProjectId: { type: 'string', description: 'Root project ID (defaults to _Root)' },
1632
+ },
1633
+ },
1634
+ handler: async (args: unknown) => {
1635
+ const schema = z.object({ rootProjectId: z.string().min(1).optional() });
1636
+ return runTool(
1637
+ 'list_project_hierarchy',
1638
+ schema,
1639
+ async (typed) => {
1640
+ const api = TeamCityAPI.getInstance();
1641
+ const rootId = typed.rootProjectId ?? '_Root';
1642
+
1643
+ type ApiProject = {
1644
+ id?: string;
1645
+ name?: string;
1646
+ parentProjectId?: string;
1647
+ projects?: { project?: unknown[] };
1648
+ };
1649
+
1650
+ async function buildHierarchy(
1651
+ projectId: string,
1652
+ depth = 0
1653
+ ): Promise<{
1654
+ id?: string;
1655
+ name?: string;
1656
+ parentId?: string;
1657
+ children: Array<{ id: string; name?: string }>;
1658
+ }> {
1659
+ const response = await api.projects.getProject(projectId);
1660
+ const project = response.data as ApiProject;
1661
+ const children: Array<{ id: string; name?: string }> = [];
1662
+
1663
+ const maybeChildren = project.projects?.project ?? [];
1664
+ if (Array.isArray(maybeChildren)) {
1665
+ for (const childRaw of maybeChildren) {
1666
+ const child = childRaw as { id?: string; name?: string };
1667
+ if (typeof child.id === 'string' && depth < 3) {
1668
+ // eslint-disable-next-line no-await-in-loop
1669
+ const sub = await buildHierarchy(child.id, depth + 1);
1670
+ children.push({ id: sub.id ?? child.id, name: sub.name });
1671
+ } else if (typeof child.id === 'string') {
1672
+ children.push({ id: child.id, name: child.name });
1673
+ }
1674
+ }
1675
+ }
1676
+
1677
+ return {
1678
+ id: project.id,
1679
+ name: project.name,
1680
+ parentId: project.parentProjectId,
1681
+ children,
1682
+ };
1683
+ }
1684
+
1685
+ const hierarchy = await buildHierarchy(rootId);
1686
+ return json(hierarchy);
1687
+ },
1688
+ args
1689
+ );
1690
+ },
1691
+ },
1692
+ ];
1693
+
1694
+ /**
1695
+ * Full mode tools - Write/modify operations (only in full mode)
1696
+ */
1697
+ const FULL_MODE_TOOLS: ToolDefinition[] = [
1698
+ // === Project Management Tools ===
1699
+ {
1700
+ name: 'create_project',
1701
+ description: 'Create a new TeamCity project',
1702
+ inputSchema: {
1703
+ type: 'object',
1704
+ properties: {
1705
+ name: { type: 'string', description: 'Project name' },
1706
+ id: { type: 'string', description: 'Project ID' },
1707
+ parentProjectId: { type: 'string', description: 'Parent project ID (defaults to _Root)' },
1708
+ description: { type: 'string', description: 'Project description' },
1709
+ },
1710
+ required: ['name', 'id'],
1711
+ },
1712
+ handler: async (args: unknown) => {
1713
+ const schema = z.object({
1714
+ name: z.string().min(1),
1715
+ id: z.string().min(1),
1716
+ description: z.string().optional(),
1717
+ parentProjectId: z.string().min(1).optional(),
1718
+ });
1719
+ return runTool(
1720
+ 'create_project',
1721
+ schema,
1722
+ async (typedArgs) => {
1723
+ const api = TeamCityAPI.getInstance();
1724
+ const project = {
1725
+ name: typedArgs.name,
1726
+ id: typedArgs.id,
1727
+ parentProject: { id: typedArgs.parentProjectId ?? '_Root' },
1728
+ description: typedArgs.description,
1729
+ };
1730
+ const response = await api.projects.addProject(project, {
1731
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
1732
+ });
1733
+ return json({ success: true, action: 'create_project', id: response.data.id });
1734
+ },
1735
+ args
1736
+ );
1737
+ },
1738
+ mode: 'full',
1739
+ },
1740
+
1741
+ {
1742
+ name: 'delete_project',
1743
+ description: 'Delete a TeamCity project',
1744
+ inputSchema: {
1745
+ type: 'object',
1746
+ properties: {
1747
+ projectId: { type: 'string', description: 'Project ID to delete' },
1748
+ },
1749
+ required: ['projectId'],
1750
+ },
1751
+ handler: async (args: unknown) => {
1752
+ const typedArgs = args as DeleteProjectArgs;
1753
+
1754
+ const api = TeamCityAPI.getInstance();
1755
+ await api.projects.deleteProject(typedArgs.projectId);
1756
+ return json({ success: true, action: 'delete_project', id: typedArgs.projectId });
1757
+ },
1758
+ mode: 'full',
1759
+ },
1760
+
1761
+ {
1762
+ name: 'update_project_settings',
1763
+ description: 'Update project settings and parameters',
1764
+ inputSchema: {
1765
+ type: 'object',
1766
+ properties: {
1767
+ projectId: { type: 'string', description: 'Project ID' },
1768
+ name: { type: 'string', description: 'New project name' },
1769
+ description: { type: 'string', description: 'New project description' },
1770
+ archived: { type: 'boolean', description: 'Archive/unarchive project' },
1771
+ },
1772
+ required: ['projectId'],
1773
+ },
1774
+ handler: async (args: unknown) => {
1775
+ const schema = z.object({
1776
+ projectId: z.string().min(1),
1777
+ name: z.string().min(1).optional(),
1778
+ description: z.string().optional(),
1779
+ archived: z.boolean().optional(),
1780
+ });
1781
+
1782
+ return runTool(
1783
+ 'update_project_settings',
1784
+ schema,
1785
+ async (typedArgs) => {
1786
+ const api = TeamCityAPI.getInstance();
1787
+
1788
+ // Emit debug info about requested changes (avoid logging secrets)
1789
+ debug('update_project_settings invoked', {
1790
+ projectId: typedArgs.projectId,
1791
+ // Only log which fields are present to reduce noise
1792
+ requestedChanges: {
1793
+ name: typeof typedArgs.name !== 'undefined',
1794
+ description: typeof typedArgs.description !== 'undefined',
1795
+ archived: typeof typedArgs.archived !== 'undefined',
1796
+ },
1797
+ });
1798
+
1799
+ if (typedArgs.name) {
1800
+ debug('Setting project field', {
1801
+ projectId: typedArgs.projectId,
1802
+ field: 'name',
1803
+ valuePreview: typedArgs.name,
1804
+ });
1805
+ await api.projects.setProjectField(typedArgs.projectId, 'name', typedArgs.name);
1806
+ }
1807
+ if (typedArgs.description !== undefined) {
1808
+ debug('Setting project field', {
1809
+ projectId: typedArgs.projectId,
1810
+ field: 'description',
1811
+ valuePreview: typedArgs.description,
1812
+ });
1813
+ await api.projects.setProjectField(
1814
+ typedArgs.projectId,
1815
+ 'description',
1816
+ typedArgs.description
1817
+ );
1818
+ }
1819
+ if (typedArgs.archived !== undefined) {
1820
+ debug('Setting project field', {
1821
+ projectId: typedArgs.projectId,
1822
+ field: 'archived',
1823
+ valuePreview: String(typedArgs.archived),
1824
+ });
1825
+ await api.projects.setProjectField(
1826
+ typedArgs.projectId,
1827
+ 'archived',
1828
+ String(typedArgs.archived)
1829
+ );
1830
+ }
1831
+
1832
+ debug('Project settings updated', {
1833
+ projectId: typedArgs.projectId,
1834
+ appliedChanges: {
1835
+ name: typedArgs.name ?? null,
1836
+ description: typedArgs.description ?? null,
1837
+ archived: typeof typedArgs.archived === 'boolean' ? typedArgs.archived : null,
1838
+ },
1839
+ });
1840
+
1841
+ return json({
1842
+ success: true,
1843
+ action: 'update_project_settings',
1844
+ id: typedArgs.projectId,
1845
+ });
1846
+ },
1847
+ args
1848
+ );
1849
+ },
1850
+ mode: 'full',
1851
+ },
1852
+
1853
+ // === Build Configuration Management ===
1854
+ {
1855
+ name: 'create_build_config',
1856
+ description: 'Create a new build configuration',
1857
+ inputSchema: {
1858
+ type: 'object',
1859
+ properties: {
1860
+ projectId: { type: 'string', description: 'Project ID' },
1861
+ name: { type: 'string', description: 'Build configuration name' },
1862
+ id: { type: 'string', description: 'Build configuration ID' },
1863
+ description: { type: 'string', description: 'Description' },
1864
+ },
1865
+ required: ['projectId', 'name', 'id'],
1866
+ },
1867
+ handler: async (args: unknown) => {
1868
+ const typedArgs = args as CreateBuildConfigArgs;
1869
+
1870
+ const api = TeamCityAPI.getInstance();
1871
+ const buildType = {
1872
+ name: typedArgs.name,
1873
+ id: typedArgs.id,
1874
+ project: { id: typedArgs.projectId },
1875
+ description: typedArgs.description,
1876
+ };
1877
+ const response = await api.buildTypes.createBuildType(undefined, buildType, {
1878
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
1879
+ });
1880
+ return json({ success: true, action: 'create_build_config', id: response.data.id });
1881
+ },
1882
+ mode: 'full',
1883
+ },
1884
+
1885
+ {
1886
+ name: 'clone_build_config',
1887
+ description: 'Clone an existing build configuration',
1888
+ inputSchema: {
1889
+ type: 'object',
1890
+ properties: {
1891
+ sourceBuildTypeId: { type: 'string', description: 'Source build type ID' },
1892
+ name: { type: 'string', description: 'New build configuration name' },
1893
+ id: { type: 'string', description: 'New build configuration ID' },
1894
+ projectId: { type: 'string', description: 'Target project ID' },
1895
+ },
1896
+ required: ['sourceBuildTypeId', 'name', 'id'],
1897
+ },
1898
+ handler: async (args: unknown) => {
1899
+ const typedArgs = args as CloneBuildConfigArgs;
1900
+
1901
+ const api = TeamCityAPI.getInstance();
1902
+ // Get source build type
1903
+ const source = await api.getBuildType(typedArgs.sourceBuildTypeId);
1904
+
1905
+ // Create new build type based on source
1906
+ const buildType = {
1907
+ ...source,
1908
+ name: typedArgs.name,
1909
+ id: typedArgs.id,
1910
+ project: { id: typedArgs.projectId ?? source.project?.id ?? '_Root' },
1911
+ };
1912
+
1913
+ const response = await api.buildTypes.createBuildType(undefined, buildType);
1914
+ return json({ success: true, action: 'clone_build_config', id: response.data.id });
1915
+ },
1916
+ mode: 'full',
1917
+ },
1918
+
1919
+ {
1920
+ name: 'update_build_config',
1921
+ description: 'Update build configuration settings',
1922
+ inputSchema: {
1923
+ type: 'object',
1924
+ properties: {
1925
+ buildTypeId: { type: 'string', description: 'Build type ID' },
1926
+ name: { type: 'string', description: 'New name' },
1927
+ description: { type: 'string', description: 'New description' },
1928
+ paused: { type: 'boolean', description: 'Pause/unpause configuration' },
1929
+ artifactRules: { type: 'string', description: 'Artifact rules' },
1930
+ },
1931
+ required: ['buildTypeId'],
1932
+ },
1933
+ handler: async (args: unknown) => {
1934
+ const typedArgs = args as UpdateBuildConfigArgs;
1935
+
1936
+ const api = TeamCityAPI.getInstance();
1937
+
1938
+ if (typedArgs.name != null && typedArgs.name !== '') {
1939
+ await api.buildTypes.setBuildTypeField(typedArgs.buildTypeId, 'name', typedArgs.name);
1940
+ }
1941
+ if (typedArgs.description !== undefined) {
1942
+ await api.buildTypes.setBuildTypeField(
1943
+ typedArgs.buildTypeId,
1944
+ 'description',
1945
+ typedArgs.description
1946
+ );
1947
+ }
1948
+ if (typedArgs.paused !== undefined) {
1949
+ await api.buildTypes.setBuildTypeField(
1950
+ typedArgs.buildTypeId,
1951
+ 'paused',
1952
+ String(typedArgs.paused)
1953
+ );
1954
+ }
1955
+ if (typedArgs.artifactRules !== undefined) {
1956
+ await api.buildTypes.setBuildTypeField(
1957
+ typedArgs.buildTypeId,
1958
+ 'artifactRules',
1959
+ typedArgs.artifactRules
1960
+ );
1961
+ }
1962
+
1963
+ return json({ success: true, action: 'update_build_config', id: typedArgs.buildTypeId });
1964
+ },
1965
+ mode: 'full',
1966
+ },
1967
+
1968
+ // === VCS attachment ===
1969
+ {
1970
+ name: 'add_vcs_root_to_build',
1971
+ description: 'Attach a VCS root to a build configuration',
1972
+ inputSchema: {
1973
+ type: 'object',
1974
+ properties: {
1975
+ buildTypeId: { type: 'string', description: 'Build type ID' },
1976
+ vcsRootId: { type: 'string', description: 'VCS root ID' },
1977
+ checkoutRules: { type: 'string', description: 'Optional checkout rules' },
1978
+ },
1979
+ required: ['buildTypeId', 'vcsRootId'],
1980
+ },
1981
+ handler: async (args: unknown) => {
1982
+ const schema = z.object({
1983
+ buildTypeId: z.string().min(1),
1984
+ vcsRootId: z.string().min(1),
1985
+ checkoutRules: z.string().optional(),
1986
+ });
1987
+ return runTool(
1988
+ 'add_vcs_root_to_build',
1989
+ schema,
1990
+ async (typed) => {
1991
+ const api = TeamCityAPI.getInstance();
1992
+ const body = {
1993
+ 'vcs-root': { id: typed.vcsRootId },
1994
+ 'checkout-rules': typed.checkoutRules,
1995
+ } as Record<string, unknown>;
1996
+ await api.buildTypes.addVcsRootToBuildType(typed.buildTypeId, undefined, body, {
1997
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
1998
+ });
1999
+ return json({
2000
+ success: true,
2001
+ action: 'add_vcs_root_to_build',
2002
+ buildTypeId: typed.buildTypeId,
2003
+ vcsRootId: typed.vcsRootId,
2004
+ });
2005
+ },
2006
+ args
2007
+ );
2008
+ },
2009
+ mode: 'full',
2010
+ },
2011
+
2012
+ // === Parameter Management ===
2013
+ {
2014
+ name: 'add_parameter',
2015
+ description: 'Add a parameter to a build configuration',
2016
+ inputSchema: {
2017
+ type: 'object',
2018
+ properties: {
2019
+ buildTypeId: { type: 'string', description: 'Build type ID' },
2020
+ name: { type: 'string', description: 'Parameter name' },
2021
+ value: { type: 'string', description: 'Parameter value' },
2022
+ },
2023
+ required: ['buildTypeId', 'name', 'value'],
2024
+ },
2025
+ handler: async (args: unknown) => {
2026
+ const typedArgs = args as AddParameterArgs;
2027
+
2028
+ const api = TeamCityAPI.getInstance();
2029
+ const parameter = {
2030
+ name: typedArgs.name,
2031
+ value: typedArgs.value,
2032
+ };
2033
+ await api.buildTypes.createBuildParameterOfBuildType(
2034
+ typedArgs.buildTypeId,
2035
+ undefined,
2036
+ parameter,
2037
+ { headers: { 'Content-Type': 'application/json', Accept: 'application/json' } }
2038
+ );
2039
+ return json({
2040
+ success: true,
2041
+ action: 'add_parameter',
2042
+ buildTypeId: typedArgs.buildTypeId,
2043
+ name: typedArgs.name,
2044
+ });
2045
+ },
2046
+ mode: 'full',
2047
+ },
2048
+
2049
+ {
2050
+ name: 'update_parameter',
2051
+ description: 'Update a build configuration parameter',
2052
+ inputSchema: {
2053
+ type: 'object',
2054
+ properties: {
2055
+ buildTypeId: { type: 'string', description: 'Build type ID' },
2056
+ name: { type: 'string', description: 'Parameter name' },
2057
+ value: { type: 'string', description: 'New parameter value' },
2058
+ },
2059
+ required: ['buildTypeId', 'name', 'value'],
2060
+ },
2061
+ handler: async (args: unknown) => {
2062
+ const typedArgs = args as UpdateParameterArgs;
2063
+
2064
+ const api = TeamCityAPI.getInstance();
2065
+ await api.buildTypes.updateBuildParameterOfBuildType(
2066
+ typedArgs.name,
2067
+ typedArgs.buildTypeId,
2068
+ undefined,
2069
+ {
2070
+ name: typedArgs.name,
2071
+ value: typedArgs.value,
2072
+ },
2073
+ { headers: { 'Content-Type': 'application/json', Accept: 'application/json' } }
2074
+ );
2075
+ return json({
2076
+ success: true,
2077
+ action: 'update_parameter',
2078
+ buildTypeId: typedArgs.buildTypeId,
2079
+ name: typedArgs.name,
2080
+ });
2081
+ },
2082
+ mode: 'full',
2083
+ },
2084
+
2085
+ {
2086
+ name: 'delete_parameter',
2087
+ description: 'Delete a parameter from a build configuration',
2088
+ inputSchema: {
2089
+ type: 'object',
2090
+ properties: {
2091
+ buildTypeId: { type: 'string', description: 'Build type ID' },
2092
+ name: { type: 'string', description: 'Parameter name' },
2093
+ },
2094
+ required: ['buildTypeId', 'name'],
2095
+ },
2096
+ handler: async (args: unknown) => {
2097
+ const typedArgs = args as DeleteParameterArgs;
2098
+
2099
+ const api = TeamCityAPI.getInstance();
2100
+ await api.buildTypes.deleteBuildParameterOfBuildType(typedArgs.buildTypeId, typedArgs.name);
2101
+ return json({
2102
+ success: true,
2103
+ action: 'delete_parameter',
2104
+ buildTypeId: typedArgs.buildTypeId,
2105
+ name: typedArgs.name,
2106
+ });
2107
+ },
2108
+ mode: 'full',
2109
+ },
2110
+
2111
+ // === VCS Root Management ===
2112
+ {
2113
+ name: 'create_vcs_root',
2114
+ description: 'Create a new VCS root',
2115
+ inputSchema: {
2116
+ type: 'object',
2117
+ properties: {
2118
+ projectId: { type: 'string', description: 'Project ID' },
2119
+ name: { type: 'string', description: 'VCS root name' },
2120
+ id: { type: 'string', description: 'VCS root ID' },
2121
+ vcsName: { type: 'string', description: 'VCS type (e.g., jetbrains.git)' },
2122
+ url: { type: 'string', description: 'Repository URL' },
2123
+ branch: { type: 'string', description: 'Default branch' },
2124
+ },
2125
+ required: ['projectId', 'name', 'id', 'vcsName', 'url'],
2126
+ },
2127
+ handler: async (args: unknown) => {
2128
+ const typedArgs = args as CreateVCSRootArgs;
2129
+
2130
+ const api = TeamCityAPI.getInstance();
2131
+ const vcsRoot = {
2132
+ name: typedArgs.name,
2133
+ id: typedArgs.id,
2134
+ vcsName: typedArgs.vcsName,
2135
+ project: { id: typedArgs.projectId },
2136
+ properties: {
2137
+ property: [
2138
+ { name: 'url', value: typedArgs.url },
2139
+ { name: 'branch', value: typedArgs.branch ?? 'refs/heads/master' },
2140
+ ],
2141
+ },
2142
+ };
2143
+ const response = await api.vcsRoots.addVcsRoot(undefined, vcsRoot, {
2144
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
2145
+ });
2146
+ return json({ success: true, action: 'create_vcs_root', id: response.data.id });
2147
+ },
2148
+ mode: 'full',
2149
+ },
2150
+
2151
+ // === Agent Management ===
2152
+ {
2153
+ name: 'authorize_agent',
2154
+ description: 'Authorize or unauthorize a build agent',
2155
+ inputSchema: {
2156
+ type: 'object',
2157
+ properties: {
2158
+ agentId: { type: 'string', description: 'Agent ID' },
2159
+ authorize: { type: 'boolean', description: 'true to authorize, false to unauthorize' },
2160
+ },
2161
+ required: ['agentId', 'authorize'],
2162
+ },
2163
+ handler: async (args: unknown) => {
2164
+ const typedArgs = args as AuthorizeAgentArgs;
2165
+
2166
+ const api = TeamCityAPI.getInstance();
2167
+ await api.agents.setAgentField(
2168
+ typedArgs.agentId,
2169
+ 'authorized',
2170
+ typedArgs.authorize ? 'true' : 'false'
2171
+ );
2172
+ return json({
2173
+ success: true,
2174
+ action: 'authorize_agent',
2175
+ agentId: typedArgs.agentId,
2176
+ authorized: typedArgs.authorize,
2177
+ });
2178
+ },
2179
+ mode: 'full',
2180
+ },
2181
+
2182
+ {
2183
+ name: 'assign_agent_to_pool',
2184
+ description: 'Assign an agent to a different pool',
2185
+ inputSchema: {
2186
+ type: 'object',
2187
+ properties: {
2188
+ agentId: { type: 'string', description: 'Agent ID' },
2189
+ poolId: { type: 'string', description: 'Agent pool ID' },
2190
+ },
2191
+ required: ['agentId', 'poolId'],
2192
+ },
2193
+ handler: async (args: unknown) => {
2194
+ const typedArgs = args as AssignAgentToPoolArgs;
2195
+
2196
+ const api = TeamCityAPI.getInstance();
2197
+ await api.agents.setAgentPool(typedArgs.agentId, undefined, {
2198
+ id: parseInt(typedArgs.poolId),
2199
+ });
2200
+ return json({
2201
+ success: true,
2202
+ action: 'assign_agent_to_pool',
2203
+ agentId: typedArgs.agentId,
2204
+ poolId: typedArgs.poolId,
2205
+ });
2206
+ },
2207
+ mode: 'full',
2208
+ },
2209
+
2210
+ // === Build Step Management ===
2211
+ {
2212
+ name: 'manage_build_steps',
2213
+ description: 'Add, update, or delete build steps',
2214
+ inputSchema: {
2215
+ type: 'object',
2216
+ properties: {
2217
+ buildTypeId: { type: 'string', description: 'Build type ID' },
2218
+ action: {
2219
+ type: 'string',
2220
+ enum: ['add', 'update', 'delete'],
2221
+ description: 'Action to perform',
2222
+ },
2223
+ stepId: { type: 'string', description: 'Step ID (for update/delete)' },
2224
+ name: { type: 'string', description: 'Step name' },
2225
+ type: { type: 'string', description: 'Step type (e.g., simpleRunner)' },
2226
+ properties: { type: 'object', description: 'Step properties' },
2227
+ },
2228
+ required: ['buildTypeId', 'action'],
2229
+ },
2230
+ handler: async (args: unknown) => {
2231
+ const typedArgs = args as ManageBuildStepsArgs;
2232
+
2233
+ const api = TeamCityAPI.getInstance();
2234
+
2235
+ switch (typedArgs.action) {
2236
+ case 'add': {
2237
+ const stepProps: Record<string, string> = Object.fromEntries(
2238
+ Object.entries(typedArgs.properties ?? {}).map(([k, v]) => [k, String(v)])
2239
+ );
2240
+ // Ensure command runner uses custom script when script.content is provided
2241
+ if (typedArgs.type === 'simpleRunner' && stepProps['script.content']) {
2242
+ stepProps['use.custom.script'] = stepProps['use.custom.script'] ?? 'true';
2243
+ }
2244
+ const step = {
2245
+ name: typedArgs.name,
2246
+ type: typedArgs.type,
2247
+ properties: {
2248
+ property: Object.entries(stepProps).map(([k, v]) => ({ name: k, value: v })),
2249
+ },
2250
+ };
2251
+ await api.buildTypes.addBuildStepToBuildType(typedArgs.buildTypeId, undefined, step, {
2252
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
2253
+ });
2254
+ return json({
2255
+ success: true,
2256
+ action: 'add_build_step',
2257
+ buildTypeId: typedArgs.buildTypeId,
2258
+ });
2259
+ }
2260
+
2261
+ case 'update': {
2262
+ if (typedArgs.stepId == null || typedArgs.stepId === '') {
2263
+ return json({
2264
+ success: false,
2265
+ action: 'update_build_step',
2266
+ error: 'Step ID is required for update action',
2267
+ });
2268
+ }
2269
+ const props = Object.entries(typedArgs.properties ?? {});
2270
+ for (const [k, v] of props) {
2271
+ // eslint-disable-next-line no-await-in-loop
2272
+ await api.buildTypes.setBuildStepParameter(
2273
+ typedArgs.buildTypeId,
2274
+ typedArgs.stepId,
2275
+ k,
2276
+ String(v),
2277
+ { headers: { 'Content-Type': 'text/plain', Accept: 'application/json' } }
2278
+ );
2279
+ }
2280
+ return json({
2281
+ success: true,
2282
+ action: 'update_build_step',
2283
+ buildTypeId: typedArgs.buildTypeId,
2284
+ stepId: typedArgs.stepId,
2285
+ });
2286
+ }
2287
+
2288
+ case 'delete':
2289
+ if (typedArgs.stepId == null || typedArgs.stepId === '') {
2290
+ return json({
2291
+ success: false,
2292
+ action: 'delete_build_step',
2293
+ error: 'Step ID is required for delete action',
2294
+ });
2295
+ }
2296
+ await api.buildTypes.deleteBuildStep(typedArgs.buildTypeId, typedArgs.stepId);
2297
+ return json({
2298
+ success: true,
2299
+ action: 'delete_build_step',
2300
+ buildTypeId: typedArgs.buildTypeId,
2301
+ stepId: typedArgs.stepId,
2302
+ });
2303
+
2304
+ default:
2305
+ return json({ success: false, error: 'Invalid action' });
2306
+ }
2307
+ },
2308
+ mode: 'full',
2309
+ },
2310
+
2311
+ // === Build Trigger Management ===
2312
+ {
2313
+ name: 'manage_build_triggers',
2314
+ description: 'Add, update, or delete build triggers',
2315
+ inputSchema: {
2316
+ type: 'object',
2317
+ properties: {
2318
+ buildTypeId: { type: 'string', description: 'Build type ID' },
2319
+ action: { type: 'string', enum: ['add', 'delete'], description: 'Action to perform' },
2320
+ triggerId: { type: 'string', description: 'Trigger ID (for delete)' },
2321
+ type: { type: 'string', description: 'Trigger type (e.g., vcsTrigger)' },
2322
+ properties: { type: 'object', description: 'Trigger properties' },
2323
+ },
2324
+ required: ['buildTypeId', 'action'],
2325
+ },
2326
+ handler: async (args: unknown) => {
2327
+ const typedArgs = args as ManageBuildTriggersArgs;
2328
+
2329
+ const api = TeamCityAPI.getInstance();
2330
+
2331
+ switch (typedArgs.action) {
2332
+ case 'add': {
2333
+ const trigger = {
2334
+ type: typedArgs.type,
2335
+ properties: {
2336
+ property: Object.entries(typedArgs.properties ?? {}).map(([k, v]) => ({
2337
+ name: k,
2338
+ value: String(v),
2339
+ })),
2340
+ },
2341
+ };
2342
+ await api.buildTypes.addTriggerToBuildType(typedArgs.buildTypeId, undefined, trigger, {
2343
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
2344
+ });
2345
+ return json({
2346
+ success: true,
2347
+ action: 'add_build_trigger',
2348
+ buildTypeId: typedArgs.buildTypeId,
2349
+ });
2350
+ }
2351
+
2352
+ case 'delete':
2353
+ if (!typedArgs.triggerId) {
2354
+ return json({
2355
+ success: false,
2356
+ action: 'delete_build_trigger',
2357
+ error: 'Trigger ID is required for delete action',
2358
+ });
2359
+ }
2360
+ await api.buildTypes.deleteTrigger(typedArgs.buildTypeId, typedArgs.triggerId);
2361
+ return json({
2362
+ success: true,
2363
+ action: 'delete_build_trigger',
2364
+ buildTypeId: typedArgs.buildTypeId,
2365
+ triggerId: typedArgs.triggerId,
2366
+ });
2367
+
2368
+ default:
2369
+ return json({ success: false, error: 'Invalid action' });
2370
+ }
2371
+ },
2372
+ mode: 'full',
2373
+ },
2374
+
2375
+ // === Batch pause/unpause specific build configurations ===
2376
+ {
2377
+ name: 'set_build_configs_paused',
2378
+ description: 'Set paused/unpaused for a list of build configurations; optionally cancel queued',
2379
+ inputSchema: {
2380
+ type: 'object',
2381
+ properties: {
2382
+ buildTypeIds: {
2383
+ type: 'array',
2384
+ items: { type: 'string' },
2385
+ description: 'List of buildType IDs',
2386
+ },
2387
+ paused: { type: 'boolean', description: 'True to pause, false to unpause' },
2388
+ cancelQueued: { type: 'boolean', description: 'Cancel queued builds for these configs' },
2389
+ },
2390
+ required: ['buildTypeIds', 'paused'],
2391
+ },
2392
+ handler: async (args: unknown) => {
2393
+ const schema = z.object({
2394
+ buildTypeIds: z.array(z.string().min(1)).min(1),
2395
+ paused: z.boolean(),
2396
+ cancelQueued: z.boolean().optional(),
2397
+ });
2398
+ return runTool(
2399
+ 'set_build_configs_paused',
2400
+ schema,
2401
+ async (typed) => {
2402
+ const api = TeamCityAPI.getInstance();
2403
+ let updated = 0;
2404
+ for (const id of typed.buildTypeIds) {
2405
+ // eslint-disable-next-line no-await-in-loop
2406
+ await api.buildTypes.setBuildTypeField(id, 'paused', String(typed.paused));
2407
+ updated += 1;
2408
+ }
2409
+ let canceled = 0;
2410
+ if (typed.cancelQueued) {
2411
+ const queue = await api.buildQueue.getAllQueuedBuilds();
2412
+ const builds = (queue.data?.build ?? []) as Array<{
2413
+ id?: number;
2414
+ buildTypeId?: string;
2415
+ }>;
2416
+ const ids = new Set(typed.buildTypeIds);
2417
+ const toCancel = builds.filter((b) => b.buildTypeId && ids.has(b.buildTypeId));
2418
+ for (const b of toCancel) {
2419
+ if (b.id == null) continue;
2420
+ // eslint-disable-next-line no-await-in-loop
2421
+ await api.buildQueue.deleteQueuedBuild(String(b.id));
2422
+ canceled += 1;
2423
+ }
2424
+ }
2425
+ return json({
2426
+ success: true,
2427
+ action: 'set_build_configs_paused',
2428
+ updated,
2429
+ canceled,
2430
+ paused: typed.paused,
2431
+ ids: typed.buildTypeIds,
2432
+ });
2433
+ },
2434
+ args
2435
+ );
2436
+ },
2437
+ mode: 'full',
2438
+ },
2439
+
2440
+ // === Queue Maintenance ===
2441
+ {
2442
+ name: 'move_queued_build_to_top',
2443
+ description: 'Move a queued build to the top of the queue',
2444
+ inputSchema: {
2445
+ type: 'object',
2446
+ properties: { buildId: { type: 'string', description: 'Queued build ID' } },
2447
+ required: ['buildId'],
2448
+ },
2449
+ handler: async (args: unknown) => {
2450
+ const schema = z.object({ buildId: z.string().min(1) });
2451
+ return runTool(
2452
+ 'move_queued_build_to_top',
2453
+ schema,
2454
+ async (typed) => {
2455
+ const api = TeamCityAPI.getInstance();
2456
+ await api.buildQueue.setQueuedBuildsOrder(undefined, {
2457
+ build: [{ id: parseInt(typed.buildId) }],
2458
+ });
2459
+ return json({
2460
+ success: true,
2461
+ action: 'move_queued_build_to_top',
2462
+ buildId: typed.buildId,
2463
+ });
2464
+ },
2465
+ args
2466
+ );
2467
+ },
2468
+ mode: 'full',
2469
+ },
2470
+ {
2471
+ name: 'reorder_queued_builds',
2472
+ description: 'Reorder queued builds by providing the desired sequence of IDs',
2473
+ inputSchema: {
2474
+ type: 'object',
2475
+ properties: { buildIds: { type: 'array', items: { type: 'string' } } },
2476
+ required: ['buildIds'],
2477
+ },
2478
+ handler: async (args: unknown) => {
2479
+ const schema = z.object({ buildIds: z.array(z.string().min(1)).min(1) });
2480
+ return runTool(
2481
+ 'reorder_queued_builds',
2482
+ schema,
2483
+ async (typed) => {
2484
+ const api = TeamCityAPI.getInstance();
2485
+ await api.buildQueue.setQueuedBuildsOrder(undefined, {
2486
+ build: typed.buildIds.map((id) => ({ id: parseInt(id) })),
2487
+ });
2488
+ return json({
2489
+ success: true,
2490
+ action: 'reorder_queued_builds',
2491
+ count: typed.buildIds.length,
2492
+ });
2493
+ },
2494
+ args
2495
+ );
2496
+ },
2497
+ mode: 'full',
2498
+ },
2499
+ {
2500
+ name: 'cancel_queued_builds_for_build_type',
2501
+ description: 'Cancel all queued builds for a specific build configuration',
2502
+ inputSchema: {
2503
+ type: 'object',
2504
+ properties: { buildTypeId: { type: 'string', description: 'Build type ID' } },
2505
+ required: ['buildTypeId'],
2506
+ },
2507
+ handler: async (args: unknown) => {
2508
+ const schema = z.object({ buildTypeId: z.string().min(1) });
2509
+ return runTool(
2510
+ 'cancel_queued_builds_for_build_type',
2511
+ schema,
2512
+ async (typed) => {
2513
+ const api = TeamCityAPI.getInstance();
2514
+ const queue = await api.buildQueue.getAllQueuedBuilds();
2515
+ const builds = (queue.data?.build ?? []) as Array<{ id?: number; buildTypeId?: string }>;
2516
+ const toCancel = builds.filter((b) => b.buildTypeId === typed.buildTypeId);
2517
+ let canceled = 0;
2518
+ for (const b of toCancel) {
2519
+ if (b.id == null) continue;
2520
+ // eslint-disable-next-line no-await-in-loop
2521
+ await api.buildQueue.deleteQueuedBuild(String(b.id));
2522
+ canceled += 1;
2523
+ }
2524
+ return json({
2525
+ success: true,
2526
+ action: 'cancel_queued_builds_for_build_type',
2527
+ buildTypeId: typed.buildTypeId,
2528
+ canceled,
2529
+ });
2530
+ },
2531
+ args
2532
+ );
2533
+ },
2534
+ mode: 'full',
2535
+ },
2536
+ {
2537
+ name: 'cancel_queued_builds_by_locator',
2538
+ description: 'Cancel all queued builds matching a queue locator expression',
2539
+ inputSchema: {
2540
+ type: 'object',
2541
+ properties: { locator: { type: 'string', description: 'Queue locator expression' } },
2542
+ required: ['locator'],
2543
+ },
2544
+ handler: async (args: unknown) => {
2545
+ const schema = z.object({ locator: z.string().min(1) });
2546
+ return runTool(
2547
+ 'cancel_queued_builds_by_locator',
2548
+ schema,
2549
+ async (typed) => {
2550
+ const api = TeamCityAPI.getInstance();
2551
+ const queue = await api.buildQueue.getAllQueuedBuilds(typed.locator);
2552
+ const builds = (queue.data?.build ?? []) as Array<{ id?: number }>;
2553
+ let canceled = 0;
2554
+ for (const b of builds) {
2555
+ if (b.id == null) continue;
2556
+ // eslint-disable-next-line no-await-in-loop
2557
+ await api.buildQueue.deleteQueuedBuild(String(b.id));
2558
+ canceled += 1;
2559
+ }
2560
+ return json({
2561
+ success: true,
2562
+ action: 'cancel_queued_builds_by_locator',
2563
+ locator: typed.locator,
2564
+ canceled,
2565
+ });
2566
+ },
2567
+ args
2568
+ );
2569
+ },
2570
+ mode: 'full',
2571
+ },
2572
+
2573
+ // === Scoped Pause/Resume (by pool) ===
2574
+ {
2575
+ name: 'pause_queue_for_pool',
2576
+ description:
2577
+ 'Disable all agents in a pool to pause queue processing; optionally cancel queued builds for a build type',
2578
+ inputSchema: {
2579
+ type: 'object',
2580
+ properties: {
2581
+ poolId: { type: 'string', description: 'Agent pool ID' },
2582
+ cancelQueuedForBuildTypeId: {
2583
+ type: 'string',
2584
+ description: 'Optional buildTypeId: cancel queued builds for this configuration',
2585
+ },
2586
+ comment: { type: 'string', description: 'Optional comment for agent disablement' },
2587
+ until: { type: 'string', description: 'Optional ISO datetime to auto-reenable' },
2588
+ },
2589
+ required: ['poolId'],
2590
+ },
2591
+ handler: async (args: unknown) => {
2592
+ const schema = z.object({
2593
+ poolId: z.string().min(1),
2594
+ cancelQueuedForBuildTypeId: z.string().min(1).optional(),
2595
+ comment: z.string().optional(),
2596
+ until: z.string().min(1).optional(),
2597
+ });
2598
+ return runTool(
2599
+ 'pause_queue_for_pool',
2600
+ schema,
2601
+ async (typed) => {
2602
+ const api = TeamCityAPI.getInstance();
2603
+ // Disable all agents in pool
2604
+ const agentsResp = await api.agents.getAllAgents(`agentPool:(id:${typed.poolId})`);
2605
+ const agents = (agentsResp.data?.agent ?? []) as Array<{ id?: string }>;
2606
+ const body: { status: boolean; comment?: { text?: string }; statusSwitchTime?: string } =
2607
+ {
2608
+ status: false,
2609
+ };
2610
+ if (typed.comment) body.comment = { text: typed.comment };
2611
+ if (typed.until) body.statusSwitchTime = typed.until;
2612
+ let disabled = 0;
2613
+ for (const a of agents) {
2614
+ const id = a.id;
2615
+ if (!id) continue;
2616
+ // eslint-disable-next-line no-await-in-loop
2617
+ await api.agents.setEnabledInfo(id, undefined, body, {
2618
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
2619
+ });
2620
+ disabled += 1;
2621
+ }
2622
+
2623
+ // Optionally cancel queued builds for provided buildTypeId
2624
+ let canceled = 0;
2625
+ if (typed.cancelQueuedForBuildTypeId) {
2626
+ const queue = await api.buildQueue.getAllQueuedBuilds();
2627
+ const builds = (queue.data?.build ?? []) as Array<{
2628
+ id?: number;
2629
+ buildTypeId?: string;
2630
+ }>;
2631
+ const toCancel = builds.filter(
2632
+ (b) => b.buildTypeId === typed.cancelQueuedForBuildTypeId
2633
+ );
2634
+ for (const b of toCancel) {
2635
+ if (b.id == null) continue;
2636
+ // eslint-disable-next-line no-await-in-loop
2637
+ await api.buildQueue.deleteQueuedBuild(String(b.id));
2638
+ canceled += 1;
2639
+ }
2640
+ }
2641
+
2642
+ return json({
2643
+ success: true,
2644
+ action: 'pause_queue_for_pool',
2645
+ poolId: typed.poolId,
2646
+ disabledAgents: disabled,
2647
+ canceledQueued: canceled,
2648
+ });
2649
+ },
2650
+ args
2651
+ );
2652
+ },
2653
+ mode: 'full',
2654
+ },
2655
+ {
2656
+ name: 'resume_queue_for_pool',
2657
+ description: 'Re-enable all agents in a pool to resume queue processing',
2658
+ inputSchema: {
2659
+ type: 'object',
2660
+ properties: { poolId: { type: 'string', description: 'Agent pool ID' } },
2661
+ required: ['poolId'],
2662
+ },
2663
+ handler: async (args: unknown) => {
2664
+ const schema = z.object({ poolId: z.string().min(1) });
2665
+ return runTool(
2666
+ 'resume_queue_for_pool',
2667
+ schema,
2668
+ async (typed) => {
2669
+ const api = TeamCityAPI.getInstance();
2670
+ const agentsResp = await api.agents.getAllAgents(`agentPool:(id:${typed.poolId})`);
2671
+ const agents = (agentsResp.data?.agent ?? []) as Array<{ id?: string }>;
2672
+ let enabled = 0;
2673
+ for (const a of agents) {
2674
+ const id = a.id;
2675
+ if (!id) continue;
2676
+ // eslint-disable-next-line no-await-in-loop
2677
+ await api.agents.setEnabledInfo(
2678
+ id,
2679
+ undefined,
2680
+ { status: true },
2681
+ { headers: { 'Content-Type': 'application/json', Accept: 'application/json' } }
2682
+ );
2683
+ enabled += 1;
2684
+ }
2685
+ return json({
2686
+ success: true,
2687
+ action: 'resume_queue_for_pool',
2688
+ poolId: typed.poolId,
2689
+ enabledAgents: enabled,
2690
+ });
2691
+ },
2692
+ args
2693
+ );
2694
+ },
2695
+ mode: 'full',
2696
+ },
2697
+ // === Agent Enable/Disable ===
2698
+ {
2699
+ name: 'set_agent_enabled',
2700
+ description: 'Enable/disable an agent, with optional comment and schedule',
2701
+ inputSchema: {
2702
+ type: 'object',
2703
+ properties: {
2704
+ agentId: { type: 'string', description: 'Agent ID' },
2705
+ enabled: { type: 'boolean', description: 'True to enable, false to disable' },
2706
+ comment: { type: 'string', description: 'Optional comment' },
2707
+ until: {
2708
+ type: 'string',
2709
+ description: 'Optional ISO datetime to auto-flip state',
2710
+ },
2711
+ },
2712
+ required: ['agentId', 'enabled'],
2713
+ },
2714
+ handler: async (args: unknown) => {
2715
+ const schema = z.object({
2716
+ agentId: z.string().min(1),
2717
+ enabled: z.boolean(),
2718
+ comment: z.string().optional(),
2719
+ until: z.string().min(1).optional(),
2720
+ });
2721
+ return runTool(
2722
+ 'set_agent_enabled',
2723
+ schema,
2724
+ async (typed) => {
2725
+ const api = TeamCityAPI.getInstance();
2726
+ const body: {
2727
+ status: boolean;
2728
+ comment?: { text?: string };
2729
+ statusSwitchTime?: string;
2730
+ } = { status: typed.enabled };
2731
+ if (typed.comment) body.comment = { text: typed.comment };
2732
+ if (typed.until) body.statusSwitchTime = typed.until;
2733
+ const resp = await api.agents.setEnabledInfo(typed.agentId, undefined, body, {
2734
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
2735
+ });
2736
+ return json({
2737
+ success: true,
2738
+ action: 'set_agent_enabled',
2739
+ agentId: typed.agentId,
2740
+ enabled: resp.data?.status ?? typed.enabled,
2741
+ });
2742
+ },
2743
+ args
2744
+ );
2745
+ },
2746
+ mode: 'full',
2747
+ },
2748
+ {
2749
+ name: 'bulk_set_agents_enabled',
2750
+ description:
2751
+ 'Bulk enable/disable agents selected by pool or locator; supports comment/schedule',
2752
+ inputSchema: {
2753
+ type: 'object',
2754
+ properties: {
2755
+ enabled: { type: 'boolean', description: 'True to enable, false to disable' },
2756
+ poolId: { type: 'string', description: 'Agent pool ID (optional)' },
2757
+ locator: {
2758
+ type: 'string',
2759
+ description: 'Agent locator expression (alternative to poolId)',
2760
+ },
2761
+ comment: { type: 'string', description: 'Optional comment' },
2762
+ until: {
2763
+ type: 'string',
2764
+ description: 'Optional ISO datetime to auto-flip state',
2765
+ },
2766
+ includeDisabled: {
2767
+ type: 'boolean',
2768
+ description:
2769
+ 'Include disabled agents in selection (default true when not filtering by enabled)',
2770
+ },
2771
+ },
2772
+ required: ['enabled'],
2773
+ },
2774
+ handler: async (args: unknown) => {
2775
+ const schema = z
2776
+ .object({
2777
+ enabled: z.boolean(),
2778
+ poolId: z.string().min(1).optional(),
2779
+ locator: z.string().min(1).optional(),
2780
+ comment: z.string().optional(),
2781
+ until: z.string().min(1).optional(),
2782
+ includeDisabled: z.boolean().optional(),
2783
+ })
2784
+ .refine((v) => Boolean(v.poolId ?? v.locator), {
2785
+ message: 'Either poolId or locator is required',
2786
+ path: ['poolId'],
2787
+ });
2788
+ return runTool(
2789
+ 'bulk_set_agents_enabled',
2790
+ schema,
2791
+ async (typed) => {
2792
+ const api = TeamCityAPI.getInstance();
2793
+ const filters: string[] = [];
2794
+ if (typed.poolId) filters.push(`agentPool:(id:${typed.poolId})`);
2795
+ if (typed.locator) filters.push(typed.locator);
2796
+ if (typed.includeDisabled === false) filters.push('enabled:true');
2797
+ const locator = filters.join(',');
2798
+
2799
+ const list = await api.agents.getAllAgents(locator);
2800
+ const agents = (list.data?.agent ?? []) as Array<{ id?: string; name?: string }>;
2801
+ const body: {
2802
+ status: boolean;
2803
+ comment?: { text?: string };
2804
+ statusSwitchTime?: string;
2805
+ } = { status: typed.enabled };
2806
+ if (typed.comment) body.comment = { text: typed.comment };
2807
+ if (typed.until) body.statusSwitchTime = typed.until;
2808
+
2809
+ const results: Array<{ id: string; ok: boolean; error?: string }> = [];
2810
+ for (const a of agents) {
2811
+ const id = String(a.id ?? '');
2812
+ if (!id) continue;
2813
+ try {
2814
+ // eslint-disable-next-line no-await-in-loop
2815
+ await api.agents.setEnabledInfo(id, undefined, body, {
2816
+ headers: {
2817
+ 'Content-Type': 'application/json',
2818
+ Accept: 'application/json',
2819
+ },
2820
+ });
2821
+ results.push({ id, ok: true });
2822
+ } catch (e) {
2823
+ const msg = e instanceof Error ? e.message : 'Unknown error';
2824
+ results.push({ id, ok: false, error: msg });
2825
+ }
2826
+ }
2827
+
2828
+ const succeeded = results.filter((r) => r.ok).length;
2829
+ const failed = results.length - succeeded;
2830
+ return json({
2831
+ success: true,
2832
+ action: 'bulk_set_agents_enabled',
2833
+ total: results.length,
2834
+ succeeded,
2835
+ failed,
2836
+ results,
2837
+ locator,
2838
+ poolId: typed.poolId,
2839
+ });
2840
+ },
2841
+ args
2842
+ );
2843
+ },
2844
+ mode: 'full',
2845
+ },
2846
+ ];
2847
+
2848
+ /**
2849
+ * Get all available tools based on current mode
2850
+ */
2851
+ export function getAvailableTools(): ToolDefinition[] {
2852
+ const mode = getMCPMode();
2853
+ if (mode === 'full') {
2854
+ const combined = [...DEV_TOOLS, ...FULL_MODE_TOOLS];
2855
+ const map = new Map<string, ToolDefinition>();
2856
+ for (const t of combined) map.set(t.name, t);
2857
+ return Array.from(map.values());
2858
+ }
2859
+ // Dev mode: include only tools not explicitly marked as full
2860
+ return DEV_TOOLS.filter((t) => t.mode !== 'full');
2861
+ }
2862
+
2863
+ /**
2864
+ * Get tool by name (respects current mode)
2865
+ */
2866
+ export function getTool(name: string): ToolDefinition | undefined {
2867
+ const tools = getAvailableTools();
2868
+ return tools.find((tool) => tool.name === name);
2869
+ }
2870
+
2871
+ /**
2872
+ * Get tool by name or throw a descriptive error if unavailable.
2873
+ * Useful in tests and call sites where the tool is required.
2874
+ */
2875
+ export function getRequiredTool(name: string): ToolDefinition {
2876
+ const tool = getTool(name);
2877
+ if (!tool) {
2878
+ const mode = getMCPMode();
2879
+ throw new Error(`Tool not available in ${mode} mode or not registered: ${name}`);
2880
+ }
2881
+ return tool;
2882
+ }
2883
+
2884
+ /**
2885
+ * Get all tool names (respects current mode)
2886
+ */
2887
+ export function getToolNames(): string[] {
2888
+ const tools = getAvailableTools();
2889
+ return tools.map((tool) => tool.name);
2890
+ }