@ffschrattenecker/tm1-mcp-server 6.0.0

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 (475) hide show
  1. package/CHANGELOG.md +1211 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +34 -0
  4. package/README.md +276 -0
  5. package/dist/config.d.ts +35 -0
  6. package/dist/config.js +238 -0
  7. package/dist/http-transport.d.ts +8 -0
  8. package/dist/http-transport.js +132 -0
  9. package/dist/index.d.ts +18 -0
  10. package/dist/index.js +164 -0
  11. package/dist/lib/callgraph/callGraph.d.ts +124 -0
  12. package/dist/lib/callgraph/callGraph.js +334 -0
  13. package/dist/lib/callgraph/choreGraph.d.ts +23 -0
  14. package/dist/lib/callgraph/choreGraph.js +102 -0
  15. package/dist/lib/callgraph/dataFlow.d.ts +74 -0
  16. package/dist/lib/callgraph/dataFlow.js +271 -0
  17. package/dist/lib/callgraph/datasourceMembership.d.ts +31 -0
  18. package/dist/lib/callgraph/datasourceMembership.js +142 -0
  19. package/dist/lib/callgraph/lintTypes.d.ts +28 -0
  20. package/dist/lib/callgraph/lintTypes.js +2 -0
  21. package/dist/lib/callgraph/mdxMembers.d.ts +29 -0
  22. package/dist/lib/callgraph/mdxMembers.js +97 -0
  23. package/dist/lib/callgraph/referenceIndex.d.ts +179 -0
  24. package/dist/lib/callgraph/referenceIndex.js +584 -0
  25. package/dist/lib/callgraph/rulesLinter.d.ts +55 -0
  26. package/dist/lib/callgraph/rulesLinter.js +776 -0
  27. package/dist/lib/callgraph/rulesParser.d.ts +26 -0
  28. package/dist/lib/callgraph/rulesParser.js +71 -0
  29. package/dist/lib/callgraph/subsetUsage.d.ts +16 -0
  30. package/dist/lib/callgraph/subsetUsage.js +134 -0
  31. package/dist/lib/callgraph/tiParser.d.ts +21 -0
  32. package/dist/lib/callgraph/tiParser.js +672 -0
  33. package/dist/lib/callgraph/tiSignatures.d.ts +32 -0
  34. package/dist/lib/callgraph/tiSignatures.js +6185 -0
  35. package/dist/lib/callgraph/tm1-adapter.d.ts +32 -0
  36. package/dist/lib/callgraph/tm1-adapter.js +159 -0
  37. package/dist/lib/callgraph/types.d.ts +53 -0
  38. package/dist/lib/callgraph/types.js +2 -0
  39. package/dist/lib/callgraph/variableEnv.d.ts +86 -0
  40. package/dist/lib/callgraph/variableEnv.js +214 -0
  41. package/dist/lib/cell-address.d.ts +12 -0
  42. package/dist/lib/cell-address.js +71 -0
  43. package/dist/lib/complexity/antipatterns.d.ts +22 -0
  44. package/dist/lib/complexity/antipatterns.js +302 -0
  45. package/dist/lib/complexity/comment-classifier.d.ts +24 -0
  46. package/dist/lib/complexity/comment-classifier.js +43 -0
  47. package/dist/lib/complexity/cross-process.d.ts +78 -0
  48. package/dist/lib/complexity/cross-process.js +114 -0
  49. package/dist/lib/complexity/process-metrics.d.ts +78 -0
  50. package/dist/lib/complexity/process-metrics.js +278 -0
  51. package/dist/lib/complexity/rules-metrics.d.ts +31 -0
  52. package/dist/lib/complexity/rules-metrics.js +99 -0
  53. package/dist/lib/concurrency.d.ts +11 -0
  54. package/dist/lib/concurrency.js +27 -0
  55. package/dist/lib/control-name.d.ts +10 -0
  56. package/dist/lib/control-name.js +10 -0
  57. package/dist/lib/coordinate-error.d.ts +3 -0
  58. package/dist/lib/coordinate-error.js +29 -0
  59. package/dist/lib/credential-format.d.ts +23 -0
  60. package/dist/lib/credential-format.js +25 -0
  61. package/dist/lib/cube-stats/fetcher.d.ts +106 -0
  62. package/dist/lib/cube-stats/fetcher.js +194 -0
  63. package/dist/lib/feeders/brackets.d.ts +47 -0
  64. package/dist/lib/feeders/brackets.js +195 -0
  65. package/dist/lib/feeders/element-type-cache.d.ts +42 -0
  66. package/dist/lib/feeders/element-type-cache.js +86 -0
  67. package/dist/lib/feeders/static-heuristics.d.ts +101 -0
  68. package/dist/lib/feeders/static-heuristics.js +202 -0
  69. package/dist/lib/git-process.d.ts +67 -0
  70. package/dist/lib/git-process.js +243 -0
  71. package/dist/lib/mask-secrets.d.ts +10 -0
  72. package/dist/lib/mask-secrets.js +99 -0
  73. package/dist/lib/mdx.d.ts +3 -0
  74. package/dist/lib/mdx.js +13 -0
  75. package/dist/lib/naming/odata-filter.d.ts +15 -0
  76. package/dist/lib/naming/odata-filter.js +81 -0
  77. package/dist/lib/naming/rules.d.ts +34 -0
  78. package/dist/lib/naming/rules.js +215 -0
  79. package/dist/lib/pro-parser.d.ts +19 -0
  80. package/dist/lib/pro-parser.js +260 -0
  81. package/dist/lib/pro-serializer.d.ts +19 -0
  82. package/dist/lib/pro-serializer.js +170 -0
  83. package/dist/lib/process-parts-schema.d.ts +45 -0
  84. package/dist/lib/process-parts-schema.js +46 -0
  85. package/dist/lib/process-refs.d.ts +88 -0
  86. package/dist/lib/process-refs.js +441 -0
  87. package/dist/lib/rules-outline.d.ts +29 -0
  88. package/dist/lib/rules-outline.js +68 -0
  89. package/dist/lib/rules-patch.d.ts +6 -0
  90. package/dist/lib/rules-patch.js +59 -0
  91. package/dist/lib/safe-regex.d.ts +15 -0
  92. package/dist/lib/safe-regex.js +37 -0
  93. package/dist/lib/sample-cells.d.ts +48 -0
  94. package/dist/lib/sample-cells.js +146 -0
  95. package/dist/lib/slim-json-schema.d.ts +20 -0
  96. package/dist/lib/slim-json-schema.js +68 -0
  97. package/dist/lib/strip-comments.d.ts +23 -0
  98. package/dist/lib/strip-comments.js +61 -0
  99. package/dist/lib/tm1-events.d.ts +16 -0
  100. package/dist/lib/tm1-events.js +29 -0
  101. package/dist/lib/v12-compat/deprecated-ti.d.ts +17 -0
  102. package/dist/lib/v12-compat/deprecated-ti.js +257 -0
  103. package/dist/lib/v12-compat/scanner.d.ts +10 -0
  104. package/dist/lib/v12-compat/scanner.js +43 -0
  105. package/dist/lib/variables-ui-data.d.ts +26 -0
  106. package/dist/lib/variables-ui-data.js +77 -0
  107. package/dist/load-env.d.ts +2 -0
  108. package/dist/load-env.js +29 -0
  109. package/dist/logger.d.ts +4 -0
  110. package/dist/logger.js +60 -0
  111. package/dist/prompts/index.d.ts +3 -0
  112. package/dist/prompts/index.js +141 -0
  113. package/dist/resources/index.d.ts +5 -0
  114. package/dist/resources/index.js +237 -0
  115. package/dist/resources/list-handler.d.ts +40 -0
  116. package/dist/resources/list-handler.js +86 -0
  117. package/dist/resources/subscriptions.d.ts +19 -0
  118. package/dist/resources/subscriptions.js +80 -0
  119. package/dist/schemas/cells.d.ts +17 -0
  120. package/dist/schemas/cells.js +13 -0
  121. package/dist/schemas/common.d.ts +16 -0
  122. package/dist/schemas/common.js +14 -0
  123. package/dist/schemas/index.d.ts +10 -0
  124. package/dist/schemas/index.js +23 -0
  125. package/dist/schemas/metadata.d.ts +70 -0
  126. package/dist/schemas/metadata.js +47 -0
  127. package/dist/schemas/monitoring.d.ts +95 -0
  128. package/dist/schemas/monitoring.js +69 -0
  129. package/dist/schemas/processes.d.ts +74 -0
  130. package/dist/schemas/processes.js +66 -0
  131. package/dist/schemas/scheduling.d.ts +13 -0
  132. package/dist/schemas/scheduling.js +13 -0
  133. package/dist/schemas/security.d.ts +19 -0
  134. package/dist/schemas/security.js +16 -0
  135. package/dist/schemas/subsets.d.ts +12 -0
  136. package/dist/schemas/subsets.js +12 -0
  137. package/dist/schemas/views.d.ts +9 -0
  138. package/dist/schemas/views.js +9 -0
  139. package/dist/session-manager.d.ts +79 -0
  140. package/dist/session-manager.js +281 -0
  141. package/dist/tm1-client/connection/profile.d.ts +13 -0
  142. package/dist/tm1-client/connection/profile.js +99 -0
  143. package/dist/tm1-client/dispatcher.d.ts +5 -0
  144. package/dist/tm1-client/dispatcher.js +31 -0
  145. package/dist/tm1-client/http.d.ts +81 -0
  146. package/dist/tm1-client/http.js +547 -0
  147. package/dist/tm1-client/services/batch-service.d.ts +123 -0
  148. package/dist/tm1-client/services/batch-service.js +455 -0
  149. package/dist/tm1-client/services/cell-service.d.ts +71 -0
  150. package/dist/tm1-client/services/cell-service.js +333 -0
  151. package/dist/tm1-client/services/cellset-transform.d.ts +26 -0
  152. package/dist/tm1-client/services/cellset-transform.js +80 -0
  153. package/dist/tm1-client/services/chore-service.d.ts +68 -0
  154. package/dist/tm1-client/services/chore-service.js +179 -0
  155. package/dist/tm1-client/services/chore-status.d.ts +11 -0
  156. package/dist/tm1-client/services/chore-status.js +127 -0
  157. package/dist/tm1-client/services/cube-service.d.ts +134 -0
  158. package/dist/tm1-client/services/cube-service.js +294 -0
  159. package/dist/tm1-client/services/dimension-service.d.ts +118 -0
  160. package/dist/tm1-client/services/dimension-service.js +249 -0
  161. package/dist/tm1-client/services/element-service.d.ts +245 -0
  162. package/dist/tm1-client/services/element-service.js +809 -0
  163. package/dist/tm1-client/services/fallback.d.ts +44 -0
  164. package/dist/tm1-client/services/fallback.js +72 -0
  165. package/dist/tm1-client/services/file-service.d.ts +53 -0
  166. package/dist/tm1-client/services/file-service.js +218 -0
  167. package/dist/tm1-client/services/hierarchy-service.d.ts +129 -0
  168. package/dist/tm1-client/services/hierarchy-service.js +332 -0
  169. package/dist/tm1-client/services/monitoring-service.d.ts +34 -0
  170. package/dist/tm1-client/services/monitoring-service.js +123 -0
  171. package/dist/tm1-client/services/odata-page.d.ts +71 -0
  172. package/dist/tm1-client/services/odata-page.js +87 -0
  173. package/dist/tm1-client/services/process-service.d.ts +278 -0
  174. package/dist/tm1-client/services/process-service.js +874 -0
  175. package/dist/tm1-client/services/process-status.d.ts +21 -0
  176. package/dist/tm1-client/services/process-status.js +89 -0
  177. package/dist/tm1-client/services/security-service.d.ts +50 -0
  178. package/dist/tm1-client/services/security-service.js +93 -0
  179. package/dist/tm1-client/services/server-service.d.ts +116 -0
  180. package/dist/tm1-client/services/server-service.js +504 -0
  181. package/dist/tm1-client/services/subset-service.d.ts +37 -0
  182. package/dist/tm1-client/services/subset-service.js +122 -0
  183. package/dist/tm1-client/services/view-service.d.ts +46 -0
  184. package/dist/tm1-client/services/view-service.js +287 -0
  185. package/dist/tm1-client.d.ts +56 -0
  186. package/dist/tm1-client.js +126 -0
  187. package/dist/tools/analysis/analyze-callgraph.d.ts +28 -0
  188. package/dist/tools/analysis/analyze-callgraph.js +350 -0
  189. package/dist/tools/analysis/analyze-chore-graph.d.ts +2 -0
  190. package/dist/tools/analysis/analyze-chore-graph.js +148 -0
  191. package/dist/tools/analysis/analyze-object-usage.d.ts +2 -0
  192. package/dist/tools/analysis/analyze-object-usage.js +143 -0
  193. package/dist/tools/analysis/audit-complexity.d.ts +2 -0
  194. package/dist/tools/analysis/audit-complexity.js +255 -0
  195. package/dist/tools/analysis/audit-feeders.d.ts +2 -0
  196. package/dist/tools/analysis/audit-feeders.js +417 -0
  197. package/dist/tools/analysis/audit-naming.d.ts +2 -0
  198. package/dist/tools/analysis/audit-naming.js +379 -0
  199. package/dist/tools/analysis/check-v12-readiness.d.ts +2 -0
  200. package/dist/tools/analysis/check-v12-readiness.js +136 -0
  201. package/dist/tools/analysis/find-orphan-dimensions.d.ts +2 -0
  202. package/dist/tools/analysis/find-orphan-dimensions.js +55 -0
  203. package/dist/tools/analysis/invalidate-callgraph-cache.d.ts +2 -0
  204. package/dist/tools/analysis/invalidate-callgraph-cache.js +40 -0
  205. package/dist/tools/analysis/trace-data-flow.d.ts +2 -0
  206. package/dist/tools/analysis/trace-data-flow.js +138 -0
  207. package/dist/tools/annotations.d.ts +12 -0
  208. package/dist/tools/annotations.js +61 -0
  209. package/dist/tools/celldata/check-feeders.d.ts +2 -0
  210. package/dist/tools/celldata/check-feeders.js +48 -0
  211. package/dist/tools/celldata/check-writable-coords.d.ts +2 -0
  212. package/dist/tools/celldata/check-writable-coords.js +126 -0
  213. package/dist/tools/celldata/execute-mdx.d.ts +17 -0
  214. package/dist/tools/celldata/execute-mdx.js +126 -0
  215. package/dist/tools/celldata/get-cell-value.d.ts +2 -0
  216. package/dist/tools/celldata/get-cell-value.js +30 -0
  217. package/dist/tools/celldata/get-view-definition.d.ts +2 -0
  218. package/dist/tools/celldata/get-view-definition.js +29 -0
  219. package/dist/tools/celldata/get-view.d.ts +2 -0
  220. package/dist/tools/celldata/get-view.js +55 -0
  221. package/dist/tools/celldata/sample-cells.d.ts +2 -0
  222. package/dist/tools/celldata/sample-cells.js +101 -0
  223. package/dist/tools/celldata/trace-cell-calculation.d.ts +2 -0
  224. package/dist/tools/celldata/trace-cell-calculation.js +53 -0
  225. package/dist/tools/celldata/trace-feeders.d.ts +2 -0
  226. package/dist/tools/celldata/trace-feeders.js +44 -0
  227. package/dist/tools/celldata/write-cells.d.ts +2 -0
  228. package/dist/tools/celldata/write-cells.js +65 -0
  229. package/dist/tools/confirm.d.ts +10 -0
  230. package/dist/tools/confirm.js +64 -0
  231. package/dist/tools/define-tool.d.ts +51 -0
  232. package/dist/tools/define-tool.js +49 -0
  233. package/dist/tools/dimension-management/bulk-upsert-elements.d.ts +2 -0
  234. package/dist/tools/dimension-management/bulk-upsert-elements.js +103 -0
  235. package/dist/tools/dimension-management/create-dimension.d.ts +2 -0
  236. package/dist/tools/dimension-management/create-dimension.js +22 -0
  237. package/dist/tools/dimension-management/create-element-attribute.d.ts +2 -0
  238. package/dist/tools/dimension-management/create-element-attribute.js +26 -0
  239. package/dist/tools/dimension-management/create-element.d.ts +2 -0
  240. package/dist/tools/dimension-management/create-element.js +31 -0
  241. package/dist/tools/dimension-management/create-hierarchy.d.ts +2 -0
  242. package/dist/tools/dimension-management/create-hierarchy.js +22 -0
  243. package/dist/tools/dimension-management/delete-dimension.d.ts +2 -0
  244. package/dist/tools/dimension-management/delete-dimension.js +25 -0
  245. package/dist/tools/dimension-management/delete-element.d.ts +2 -0
  246. package/dist/tools/dimension-management/delete-element.js +26 -0
  247. package/dist/tools/dimension-management/delete-elements.d.ts +2 -0
  248. package/dist/tools/dimension-management/delete-elements.js +44 -0
  249. package/dist/tools/dimension-management/delete-hierarchy.d.ts +2 -0
  250. package/dist/tools/dimension-management/delete-hierarchy.js +35 -0
  251. package/dist/tools/dimension-management/get-element-attribute-values.d.ts +2 -0
  252. package/dist/tools/dimension-management/get-element-attribute-values.js +77 -0
  253. package/dist/tools/dimension-management/list-element-attributes.d.ts +2 -0
  254. package/dist/tools/dimension-management/list-element-attributes.js +31 -0
  255. package/dist/tools/dimension-management/move-element.d.ts +2 -0
  256. package/dist/tools/dimension-management/move-element.js +28 -0
  257. package/dist/tools/dimension-management/update-element-attribute-value.d.ts +2 -0
  258. package/dist/tools/dimension-management/update-element-attribute-value.js +80 -0
  259. package/dist/tools/dimension-management/update-element.d.ts +2 -0
  260. package/dist/tools/dimension-management/update-element.js +35 -0
  261. package/dist/tools/error-format.d.ts +22 -0
  262. package/dist/tools/error-format.js +130 -0
  263. package/dist/tools/fileops/delete-file.d.ts +2 -0
  264. package/dist/tools/fileops/delete-file.js +32 -0
  265. package/dist/tools/fileops/get-file-content.d.ts +2 -0
  266. package/dist/tools/fileops/get-file-content.js +76 -0
  267. package/dist/tools/fileops/list-files.d.ts +2 -0
  268. package/dist/tools/fileops/list-files.js +43 -0
  269. package/dist/tools/fileops/search-files.d.ts +2 -0
  270. package/dist/tools/fileops/search-files.js +76 -0
  271. package/dist/tools/fileops/upload-file.d.ts +2 -0
  272. package/dist/tools/fileops/upload-file.js +69 -0
  273. package/dist/tools/format.d.ts +57 -0
  274. package/dist/tools/format.js +157 -0
  275. package/dist/tools/hierarchy.d.ts +6 -0
  276. package/dist/tools/hierarchy.js +27 -0
  277. package/dist/tools/index.d.ts +4 -0
  278. package/dist/tools/index.js +263 -0
  279. package/dist/tools/local-file.d.ts +16 -0
  280. package/dist/tools/local-file.js +88 -0
  281. package/dist/tools/metadata/get-ancestors.d.ts +2 -0
  282. package/dist/tools/metadata/get-ancestors.js +36 -0
  283. package/dist/tools/metadata/get-descendants.d.ts +2 -0
  284. package/dist/tools/metadata/get-descendants.js +64 -0
  285. package/dist/tools/metadata/get-hierarchy.d.ts +2 -0
  286. package/dist/tools/metadata/get-hierarchy.js +130 -0
  287. package/dist/tools/metadata/list-chores.d.ts +2 -0
  288. package/dist/tools/metadata/list-chores.js +62 -0
  289. package/dist/tools/metadata/list-cubes.d.ts +2 -0
  290. package/dist/tools/metadata/list-cubes.js +128 -0
  291. package/dist/tools/metadata/list-dimensions.d.ts +2 -0
  292. package/dist/tools/metadata/list-dimensions.js +131 -0
  293. package/dist/tools/metadata/list-processes-grouped.d.ts +2 -0
  294. package/dist/tools/metadata/list-processes-grouped.js +96 -0
  295. package/dist/tools/metadata/list-processes.d.ts +2 -0
  296. package/dist/tools/metadata/list-processes.js +108 -0
  297. package/dist/tools/metadata/resolve-default-members.d.ts +2 -0
  298. package/dist/tools/metadata/resolve-default-members.js +46 -0
  299. package/dist/tools/model-building/check-cube-rule.d.ts +2 -0
  300. package/dist/tools/model-building/check-cube-rule.js +51 -0
  301. package/dist/tools/model-building/clear-cube.d.ts +2 -0
  302. package/dist/tools/model-building/clear-cube.js +46 -0
  303. package/dist/tools/model-building/create-cube.d.ts +2 -0
  304. package/dist/tools/model-building/create-cube.js +34 -0
  305. package/dist/tools/model-building/delete-cube.d.ts +2 -0
  306. package/dist/tools/model-building/delete-cube.js +27 -0
  307. package/dist/tools/model-building/get-all-cube-rules.d.ts +2 -0
  308. package/dist/tools/model-building/get-all-cube-rules.js +149 -0
  309. package/dist/tools/model-building/get-cube-rules.d.ts +2 -0
  310. package/dist/tools/model-building/get-cube-rules.js +69 -0
  311. package/dist/tools/model-building/rules-source.d.ts +21 -0
  312. package/dist/tools/model-building/rules-source.js +49 -0
  313. package/dist/tools/model-building/search-rules.d.ts +2 -0
  314. package/dist/tools/model-building/search-rules.js +132 -0
  315. package/dist/tools/model-building/set-cube-rules.d.ts +2 -0
  316. package/dist/tools/model-building/set-cube-rules.js +81 -0
  317. package/dist/tools/model-building/unload-cube.d.ts +2 -0
  318. package/dist/tools/model-building/unload-cube.js +23 -0
  319. package/dist/tools/operations/diagnose-process-error.d.ts +2 -0
  320. package/dist/tools/operations/diagnose-process-error.js +178 -0
  321. package/dist/tools/operations/error-log-helpers.d.ts +25 -0
  322. package/dist/tools/operations/error-log-helpers.js +57 -0
  323. package/dist/tools/operations/get-audit-log.d.ts +2 -0
  324. package/dist/tools/operations/get-audit-log.js +70 -0
  325. package/dist/tools/operations/get-cube-stats.d.ts +2 -0
  326. package/dist/tools/operations/get-cube-stats.js +107 -0
  327. package/dist/tools/operations/get-error-log-content.d.ts +2 -0
  328. package/dist/tools/operations/get-error-log-content.js +164 -0
  329. package/dist/tools/operations/get-jobs.d.ts +3 -0
  330. package/dist/tools/operations/get-jobs.js +51 -0
  331. package/dist/tools/operations/get-message-log.d.ts +2 -0
  332. package/dist/tools/operations/get-message-log.js +63 -0
  333. package/dist/tools/operations/get-server-info.d.ts +2 -0
  334. package/dist/tools/operations/get-server-info.js +180 -0
  335. package/dist/tools/operations/get-server-state.d.ts +2 -0
  336. package/dist/tools/operations/get-server-state.js +129 -0
  337. package/dist/tools/operations/get-sessions.d.ts +2 -0
  338. package/dist/tools/operations/get-sessions.js +76 -0
  339. package/dist/tools/operations/get-threads.d.ts +3 -0
  340. package/dist/tools/operations/get-threads.js +50 -0
  341. package/dist/tools/operations/get-transaction-log.d.ts +2 -0
  342. package/dist/tools/operations/get-transaction-log.js +63 -0
  343. package/dist/tools/operations/list-error-logs.d.ts +8 -0
  344. package/dist/tools/operations/list-error-logs.js +157 -0
  345. package/dist/tools/operations/save-data.d.ts +2 -0
  346. package/dist/tools/operations/save-data.js +50 -0
  347. package/dist/tools/pagination.d.ts +32 -0
  348. package/dist/tools/pagination.js +116 -0
  349. package/dist/tools/scheduling/create-chore.d.ts +2 -0
  350. package/dist/tools/scheduling/create-chore.js +93 -0
  351. package/dist/tools/scheduling/delete-chore.d.ts +2 -0
  352. package/dist/tools/scheduling/delete-chore.js +22 -0
  353. package/dist/tools/scheduling/execute-chore.d.ts +2 -0
  354. package/dist/tools/scheduling/execute-chore.js +52 -0
  355. package/dist/tools/scheduling/toggle-chore.d.ts +2 -0
  356. package/dist/tools/scheduling/toggle-chore.js +22 -0
  357. package/dist/tools/scheduling/update-chore.d.ts +2 -0
  358. package/dist/tools/scheduling/update-chore.js +71 -0
  359. package/dist/tools/schemas/common.d.ts +10 -0
  360. package/dist/tools/schemas/common.js +23 -0
  361. package/dist/tools/schemas/items-analysis.d.ts +394 -0
  362. package/dist/tools/schemas/items-analysis.js +419 -0
  363. package/dist/tools/schemas/items-cells.d.ts +70 -0
  364. package/dist/tools/schemas/items-cells.js +65 -0
  365. package/dist/tools/schemas/items-common.d.ts +18 -0
  366. package/dist/tools/schemas/items-common.js +39 -0
  367. package/dist/tools/schemas/items-fileops.d.ts +11 -0
  368. package/dist/tools/schemas/items-fileops.js +13 -0
  369. package/dist/tools/schemas/items-metadata.d.ts +262 -0
  370. package/dist/tools/schemas/items-metadata.js +184 -0
  371. package/dist/tools/schemas/items-monitoring.d.ts +79 -0
  372. package/dist/tools/schemas/items-monitoring.js +78 -0
  373. package/dist/tools/schemas/items-processes.d.ts +279 -0
  374. package/dist/tools/schemas/items-processes.js +235 -0
  375. package/dist/tools/schemas/items-scheduling.d.ts +25 -0
  376. package/dist/tools/schemas/items-scheduling.js +26 -0
  377. package/dist/tools/schemas/items-security.d.ts +19 -0
  378. package/dist/tools/schemas/items-security.js +12 -0
  379. package/dist/tools/schemas/items-subsets.d.ts +2 -0
  380. package/dist/tools/schemas/items-subsets.js +4 -0
  381. package/dist/tools/schemas/items-views.d.ts +38 -0
  382. package/dist/tools/schemas/items-views.js +26 -0
  383. package/dist/tools/schemas/items.d.ts +12 -0
  384. package/dist/tools/schemas/items.js +23 -0
  385. package/dist/tools/schemas/markdown-capable.d.ts +21 -0
  386. package/dist/tools/schemas/markdown-capable.js +58 -0
  387. package/dist/tools/schemas/output-schema.d.ts +24 -0
  388. package/dist/tools/schemas/output-schema.js +25 -0
  389. package/dist/tools/security/assign-client-group.d.ts +2 -0
  390. package/dist/tools/security/assign-client-group.js +20 -0
  391. package/dist/tools/security/create-client.d.ts +2 -0
  392. package/dist/tools/security/create-client.js +28 -0
  393. package/dist/tools/security/delete-client.d.ts +2 -0
  394. package/dist/tools/security/delete-client.js +22 -0
  395. package/dist/tools/security/get-client.d.ts +2 -0
  396. package/dist/tools/security/get-client.js +20 -0
  397. package/dist/tools/security/list-clients.d.ts +2 -0
  398. package/dist/tools/security/list-clients.js +86 -0
  399. package/dist/tools/security/list-groups.d.ts +2 -0
  400. package/dist/tools/security/list-groups.js +43 -0
  401. package/dist/tools/security/remove-client-group.d.ts +2 -0
  402. package/dist/tools/security/remove-client-group.js +27 -0
  403. package/dist/tools/security/update-client.d.ts +2 -0
  404. package/dist/tools/security/update-client.js +22 -0
  405. package/dist/tools/subsets/create-subset.d.ts +2 -0
  406. package/dist/tools/subsets/create-subset.js +44 -0
  407. package/dist/tools/subsets/delete-subset.d.ts +2 -0
  408. package/dist/tools/subsets/delete-subset.js +26 -0
  409. package/dist/tools/subsets/get-subset.d.ts +2 -0
  410. package/dist/tools/subsets/get-subset.js +29 -0
  411. package/dist/tools/subsets/list-subsets.d.ts +2 -0
  412. package/dist/tools/subsets/list-subsets.js +36 -0
  413. package/dist/tools/subsets/update-subset.d.ts +2 -0
  414. package/dist/tools/subsets/update-subset.js +33 -0
  415. package/dist/tools/ti-development/check-process-code.d.ts +2 -0
  416. package/dist/tools/ti-development/check-process-code.js +96 -0
  417. package/dist/tools/ti-development/compile-process.d.ts +2 -0
  418. package/dist/tools/ti-development/compile-process.js +32 -0
  419. package/dist/tools/ti-development/copy-process.d.ts +2 -0
  420. package/dist/tools/ti-development/copy-process.js +32 -0
  421. package/dist/tools/ti-development/delete-process.d.ts +2 -0
  422. package/dist/tools/ti-development/delete-process.js +26 -0
  423. package/dist/tools/ti-development/diff-process-with-file.d.ts +2 -0
  424. package/dist/tools/ti-development/diff-process-with-file.js +208 -0
  425. package/dist/tools/ti-development/diff-processes.d.ts +2 -0
  426. package/dist/tools/ti-development/diff-processes.js +312 -0
  427. package/dist/tools/ti-development/execute-process.d.ts +8 -0
  428. package/dist/tools/ti-development/execute-process.js +109 -0
  429. package/dist/tools/ti-development/export-process-to-git.d.ts +2 -0
  430. package/dist/tools/ti-development/export-process-to-git.js +113 -0
  431. package/dist/tools/ti-development/export-process-to-pro.d.ts +2 -0
  432. package/dist/tools/ti-development/export-process-to-pro.js +117 -0
  433. package/dist/tools/ti-development/get-all-processes-code.d.ts +2 -0
  434. package/dist/tools/ti-development/get-all-processes-code.js +131 -0
  435. package/dist/tools/ti-development/get-process-code.d.ts +2 -0
  436. package/dist/tools/ti-development/get-process-code.js +100 -0
  437. package/dist/tools/ti-development/get-process-datasource.d.ts +2 -0
  438. package/dist/tools/ti-development/get-process-datasource.js +20 -0
  439. package/dist/tools/ti-development/get-process-parameters.d.ts +2 -0
  440. package/dist/tools/ti-development/get-process-parameters.js +25 -0
  441. package/dist/tools/ti-development/get-process-variables.d.ts +2 -0
  442. package/dist/tools/ti-development/get-process-variables.js +38 -0
  443. package/dist/tools/ti-development/get-process.d.ts +2 -0
  444. package/dist/tools/ti-development/get-process.js +163 -0
  445. package/dist/tools/ti-development/import-pro-file.d.ts +2 -0
  446. package/dist/tools/ti-development/import-pro-file.js +153 -0
  447. package/dist/tools/ti-development/import-process-from-git.d.ts +2 -0
  448. package/dist/tools/ti-development/import-process-from-git.js +198 -0
  449. package/dist/tools/ti-development/install-pro-bundle.d.ts +2 -0
  450. package/dist/tools/ti-development/install-pro-bundle.js +288 -0
  451. package/dist/tools/ti-development/preflight.d.ts +39 -0
  452. package/dist/tools/ti-development/preflight.js +56 -0
  453. package/dist/tools/ti-development/process-backup.d.ts +29 -0
  454. package/dist/tools/ti-development/process-backup.js +118 -0
  455. package/dist/tools/ti-development/search-code.d.ts +2 -0
  456. package/dist/tools/ti-development/search-code.js +208 -0
  457. package/dist/tools/ti-development/upsert-process.d.ts +2 -0
  458. package/dist/tools/ti-development/upsert-process.js +167 -0
  459. package/dist/tools/ti-development/validate-process-refs.d.ts +2 -0
  460. package/dist/tools/ti-development/validate-process-refs.js +73 -0
  461. package/dist/tools/views/create-mdx-view.d.ts +2 -0
  462. package/dist/tools/views/create-mdx-view.js +21 -0
  463. package/dist/tools/views/create-native-view.d.ts +2 -0
  464. package/dist/tools/views/create-native-view.js +81 -0
  465. package/dist/tools/views/delete-view.d.ts +2 -0
  466. package/dist/tools/views/delete-view.js +23 -0
  467. package/dist/tools/views/list-views.d.ts +2 -0
  468. package/dist/tools/views/list-views.js +32 -0
  469. package/dist/tools/with-annotations.d.ts +6 -0
  470. package/dist/tools/with-annotations.js +339 -0
  471. package/dist/types.d.ts +409 -0
  472. package/dist/types.js +91 -0
  473. package/dist/version.d.ts +4 -0
  474. package/dist/version.js +18 -0
  475. package/package.json +107 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,1211 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [6.0.0] - 2026-09-25
