@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.
- package/CHANGELOG.md +1211 -0
- package/LICENSE +21 -0
- package/NOTICE +34 -0
- package/README.md +276 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.js +238 -0
- package/dist/http-transport.d.ts +8 -0
- package/dist/http-transport.js +132 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +164 -0
- package/dist/lib/callgraph/callGraph.d.ts +124 -0
- package/dist/lib/callgraph/callGraph.js +334 -0
- package/dist/lib/callgraph/choreGraph.d.ts +23 -0
- package/dist/lib/callgraph/choreGraph.js +102 -0
- package/dist/lib/callgraph/dataFlow.d.ts +74 -0
- package/dist/lib/callgraph/dataFlow.js +271 -0
- package/dist/lib/callgraph/datasourceMembership.d.ts +31 -0
- package/dist/lib/callgraph/datasourceMembership.js +142 -0
- package/dist/lib/callgraph/lintTypes.d.ts +28 -0
- package/dist/lib/callgraph/lintTypes.js +2 -0
- package/dist/lib/callgraph/mdxMembers.d.ts +29 -0
- package/dist/lib/callgraph/mdxMembers.js +97 -0
- package/dist/lib/callgraph/referenceIndex.d.ts +179 -0
- package/dist/lib/callgraph/referenceIndex.js +584 -0
- package/dist/lib/callgraph/rulesLinter.d.ts +55 -0
- package/dist/lib/callgraph/rulesLinter.js +776 -0
- package/dist/lib/callgraph/rulesParser.d.ts +26 -0
- package/dist/lib/callgraph/rulesParser.js +71 -0
- package/dist/lib/callgraph/subsetUsage.d.ts +16 -0
- package/dist/lib/callgraph/subsetUsage.js +134 -0
- package/dist/lib/callgraph/tiParser.d.ts +21 -0
- package/dist/lib/callgraph/tiParser.js +672 -0
- package/dist/lib/callgraph/tiSignatures.d.ts +32 -0
- package/dist/lib/callgraph/tiSignatures.js +6185 -0
- package/dist/lib/callgraph/tm1-adapter.d.ts +32 -0
- package/dist/lib/callgraph/tm1-adapter.js +159 -0
- package/dist/lib/callgraph/types.d.ts +53 -0
- package/dist/lib/callgraph/types.js +2 -0
- package/dist/lib/callgraph/variableEnv.d.ts +86 -0
- package/dist/lib/callgraph/variableEnv.js +214 -0
- package/dist/lib/cell-address.d.ts +12 -0
- package/dist/lib/cell-address.js +71 -0
- package/dist/lib/complexity/antipatterns.d.ts +22 -0
- package/dist/lib/complexity/antipatterns.js +302 -0
- package/dist/lib/complexity/comment-classifier.d.ts +24 -0
- package/dist/lib/complexity/comment-classifier.js +43 -0
- package/dist/lib/complexity/cross-process.d.ts +78 -0
- package/dist/lib/complexity/cross-process.js +114 -0
- package/dist/lib/complexity/process-metrics.d.ts +78 -0
- package/dist/lib/complexity/process-metrics.js +278 -0
- package/dist/lib/complexity/rules-metrics.d.ts +31 -0
- package/dist/lib/complexity/rules-metrics.js +99 -0
- package/dist/lib/concurrency.d.ts +11 -0
- package/dist/lib/concurrency.js +27 -0
- package/dist/lib/control-name.d.ts +10 -0
- package/dist/lib/control-name.js +10 -0
- package/dist/lib/coordinate-error.d.ts +3 -0
- package/dist/lib/coordinate-error.js +29 -0
- package/dist/lib/credential-format.d.ts +23 -0
- package/dist/lib/credential-format.js +25 -0
- package/dist/lib/cube-stats/fetcher.d.ts +106 -0
- package/dist/lib/cube-stats/fetcher.js +194 -0
- package/dist/lib/feeders/brackets.d.ts +47 -0
- package/dist/lib/feeders/brackets.js +195 -0
- package/dist/lib/feeders/element-type-cache.d.ts +42 -0
- package/dist/lib/feeders/element-type-cache.js +86 -0
- package/dist/lib/feeders/static-heuristics.d.ts +101 -0
- package/dist/lib/feeders/static-heuristics.js +202 -0
- package/dist/lib/git-process.d.ts +67 -0
- package/dist/lib/git-process.js +243 -0
- package/dist/lib/mask-secrets.d.ts +10 -0
- package/dist/lib/mask-secrets.js +99 -0
- package/dist/lib/mdx.d.ts +3 -0
- package/dist/lib/mdx.js +13 -0
- package/dist/lib/naming/odata-filter.d.ts +15 -0
- package/dist/lib/naming/odata-filter.js +81 -0
- package/dist/lib/naming/rules.d.ts +34 -0
- package/dist/lib/naming/rules.js +215 -0
- package/dist/lib/pro-parser.d.ts +19 -0
- package/dist/lib/pro-parser.js +260 -0
- package/dist/lib/pro-serializer.d.ts +19 -0
- package/dist/lib/pro-serializer.js +170 -0
- package/dist/lib/process-parts-schema.d.ts +45 -0
- package/dist/lib/process-parts-schema.js +46 -0
- package/dist/lib/process-refs.d.ts +88 -0
- package/dist/lib/process-refs.js +441 -0
- package/dist/lib/rules-outline.d.ts +29 -0
- package/dist/lib/rules-outline.js +68 -0
- package/dist/lib/rules-patch.d.ts +6 -0
- package/dist/lib/rules-patch.js +59 -0
- package/dist/lib/safe-regex.d.ts +15 -0
- package/dist/lib/safe-regex.js +37 -0
- package/dist/lib/sample-cells.d.ts +48 -0
- package/dist/lib/sample-cells.js +146 -0
- package/dist/lib/slim-json-schema.d.ts +20 -0
- package/dist/lib/slim-json-schema.js +68 -0
- package/dist/lib/strip-comments.d.ts +23 -0
- package/dist/lib/strip-comments.js +61 -0
- package/dist/lib/tm1-events.d.ts +16 -0
- package/dist/lib/tm1-events.js +29 -0
- package/dist/lib/v12-compat/deprecated-ti.d.ts +17 -0
- package/dist/lib/v12-compat/deprecated-ti.js +257 -0
- package/dist/lib/v12-compat/scanner.d.ts +10 -0
- package/dist/lib/v12-compat/scanner.js +43 -0
- package/dist/lib/variables-ui-data.d.ts +26 -0
- package/dist/lib/variables-ui-data.js +77 -0
- package/dist/load-env.d.ts +2 -0
- package/dist/load-env.js +29 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.js +60 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.js +141 -0
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.js +237 -0
- package/dist/resources/list-handler.d.ts +40 -0
- package/dist/resources/list-handler.js +86 -0
- package/dist/resources/subscriptions.d.ts +19 -0
- package/dist/resources/subscriptions.js +80 -0
- package/dist/schemas/cells.d.ts +17 -0
- package/dist/schemas/cells.js +13 -0
- package/dist/schemas/common.d.ts +16 -0
- package/dist/schemas/common.js +14 -0
- package/dist/schemas/index.d.ts +10 -0
- package/dist/schemas/index.js +23 -0
- package/dist/schemas/metadata.d.ts +70 -0
- package/dist/schemas/metadata.js +47 -0
- package/dist/schemas/monitoring.d.ts +95 -0
- package/dist/schemas/monitoring.js +69 -0
- package/dist/schemas/processes.d.ts +74 -0
- package/dist/schemas/processes.js +66 -0
- package/dist/schemas/scheduling.d.ts +13 -0
- package/dist/schemas/scheduling.js +13 -0
- package/dist/schemas/security.d.ts +19 -0
- package/dist/schemas/security.js +16 -0
- package/dist/schemas/subsets.d.ts +12 -0
- package/dist/schemas/subsets.js +12 -0
- package/dist/schemas/views.d.ts +9 -0
- package/dist/schemas/views.js +9 -0
- package/dist/session-manager.d.ts +79 -0
- package/dist/session-manager.js +281 -0
- package/dist/tm1-client/connection/profile.d.ts +13 -0
- package/dist/tm1-client/connection/profile.js +99 -0
- package/dist/tm1-client/dispatcher.d.ts +5 -0
- package/dist/tm1-client/dispatcher.js +31 -0
- package/dist/tm1-client/http.d.ts +81 -0
- package/dist/tm1-client/http.js +547 -0
- package/dist/tm1-client/services/batch-service.d.ts +123 -0
- package/dist/tm1-client/services/batch-service.js +455 -0
- package/dist/tm1-client/services/cell-service.d.ts +71 -0
- package/dist/tm1-client/services/cell-service.js +333 -0
- package/dist/tm1-client/services/cellset-transform.d.ts +26 -0
- package/dist/tm1-client/services/cellset-transform.js +80 -0
- package/dist/tm1-client/services/chore-service.d.ts +68 -0
- package/dist/tm1-client/services/chore-service.js +179 -0
- package/dist/tm1-client/services/chore-status.d.ts +11 -0
- package/dist/tm1-client/services/chore-status.js +127 -0
- package/dist/tm1-client/services/cube-service.d.ts +134 -0
- package/dist/tm1-client/services/cube-service.js +294 -0
- package/dist/tm1-client/services/dimension-service.d.ts +118 -0
- package/dist/tm1-client/services/dimension-service.js +249 -0
- package/dist/tm1-client/services/element-service.d.ts +245 -0
- package/dist/tm1-client/services/element-service.js +809 -0
- package/dist/tm1-client/services/fallback.d.ts +44 -0
- package/dist/tm1-client/services/fallback.js +72 -0
- package/dist/tm1-client/services/file-service.d.ts +53 -0
- package/dist/tm1-client/services/file-service.js +218 -0
- package/dist/tm1-client/services/hierarchy-service.d.ts +129 -0
- package/dist/tm1-client/services/hierarchy-service.js +332 -0
- package/dist/tm1-client/services/monitoring-service.d.ts +34 -0
- package/dist/tm1-client/services/monitoring-service.js +123 -0
- package/dist/tm1-client/services/odata-page.d.ts +71 -0
- package/dist/tm1-client/services/odata-page.js +87 -0
- package/dist/tm1-client/services/process-service.d.ts +278 -0
- package/dist/tm1-client/services/process-service.js +874 -0
- package/dist/tm1-client/services/process-status.d.ts +21 -0
- package/dist/tm1-client/services/process-status.js +89 -0
- package/dist/tm1-client/services/security-service.d.ts +50 -0
- package/dist/tm1-client/services/security-service.js +93 -0
- package/dist/tm1-client/services/server-service.d.ts +116 -0
- package/dist/tm1-client/services/server-service.js +504 -0
- package/dist/tm1-client/services/subset-service.d.ts +37 -0
- package/dist/tm1-client/services/subset-service.js +122 -0
- package/dist/tm1-client/services/view-service.d.ts +46 -0
- package/dist/tm1-client/services/view-service.js +287 -0
- package/dist/tm1-client.d.ts +56 -0
- package/dist/tm1-client.js +126 -0
- package/dist/tools/analysis/analyze-callgraph.d.ts +28 -0
- package/dist/tools/analysis/analyze-callgraph.js +350 -0
- package/dist/tools/analysis/analyze-chore-graph.d.ts +2 -0
- package/dist/tools/analysis/analyze-chore-graph.js +148 -0
- package/dist/tools/analysis/analyze-object-usage.d.ts +2 -0
- package/dist/tools/analysis/analyze-object-usage.js +143 -0
- package/dist/tools/analysis/audit-complexity.d.ts +2 -0
- package/dist/tools/analysis/audit-complexity.js +255 -0
- package/dist/tools/analysis/audit-feeders.d.ts +2 -0
- package/dist/tools/analysis/audit-feeders.js +417 -0
- package/dist/tools/analysis/audit-naming.d.ts +2 -0
- package/dist/tools/analysis/audit-naming.js +379 -0
- package/dist/tools/analysis/check-v12-readiness.d.ts +2 -0
- package/dist/tools/analysis/check-v12-readiness.js +136 -0
- package/dist/tools/analysis/find-orphan-dimensions.d.ts +2 -0
- package/dist/tools/analysis/find-orphan-dimensions.js +55 -0
- package/dist/tools/analysis/invalidate-callgraph-cache.d.ts +2 -0
- package/dist/tools/analysis/invalidate-callgraph-cache.js +40 -0
- package/dist/tools/analysis/trace-data-flow.d.ts +2 -0
- package/dist/tools/analysis/trace-data-flow.js +138 -0
- package/dist/tools/annotations.d.ts +12 -0
- package/dist/tools/annotations.js +61 -0
- package/dist/tools/celldata/check-feeders.d.ts +2 -0
- package/dist/tools/celldata/check-feeders.js +48 -0
- package/dist/tools/celldata/check-writable-coords.d.ts +2 -0
- package/dist/tools/celldata/check-writable-coords.js +126 -0
- package/dist/tools/celldata/execute-mdx.d.ts +17 -0
- package/dist/tools/celldata/execute-mdx.js +126 -0
- package/dist/tools/celldata/get-cell-value.d.ts +2 -0
- package/dist/tools/celldata/get-cell-value.js +30 -0
- package/dist/tools/celldata/get-view-definition.d.ts +2 -0
- package/dist/tools/celldata/get-view-definition.js +29 -0
- package/dist/tools/celldata/get-view.d.ts +2 -0
- package/dist/tools/celldata/get-view.js +55 -0
- package/dist/tools/celldata/sample-cells.d.ts +2 -0
- package/dist/tools/celldata/sample-cells.js +101 -0
- package/dist/tools/celldata/trace-cell-calculation.d.ts +2 -0
- package/dist/tools/celldata/trace-cell-calculation.js +53 -0
- package/dist/tools/celldata/trace-feeders.d.ts +2 -0
- package/dist/tools/celldata/trace-feeders.js +44 -0
- package/dist/tools/celldata/write-cells.d.ts +2 -0
- package/dist/tools/celldata/write-cells.js +65 -0
- package/dist/tools/confirm.d.ts +10 -0
- package/dist/tools/confirm.js +64 -0
- package/dist/tools/define-tool.d.ts +51 -0
- package/dist/tools/define-tool.js +49 -0
- package/dist/tools/dimension-management/bulk-upsert-elements.d.ts +2 -0
- package/dist/tools/dimension-management/bulk-upsert-elements.js +103 -0
- package/dist/tools/dimension-management/create-dimension.d.ts +2 -0
- package/dist/tools/dimension-management/create-dimension.js +22 -0
- package/dist/tools/dimension-management/create-element-attribute.d.ts +2 -0
- package/dist/tools/dimension-management/create-element-attribute.js +26 -0
- package/dist/tools/dimension-management/create-element.d.ts +2 -0
- package/dist/tools/dimension-management/create-element.js +31 -0
- package/dist/tools/dimension-management/create-hierarchy.d.ts +2 -0
- package/dist/tools/dimension-management/create-hierarchy.js +22 -0
- package/dist/tools/dimension-management/delete-dimension.d.ts +2 -0
- package/dist/tools/dimension-management/delete-dimension.js +25 -0
- package/dist/tools/dimension-management/delete-element.d.ts +2 -0
- package/dist/tools/dimension-management/delete-element.js +26 -0
- package/dist/tools/dimension-management/delete-elements.d.ts +2 -0
- package/dist/tools/dimension-management/delete-elements.js +44 -0
- package/dist/tools/dimension-management/delete-hierarchy.d.ts +2 -0
- package/dist/tools/dimension-management/delete-hierarchy.js +35 -0
- package/dist/tools/dimension-management/get-element-attribute-values.d.ts +2 -0
- package/dist/tools/dimension-management/get-element-attribute-values.js +77 -0
- package/dist/tools/dimension-management/list-element-attributes.d.ts +2 -0
- package/dist/tools/dimension-management/list-element-attributes.js +31 -0
- package/dist/tools/dimension-management/move-element.d.ts +2 -0
- package/dist/tools/dimension-management/move-element.js +28 -0
- package/dist/tools/dimension-management/update-element-attribute-value.d.ts +2 -0
- package/dist/tools/dimension-management/update-element-attribute-value.js +80 -0
- package/dist/tools/dimension-management/update-element.d.ts +2 -0
- package/dist/tools/dimension-management/update-element.js +35 -0
- package/dist/tools/error-format.d.ts +22 -0
- package/dist/tools/error-format.js +130 -0
- package/dist/tools/fileops/delete-file.d.ts +2 -0
- package/dist/tools/fileops/delete-file.js +32 -0
- package/dist/tools/fileops/get-file-content.d.ts +2 -0
- package/dist/tools/fileops/get-file-content.js +76 -0
- package/dist/tools/fileops/list-files.d.ts +2 -0
- package/dist/tools/fileops/list-files.js +43 -0
- package/dist/tools/fileops/search-files.d.ts +2 -0
- package/dist/tools/fileops/search-files.js +76 -0
- package/dist/tools/fileops/upload-file.d.ts +2 -0
- package/dist/tools/fileops/upload-file.js +69 -0
- package/dist/tools/format.d.ts +57 -0
- package/dist/tools/format.js +157 -0
- package/dist/tools/hierarchy.d.ts +6 -0
- package/dist/tools/hierarchy.js +27 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.js +263 -0
- package/dist/tools/local-file.d.ts +16 -0
- package/dist/tools/local-file.js +88 -0
- package/dist/tools/metadata/get-ancestors.d.ts +2 -0
- package/dist/tools/metadata/get-ancestors.js +36 -0
- package/dist/tools/metadata/get-descendants.d.ts +2 -0
- package/dist/tools/metadata/get-descendants.js +64 -0
- package/dist/tools/metadata/get-hierarchy.d.ts +2 -0
- package/dist/tools/metadata/get-hierarchy.js +130 -0
- package/dist/tools/metadata/list-chores.d.ts +2 -0
- package/dist/tools/metadata/list-chores.js +62 -0
- package/dist/tools/metadata/list-cubes.d.ts +2 -0
- package/dist/tools/metadata/list-cubes.js +128 -0
- package/dist/tools/metadata/list-dimensions.d.ts +2 -0
- package/dist/tools/metadata/list-dimensions.js +131 -0
- package/dist/tools/metadata/list-processes-grouped.d.ts +2 -0
- package/dist/tools/metadata/list-processes-grouped.js +96 -0
- package/dist/tools/metadata/list-processes.d.ts +2 -0
- package/dist/tools/metadata/list-processes.js +108 -0
- package/dist/tools/metadata/resolve-default-members.d.ts +2 -0
- package/dist/tools/metadata/resolve-default-members.js +46 -0
- package/dist/tools/model-building/check-cube-rule.d.ts +2 -0
- package/dist/tools/model-building/check-cube-rule.js +51 -0
- package/dist/tools/model-building/clear-cube.d.ts +2 -0
- package/dist/tools/model-building/clear-cube.js +46 -0
- package/dist/tools/model-building/create-cube.d.ts +2 -0
- package/dist/tools/model-building/create-cube.js +34 -0
- package/dist/tools/model-building/delete-cube.d.ts +2 -0
- package/dist/tools/model-building/delete-cube.js +27 -0
- package/dist/tools/model-building/get-all-cube-rules.d.ts +2 -0
- package/dist/tools/model-building/get-all-cube-rules.js +149 -0
- package/dist/tools/model-building/get-cube-rules.d.ts +2 -0
- package/dist/tools/model-building/get-cube-rules.js +69 -0
- package/dist/tools/model-building/rules-source.d.ts +21 -0
- package/dist/tools/model-building/rules-source.js +49 -0
- package/dist/tools/model-building/search-rules.d.ts +2 -0
- package/dist/tools/model-building/search-rules.js +132 -0
- package/dist/tools/model-building/set-cube-rules.d.ts +2 -0
- package/dist/tools/model-building/set-cube-rules.js +81 -0
- package/dist/tools/model-building/unload-cube.d.ts +2 -0
- package/dist/tools/model-building/unload-cube.js +23 -0
- package/dist/tools/operations/diagnose-process-error.d.ts +2 -0
- package/dist/tools/operations/diagnose-process-error.js +178 -0
- package/dist/tools/operations/error-log-helpers.d.ts +25 -0
- package/dist/tools/operations/error-log-helpers.js +57 -0
- package/dist/tools/operations/get-audit-log.d.ts +2 -0
- package/dist/tools/operations/get-audit-log.js +70 -0
- package/dist/tools/operations/get-cube-stats.d.ts +2 -0
- package/dist/tools/operations/get-cube-stats.js +107 -0
- package/dist/tools/operations/get-error-log-content.d.ts +2 -0
- package/dist/tools/operations/get-error-log-content.js +164 -0
- package/dist/tools/operations/get-jobs.d.ts +3 -0
- package/dist/tools/operations/get-jobs.js +51 -0
- package/dist/tools/operations/get-message-log.d.ts +2 -0
- package/dist/tools/operations/get-message-log.js +63 -0
- package/dist/tools/operations/get-server-info.d.ts +2 -0
- package/dist/tools/operations/get-server-info.js +180 -0
- package/dist/tools/operations/get-server-state.d.ts +2 -0
- package/dist/tools/operations/get-server-state.js +129 -0
- package/dist/tools/operations/get-sessions.d.ts +2 -0
- package/dist/tools/operations/get-sessions.js +76 -0
- package/dist/tools/operations/get-threads.d.ts +3 -0
- package/dist/tools/operations/get-threads.js +50 -0
- package/dist/tools/operations/get-transaction-log.d.ts +2 -0
- package/dist/tools/operations/get-transaction-log.js +63 -0
- package/dist/tools/operations/list-error-logs.d.ts +8 -0
- package/dist/tools/operations/list-error-logs.js +157 -0
- package/dist/tools/operations/save-data.d.ts +2 -0
- package/dist/tools/operations/save-data.js +50 -0
- package/dist/tools/pagination.d.ts +32 -0
- package/dist/tools/pagination.js +116 -0
- package/dist/tools/scheduling/create-chore.d.ts +2 -0
- package/dist/tools/scheduling/create-chore.js +93 -0
- package/dist/tools/scheduling/delete-chore.d.ts +2 -0
- package/dist/tools/scheduling/delete-chore.js +22 -0
- package/dist/tools/scheduling/execute-chore.d.ts +2 -0
- package/dist/tools/scheduling/execute-chore.js +52 -0
- package/dist/tools/scheduling/toggle-chore.d.ts +2 -0
- package/dist/tools/scheduling/toggle-chore.js +22 -0
- package/dist/tools/scheduling/update-chore.d.ts +2 -0
- package/dist/tools/scheduling/update-chore.js +71 -0
- package/dist/tools/schemas/common.d.ts +10 -0
- package/dist/tools/schemas/common.js +23 -0
- package/dist/tools/schemas/items-analysis.d.ts +394 -0
- package/dist/tools/schemas/items-analysis.js +419 -0
- package/dist/tools/schemas/items-cells.d.ts +70 -0
- package/dist/tools/schemas/items-cells.js +65 -0
- package/dist/tools/schemas/items-common.d.ts +18 -0
- package/dist/tools/schemas/items-common.js +39 -0
- package/dist/tools/schemas/items-fileops.d.ts +11 -0
- package/dist/tools/schemas/items-fileops.js +13 -0
- package/dist/tools/schemas/items-metadata.d.ts +262 -0
- package/dist/tools/schemas/items-metadata.js +184 -0
- package/dist/tools/schemas/items-monitoring.d.ts +79 -0
- package/dist/tools/schemas/items-monitoring.js +78 -0
- package/dist/tools/schemas/items-processes.d.ts +279 -0
- package/dist/tools/schemas/items-processes.js +235 -0
- package/dist/tools/schemas/items-scheduling.d.ts +25 -0
- package/dist/tools/schemas/items-scheduling.js +26 -0
- package/dist/tools/schemas/items-security.d.ts +19 -0
- package/dist/tools/schemas/items-security.js +12 -0
- package/dist/tools/schemas/items-subsets.d.ts +2 -0
- package/dist/tools/schemas/items-subsets.js +4 -0
- package/dist/tools/schemas/items-views.d.ts +38 -0
- package/dist/tools/schemas/items-views.js +26 -0
- package/dist/tools/schemas/items.d.ts +12 -0
- package/dist/tools/schemas/items.js +23 -0
- package/dist/tools/schemas/markdown-capable.d.ts +21 -0
- package/dist/tools/schemas/markdown-capable.js +58 -0
- package/dist/tools/schemas/output-schema.d.ts +24 -0
- package/dist/tools/schemas/output-schema.js +25 -0
- package/dist/tools/security/assign-client-group.d.ts +2 -0
- package/dist/tools/security/assign-client-group.js +20 -0
- package/dist/tools/security/create-client.d.ts +2 -0
- package/dist/tools/security/create-client.js +28 -0
- package/dist/tools/security/delete-client.d.ts +2 -0
- package/dist/tools/security/delete-client.js +22 -0
- package/dist/tools/security/get-client.d.ts +2 -0
- package/dist/tools/security/get-client.js +20 -0
- package/dist/tools/security/list-clients.d.ts +2 -0
- package/dist/tools/security/list-clients.js +86 -0
- package/dist/tools/security/list-groups.d.ts +2 -0
- package/dist/tools/security/list-groups.js +43 -0
- package/dist/tools/security/remove-client-group.d.ts +2 -0
- package/dist/tools/security/remove-client-group.js +27 -0
- package/dist/tools/security/update-client.d.ts +2 -0
- package/dist/tools/security/update-client.js +22 -0
- package/dist/tools/subsets/create-subset.d.ts +2 -0
- package/dist/tools/subsets/create-subset.js +44 -0
- package/dist/tools/subsets/delete-subset.d.ts +2 -0
- package/dist/tools/subsets/delete-subset.js +26 -0
- package/dist/tools/subsets/get-subset.d.ts +2 -0
- package/dist/tools/subsets/get-subset.js +29 -0
- package/dist/tools/subsets/list-subsets.d.ts +2 -0
- package/dist/tools/subsets/list-subsets.js +36 -0
- package/dist/tools/subsets/update-subset.d.ts +2 -0
- package/dist/tools/subsets/update-subset.js +33 -0
- package/dist/tools/ti-development/check-process-code.d.ts +2 -0
- package/dist/tools/ti-development/check-process-code.js +96 -0
- package/dist/tools/ti-development/compile-process.d.ts +2 -0
- package/dist/tools/ti-development/compile-process.js +32 -0
- package/dist/tools/ti-development/copy-process.d.ts +2 -0
- package/dist/tools/ti-development/copy-process.js +32 -0
- package/dist/tools/ti-development/delete-process.d.ts +2 -0
- package/dist/tools/ti-development/delete-process.js +26 -0
- package/dist/tools/ti-development/diff-process-with-file.d.ts +2 -0
- package/dist/tools/ti-development/diff-process-with-file.js +208 -0
- package/dist/tools/ti-development/diff-processes.d.ts +2 -0
- package/dist/tools/ti-development/diff-processes.js +312 -0
- package/dist/tools/ti-development/execute-process.d.ts +8 -0
- package/dist/tools/ti-development/execute-process.js +109 -0
- package/dist/tools/ti-development/export-process-to-git.d.ts +2 -0
- package/dist/tools/ti-development/export-process-to-git.js +113 -0
- package/dist/tools/ti-development/export-process-to-pro.d.ts +2 -0
- package/dist/tools/ti-development/export-process-to-pro.js +117 -0
- package/dist/tools/ti-development/get-all-processes-code.d.ts +2 -0
- package/dist/tools/ti-development/get-all-processes-code.js +131 -0
- package/dist/tools/ti-development/get-process-code.d.ts +2 -0
- package/dist/tools/ti-development/get-process-code.js +100 -0
- package/dist/tools/ti-development/get-process-datasource.d.ts +2 -0
- package/dist/tools/ti-development/get-process-datasource.js +20 -0
- package/dist/tools/ti-development/get-process-parameters.d.ts +2 -0
- package/dist/tools/ti-development/get-process-parameters.js +25 -0
- package/dist/tools/ti-development/get-process-variables.d.ts +2 -0
- package/dist/tools/ti-development/get-process-variables.js +38 -0
- package/dist/tools/ti-development/get-process.d.ts +2 -0
- package/dist/tools/ti-development/get-process.js +163 -0
- package/dist/tools/ti-development/import-pro-file.d.ts +2 -0
- package/dist/tools/ti-development/import-pro-file.js +153 -0
- package/dist/tools/ti-development/import-process-from-git.d.ts +2 -0
- package/dist/tools/ti-development/import-process-from-git.js +198 -0
- package/dist/tools/ti-development/install-pro-bundle.d.ts +2 -0
- package/dist/tools/ti-development/install-pro-bundle.js +288 -0
- package/dist/tools/ti-development/preflight.d.ts +39 -0
- package/dist/tools/ti-development/preflight.js +56 -0
- package/dist/tools/ti-development/process-backup.d.ts +29 -0
- package/dist/tools/ti-development/process-backup.js +118 -0
- package/dist/tools/ti-development/search-code.d.ts +2 -0
- package/dist/tools/ti-development/search-code.js +208 -0
- package/dist/tools/ti-development/upsert-process.d.ts +2 -0
- package/dist/tools/ti-development/upsert-process.js +167 -0
- package/dist/tools/ti-development/validate-process-refs.d.ts +2 -0
- package/dist/tools/ti-development/validate-process-refs.js +73 -0
- package/dist/tools/views/create-mdx-view.d.ts +2 -0
- package/dist/tools/views/create-mdx-view.js +21 -0
- package/dist/tools/views/create-native-view.d.ts +2 -0
- package/dist/tools/views/create-native-view.js +81 -0
- package/dist/tools/views/delete-view.d.ts +2 -0
- package/dist/tools/views/delete-view.js +23 -0
- package/dist/tools/views/list-views.d.ts +2 -0
- package/dist/tools/views/list-views.js +32 -0
- package/dist/tools/with-annotations.d.ts +6 -0
- package/dist/tools/with-annotations.js +339 -0
- package/dist/types.d.ts +409 -0
- package/dist/types.js +91 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.js +18 -0
- 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
|