11
+
12
+ ### Breaking
13
+
14
+ - **Published as `@ffschrattenecker/tm1-mcp-server`.** This fork is no longer released under
15
+ the unscoped `tm1-mcp-server` npm name, which belongs to upstream (flameY3T1). Install with
16
+ `npx -y @ffschrattenecker/tm1-mcp-server`. The command is still `tm1-mcp-server`, and the
17
+ User-Agent keeps the unscoped name.
18
+ - **`tm1_set_cube_rules` preflight.** Before writing, the full resulting text (after `edits`
19
+ are applied) is checked with `tm1.CheckRules`. Any error returns `VALIDATION_ERROR` with
20
+ `stage:"preflight"`, `check:"syntax"` and `errors[]`, and nothing is written. The Rules PATCH
21
+ itself stores syntactically broken text without an error (verified on 11.8.03500), so until
22
+ now the check was only as good as the caller's discipline. `preflight:false` opts out.
23
+ - **`tm1_write_cells` refuses a `dimensions` list that does not cover the cube.** A dimension
24
+ left out used to land on its default member without an error. Verified on 11.8.03500: a
25
+ write that left out the measure dimension overwrote the value at its first element. Unknown and
26
+ duplicated names are refused too. Nothing is written in any of these cases. The one dimension
27
+ that may be left out is `Sandboxes` (added to every cube by `EnableSandboxDimension=true`).
28
+ It is now bound to `Base` explicitly, and the result says so as `sandboxDefaulted: "Base"`,
29
+ instead of relying on TM1's default member, which is `Base` only while no sandbox has
30
+ `IncludeInSandboxDimension=true`. `dimensions` may come in any order; each cell's elements
31
+ follow it. A named sandbox is addressable only once `IncludeInSandboxDimension` is true.
32
+ - **The reference check also resolves element literals in cell functions**, in both
33
+ `tm1_validate_process_refs` and the install preflight. `CellGetN/S`, `CellPutN/S`,
34
+ `CellIncrementN`, `CellIsUpdateable` and `CellPutProportionalSpread` on an existing cube: each
35
+ literal (or literal-bound) element argument is looked up in the dimension at its position. A
36
+ missing one is an issue of kind `element` with its `dimension`, and the preflight refuses the
37
+ install. Why: TI does not abort on a missing element. Verified on 11.8.03500, the process ends
38
+ `HasMinorErrors`, the rest runs, and the value is not written. The rules against false
39
+ positives were checked live:
40
+ - The lookup is TM1's own resolution: case- and space-insensitive, aliases accepted,
41
+ `'Hierarchy:Element'` read against that hierarchy.
42
+ - TI cell calls never pass the `Sandboxes` dimension, so positions skip it; a call whose
43
+ argument count doesn't match is skipped.
44
+ - Elements the same code inserts are excused. A dimension the code inserts computed names
45
+ into excuses every literal in it.
46
+ - Variables (datasource fields, parameters) are not checked and do not set `partial`.
47
+ - `DimIx`/`ElementIndex` stay existence probes.
48
+ - Lookups are capped at 200 distinct pairs per report; the rest counts as `unresolvableArgs`.
49
+
50
+ New output field `elementRefsScanned`.
51
+ - **An overwrite is refused when its backup cannot be written** (see Added). An unwritable
52
+ `TM1_PROCESS_BACKUP_DIR` used to be irrelevant to a deploy; now it fails with nothing
53
+ changed on the server. `TM1_PROCESS_BACKUP_DIR=off` restores the old behaviour.
54
+ - **The import tools replace the whole definition on an update.** `tm1_import_pro_file`,
55
+ `tm1_import_process_from_git` and `tm1_install_pro_bundle` used to skip an empty parameter
56
+ list, an empty variable layout and a `None` datasource, so the installed values stayed. The
57
+ code tabs were already replaced in full. The result was that importing an older version
58
+ of a process did not restore it. Verified on 11.8.03500 while restoring a backup: the
59
+ parameter the newer version had added was still there. On a create nothing changes.
60
+ `tm1_upsert_process` still keeps whatever the call leaves out.
61
+
62
+ ### Added
63
+
64
+ - **Automatic backup before a process is overwritten.** `tm1_upsert_process`, both import
65
+ tools and `tm1_install_pro_bundle` export the installed version as a tm1-git pair before
66
+ their first write and return the paths as `backup: { json, ti }`. Restore it with
67
+ `tm1_import_process_from_git`. Until now the only rollback copy was one the caller had
68
+ remembered to export first. Details:
69
+ - The default directory is `~/.tm1-mcp-server/backups`, split per connection and process.
70
+ Set it with `TM1_PROCESS_BACKUP_DIR`, or turn backups off with `off`.
71
+ - The directory is chosen by the server, never by the caller, which is why it is on without
72
+ `TM1_LOCAL_FILE_ROOT`.
73
+ - The code is written unmasked, because a masked backup restores placeholder literals and
74
+ fails at runtime. The ODBC password is never written.
75
+ - The backup runs after the confirm check and the preflight, so a refused call leaves no file.
76
+ - Live-tested on 11.8.03500: overwrite, then restore from the backup, gives the same export as
77
+ before the overwrite. The one difference is line endings: the import writes CRLF.
78
+
79
+ - `tm1_check_writable_coords` takes an optional `dimensions` list, resolved exactly like
80
+ `tm1_write_cells` (any order, `Sandboxes` bound to `Base`). The documented pre-write check can
81
+ then check the cell the write will address, instead of refusing the coordinates the write accepts.
82
+ - `tm1_check_cube_rule` takes the same sources as `tm1_set_cube_rules`: `rules`, `edits` or
83
+ `filePath`. A patch can be validated exactly as it would be installed, without the caller
84
+ rebuilding the whole file to check it.
85
+ - `tm1_get_server_info` returns `mcpServer: { name, version }`, the MCP server's own package
86
+ identity. A client can gate on the server version from a tool result instead of guessing it
87
+ from which schema fields exist.
88
+
89
+ ### Known issues
90
+
91
+ - `tm1_sample_cells` returns no cells on a cube with a `Sandboxes` dimension even when it holds
92
+ data (seen on 11.8.03500). Not investigated yet. Use `tm1_execute_mdx` with an explicit
93
+ `[Sandboxes].[Base]` until it is.
94
+
95
+ ### Fixed
96
+
97
+ - `tm1_invalidate_callgraph_cache` is annotated `readOnlyHint` and so is available in readonly
98
+ mode. It only drops an in-memory index and touches no TM1 object. Its description no longer
99
+ says to call it after every deploy: the server has invalidated on every mutating call since
100
+ 4.x, so the old advice cost a turn for nothing.
101
+ - The preflight's reference-failure hint no longer says "correct the name". It asks the
102
+ model to report each unresolved name to the user first. A near match (`SalesPlan` for
103
+ `'Sales Plan'`) is a different object, and swapping it in unasked is the silent
104
+ substitution the check exists to stop.
105
+
106
+ ## [5.0.0] - 2026-09-24
107
+
108
+ ### Breaking
109
+
110
+ - **Install preflight also runs the reference check, on the exact payload.**
111
+ `tm1_import_pro_file`, `tm1_import_process_from_git`, `tm1_install_pro_bundle` and now
112
+ `tm1_upsert_process` (new `preflight`, default true) run the syntax check and then the
113
+ `tm1_validate_process_refs` check before writing anything. A literal cube or dimension
114
+ name that does not exist on the server aborts the install with `VALIDATION_ERROR`
115
+ (`stage: "preflight"`, `check: "references"`, `issues[]`). Before, preflight ran the syntax
116
+ check only, and TM1 never resolves names at compile time. `upsert_process` checks the
117
+ process as it will be after the call: omitted tabs, parameters and variables keep their
118
+ installed values. `import_process_from_git` deploys the raw `.ti` blob, so it also
119
+ refuses a blob with code outside the four tab regions, or a tab region that appears
120
+ twice: that code would install without having been checked. *Action:* a deploy that
121
+ references an object its own code does not create must create the object first, or pass
122
+ `preflight: false`, which skips both checks.
123
+ - **Overwriting an installed process needs `confirm`.** `tm1_upsert_process`,
124
+ `tm1_import_pro_file` and `tm1_import_process_from_git` reject an update of an existing
125
+ process unless `confirm` repeats the process name, and nothing is written.
126
+ `tm1_install_pro_bundle` works out every file that would overwrite before the first
127
+ write, and needs `confirm` set to the directory's last path segment. `dryRun` returns the
128
+ list (`overwrites[]`) without it. Creating a new process needs no confirm. All four are
129
+ now annotated `destructiveHint: true`. `tm1_copy_process` is unchanged: TM1 refuses to
130
+ copy onto an existing name, so it never overwrites. *Action:* pass `confirm` on every
131
+ update of an existing process, or use `mode: "create"` to refuse overwrites outright.
132
+ - **`tm1_bulk_upsert_elements` needs `confirm` (the dimension name) when `components`
133
+ would remove existing children.** Components replace a consolidation's child set, so
134
+ listing `[A]` under a parent that holds `{A, B}` drops `B`. The removals are computed
135
+ before anything is written: the `$batch` create pass commits as it goes, so they could
136
+ not be computed afterwards. The call fails with `VALIDATION_ERROR` and
137
+ `details.removals[{parent, children}]` for the model to show the user. New `dryRun:
138
+ true` returns the full plan (`creates`, `updates`, `typeChanges`, `removals`) and writes
139
+ nothing. Calls whose components keep every child need no confirm. *Action:* pass
140
+ `confirm` when a removal is intended, or list the complete child set.
141
+
142
+ ### Changed
143
+
144
+ - **`tm1_validate_process_refs` reports its coverage and stops flagging legitimate
145
+ patterns.** It now returns `tabsChecked`, `unresolvableArgs` and `partial`. `partial` is
146
+ true when object names are passed as parameters or computed values, so those references
147
+ were not checked. Existence probes (`DimensionExists`, `CubeExists`, `HierarchyExists`,
148
+ `SubsetExists`, `ViewExists`) and names the same code creates (`CubeCreate`,
149
+ `DimensionCreate`) are no longer reported as unresolved, so the
150
+ `IF(DimensionExists('X') = 0); DimensionCreate('X');` pattern passes. The scan moved to a
151
+ shared core that the install tools' preflight now also runs.
152
+ - **`tm1_check_process_code` reports `tabsChecked` and `partial`.** Omitted tabs compile as
153
+ empty, so a clean result on a fragment says nothing about the tabs left out. `partial:
154
+ true` makes that visible: a validated prolog is not a validated process.
155
+
156
+ ## [4.1.0] - 2026-09-24
157
+
158
+ ### Added
159
+
160
+ - **`tm1_get_hierarchy` takes `countOnly: true`**: totals by type and level (`counts.byType`,
161
+ `counts.byLevel`, `counts.maxLevel`) with an empty `elements` array. The filters still
162
+ apply. It reads only `Type,Level` from the Elements collection, so sizing a dimension no
163
+ longer means probing with a growing `topN`.
164
+ - **`tm1_get_element_attribute_values` reads every element when `elementName` is
165
+ omitted**: a name-sorted page of `{elementName, values}` rows in the usual page envelope,
166
+ with `attributeNames` to narrow the columns. The window is pushed into the MDX row set, so
167
+ the query text stays short however large the page is. Passing `elementName` returns the
168
+ same single-element shape as before.
169
+ - **Response-size guard (`TM1_MAX_RESPONSE_CHARS`, default 80000).** A successful result
170
+ over the limit is replaced by a `RESPONSE_TOO_LARGE` error that gives the size and a
171
+ hint derived from the tool's own parameters (`offset`/`limit`, `lineRange`/`outline`,
172
+ `countOnly`, `maxBytes`). The result is never truncated. Before this, 23 recorded
173
+ results overflowed Claude Code's cap and reached the model as a file offload or nothing.
174
+ - **`tm1_get_cube_rules` has `outline` and `lineRange` modes for large rule files.**
175
+ `outline: true` returns the section markers (SKIPCHECK, FEEDERS, FEEDSTRINGS, UNDEFVALS,
176
+ and the first worded line of each comment block) with 1-based line numbers and
177
+ `lineCount`, capped at 200 entries. `lineRange: [from, to]` returns only those lines,
178
+ verbatim with no number prefixes, so a slice can be quoted back as a patch `find`. A 130 KB
179
+ rule file used to overflow the client's result cap.
180
+ - **`tm1_set_cube_rules` takes `edits` (a find/replace patch) or `filePath`** as
181
+ alternatives to the full `rules` text. Exactly one source is required. Edits apply in
182
+ order to the current rules. Each `find` must match exactly once, otherwise the call
183
+ fails with `VALIDATION_ERROR`, the match count and the matching lines, and nothing is
184
+ written. Line endings are normalized, so an LF slice from `get_cube_rules` matches CRLF
185
+ stored text. `filePath` reads a host file under `TM1_LOCAL_FILE_ROOT`. `confirm` is still
186
+ required. This removes the REST fallback that 10–16 KB rule edits needed.
187
+ - **`tm1_delete_elements`**: delete many elements of one hierarchy in one call, through
188
+ `$batch` where the server has it and per request otherwise. `confirm` is the dimension
189
+ name. It is not all-or-nothing: the result counts `deleted` and `failed` and lists each
190
+ failure with its error, and `success` is true only when every element went. It replaces
191
+ runs of 18–24 single `delete_element` calls.
192
+
193
+
194
+ ### Changed
195
+
196
+ - **`hierarchyName` defaults to the dimension name** on the 15 tools that use a hierarchy
197
+ to locate something: `get_hierarchy`, `get_ancestors`, `get_descendants`, the element and
198
+ element-attribute tools, and the subset tools. Omitting it was the most common schema
199
+ error in recorded usage. `create_hierarchy` and `delete_hierarchy` keep it required, since
200
+ there the hierarchy is the subject and the same-named one can be neither created nor
201
+ deleted on its own.
202
+ - **`tm1_update_element_attribute_value` takes `value` as a string and an `updates[]`
203
+ batch.** The value is coerced to the attribute's type on the server: a Numeric attribute
204
+ takes `"12.5"`, String and Alias attributes take the text. A bare number is still
205
+ accepted. An unknown attribute or a non-number for a Numeric one fails with
206
+ `VALIDATION_ERROR` before anything is written. `updates[]` writes many values in one
207
+ cellset PATCH, instead of one call per value.
208
+ - **A coordinate with the wrong number of elements says which dimension is missing.**
209
+ `tm1_get_cell_value`, `tm1_write_cells` and `tm1_check_writable_coords` raise
210
+ `VALIDATION_ERROR` with the cube's dimension order in the hint, the uncovered positions
211
+ in the message, and a dimension → element pairing in `details`, so a forgotten `Sandboxes`
212
+ or `Version` shows up at once. `get_cell_value` used to fail here as a "Generic TM1
213
+ error".
214
+ - Input problems in `tm1_sample_cells`, `tm1_get_cube_stats` and the file upload and delete
215
+ tools are now `VALIDATION_ERROR`s. They used to be generic errors or ad-hoc `{error}`
216
+ bodies.
217
+ - `tm1_get_file_content` defaults to `maxBytes` 64 KB (was 256 KB), so the default read
218
+ fits under the response limit.
219
+
220
+ ### Fixed
221
+
222
+ - **`tm1_delete_hierarchy` refuses a dimension's default (same-named) hierarchy.** The
223
+ description always said this could not be done. TM1 11.8 does not refuse it, though: it
224
+ answers 204 and leaves a dimension listed with no hierarchies at all (verified live).
225
+ The tool now fails with `VALIDATION_ERROR` and points to `tm1_delete_dimension`.
226
+ - **`tm1_copy_process` onto an existing target fails with `CONFLICT`** instead of a
227
+ "Generic TM1 error". TM1 already refuses the POST and leaves the target untouched
228
+ (verified live), so copy never overwrote. It now says so up front.
229
+
230
+ ## [4.0.0] - 2026-08-30
231
+
232
+ ### Breaking
233
+
234
+ - **`tm1_unload_cube` is v11-only.** v12 answers `tm1.Unload` with "Demand load,
235
+ loading and unloading of cubes is no longer supported" — the feature is gone with no
236
+ successor, so the tool is withheld rather than offered and refused. It no longer appears
237
+ in `tools/list` against v12. *Action:* branch on the server version; on v12 the call
238
+ never worked.
239
+ - **`tm1_get_audit_log`, `tm1_get_message_log` and `tm1_get_transaction_log` are
240
+ v11-only.** v12 deprecated the underlying collections in 12.0.0: they answer 200 with
241
+ nothing and have no successor endpoint. *Action:* as above.
242
+ - **`tm1_execute_chore` reports how the chore ended** instead of always answering
243
+ `{success: true}` when the HTTP call did not throw. On v12 12.5.0+ it returns
244
+ `{success, outcome, choreErrorStatus, errorLogFile}`. *Action:* a chore whose step failed
245
+ now surfaces as a failure; callers that treated every response as success must branch on
246
+ `outcome`.
247
+ - **`oDBCConnection` removed from the datasource model.** TM1 has no such field — it was
248
+ always `undefined`. *Action:* none.
249
+ - **`lockType` removed from the thread shape.** No v11 thread ever carried it. *Action:*
250
+ none.
251
+
252
+ ### Added
253
+
254
+ - `tm1_get_process_variables` and `tm1_get_process` report `ignoredColumns` — the
255
+ datasource columns a process ignores. They live only in `VariablesUIData`, which no
256
+ version declares, so a plain GET never returned them and the tools read the process as if
257
+ those columns did not exist. Carried through `tm1_copy_process`, both diff tools, and the
258
+ `.pro` and Git round trips.
259
+ - `tm1_list_dimensions` publishes `lastUpdated` with `includeLastUpdated: true`.
260
+
261
+ ### Fixed
262
+
263
+ - **`tm1_get_cell_value` no longer reports a non-existent coordinate as an empty cell.**
264
+ The MDX selects exactly one member, so an empty cell arrives as a cell with a null
265
+ `Value`; an empty *cellset* means a member did not resolve. v11 refuses such an MDX, but
266
+ v12 answers 200 with no cells and the service returned `{value: null}` — a typo in an
267
+ element name read as "this cell is empty". Both versions now raise `NOT_FOUND` naming the
268
+ cube and coordinate.
269
+ - **`tm1_clear_cube` clears a whole cube on v12 again.** `tm1.Clear` was taken for the v12
270
+ route; measured against a real cube, neither 11.8 nor 12.5 resolves it and neither
271
+ declares a clear action in `$metadata`. A full clear now runs `CubeClearData()` through an
272
+ ephemeral TI on both versions. A partial clear needs `tm1.Clear`, which no reachable
273
+ server offers, and now fails fast with `UNSUPPORTED_OPERATION` and the bedrock pointer.
274
+ - **`DataSource.usesUnicode` was discarded on the version that supports it.** It was
275
+ dropped on v11 as "v12-only" and sent on v12 — backwards. TM1 validates datasource
276
+ properties per *source type*: 11.8 rejects it for ASCII, accepts it for ODBC, returns it
277
+ from a plain GET and writes it to `.pro` line 559; 12.5 never returns it at all. The gate
278
+ is now `type === "ODBC"`.
279
+ - **`.pro` round trips no longer lose the ODBC unicode setting.** Line 559 was omitted as
280
+ carrying "no portable information" while a REST-created process defaults to `559,1`, so
281
+ export + import silently turned unicode on.
282
+ - **The naming audit's TAB prefilter never matched anything.** The clause carried the
283
+ literal text `%09`, and its only caller runs the filter through `encodeURIComponent()` —
284
+ so `%2509` went out and the server searched for three characters no name contains. Every
285
+ tab-containing element was invisible to `tm1_audit_naming`.
286
+ - **Anonymous sessions no longer break `tm1_list_sessions`.** `GET /Sessions` returns
287
+ `User: null` for a session with no signed-in user; the response type and the recorded
288
+ wire contract both admitted only an object.
289
+ - **`errorLogFile` was never filled in** — the execute calls omitted the `$expand`, so the
290
+ filename was always absent on both versions.
291
+
292
+ ### Changed
293
+
294
+ - **`tm1_audit_naming` flags TAB in element names on every version, not only v12.** The
295
+ v12 gate rested on Planning Analytics 3.1 reserving TAB as the name/alias separator, which
296
+ neither 11.8 nor 12.5 demonstrates: the name round-trips verbatim, no alias appears, and
297
+ MDX addresses it like any other element. TAB stays a bad character regardless — invisible
298
+ in UIs, ambiguous against other whitespace, a field separator in TI and CSV round trips.
299
+ No naming rule differs by version now, so `versionOverride` sets only the reported
300
+ `appliedMajor`.
301
+ - Two descriptions corrected: `tm1_execute_chore` and `tm1_create_chore` described chore
302
+ exit codes and `ExecutionMode` in terms that did not match measured behaviour.
303
+
304
+ ### Removed
305
+
306
+ - `maskSecrets` on `tm1_get_process_datasource`. Its only job was masking, which is now
307
+ unconditional. Callers still passing it are unaffected — unknown input keys are dropped.
308
+
309
+ ### Internal
310
+
311
+ No client-visible change: tool metadata now lives in exactly one place per tool
312
+ (`defineTool()`, both metadata maps deleted); each wire shape is defined once and its
313
+ TypeScript type derived; Markdown tables name their fields via `columnsOf()` instead of
314
+ restating them; two spent codemods deleted and `BatchService`'s scope recorded.
315
+
316
+ ## [3.1.0] - 2026-08-18
317
+
318
+ ### Changed
319
+
320
+ - **`includeDataSourcePassword` is v12-only; on v11 both export tools now refuse it.** The
321
+ credential the v11 REST API hands out is scoped to one *run* of one server, not to the server.
322
+ Measured against 11.8.02900.8 across two service restarts: the same cleartext produced three
323
+ different values, and a value carried across a restart aborts the process at connect time with
324
+ `Unable to open data source` — on the `.pro` path and the git path alike, with the same file
325
+ working again once `dataSourcePassword` supplies the password. Nothing fixes that from this side,
326
+ because the durable form (slot 565 of TM1's own Datadir `.pro`) is never exposed over REST.
327
+
328
+ So on v11 the flag could only carry a credential through a window in which `tm1_copy_process`
329
+ would have worked anyway, and outside that window it failed with no visible sign — the exported
330
+ file still looks complete. It now refuses and names the two paths that do work: `tm1_copy_process`
331
+ to clone a process with its password inside one instance, `dataSourcePassword` to deploy anywhere
332
+ else or later. On v12 the exported value is the plain password, which has no such lifetime, so the
333
+ flag stays — still opt-in and still requiring a file target, so the credential never enters the
334
+ response.
335
+
336
+ - **Corrected what the `.pro` tools claim about passwords.** `tm1_import_pro_file` documented that a
337
+ password "is never read from the file", which is wrong: slot 565 *is* read from files written by
338
+ `tm1_export_process_to_pro`, and that is how a password survives an export/import round trip —
339
+ measured end to end against 11.8, including a negative control (same file with slot 565 removed
340
+ aborts on connect). What is ignored is slot 565 in TM1's *own* Datadir `.pro` files, which use a
341
+ different, non-deterministic encoding that cannot be replayed over REST.
342
+
343
+ `tm1_export_process_to_pro` now also states that its output is not a Datadir drop-in. TM1 does
344
+ load such a file at startup and rewrites it in its own dialect, but it decodes slot 565 with its
345
+ own scheme: an exported password becomes garbage that TM1 then persists, leaving a process that
346
+ looks configured and fails at runtime.
347
+
348
+ - **`tm1_write_cells` writes a whole batch in three requests instead of three per cell.** Each cell
349
+ had its own cellset, PATCH and delete — 120 requests for 40 cells, measured. TM1py (and tm1npm,
350
+ which ports it) build one cellset over every target coordinate and PATCH the cell array once;
351
+ verified against 11.8 at **40 cells in 3 requests, 9 ms**, values read back correct.
352
+
353
+ Behaviour changes on failure: TM1 refuses a batch containing a non-writable cell **whole**, so
354
+ nothing in it lands — where the old per-cell loop committed the cells before the offender. The
355
+ error names only a status code, so the failing batch is then re-walked cell by cell to identify
356
+ the coordinate and restore the `written`/`failed`/`notAttempted` report. That costs what the old
357
+ implementation always cost, but only when a write is refused.
358
+
359
+ - **`tm1_get_hierarchy` reads edge weights from the elements, and filters by type server-side.**
360
+ Weights came from the hierarchy's entire `Edges` collection — 21.6 MB and 594 ms for a
361
+ 171k-element dimension, in a second round trip. `Element` has an `Edges` navigation carrying its
362
+ own outgoing edges, so the page that fetches the elements now brings their weights with it: one
363
+ request, and bounded by the page's fan-out rather than by the dimension.
364
+
365
+ `elementType` also stopped being a client-side filter. It pushes down as the ordinal
366
+ (`Type eq 3`); the name form is accepted by TM1 and matches nothing, silently, which is why it
367
+ had been left to the client. A consolidated page of a 171k-element dimension went from fetching
368
+ the whole dimension to **410 KB in one request**.
369
+
370
+ - **`tm1_audit_naming` checks element names on the server, and now checks all of them.** The audit
371
+ downloaded every element name of every dimension — 15.2 MB for a single 171k-element dimension,
372
+ 66 MB across a real model — and stopped at `maxElementsPerDim`, beyond which it examined only a
373
+ prefix. Every element rule is character-based, and TM1 implements the OData functions they need,
374
+ so the server does the narrowing and returns only candidates: **66 MB → 400 KB** on that model,
375
+ while the elements examined went from a 100k cap to **1,280,396**, surfacing 64 violations.
376
+
377
+ `maxElementsPerDim` now bounds how many offenders are REPORTED, not how many elements are
378
+ checked, and `scanned.elements` counts what the server examined. The filter is a prefilter only —
379
+ the same `checkName` still decides on every candidate — and its soundness is asserted live: the
380
+ suite plants an element whose name contains a reserved character and requires the audit to find
381
+ it, on v11 and v12.
382
+
383
+ - **`tm1_audit_complexity` issues one request instead of one per process.** The consistency scan
384
+ listed every process, then asked each one for its variables — 221 extra round trips on a
385
+ 221-process model, measured. `Variables` is a complex-typed property, so the process list can
386
+ carry it: `$select=Name,Variables` answers for the whole model at once. 225 requests → 5, and
387
+ 3.4 s → 94 ms on that model. Output is unchanged.
388
+
389
+ - **`tm1_audit_feeders` takes cube dimensions off the bulk rules request.** The static scan needs
390
+ each cube's dimension order to score how broadly a feeder is pinned, and asked for it one cube at
391
+ a time — a GET per rule-bearing cube on top of the bulk rules query. The same request can expand
392
+ them: `$select=Name,Rules&$expand=Dimensions($select=Name)`. Measured on 11.8 against a 12-cube
393
+ model, **18 requests → 11**, with the seven per-cube lookups gone and the report identical. The
394
+ expansion is opt-in, so callers that only read rules text still pay nothing for it. A server that
395
+ answers without the expansion still falls back to the per-cube lookup, because a missing
396
+ dimension list would quietly change every ratio the scan computes.
397
+
398
+ ### Added
399
+
400
+ - **`includeDataSourcePassword` on both export tools carries the ODBC password.** Off by default,
401
+ and it requires `writeToFile`/`writeToDir`, so the credential goes to a file and never into the
402
+ response the model sees. `.pro` writes it to slot 565, the Git `.json` keeps the `password` field
403
+ and reports `credentialsOmitted: false`. Verified against 11.8: export a process, delete it,
404
+ re-import, and the stored credential is bit-identical (`W0br6scX06nUHxVZQrQC+g==` before and
405
+ after) — TM1 recognises its own ciphertext and stores it unchanged rather than encrypting it a
406
+ second time.
407
+
408
+ What it is worth depends on the target, and both facts were measured, not assumed. On 11.8 the
409
+ value is a ciphertext **bound to one server**: the same plain text yields
410
+ `W0br6scX06nUHxVZQrQC+g==` on one instance and `5QUCtEDCEjECPJ1HIYDlVQ==` on another, so it
411
+ restores a process on its own instance but is useless for moving one elsewhere — for that, supply
412
+ the plain password via `dataSourcePassword` on import. On v12 the API returns the password **in
413
+ plain text**, so an exported file there holds a usable credential; both tools say so in their
414
+ descriptions. Without the flag nothing changes: the datasource still carries only a `[redacted]`
415
+ marker, and that marker is now kept out of the file as well.
416
+
417
+ - **`tm1_import_pro_file` takes a `dataSourcePassword`.** A `.pro` stores the ODBC password only as
418
+ a server-encrypted blob, so an imported ODBC process arrived with its DSN, user and query but no
419
+ credential, and there was no way to supply one in the same call — `tm1_import_process_from_git`
420
+ already had that parameter. Measured on a real model: of 30 ODBC processes, 29 connect through a
421
+ registered DSN plus credentials and none through a connection string, so the password is the only
422
+ piece of the connection that a `.pro` cannot carry.
423
+
424
+ ### Fixed
425
+
426
+ - **`.pro` export and import lost the ODBC query, the datasource name and the subset.** Three line
427
+ codes were wrong or missing, so `tm1_export_process_to_pro` wrote files without the SQL and
428
+ `tm1_import_pro_file` silently deployed processes whose datasource had lost its target. The codes
429
+ were pinned two ways: by scanning 1001 `.pro` files written by TM1 11.8 (30 of them ODBC) and by a
430
+ write probe — create a process over REST with marker values, then read the file TM1 wrote back.
431
+
432
+ - The ODBC query lives in `566,<n>` followed by `n` lines. Every ODBC file carries that header,
433
+ every non-ODBC file carries `566,0`. It was neither written nor read; the largest query in the
434
+ scanned corpus is 26 lines.
435
+ - `586` is `DataSourceNameForServer` and `585` is `DataSourceNameForClient` — the serializer wrote
436
+ the server name into `585` and the parser read it from there. In files TM1 wrote, `585` is
437
+ frequently empty, so importing a real `.pro` lost the cube name or file path outright. This hit
438
+ every datasource type, not just ODBC.
439
+ - The subset name is `571`; `570` holds view names. The parser read subsets from `570` and
440
+ therefore never found one.
441
+
442
+ Variable byte offsets (`580`/`581`) were not written either, which makes an exported fixed-width
443
+ process unusable — those offsets *are* the column layout. They now round-trip; TM1 writes zeros
444
+ for delimited sources and those are dropped again on read.
445
+
446
+ Three more mismatches surfaced from write probes over the remaining datasource variants:
447
+ a fixed-width ASCII source is its own `.pro` type (`562,"POSITIONDELIMITED"`, not a flag on
448
+ `CHARACTERDELIMITED`) and parsed as *no datasource at all*; view and subset names are written
449
+ unquoted, so TM1 stores `570,Ansicht, mit "Komma"` verbatim; and `585` stays empty when no client
450
+ name is set instead of repeating the server name.
451
+
452
+ Both directions now use TM1's codes, including the line counts on the code sections (`572,138`),
453
+ which keeps TI code that looks like a header line inside its section. Files written by earlier
454
+ versions still parse — `585` and a subset in `570` are accepted as fallbacks. The encrypted
455
+ password blob (`565`) stays out of the export by design. Verified end to end against 11.8: export
456
+ a process with a three-line query, delete it, re-import from the `.pro`, and the query, server and
457
+ client names come back byte-identical; all 1001 corpus files parse without error.
458
+
459
+ - **`tm1_bulk_upsert_elements` dropped consolidation weights.** The single-element tools were fixed
460
+ for this in the same release; the bulk path — the one that actually builds hierarchies — was
461
+ missed, and it is the more consequential of the two. TM1 accepts `Weight` inside the `Components`
462
+ link payload and ignores it, so every edge landed at 1 no matter what was asked for. Verified by
463
+ driving the tool against 11.8: a component asked for at `-1` read back as `+1`, and the
464
+ consolidation then added where it was supposed to subtract — wrong numbers, no error anywhere.
465
+ Both write paths (`$batch` and the per-request fallback) now PATCH the deviating weights onto the
466
+ Edge entity once the links exist. Weights of 1 cost nothing, as before. Re-measured after the
467
+ fix: `Q1 = Jan + Feb − Mar` returns 25 for 10/20/5, where it returned 35 before.
468
+
469
+ - **A TM1 error body could put a non-string into the error `details` field.** The message was read
470
+ as `error.message.value ?? error.message ?? raw`, so a body whose `message` was an object without
471
+ a `value` handed that object to a field typed as a string. Both shapes are now read explicitly
472
+ and anything else falls back to the raw body. Found by turning on the `no-unsafe-*` lint rules
473
+ for `src/`, which are now errors: every one of the 25 sites they flagged was unvalidated server
474
+ data being read as if it had a type.
475
+
476
+ - **`tm1_set_cube_rules` took a `skipCheck` parameter that did nothing.** It was accepted,
477
+ defaulted to `true`, forwarded to a service argument that was never read, and echoed back in the
478
+ success payload — so a caller was told it had switched something on. SKIPCHECK is a line inside
479
+ the rules text and nothing else; there is no separate switch. The parameter is gone, and the
480
+ tool description no longer claims the rules text *must* contain SKIPCHECK — it explains what the
481
+ line does instead. Passing `skipCheck` now has the same effect it always had: none.
482
+
483
+ - **`tm1_get_cube_stats` fanned out without a limit.** A batch of cube names issued one
484
+ `}StatsByCube` MDX per cube, all at once, bounded only by how many names the caller sent. It now
485
+ runs at most ten in flight — the same width `tm1_audit_feeders` uses for the identical call —
486
+ and `cubeNames` accepts at most 500 entries.
487
+
488
+ - **`.env.example` advertised a request timeout the code does not use.** It showed
489
+ `TM1_REQUEST_TIMEOUT=600000` while the built-in default is `30000`, so anyone copying the file
490
+ as a starting point expected ten minutes and got thirty seconds. It now shows the real default,
491
+ with a note about which readers justify raising it.
492
+
493
+ - **`tm1_upsert_process` could create an ODBC data source but not its SQL.** The tool carried its
494
+ own copy of the data-source schema, and that copy had drifted from the shared one: no `query`,
495
+ no `oDBCConnection`, no `usesUnicode`. Because the schema is strict, passing `query` was rejected
496
+ outright — while `tm1_get_process_datasource` read it back happily, and the git round-trip
497
+ schema had it all along. The tool now uses the shared schema, so what can be read can be written.
498
+
499
+ - **`tm1_diff_processes` and `tm1_diff_process_with_file` ignored the ODBC query.** Two processes
500
+ differing only in their SQL were reported identical. Both now compare `query` and
501
+ `oDBCConnection`; `password` stays out of the comparison, since both sides read back redacted
502
+ and could only produce noise.
503
+
504
+ - **Consolidation weights were silently dropped on write.** `tm1_create_element`,
505
+ `tm1_update_element` and `tm1_move_element` sent `Weight` inside the `Components` link payload.
506
+ TM1 accepts that body and ignores the field: the edge is created with weight 1 whatever was
507
+ asked for. Verified live — a consolidation created with weight -1 read back as 1 from the Edges
508
+ collection itself, so nothing downstream could have recovered the intent.
509
+
510
+ A dropped -1 is not cosmetic: it is the weight that nets costs against revenue, and turning it
511
+ into +1 inverts the consolidation. The weight lives on the Edge entity and is now PATCHed there
512
+ once the link exists — only for weights that differ from the default, so an all-1 consolidation
513
+ costs no extra request.
514
+
515
+ - **`format: "markdown"` now reaches clients that read `structuredContent`.**
516
+ The rendered table went out in `content[0].text` while `structuredContent` carried the JSON
517
+ payload. Claude Code discards `content` whenever `structuredContent` is present, so the table
518
+ never arrived and the caller got the JSON it had asked not to get — a silent no-op across all
519
+ 34 tools that take `format`.
520
+
521
+ Markdown responses now send the table both ways: as the text block (for clients like Kiro) and
522
+ as `structuredContent: { markdown }`. The JSON payload is omitted in that mode.
523
+
524
+ This widens the published `outputSchema` of those 34 tools — top-level fields become optional,
525
+ plus an optional `markdown` — because the MCP SDK cannot express "either shape" (a `z.union`
526
+ outputSchema makes it publish no schema at all). Responses are still validated strictly: the
527
+ server selects the matching strict shape per response. Net effect on `tools/list` is 1.3 KB
528
+ smaller, since the dropped `required` arrays outweigh the added property.
529
+
530
+ New gate `npm run lint:markdown-schema` fails the build when a tool accepts `format` without a
531
+ schema that can carry the table.
532
+
533
+ ## [3.0.1] - 2026-08-10
534
+
535
+ ### Fixed
536
+
537
+ - **`TM1_RESPONSE_MODE` defaults back to `legacy` — results ship `content[0].text` again.**
538
+ The 3.0.0 default dropped the text block, which blanks every tool call on clients that read
539
+ `content[]` and ignore `structuredContent` (Kiro's IDE; verified live). No handshake field
540
+ identifies them, so the default has to be the shape all clients can read.
541
+
542
+ Its 52% saving was measured on the wire, not in context: Claude Code discards `content` whenever
543
+ `structuredContent` is present, so both-ways costs one copy. Real only for clients that serialize
544
+ the whole `CallToolResult` into the prompt — `TM1_RESPONSE_MODE=structured` still serves those,
545
+ and is no longer deprecated.
546
+
547
+ ## [3.0.0] - 2026-08-09
548
+
549
+ ### Security
550
+
551
+ - **Credential masking moved onto the error path.** pino's key-based `redact` masks a field _named_
552
+ `password`, never a credential inside a message string — which is exactly what TM1 returns on an
553
+ ODBC failure (`login failed for PWD=hunter2`). `classifyHttpError` now sanitizes the server's
554
+ text where it enters the error model, covering both the log and the client exit.
555
+
556
+ - **ODBC masking is grammar-aware.** The old `[^;]+` value pattern stopped at the first inner `;`,
557
+ masking `{abc` and leaving `def};` behind — a partial leak that _looked_ masked. Brace-quoted
558
+ values are now matched whole.
559
+
560
+ - **`maskSecrets: false` requires operator consent.** The parameter let the **model** switch off a
561
+ security control. It is now ignored unless `TM1_ALLOW_UNMASKED_SECRETS=true`; the default masks
562
+ anyway rather than failing. Affects all eleven tools exposing it.
563
+
564
+ - **Confirmation guards extended beyond deletes** to `tm1_execute_process`, `tm1_execute_chore`,
565
+ `tm1_write_cells`, `tm1_set_cube_rules` and `tm1_upload_file` — irreversible writes and TI
566
+ side-effects previously sat outside a guard that only covered object destruction. **Breaking:**
567
+ these five now require `confirm`. Misuse protection, not access control.
568
+
569
+ - **Positioning documented (README).** One TM1 identity per process; the HTTP transport is
570
+ single-tenant and its bearer token authenticates the endpoint, not a caller; `readwrite` with an
571
+ admin account is a developer configuration. Stated so nobody infers an isolation boundary that
572
+ does not exist.
573
+
574
+ - **`fast-uri` override raised to `^3.1.5`, `ip-address` pinned to `^10.4.0`.** Both ship to
575
+ consumers as runtime dependencies via `@modelcontextprotocol/sdk`. GHSA-7p8r-x3mc-p8w7 grew past
576
+ the `^3.1.4` override shipped in 2.1.0, which silently stopped being sufficient; `ip-address`
577
+ `<=10.3.0` carries GHSA-4xrf-jv44-h6hh and GHSA-22jq-vg5j-6vgg (misclassification that can
578
+ bypass SSRF checks). Neither override is a semver escape. The CI gate
579
+ `npm audit --omit=dev --audit-level=high` went from exit 1 to exit 0.
580
+
581
+ ### Changed — BREAKING
582
+
583
+ - **Successful tool results no longer ship their payload twice; `structured` is the new default.**
584
+ Every tool declares an `outputSchema`, so the payload was parsed into `structuredContent` _and_
585
+ left in `content[0].text`. Measured: **13898 B → 6612 B, a 52% cut.** Spec-legal, since
586
+ `CallToolResult.content` may be empty when an `outputSchema` is declared.
587
+
588
+ **Breaking for clients that read `content[0].text` and ignore `structuredContent`** — set
589
+ `TM1_RESPONSE_MODE=legacy` to restore the old wire format. Verified against Claude Code.
590
+ `legacy` is **deprecated** and will be removed in a future major; it exists only as a
591
+ transitional escape hatch.
592
+ Unaffected: `format: "markdown"` and error results.
593
+
594
+ - **A TI result now says whether the run committed.** `ExecuteWithReturn` answers HTTP 200 whatever
595
+ happened, so the outcome lives entirely in `ProcessExecuteStatusCode` — and a missing field
596
+ defaulted to success. Results now carry an `outcome` over all six codes, grouped by commit
597
+ semantics measured live on v11 11.8 and v12 12.5.9:
598
+
599
+ - `succeeded` — `CompletedSuccessfully`
600
+ - `completed_with_errors` — `CompletedWithMessages`, `QuitCalled`, `HasMinorErrors`. **Changes
601
+ WERE committed; a blind retry can double-post them.**
602
+ - `rolled_back` — `Aborted`, `RollbackCalled`. Nothing committed.
603
+ - `indeterminate` — no status code, an unknown code, or a call that errored mid-run.
604
+
605
+ `ProcessResult` is a discriminated union, so `{success: true, processErrorStatus: "Aborted"}` no
606
+ longer typechecks. Note that `succeeded` is not proof the process reached its intended end —
607
+ `ProcessBreak` also reports `CompletedSuccessfully` (verified live).
608
+
609
+ **Breaking** for `tm1_execute_process` and `tm1_save_data`: new required `outcome` field, and only
610
+ `succeeded` keeps `success: true`, so a status-less response now yields `success: false` with
611
+ `isError`. Real servers always send the field, so that is the defensive branch.
612
+ `tm1_clear_cube` shares the classifier: a rolled-back or unconfirmed clear raises, a
613
+ committed-with-messages clear stands.
614
+
615
+ ### Changed
616
+
617
+ - **The unbounded escape hatches are now bounded.** `fetchAll` and `limit=0` opt out of the page
618
+ _size_, not of every limit — a 200k-element dimension serialized 200k rows into one response.
619
+ `paginate()` caps them at 5000 and reports the rest via `has_more`/`next_offset`, so a capped
620
+ call is just a first page. Also: `tm1_get_hierarchy.topN` ceiling 10000,
621
+ `tm1_analyze_object_usage` without `limit` is bounded bulk, and `tm1_trace_data_flow` — which had
622
+ no limit at all — gains 500 per direction with `counts` left unclipped.
623
+
624
+ - **`tm1_audit_complexity` fans out its per-process reads.** The `consistency` scope is in the
625
+ default scope set and walked one `getVariables` round-trip per process serially — 276ms
626
+ estimated vs 84ms measured on a 92-process model. Now 8 in flight. Order and fail-fast
627
+ behaviour unchanged.
628
+
629
+ - **Annotations: irreversible overwrites now declare `destructiveHint: true`.** The taxonomy meant
630
+ "deletes an object", so full-replacement writes advertised `false` and a client's
631
+ confirm-before-destructive prompt never fired. `tm1_write_cells` is now `DESTRUCTIVE`;
632
+ `tm1_set_cube_rules` and `tm1_bulk_upsert_elements` use a new `IDEMPOTENT_DESTRUCTIVE` class —
633
+ the two properties are orthogonal. No `readOnlyHint` changed, so `TM1_MODE=readonly` exposes the
634
+ same tools as before.
635
+
636
+ - **`tm1_bulk_upsert_elements` folds its element writes into OData `$batch`.** N elements now cost
637
+ four batched passes (create, type-probe, type-patch, components) instead of N round-trips.
638
+ Servers without a usable `$batch` fall back transparently; inputs, outputs and error behaviour
639
+ are unchanged. Live-validated against v11 11.8 and v12 / Planning Analytics Engine 12.5.9.
640
+
641
+ - **`ViewService.list()` queries the public and private scopes in parallel.** Result order and
642
+ error handling unchanged. MDX stays in the `$select` — `tm1_list_views` advertises it, so
643
+ dropping it would be a breaking output change, not an optimisation.
644
+
645
+ - **CI now runs `npm run lint:format`.** `verify` already ran `prettier --check`, so the local gate
646
+ was stricter than the one guarding main while the README claimed they matched.
647
+
648
+ - **`docs/ARCHITECTURE.md` service-conventions table corrected.** The version-branch idiom is
649
+ `this.http.version === 11`, not the pre-v12 `tm1Version.startsWith("11")`, and the "services hold
650
+ no state" row now names `BatchService` as the deliberate exception.
651
+
652
+ ### Fixed
653
+
654
+ - **"This server keeps no statistics" no longer reads as "your model is broken".** TM1 v12 ships no
655
+ `}Stats*` control cubes (measured on 12.5.9: only security and element-attribute ones), so the
656
+ shared `}StatsByCube` fetcher handed the model a raw OData error and the user read it as a broken
657
+ model. The failure is now classified once, for both callers, keeping two cases apart: `absent`
658
+ (no statistics cubes here) versus `denied` (they exist, this account may not read them — TM1
659
+ answers that with HTTP 400 `ObjectSecurityNoReadRights`, not 403).
660
+
661
+ The classification is **structural, and reads no error text**. The same condition is worded three
662
+ ways across this project's own servers — `'}StatsByCube' can not be found in collection of type
663
+ 'Cube'` (v11 en), `There is no cube named "}StatsByCube".` (v12), and
664
+ `Syntaxfehler bei oder in der Nähe von: …` (v11 on a German locale) — so a matcher over prose is
665
+ correct only on the machine it was written against and fails silently everywhere else. Instead
666
+ the denial is recognised by its untranslated identifier, and absence is answered by asking the
667
+ server: new `CubeService.exists()` (`GET Cubes('}StatsByCube')?$select=Name`, 404 → false), run
668
+ once per connection and only on the failure path. A 200 means the statistics cube is fine and
669
+ this one query was not, so the original error propagates untouched — a missing *user* cube stays
670
+ a per-cube error.
671
+
672
+ `tm1_get_cube_stats` returns `statsUnavailable {reason, message}` alongside its items;
673
+ `tm1_audit_feeders` returns `runtimeUnavailable` and still delivers the static findings in
674
+ `mode: "both"`. `mode: "static"` never touched the cube and is unchanged.
675
+
676
+ - **The callgraph's four-variant OData fallback no longer swallows the real error.**
677
+ `fetchForCallgraph()` caught _everything_, so an expired session, a timeout or a denial each
678
+ bought three more full `/Processes` scans — about `4 × 30 s` — and a later shape that answered
679
+ masked the first failure. Systemic failures and denials now surface immediately; only TM1
680
+ refusing the query _shape_ (400/501) advances, and the working shape is cached per connection.
681
+
682
+ - **A permission denial no longer reads as "this cube has no views".** `ViewService.list()` caught
683
+ every per-scope error and returned an empty list, making "you may not see them" indistinguishable
684
+ from "there are none". Denials propagate; a genuinely absent scope (404 on `/PrivateViews`) is
685
+ still skipped.
686
+
687
+ - **`$batch` chunks are bounded by payload size, not just request count.** 200 sub-requests with
688
+ long element names run to megabytes while the counter is still under its cap, and a body past a
689
+ proxy's limit (nginx defaults to 1 MiB) returns 400/413 — which the service read as "no `$batch`
690
+ here". A chunk now closes at whichever bound comes first, measured in UTF-8 bytes. An
691
+ over-budget single request is sent alone rather than dropped. Chunks stay serial.
692
+
693
+ - **An ambiguous first `$batch` 400 is settled by a counter-probe.** A gateway that does not route
694
+ the endpoint and a payload TM1 refuses both answer 400; reading the second as the first pinned
695
+ the connection to "no `$batch`" for the whole session. On a 400, while no batch has yet
696
+ succeeded and at most once per connection, one minimal envelope is sent: readable means `$batch`
697
+ works, so the connection is marked supported and the original error propagates unretried.
698
+ Verified live — v12 rejects duplicate sub-request ids with exactly this 400. Only 400 is probed;
699
+ 404/405/501 concern a constant URL and method, 403 an identity the probe shares, and a 500 can
700
+ follow a partial commit where the replay-safe fallback is correct.
701
+
702
+ - **A failed element-type lookup is no longer cached forever.** The feeder audit's type cache
703
+ stored `null` on any error with no TTL, so one transient timeout marked a whole dimension "type
704
+ unknown" for the rest of the run. Failures now retry, bounded at three consecutive ones per
705
+ dimension — unbounded retry would be worse, since a security denial (HTTP 400
706
+ `ObjectSecurityNoReadRights`) is deterministic and the lookup runs once per feeder entry. The
707
+ read also moved to `$select=Name,Type`, dropping an `$expand=Parents` and Edges scan.
708
+
709
+ - **HTTP transport no longer leaks a listener per request.** Each request builds a fresh
710
+ `McpServer` that attaches a `SubscriptionRegistry` listener to the process-global `tm1Events`
711
+ emitter, and `server.close()` cannot detach it — so every TM1 mutation fanned out across all
712
+ historical registries. `buildMcpServer` now returns `{server, dispose}` and every teardown path
713
+ calls it.
714
+
715
+ - **The callgraph cache can no longer publish a pre-mutation index.**
716
+ `invalidateCallgraphCache()` could not reach a build already in flight, which then wrote its
717
+ stale snapshot back with a fresh timestamp and served it for a full 60s TTL. Builds now capture
718
+ a generation counter and refuse to publish if an invalidation happened while they ran.
719
+
720
+ - **`tm1_sample_cells` no longer reports `truncated: true` for an exact-size result.** It asks for
721
+ one cell more than requested and decides from that sentinel instead of inferring from a full
722
+ page; the extra row is dropped, so the response contract is unchanged.
723
+
724
+ - **Timestamp inputs are validated instead of decorated.** `since`/`until` got a bare `"Z"`
725
+ appended to whatever arrived, so `"yesterday"` became `"yesterdayZ"` in an OData `$filter` and
726
+ TM1 answered with a parse error naming neither parameter nor value. Now checked against ISO-8601;
727
+ ambiguous locale formats like `08/06/2026` are rejected rather than silently read as 6 August.
728
+
729
+
730
+ ## [2.1.0] - 2026-07-26
731
+
732
+ ### Security
733
+
734
+ - **`fast-uri` pinned to `^3.1.4` via `overrides`.** GHSA-v2hh-gcrm-f6hx and GHSA-4c8g-83qw-93j6
735
+ (host confusion via a literal backslash authority delimiter, and via failed IDN canonicalization)
736
+ affect `fast-uri` 3.0.0–3.1.3. It reaches us as a *runtime* dependency through
737
+ `@modelcontextprotocol/sdk` → `ajv`, so it ships to consumers rather than being a dev-only
738
+ advisory. The patched 3.1.4 sits inside `ajv`'s own `^3.0.1` range, so the override is not a
739
+ semver escape. No SDK release carries the fix yet — 1.29.0 is current.
740
+
741
+ ### Added
742
+
743
+ - **Coverage ratchet gate** (`npm run coverage:check`, wired into `npm run verify` and CI).
744
+ Coverage floors moved out of `vitest.config.ts` into `coverage-thresholds.json` — one source
745
+ of truth read by both `vitest` (hard thresholds) and the new
746
+ `scripts/check-coverage-ratchet.mjs`. The gate fails in **both** directions: below the floor,
747
+ and more than `slack` (5) points above it, printing the exact JSON to raise the floor with.
748
+ This closes a 40-point blind spot — the floors said 22% while real coverage had already grown
749
+ past 65%, so a large regression could have landed green. Floors baselined at the measured
750
+ level minus 2 points (lines 63 / statements 62 / functions 55 / branches 52); informational
751
+ targets 75/75/70/62. Coverage reporters switched to `text-summary` + `json-summary` + `html`,
752
+ and `**/*.d.ts` is excluded from the measured set. See "Coverage Policy" in the README.
753
+
754
+ - **`tm1_get_hierarchy` is now pageable — `offset`, plus `total`/`has_more` in the response.**
755
+ Large dimensions were unreachable past `topN`: the tool capped at 1000 elements with no way to
756
+ ask for the next 1000, so the only route to element 1001 was raising `topN` and pulling the
757
+ whole set into the context window. `offset` walks the dimension in pages of any size, and
758
+ `total` reports the filtered element count so a client knows when to stop. Measured on a live
759
+ 211,852-element dimension: 46.7KB per 50-element page against 915.9KB for the old `topN=1000`
760
+ default and 67MB for the uncapped fetch. `truncated` keeps its meaning but is now exact — it
761
+ was derived from `elements.length === topN`, which cried truncation whenever the last page
762
+ happened to be exactly `topN` long.
763
+
764
+ ### Changed
765
+
766
+ - **`list_*` tools push `$top`/`$skip` down to TM1 instead of fetching the whole collection and
767
+ slicing it in-process.** This does not change what an agent sees — the `Page<T>` envelope, the
768
+ `limit=50` default and every field are identical — it changes what crosses the TM1→MCP hop.
769
+ Measured live at `limit=50`: `tm1_list_dimensions` with `includeElementStats` 213MB → 98MB
770
+ (340-dimension model; the pathological single JSON string that response used to be is the point
771
+ of the change, not the milliseconds), `tm1_list_processes` 180.6KB → 15.4KB, `tm1_list_cubes`
772
+ 49.3KB → 13.5KB.
773
+ - Push-down happens automatically, but only where it is *correct*: `@odata.count` counts rows
774
+ after `$filter`, so a filter that cannot be expressed in OData (`nameRegex`, `excludePattern`,
775
+ `changedSince`) would make `total` count rows the caller can never reach and `has_more`
776
+ promise pages that come back empty. Those requests — plus `fetchAll` and `limit=0` — fall back
777
+ to the previous full-scan behaviour. Server-expressible filters (`includeControl`, `nameExact`,
778
+ `nameContains`, `nameNotContains`) move into `$filter`.
779
+ - Every pushed-down request carries `$orderby=Name`. `$skip` without a sort is undefined in
780
+ OData and TM1 answers in internal index order, which shifts whenever an object is created or
781
+ deleted — a page walk would silently duplicate or drop rows.
782
+ - **Ordering change:** `tm1_list_cubes`, `tm1_list_dimensions` and `tm1_list_processes` now
783
+ return rows sorted by name on *both* paths (the fallback sorts client-side to match TM1's
784
+ collation). They previously echoed TM1's internal index order, so a given `offset` can land
785
+ on a different row than before.
786
+ - Not included: `tm1_list_views`, `tm1_list_subsets`, `tm1_list_clients`, `tm1_list_error_logs`.
787
+ Live probing confirmed `$top`/`$skip`/`$orderby`/`$count=true` all work on their endpoints
788
+ (`/Cubes('c')/Views`, `/PrivateViews`, `.../Subsets`, `/PrivateSubsets`, `/Users`,
789
+ `/ErrorLogFiles`), so they stay viable follow-ups; views and subsets additionally need a
790
+ two-scope (public + private) merge, which is why they were not bundled here.
791
+
792
+ - **Smaller `tools/list` payload — ~28.6KB (12%) off every session's context budget**, with no change to
793
+ input validation, output validation, or any tool's behaviour:
794
+ - Advertised JSON Schemas are slimmed on the way out: the `z.number().int()` safe-integer sentinels
795
+ (`minimum: -9007199254740991` / `maximum: 9007199254740991`) and the redundant `$schema` header are
796
+ stripped for both input and output schemas (~25.5KB). Real bounds (`limit` max 500, `offset` min 0)
797
+ are preserved; Zod still validates exactly as before.
798
+ - Shared pagination/format parameter descriptions no longer restate what the schema already emits as
799
+ `default` / `minimum` / `maximum` / `enum` — paid back across 33 tools (~2.8KB).
800
+ - `tm1_analyze_callgraph`'s output schema factors its repeated `EffectiveValue` sub-schema into
801
+ `definitions` + `$ref` (6.3KB → 4.8KB), keeping the typed drift guard intact.
802
+
803
+ ### Fixed
804
+
805
+ - `tm1_analyze_callgraph`'s output drift guard now actually bites on the node tree. `tree` is a union
806
+ of the full and compact node shapes, and a non-strict Zod object strips unknown keys instead of
807
+ rejecting them — so a full-mode node with a corrupt `incomingEdge` or `env` quietly matched the
808
+ compact variant with the corrupt keys thrown away. Both variants are strict now, which aligns the
809
+ runtime check with the `additionalProperties: false` the published schema already advertised. No
810
+ response data was ever lost by this (the validator's parsed output is discarded; the original
811
+ payload is what ships).
812
+
813
+ ## [2.0.0] - 2026-07-19
814
+
815
+ ### Added
816
+
817
+ - **TM1 v12 (Planning Analytics Engine) support** — rerooted REST + `/{instance}/auth/v1/session` login (`s2s` live-validated; `basic`/`access_token`/`oidc`/`iam` unit-validated).
818
+ - **v12 Jobs/Activity monitoring** — `tm1_list_jobs`, `tm1_cancel_job`; monitoring tools version-gated (v11 → thread tools, v12 → job tools).
819
+ - **Element-level data flow** — `tm1_trace_data_flow` gains `element`+`dimension` inputs answering "which processes touch element X of dimension D". Each process is classified `access = source | write | zero-out | indeterminate`, resolved from in-code subset builds, stored view/subset datasources (native-title/static exact, MDX by literal member), and — opt-in `resolveComputed` — live-evaluated computed axis selectors. Unresolved/computed cases are flagged, never silently dropped.
820
+ - `tm1_analyze_callgraph` surfaces dynamic/parameter `ExecuteProcess` targets as `unresolvedCalls`, and folds constant string-concat targets (`'zA'|'zB'` → `zAzB`) into real edges.
821
+ - `tm1_get_message_log` accepts `level` / `since` / `until` inputs and pushes the text/level/time filter server-side, so a match older than the fetched window is still found (was a silent "no error found").
822
+ - `tm1_get_transaction_log` reports `coverage` (`complete` / `partial`) and `scannedFrom` — a capped adaptive backfill is no longer mistaken for a full scan.
823
+ - `tm1_execute_mdx` / `tm1_get_view` set `axes_clipped` when a paginated read clips axis tuples to the returned cell window.
824
+
825
+ ### Changed
826
+
827
+ - **Breaking:** 14 tools that took a bare top-level `name` input now require an entity-qualified key (`cubeName`, `dimensionName`, `clientName`, `processName`, `objectName`): `tm1_create_cube`/`tm1_delete_cube`, `tm1_create_dimension`/`tm1_delete_dimension`, `tm1_create_client`/`tm1_delete_client`/`tm1_get_client`/`tm1_update_client`, `tm1_analyze_object_usage`, `tm1_upsert_process`/`tm1_compile_process`/`tm1_check_process_code`, `tm1_import_process_from_git`, `tm1_import_pro_file`. Response fields are unchanged.
828
+ - `tm1_execute_mdx` / `tm1_get_view` no longer return the full axis tuple list when the cell count is capped — axes are clipped to the returned window, so a `limit` read of a large view stays small (cell↔tuple mapping preserved).
829
+ - `tm1_list_cubes` no longer pulls full cube `Rules` text on the default list path (`$select=Name`).
830
+ - `tm1_save_data` is hidden on TM1 v12 — Planning Analytics Engine removed `SaveDataAll`/`CubeSaveData`; the cloud engine persists automatically.
831
+ - `tm1_resolve_default_members` reports `confidence: "medium"` for a server-derived (single-root) default; `"high"` is reserved for an explicitly maintained default member.
832
+ - `tm1_bulk_upsert_elements` runs element writes concurrently, and its consolidation `components` list is documented as a full replace of the child set (omit it to leave existing children unchanged).
833
+
834
+ - **Breaking:** git tools use TM1's native `#region <Tab>` / `#endregion` code format (byte-identical to the server `Code` blob; nested user folds preserved). `.ti` files from earlier versions are no longer importable — re-export.
835
+ - `tm1_analyze_callgraph` output is now a typed, recursive schema.
836
+ - `tm1_get_all_processes_code` / `tm1_get_all_cube_rules` default-cap full-code responses at 50 objects, pushed server-side (`$top`) — the default call no longer dumps the whole model. `limit=0` restores uncapped; summary mode still surveys everything. New `countIsExact` output flag marks `count` as a lower bound when the server omits a total.
837
+
838
+ ### Fixed
839
+
840
+ - `tm1_execute_process` reports the real TI outcome (via `tm1.ExecuteWithReturn`): runs finishing `CompletedWithMinorErrors` or aborted no longer read as clean success; the error log file is surfaced.
841
+ - `tm1_get_hierarchy` returns real consolidation edge weights from the Edges collection — previously every child weight was reported as `1` (wrong for e.g. P&L dims consolidating costs with `-1`).
842
+ - All user-facing lint/parser/v12-deprecation messages are now English (were German).
843
+ - README documents the actual `.env` resolution order (shell/MCP env > `DOTENV_CONFIG_PATH` > cwd > package root) — the old instructions could not work under `npx`.
844
+ - git import rejects malformed/unbalanced `#region` blobs instead of silently deploying partial code.
845
+ - v12: correct product version (`ProductVersion` scalar fallback); version coerced to 12 when instance-configured; rerooting hardened (instance URL-encode, `$`-injection guard, bounded IAM token exchange); `tm1_list_jobs` null-safe.
846
+ - MDX cell reads/writes escape `]` in cube/dimension/element names, so an element like `Q4]Adj` is addressed correctly instead of breaking or mis-targeting the cell.
847
+ - `tm1_write_cells` honors an explicit alternate hierarchy in a coordinate instead of always addressing the default hierarchy — previously a silent write to a same-named default-hierarchy member.
848
+
849
+ ### Security
850
+
851
+ - MCP **resources** now mask secrets like the tool surface: `tm1://process/{name}/code` masks credential literals unconditionally; `tm1://server/info` no longer exposes the raw server configuration dump.
852
+ - `tm1_get_server_info` masks credentials in its `_raw` configuration dump.
853
+ - The HTTP transport matches the `/mcp` route exactly — a path like `/mcpFoo` no longer routes as MCP.
854
+ - v12 credentials (`clientSecret`/`accessToken`/`apiKey`/`camPassport`) redacted in logs.
855
+
856
+ ## [1.0.4] - 2026-07-12
857
+
858
+ ### Security
859
+
860
+ - `tm1_get_all_processes_code` masks credential literals by default (new
861
+ `maskSecrets` flag) — it was the only code-returning tool without masking.
862
+ - ODBC connection strings (`oDBCConnection`, `PWD=`/`UID=` pairs) are masked
863
+ by default in `tm1_get_process`, `tm1_get_process_datasource` (new
864
+ `maskSecrets` flag) and the git-export `.json`; previously only the
865
+ `password` field was stripped.
866
+ - Local-file confinement (`TM1_LOCAL_FILE_ROOT`) is symlink-aware: targets are
867
+ `realpath`-checked against the resolved root.
868
+ - HTTP transport refuses a non-loopback bind (`TM1_MCP_HTTP_HOST`) without
869
+ `TM1_MCP_HTTP_TOKEN`; loopback stays warn-only.
870
+
871
+ ### Added
872
+
873
+ - `tm1_get_all_processes_code` `summary` mode: per-process line metrics
874
+ instead of code bodies.
875
+ - Every tool carries an auto-derived human-readable `title`
876
+ (`tm1_get_process_code` → "Get Process Code").
877
+
878
+ ### Fixed
879
+
880
+ - Output-schema drift returns an `isError` tool result instead of a raw
881
+ JSON-RPC protocol error.
882
+ - `tm1_analyze_chore_graph` not-found warning conforms to the output schema
883
+ again (was rejected by strict validation, so it never reached the client).
884
+ - Git/pro export create missing target directories instead of raw `ENOENT`.
885
+
886
+ ### Changed
887
+
888
+ - **Breaking:** input params renamed for cross-tool consistency —
889
+ `tm1_bulk_upsert_elements` `hierarchy` → `hierarchyName`; the chore family
890
+ (`create/delete/execute/toggle/update_chore`, `analyze_chore_graph`) now
891
+ uniformly takes `choreName` (was `name`; analyze was `chore`). MCP clients
892
+ re-read schemas per session and pick the new names up automatically.
893
+ - `tm1_get_process` declares a strict `outputSchema` like its siblings.
894
+ - `tm1_get_descendants`: `topN` cap (default 1000) + `truncated` flag —
895
+ no more full-dimension dumps from a root consolidation.
896
+ - `tm1_get_process` fetches its enabled sections in parallel (was up to 5
897
+ sequential REST calls).
898
+ - Publishing runs a clean `prepack` (`rm -rf dist && npm run build`); release
899
+ flow documented in `RELEASING.md`.
900
+ - `tm1_export_process_to_git` with `writeToDir` returns metadata only (no
901
+ inline `json`/`ti` echo); inline export unchanged. Mirrors
902
+ `tm1_import_process_from_git`.
903
+
904
+ ## [1.0.3] - 2026-07-05
905
+
906
+ Audit + live-sweep release, plus the process `HasSecurityAccess` read-side and
907
+ a git-export format alignment. Bundles the 2026-07-03 "beyond the basics" audit
908
+ fixes (transport lifecycle, cellset leak, error honesty, confirm-guard
909
+ coverage) and tool gaps found while sweeping ~35 tools against a production
910
+ TM1 11.8 server; the read-side of `HasSecurityAccess` (the write path landed in
911
+ the same release); and the git-export `.json` moved to TM1's native OData
912
+ shape. Behavior changes are called out below.
913
+
914
+ ### ⚠️ Behavior change
915
+
916
+ - `tm1_export_process_to_git` now emits the `.json` in TM1's OData-native
917
+ shape: top-level order `name, hasSecurityAccess, dataSource, parameters,
918
+ variables`, and parameter objects as `name, prompt, value, type`. The
919
+ parameter default uses the OData-native key **`value`** (previously the
920
+ internal name `defaultValue`). `tm1_import_process_from_git` reads `value`
921
+ and still accepts legacy `defaultValue` files for back-compat. The change is
922
+ confined to the git file format; the internal contract and
923
+ `tm1_upsert_process` input remain `defaultValue`. JSON key order is cosmetic
924
+ — import parses by key, so the round-trip is unaffected.
925
+
926
+ - The `confirm: true` guard now covers the **entire** object-destruction
927
+ surface: `tm1_delete_element`, `tm1_delete_hierarchy`, `tm1_delete_subset`,
928
+ `tm1_delete_view`, `tm1_delete_chore`, `tm1_delete_client`,
929
+ `tm1_delete_file`, and `tm1_remove_client_group` join the previously guarded
930
+ deletes. Calls without `confirm: true` are rejected with a hint (a unit test
931
+ gates the tool set so new destructive tools cannot ship unguarded).
932
+ - `tm1_write_cells` reports partial failures honestly: `allSettled` semantics
933
+ with `{ written, failed, notAttempted }` instead of failing the whole batch
934
+ on the first bad cell.
935
+
936
+ ### Added
937
+
938
+ - Git-process roundtrip carries `HasSecurityAccess`: `tm1_export_process_to_git`
939
+ reads and emits it, `tm1_import_process_from_git` applies it (PATCH, only
940
+ when declared in the file — existing server values are preserved otherwise),
941
+ and `tm1_upsert_process` accepts it as an input field. `Caption` was
942
+ evaluated and deliberately left out: TM1 offers no reliable write path
943
+ (`}ElementAttributes_}Processes` is absent on attribute-less dimensions), so
944
+ a lossy field is not pretended to be lossless.
945
+ - `tm1_get_process` — a native full read of a TI process, the read-twin of
946
+ `tm1_upsert_process`. One call returns the four code tabs, parameters,
947
+ variables, datasource, and the `HasSecurityAccess` flag using the same field
948
+ names as `upsert_process`. Every part sits behind an include-flag (all
949
+ default `true`) that gates its REST call, so a caller can skip parts it does
950
+ not need; `maskSecrets` and `stripComments` mirror `tm1_get_process_code`.
951
+ For git persistence use `tm1_export_process_to_git` instead — this tool is
952
+ for reading/understanding a process, not serialization.
953
+ - `tm1_get_all_processes_code` now carries each process's `hasSecurityAccess`
954
+ flag per row, so the audit bulk-load can answer which processes run elevated
955
+ (previously the flag was readable only through the git export).
956
+ - `tm1_get_process_code` gains an opt-in `includeSecurityAccess` flag (default
957
+ `false`, so pure code reads stay a single request); when `true` it adds the
958
+ `hasSecurityAccess` field via a dedicated metadata GET.
959
+ - `tm1_validate_process_refs` now resolves much more of the real-world TI
960
+ surface: `DIMIX`, `CellIncrementN`, `CellPutProportionalSpread`,
961
+ `ViewZeroOut`, `CubeClearData`; cube/dimension args in position 2
962
+ (`CellPutN/S`, `AttrPutN/S`, `ElementSecurityPut`) are extracted with a
963
+ paren/quote walker that handles nested function calls, multi-line calls, and
964
+ TI `''` escapes; and variable object names bound to a single literal
965
+ (`sCube = 'Sales'; CellGetN(sCube, ...)`) resolve through the per-process
966
+ variable environment. Params, datasource variables, and reassigned
967
+ variables stay conservatively unresolved — no false positives.
968
+ - HTTP transport (Streamable) builds an isolated server+transport pair per
969
+ request instead of sharing one across sessions.
970
+
971
+ ### Fixed
972
+
973
+ - Read-path cellsets (`tm1_get_view`, `tm1_execute_mdx`, sampling) are freed
974
+ on the server after use — long-lived sessions no longer leak TM1 memory.
975
+ - Service layer propagates systemic transport errors (auth loss, outages)
976
+ instead of degrading them to empty results (`exists()` probes pinned to
977
+ 404-only, callgraph/audit tools fail loud on outage).
978
+ - `tm1_execute_process`: client-side aborts are reported as *unconfirmed*
979
+ (with a list/cancel-thread hint) instead of pretending the process failed;
980
+ TI failure status keeps the `isError` flag.
981
+ - Session manager: stale-cookie re-auth short-circuits the 401 storm when
982
+ many parallel requests race; keep-alive no longer clears a fresh cookie.
983
+ - `tm1_check_process_code`: syntax errors return a self-describing
984
+ `VALIDATION_ERROR` payload (short message + actionable hint) instead of a
985
+ generic `TM1_ERROR` envelope with the whole payload duplicated into
986
+ `message`; the isError normalizer no longer falls back to raw-JSON
987
+ duplication for any tool.
988
+ - OData key segments with embedded quotes are escaped in the rules linter;
989
+ `]` is escaped in attribute-value MDX.
990
+ - `TM1_MODE` parsing is case-insensitive and fails fast on unknown values
991
+ (a typo no longer silently granted read-write).
992
+ - Crash exit: `uncaughtException` terminates with exit code 1 (was 0), so
993
+ supervisors detect the failure.
994
+ - Element "already exists" detection pinned cross-version (v11 HTTP 400 vs
995
+ 409) with a unit test, keeping `tm1_bulk_upsert_elements` idempotent.
996
+ - Masking property tests exercise the real logger construction path (a fake
997
+ copy had let redaction regressions slip); `Cookie` headers joined the
998
+ redaction list.
999
+
1000
+ ## [1.0.2] - 2026-07-02
1001
+
1002
+ Hardening release: security, bounded outputs, robustness, and internal
1003
+ layering. Two output-shape changes are noted below — they affect how a client
1004
+ reads results, though in practice an MCP agent reads the envelope dynamically.
1005
+
1006
+ ### ⚠️ Output-shape changes
1007
+
1008
+ - `tm1_get_view` now returns a paginated envelope
1009
+ (`{ items, total, count, offset, has_more, next_offset, axes }`) instead of a
1010
+ raw cellset, and paginates by default. Pass `fetchAll: true` (or `limit: 0`)
1011
+ for the full cellset. The cell array moved from `cells` to `items`.
1012
+ - `tm1_resolve_default_member` was removed; use `tm1_resolve_default_members`
1013
+ with a single-item array (`items: [{ dimensionName }]`). The resolved member
1014
+ is `results[0].resolved.name` (content is identical to the old tool).
1015
+
1016
+ ### Added
1017
+
1018
+ - `tm1_get_view`: `format='markdown'` pivot-grid/flat-table rendering plus
1019
+ `limit`/`offset`/`fetchAll` pagination (`$top`/`$skip` pushed server-side),
1020
+ reusing the `tm1_execute_mdx` envelope.
1021
+ - `tm1_get_hierarchy`: default element cap with a `truncated` flag on cut output.
1022
+ - Code-reading TI tools (`tm1_get_process_code`, `tm1_export_process_to_pro`,
1023
+ `tm1_export_process_to_git`, `tm1_diff_processes`, `tm1_diff_process_with_file`)
1024
+ gain a `maskSecrets` flag (default `true`) that masks inline ODBC/connection
1025
+ credentials before returning or writing code.
1026
+ - outputSchema byte-budget CI gate (`lint:output-schema-budget`) guarding the
1027
+ tools/list payload against schema bloat; wired into `npm run verify` and CI.
1028
+
1029
+ ### Changed
1030
+
1031
+ - Tool responses now emit compact JSON (disk artifacts stay pretty-printed),
1032
+ cutting every large response body.
1033
+ - Trimmed verbose top-level tool descriptions that restated per-field docs.
1034
+ - `TM1Client` uses composition over inheritance so the raw transport surface is
1035
+ no longer reachable from the tools layer (compiler-enforced, not just lint).
1036
+
1037
+ ### Removed
1038
+
1039
+ - `tm1_resolve_default_member` (merged into `tm1_resolve_default_members`);
1040
+ tool count 112 → 111.
1041
+
1042
+ ### Fixed
1043
+
1044
+ - Inline ODBC/connection-string credentials in TI code are now masked in the
1045
+ five code-reading tools (previously returned — and for git export, written to
1046
+ disk — in plaintext).
1047
+ - Transaction-log windowing/probe paths no longer swallow connection outages or
1048
+ permission denials as an empty "no data in range" result.
1049
+ - Network-error classification uses `err.cause.code` (undici) instead of brittle
1050
+ message-substring matching that varied by Node version and locale.
1051
+ - `asOutputSchema` no longer reads Zod's private `_def`; uses the public
1052
+ accessor and pins Zod to an exact version with a regression test.
1053
+
1054
+ ## [1.0.1] - 2026-06-30
1055
+
1056
+ ### Added
1057
+
1058
+ - `tm1_trace_data_flow`: new analysis tool that traces a cube's data flow in one
1059
+ call instead of `analyze_object_usage` + N× `get_process_code`. `downstream`
1060
+ lists processes that read the cube and the cubes they write to; `upstream`
1061
+ lists processes that write the cube and where they source data. Combines
1062
+ code-level CellGet/CellPut/DB access with each process's datasource (one bulk
1063
+ OData fetch), so view-sourced reads with no CellGet are caught too.
1064
+
1065
+ - `tm1_get_message_log`: each entry now surfaces an optional `errorFile` field —
1066
+ the TI error filename parsed out of the message text — so it can be passed
1067
+ straight to `tm1_get_error_log_content` without manual string-copying.
1068
+ - `tm1_sample_cells`: opt-in `includeStrings` flag to sample String value
1069
+ fields. Swaps NON EMPTY for a `<> ""` FILTER and scans all members including
1070
+ consolidations (string values do not roll up and can sit on C elements). A
1071
+ zero-result numeric run now hints at the flag.
1072
+ - `tm1_get_process_code`: opt-in `stripComments` flag that collapses runs of 4+
1073
+ consecutive comment lines into a `# [... N lines commented out ...]` marker to
1074
+ reduce dead-code context. Comment-heavy tabs surface a hint when not stripped.
1075
+
1076
+ ### Fixed
1077
+
1078
+ - Corrected the read/write access taxonomy behind `tm1_analyze_object_usage` and
1079
+ `tm1_trace_data_flow`. Now classified: element/dimension attribute value access
1080
+ (`AttrPutN/S`, `ElementAttrPutN/S` writes; `ATTRN/S`, `AttrNL/SL`,
1081
+ `ElementAttrN/S/NL/SL` reads) and cube attributes (`CubeAttrPutN/S` writes,
1082
+ `CubeATTRNL/SL` reads). Removed classification of functions that do not exist in
1083
+ TM1 TI — `CellIncrement` (only `CellIncrementN`), `CubePutN/S`, `ViewPutN/S`,
1084
+ `CubeGetN/S`, `ViewGetN/S`, `ViewAttr*`, base-form `CubeAttrN/S`, `AttributeGet`,
1085
+ `AttributePut` — so they are no longer mis-counted as reads/writes. The bogus
1086
+ `CellIncrement` TI signature was also dropped.
1087
+
1088
+ ## [1.0.0] - 2026-06-24
1089
+
1090
+ Initial public release.
1091
+
1092
+ ### Architecture
1093
+
1094
+ - Service-composition architecture: all TM1 REST calls go through a service
1095
+ under `src/tm1-client/services/`; the `lint:no-flat-api` CI gate prevents
1096
+ regression to flat-client calls.
1097
+ - 111 MCP tools across 12 categories (metadata, model building, dimension
1098
+ management, subsets, views, cell data, TI development, TI lifecycle,
1099
+ process execution, scheduling, security, operations, analysis).
1100
+ - Four read-only MCP resources (`tm1://server/info`, `tm1://server/state`,
1101
+ `tm1://process/{name}/code`, `tm1://cube/{name}/rules`) with name-autocomplete
1102
+ completion callbacks.
1103
+
1104
+ ### Transports
1105
+
1106
+ - stdio transport (default) for local Claude Code / Claude Desktop.
1107
+ - Streamable HTTP transport (stateless `POST /mcp`) with DNS-rebinding
1108
+ protection, `Host`/`Origin` validation, and configurable bind host/port/origins.
1109
+
1110
+ ### Authentication
1111
+
1112
+ - Native TM1 auth (`TM1_USER` / `TM1_PASSWORD`) is the default.
1113
+ - CAM (Cognos Access Manager) login. Set `TM1_NAMESPACE` for namespace auth
1114
+ (sends `Authorization: CAMNamespace base64(user:password:namespace)`) or
1115
+ `TM1_CAM_PASSPORT` for a pre-obtained passport (sends
1116
+ `Authorization: CAMPassport <token>`, takes precedence and needs no
1117
+ user/password).
1118
+
1119
+ ### Modes
1120
+
1121
+ - `TM1_MODE=readonly` (default) restricts tool registration to non-destructive
1122
+ tools for production instances; `readwrite` opts in to the full lifecycle.
1123
+
1124
+ ### TI analysis
1125
+
1126
+ - `tm1_analyze_callgraph` — ExecuteProcess/RunProcess call tree with parameter
1127
+ env propagation, `mode='summary'` aggregates, and global fan-out/fan-in
1128
+ ranking when `start` is omitted.
1129
+ - `tm1_audit_feeders` — static overfeeding heuristics S1–S5 plus a runtime
1130
+ fed/populated-ratio metric (`}StatsByCube` evidence) calibrated to the
1131
+ TM1 community (≥50× hint, ≥100× evidence); runtime evidence escalates static
1132
+ findings.
1133
+ - `tm1_audit_naming` — bulk-scan TM1 objects against IBM Planning Analytics
1134
+ naming conventions (PA 2.0 + 3.1).
1135
+ - `tm1_audit_complexity` — TI/rule complexity metrics plus an opt-in
1136
+ antipatterns lint scope (cognitive-style scoreV2, dead-assignment rule).
1137
+ - `tm1_analyze_object_usage` (with `mode='summary'` per-source aggregation),
1138
+ `tm1_analyze_chore_graph`, `tm1_invalidate_callgraph_cache`,
1139
+ `tm1_find_orphan_dimensions`, `tm1_check_v12_readiness`.
1140
+
1141
+ ### TI lifecycle (.pro)
1142
+
1143
+ - `tm1_import_pro_file`, `tm1_diff_process_with_file`, `tm1_install_pro_bundle`,
1144
+ `tm1_export_process_to_pro`, `tm1_upsert_process`, `tm1_diff_processes`.
1145
+
1146
+ ### Pre-write validation
1147
+
1148
+ - `tm1_check_process_code`, `tm1_check_cube_rule`, `tm1_validate_process_refs`,
1149
+ `tm1_check_writable_coords`.
1150
+
1151
+ ### Cell data and search
1152
+
1153
+ - `tm1_execute_mdx` with `format=markdown` pivot/flat rendering.
1154
+ - `tm1_search_code` with `deduplicateByLine` and a `groupBy` (`'process'` |
1155
+ `'tab'`) match-count aggregation mode; `tm1_search_rules` regex search across
1156
+ cube rules.
1157
+ - `tm1_list_error_logs` with a `groupBy='process'` audit-summary mode
1158
+ (per process `{count, firstSeen, lastSeen, spanDays, perDay}`).
1159
+
1160
+ ### Reliability and performance
1161
+
1162
+ - Removed pretty-print JSON from tool output; gzip responses; method-aware
1163
+ timeout hints; parallel `writeCells`.
1164
+ - Transaction-log query hardening: fail-fast preflight probe, Z-normalized
1165
+ `since` filter, and adaptive time-window backfill to avoid full-scan timeouts.
1166
+ - TM1 security denials (HTTP 400) classified as `PERMISSION_DENIED`;
1167
+ HTTP transport distinguishes `LOCK_TIMEOUT` from `CONNECTION_FAILED`.
1168
+ - Strict (`additionalProperties: false`) output schemas across tools.
1169
+ - Secrets masked in tool output.
1170
+ - `.env` is loaded from the package/repo root (the directory containing `dist/`)
1171
+ in addition to the current working directory, so MCP clients that spawn the
1172
+ server with their own cwd still pick up a repo `.env`. dotenv v17 startup tips
1173
+ are suppressed (`quiet`) so they cannot corrupt the stdio JSON-RPC stream.
1174
+
1175
+ ### Security
1176
+
1177
+ - Host-file access for the `.pro` round-trip tools (`tm1_diff_process_with_file`,
1178
+ `tm1_validate_process_refs`, `tm1_export_process_to_pro`, `tm1_import_pro_file`,
1179
+ `tm1_install_pro_bundle`) is gated behind the `TM1_LOCAL_FILE_ROOT` environment
1180
+ variable and **disabled by default**. When unset, the `filePath` / `writeToFile`
1181
+ / `directory` parameters are rejected and the tools accept only inline
1182
+ `content`; when set, supplied paths must resolve within that root (no `..`
1183
+ traversal).
1184
+ - `.env.example` ships with TLS verification on: `TM1_SSL_REJECT_UNAUTHORIZED`
1185
+ is commented out so the secure code default (`true`) applies unless a user
1186
+ deliberately opts out for self-signed certs.
1187
+
1188
+ ### Documentation
1189
+
1190
+ - README, ARCHITECTURE, CONTRIBUTING, and SECURITY policy for open-source release.
1191
+
1192
+ ### CI
1193
+
1194
+ - Quality gates: strict typecheck, ESLint, `lint:no-flat-api`,
1195
+ annotation-coverage, and tool-registration wiring.
1196
+
1197
+ [Unreleased]: https://github.com/ffschrattenecker/tm1-mcp-server/compare/v6.0.0...HEAD
1198
+ [6.0.0]: https://github.com/ffschrattenecker/tm1-mcp-server/compare/v5.0.0...v6.0.0
1199
+ [5.0.0]: https://github.com/ffschrattenecker/tm1-mcp-server/compare/v4.1.0...v5.0.0
1200
+ [4.1.0]: https://github.com/ffschrattenecker/tm1-mcp-server/compare/v4.0.0...v4.1.0
1201
+ [4.0.0]: https://github.com/flameY3T1/tm1-mcp-server/compare/v3.1.0...v4.0.0
1202
+ [3.1.0]: https://github.com/flameY3T1/tm1-mcp-server/compare/v3.0.1...v3.1.0
1203
+ [3.0.1]: https://github.com/flameY3T1/tm1-mcp-server/compare/v3.0.0...v3.0.1
1204
+ [3.0.0]: https://github.com/flameY3T1/tm1-mcp-server/compare/v2.1.0...v3.0.0
1205
+ [2.1.0]: https://github.com/flameY3T1/tm1-mcp-server/compare/v2.0.0...v2.1.0
1206
+ [2.0.0]: https://github.com/flameY3T1/tm1-mcp-server/compare/v1.0.4...v2.0.0
1207
+ [1.0.4]: https://github.com/flameY3T1/tm1-mcp-server/compare/v1.0.3...v1.0.4
1208
+ [1.0.3]: https://github.com/flameY3T1/tm1-mcp-server/compare/v1.0.2...v1.0.3
1209
+ [1.0.2]: https://github.com/flameY3T1/tm1-mcp-server/compare/v1.0.1...v1.0.2
1210
+ [1.0.1]: https://github.com/flameY3T1/tm1-mcp-server/compare/v1.0.0...v1.0.1
1211
+ [1.0.0]: https://github.com/flameY3T1/tm1-mcp-server/releases/tag/v1.0.0