@cplace/mcp-server 1.9.1 → 1.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/README.md +12 -13
  2. package/dist/index.js +4 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/plugins/app-catalog.js +1 -1
  5. package/dist/plugins/app-catalog.js.map +1 -1
  6. package/dist/plugins/application-settings.d.ts.map +1 -1
  7. package/dist/plugins/application-settings.js +6 -3
  8. package/dist/plugins/application-settings.js.map +1 -1
  9. package/dist/plugins/core/widget-specifications/cf.cplace.platform.tableWidget/columns.md +6 -0
  10. package/dist/plugins/core.d.ts.map +1 -1
  11. package/dist/plugins/core.js +25 -13
  12. package/dist/plugins/core.js.map +1 -1
  13. package/dist/plugins/forms-wizard.js +2 -2
  14. package/dist/plugins/forms-wizard.js.map +1 -1
  15. package/dist/plugins/history.d.ts.map +1 -1
  16. package/dist/plugins/history.js +6 -3
  17. package/dist/plugins/history.js.map +1 -1
  18. package/dist/plugins/jobs.js +2 -2
  19. package/dist/plugins/jobs.js.map +1 -1
  20. package/dist/plugins/layouts.d.ts.map +1 -1
  21. package/dist/plugins/layouts.js +17 -8
  22. package/dist/plugins/layouts.js.map +1 -1
  23. package/dist/plugins/low-code.d.ts.map +1 -1
  24. package/dist/plugins/low-code.js +48 -17
  25. package/dist/plugins/low-code.js.map +1 -1
  26. package/dist/plugins/project-planning.d.ts.map +1 -1
  27. package/dist/plugins/project-planning.js +6 -3
  28. package/dist/plugins/project-planning.js.map +1 -1
  29. package/dist/plugins/resource-management.d.ts.map +1 -1
  30. package/dist/plugins/resource-management.js +6 -3
  31. package/dist/plugins/resource-management.js.map +1 -1
  32. package/dist/plugins/solution-management.d.ts.map +1 -1
  33. package/dist/plugins/solution-management.js +6 -3
  34. package/dist/plugins/solution-management.js.map +1 -1
  35. package/dist/plugins/types-write.d.ts.map +1 -1
  36. package/dist/plugins/types-write.js +6 -3
  37. package/dist/plugins/types-write.js.map +1 -1
  38. package/dist/plugins/widget-specifications.d.ts.map +1 -1
  39. package/dist/plugins/widget-specifications.js +2 -2
  40. package/dist/plugins/widget-specifications.js.map +1 -1
  41. package/dist/plugins/workspace-admin.d.ts.map +1 -1
  42. package/dist/plugins/workspace-admin.js +6 -3
  43. package/dist/plugins/workspace-admin.js.map +1 -1
  44. package/dist/str-replace-utils.js +1 -1
  45. package/dist/str-replace-utils.js.map +1 -1
  46. package/dist/tools/apps-catalog.d.ts +1 -1
  47. package/dist/tools/apps-catalog.d.ts.map +1 -1
  48. package/dist/tools/apps-catalog.js +16 -12
  49. package/dist/tools/apps-catalog.js.map +1 -1
  50. package/dist/tools/board-widget.d.ts +2 -2
  51. package/dist/tools/board-widget.d.ts.map +1 -1
  52. package/dist/tools/board-widget.js +354 -201
  53. package/dist/tools/board-widget.js.map +1 -1
  54. package/dist/tools/change-listeners.d.ts +2 -2
  55. package/dist/tools/change-listeners.d.ts.map +1 -1
  56. package/dist/tools/change-listeners.js +125 -57
  57. package/dist/tools/change-listeners.js.map +1 -1
  58. package/dist/tools/common-schemas.d.ts +1 -1
  59. package/dist/tools/common-schemas.d.ts.map +1 -1
  60. package/dist/tools/common-schemas.js +5 -3
  61. package/dist/tools/common-schemas.js.map +1 -1
  62. package/dist/tools/csv-export.d.ts +2 -2
  63. package/dist/tools/csv-export.d.ts.map +1 -1
  64. package/dist/tools/csv-export.js +29 -24
  65. package/dist/tools/csv-export.js.map +1 -1
  66. package/dist/tools/documents.d.ts +2 -2
  67. package/dist/tools/documents.d.ts.map +1 -1
  68. package/dist/tools/documents.js +34 -14
  69. package/dist/tools/documents.js.map +1 -1
  70. package/dist/tools/expert-settings.d.ts +3 -3
  71. package/dist/tools/expert-settings.d.ts.map +1 -1
  72. package/dist/tools/expert-settings.js +97 -38
  73. package/dist/tools/expert-settings.js.map +1 -1
  74. package/dist/tools/get-operations.d.ts +2 -2
  75. package/dist/tools/get-operations.d.ts.map +1 -1
  76. package/dist/tools/get-operations.js +29 -21
  77. package/dist/tools/get-operations.js.map +1 -1
  78. package/dist/tools/job-schedule-trigger.d.ts +2 -2
  79. package/dist/tools/job-schedule-trigger.d.ts.map +1 -1
  80. package/dist/tools/job-schedule-trigger.js +19 -10
  81. package/dist/tools/job-schedule-trigger.js.map +1 -1
  82. package/dist/tools/job-scripts.d.ts +2 -2
  83. package/dist/tools/job-scripts.d.ts.map +1 -1
  84. package/dist/tools/job-scripts.js +119 -55
  85. package/dist/tools/job-scripts.js.map +1 -1
  86. package/dist/tools/jobs.d.ts +2 -2
  87. package/dist/tools/jobs.d.ts.map +1 -1
  88. package/dist/tools/jobs.js +68 -38
  89. package/dist/tools/jobs.js.map +1 -1
  90. package/dist/tools/layout-richstring-shared.d.ts +24 -1
  91. package/dist/tools/layout-richstring-shared.d.ts.map +1 -1
  92. package/dist/tools/layout-richstring-shared.js +99 -1
  93. package/dist/tools/layout-richstring-shared.js.map +1 -1
  94. package/dist/tools/layout-richstring-widgets.d.ts +94 -2
  95. package/dist/tools/layout-richstring-widgets.d.ts.map +1 -1
  96. package/dist/tools/layout-richstring-widgets.js +247 -25
  97. package/dist/tools/layout-richstring-widgets.js.map +1 -1
  98. package/dist/tools/layout.d.ts +5 -4
  99. package/dist/tools/layout.d.ts.map +1 -1
  100. package/dist/tools/layout.js +235 -124
  101. package/dist/tools/layout.js.map +1 -1
  102. package/dist/tools/linting.d.ts +2 -2
  103. package/dist/tools/linting.d.ts.map +1 -1
  104. package/dist/tools/linting.js +5 -5
  105. package/dist/tools/linting.js.map +1 -1
  106. package/dist/tools/page-action-simulation.d.ts +18 -0
  107. package/dist/tools/page-action-simulation.d.ts.map +1 -0
  108. package/dist/tools/page-action-simulation.js +88 -0
  109. package/dist/tools/page-action-simulation.js.map +1 -0
  110. package/dist/tools/page-actions.d.ts +60 -0
  111. package/dist/tools/page-actions.d.ts.map +1 -0
  112. package/dist/tools/page-actions.js +284 -0
  113. package/dist/tools/page-actions.js.map +1 -0
  114. package/dist/tools/pages.d.ts +3 -3
  115. package/dist/tools/pages.d.ts.map +1 -1
  116. package/dist/tools/pages.js +237 -112
  117. package/dist/tools/pages.js.map +1 -1
  118. package/dist/tools/ppt-export-schemas.d.ts +1 -1
  119. package/dist/tools/ppt-export-schemas.d.ts.map +1 -1
  120. package/dist/tools/ppt-export-schemas.js +269 -122
  121. package/dist/tools/ppt-export-schemas.js.map +1 -1
  122. package/dist/tools/ppt-export.d.ts +2 -2
  123. package/dist/tools/ppt-export.d.ts.map +1 -1
  124. package/dist/tools/ppt-export.js +82 -43
  125. package/dist/tools/ppt-export.js.map +1 -1
  126. package/dist/tools/profile-management.d.ts +2 -2
  127. package/dist/tools/profile-management.d.ts.map +1 -1
  128. package/dist/tools/profile-management.js +109 -82
  129. package/dist/tools/profile-management.js.map +1 -1
  130. package/dist/tools/references.d.ts +2 -2
  131. package/dist/tools/references.d.ts.map +1 -1
  132. package/dist/tools/references.js +36 -24
  133. package/dist/tools/references.js.map +1 -1
  134. package/dist/tools/resource-planner-widget.d.ts +2 -2
  135. package/dist/tools/resource-planner-widget.d.ts.map +1 -1
  136. package/dist/tools/resource-planner-widget.js +334 -138
  137. package/dist/tools/resource-planner-widget.js.map +1 -1
  138. package/dist/tools/richstring-marker-resolver.d.ts +16 -0
  139. package/dist/tools/richstring-marker-resolver.d.ts.map +1 -0
  140. package/dist/tools/richstring-marker-resolver.js +47 -0
  141. package/dist/tools/richstring-marker-resolver.js.map +1 -0
  142. package/dist/tools/richstring-widgets.d.ts +6 -16
  143. package/dist/tools/richstring-widgets.d.ts.map +1 -1
  144. package/dist/tools/richstring-widgets.js +184 -129
  145. package/dist/tools/richstring-widgets.js.map +1 -1
  146. package/dist/tools/schedule.d.ts +2 -2
  147. package/dist/tools/schedule.d.ts.map +1 -1
  148. package/dist/tools/schedule.js +23 -14
  149. package/dist/tools/schedule.js.map +1 -1
  150. package/dist/tools/script-logs.d.ts +2 -2
  151. package/dist/tools/script-logs.d.ts.map +1 -1
  152. package/dist/tools/script-logs.js +71 -32
  153. package/dist/tools/script-logs.js.map +1 -1
  154. package/dist/tools/script.d.ts +2 -2
  155. package/dist/tools/script.d.ts.map +1 -1
  156. package/dist/tools/script.js +44 -26
  157. package/dist/tools/script.js.map +1 -1
  158. package/dist/tools/search.d.ts +2 -2
  159. package/dist/tools/search.d.ts.map +1 -1
  160. package/dist/tools/search.js +139 -102
  161. package/dist/tools/search.js.map +1 -1
  162. package/dist/tools/solution-packages.d.ts +2 -2
  163. package/dist/tools/solution-packages.d.ts.map +1 -1
  164. package/dist/tools/solution-packages.js +149 -61
  165. package/dist/tools/solution-packages.js.map +1 -1
  166. package/dist/tools/system.d.ts +2 -2
  167. package/dist/tools/system.d.ts.map +1 -1
  168. package/dist/tools/system.js +43 -21
  169. package/dist/tools/system.js.map +1 -1
  170. package/dist/tools/type-layouts.d.ts +2 -2
  171. package/dist/tools/type-layouts.d.ts.map +1 -1
  172. package/dist/tools/type-layouts.js +67 -31
  173. package/dist/tools/type-layouts.js.map +1 -1
  174. package/dist/tools/type-management.d.ts +86 -70
  175. package/dist/tools/type-management.d.ts.map +1 -1
  176. package/dist/tools/type-management.js +407 -138
  177. package/dist/tools/type-management.js.map +1 -1
  178. package/dist/tools/url-resolution.d.ts +2 -2
  179. package/dist/tools/url-resolution.d.ts.map +1 -1
  180. package/dist/tools/url-resolution.js +16 -12
  181. package/dist/tools/url-resolution.js.map +1 -1
  182. package/dist/tools/users.d.ts +2 -2
  183. package/dist/tools/users.d.ts.map +1 -1
  184. package/dist/tools/users.js +24 -14
  185. package/dist/tools/users.js.map +1 -1
  186. package/dist/tools/validators.d.ts +2 -2
  187. package/dist/tools/validators.d.ts.map +1 -1
  188. package/dist/tools/validators.js +68 -35
  189. package/dist/tools/validators.js.map +1 -1
  190. package/dist/tools/version-check.d.ts +2 -2
  191. package/dist/tools/version-check.d.ts.map +1 -1
  192. package/dist/tools/version-check.js +36 -30
  193. package/dist/tools/version-check.js.map +1 -1
  194. package/dist/tools/version-history.d.ts +2 -2
  195. package/dist/tools/version-history.d.ts.map +1 -1
  196. package/dist/tools/version-history.js +72 -41
  197. package/dist/tools/version-history.js.map +1 -1
  198. package/dist/tools/widget-simulation.d.ts +5 -6
  199. package/dist/tools/widget-simulation.d.ts.map +1 -1
  200. package/dist/tools/widget-simulation.js +60 -42
  201. package/dist/tools/widget-simulation.js.map +1 -1
  202. package/dist/tools/widget-tool-helpers.d.ts +17 -1
  203. package/dist/tools/widget-tool-helpers.d.ts.map +1 -1
  204. package/dist/tools/widget-tool-helpers.js +41 -6
  205. package/dist/tools/widget-tool-helpers.js.map +1 -1
  206. package/dist/tools/widgets.d.ts +2 -2
  207. package/dist/tools/widgets.d.ts.map +1 -1
  208. package/dist/tools/widgets.js +62 -43
  209. package/dist/tools/widgets.js.map +1 -1
  210. package/dist/tools/wizards.d.ts +2 -2
  211. package/dist/tools/wizards.d.ts.map +1 -1
  212. package/dist/tools/wizards.js +378 -182
  213. package/dist/tools/wizards.js.map +1 -1
  214. package/dist/tools/workflow-execution.d.ts +2 -2
  215. package/dist/tools/workflow-execution.d.ts.map +1 -1
  216. package/dist/tools/workflow-execution.js +27 -19
  217. package/dist/tools/workflow-execution.js.map +1 -1
  218. package/dist/tools/workflow-scripts.d.ts +2 -2
  219. package/dist/tools/workflow-scripts.d.ts.map +1 -1
  220. package/dist/tools/workflow-scripts.js +168 -81
  221. package/dist/tools/workflow-scripts.js.map +1 -1
  222. package/dist/tools/workflow.d.ts +2 -2
  223. package/dist/tools/workflow.d.ts.map +1 -1
  224. package/dist/tools/workflow.js +185 -74
  225. package/dist/tools/workflow.js.map +1 -1
  226. package/dist/tools/workspace-admin.d.ts +2 -2
  227. package/dist/tools/workspace-admin.d.ts.map +1 -1
  228. package/dist/tools/workspace-admin.js +82 -40
  229. package/dist/tools/workspace-admin.js.map +1 -1
  230. package/dist/tools/workspace-core.d.ts +2 -2
  231. package/dist/tools/workspace-core.d.ts.map +1 -1
  232. package/dist/tools/workspace-core.js +93 -53
  233. package/dist/tools/workspace-core.js.map +1 -1
  234. package/dist/utils/dateValidation.js.map +1 -1
  235. package/package.json +9 -4
@@ -1,122 +1,300 @@
1
- import { z } from "zod";
2
- import { debugLogWithTag } from "../logger.js";
1
+ import { z } from 'zod';
2
+ import { debugLogWithTag } from '../logger.js';
3
3
  const TOOL_MANAGE_TYPE_DEFINITION = 'cplace_manage_type_definition';
4
4
  const TOOL_MANAGE_ATTRIBUTE_DEFINITION = 'cplace_manage_attribute_definition';
5
5
  const TOOL_DELETE_TYPE_DEFINITION = 'cplace_delete_type_definition';
6
6
  const TOOL_DELETE_ATTRIBUTE_DEFINITION = 'cplace_delete_attribute_definition';
7
+ const TOOL_LIST_CUSTOM_CONSTRAINT_TYPES = 'cplace_list_custom_constraint_types';
8
+ let cachedCustomConstraintTypes = null;
9
+ const MANAGE_ATTRIBUTE_BASE_DESCRIPTION = 'Create or update attribute definitions within existing type definitions. Supports all major constraint types including string, number, boolean, date, reference, enumeration, and specialized types like rich text and colors. Provides comprehensive configuration options for display properties, validation, and low-code integration.';
10
+ export function buildManageAttributeDefinitionDescription(customTypes) {
11
+ if (customTypes && customTypes.length > 0) {
12
+ const lines = customTypes.map((ct) => {
13
+ const mult = ct.allowedMultiplicities && ct.allowedMultiplicities.length > 0
14
+ ? `multiplicity: ${ct.allowedMultiplicities.join(', ')}`
15
+ : 'any multiplicity';
16
+ return `- ${ct.constraintName} (${mult})`;
17
+ });
18
+ return `${MANAGE_ATTRIBUTE_BASE_DESCRIPTION}\n\nCustom constraint types detected at startup:\n${lines.join('\n')}\nFor live/authoritative list, call cplace_list_custom_constraint_types.`;
19
+ }
20
+ return `${MANAGE_ATTRIBUTE_BASE_DESCRIPTION}\n\nCustom constraint types from installed plugins are supported. Call cplace_list_custom_constraint_types to see names and allowed multiplicities.`;
21
+ }
22
+ export async function primeCustomConstraintTypeCache(client) {
23
+ try {
24
+ const controller = new AbortController();
25
+ const timeoutId = setTimeout(() => controller.abort(), 5000);
26
+ try {
27
+ const result = await client.makeApiRequest('json/custom-constraint-types', 'GET');
28
+ clearTimeout(timeoutId);
29
+ const entries = Array.isArray(result) ? result : (result?.result ?? []);
30
+ if (Array.isArray(entries)) {
31
+ cachedCustomConstraintTypes = entries;
32
+ TYPE_MANAGEMENT_TOOL_DEFINITIONS[TOOL_MANAGE_ATTRIBUTE_DEFINITION].description =
33
+ buildManageAttributeDefinitionDescription(cachedCustomConstraintTypes);
34
+ debugLogWithTag('TYPE_MANAGEMENT', `Primed custom constraint type cache with ${entries.length} entries`);
35
+ }
36
+ }
37
+ finally {
38
+ clearTimeout(timeoutId);
39
+ }
40
+ }
41
+ catch (error) {
42
+ debugLogWithTag('TYPE_MANAGEMENT', `Failed to prime custom constraint type cache: ${error instanceof Error ? error.message : String(error)}`);
43
+ cachedCustomConstraintTypes = null;
44
+ }
45
+ }
46
+ function appendCustomConstraintHintIfNeeded(errorText) {
47
+ const isUnknownType = errorText.includes('Unknown constraint type');
48
+ const isBadMultiplicity = errorText.includes('Multiplicity') && errorText.includes('not allowed');
49
+ if (isUnknownType || isBadMultiplicity) {
50
+ return (errorText +
51
+ '\n\nHint: call cplace_list_custom_constraint_types to see supported custom constraint names and their allowed multiplicities.');
52
+ }
53
+ return errorText;
54
+ }
7
55
  export const TYPE_MANAGEMENT_TOOL_DEFINITIONS = {
8
56
  [TOOL_MANAGE_TYPE_DEFINITION]: {
9
- description: "Create or update type definitions in a workspace with comprehensive configuration options. All properties from the enhanced read endpoint are available for both creation and updates to enable complete type configuration.",
57
+ description: 'Create or update type definitions in a workspace with comprehensive configuration options. All properties from the enhanced read endpoint are available for both creation and updates to enable complete type configuration.',
10
58
  inputSchema: {
11
- operation: z.enum(["create", "update"]).describe("Operation type: 'create' for new type definitions, 'update' for existing type definitions"),
12
- workspaceId: z.string().optional().describe("Required for both: Target workspace ID (e.g., 'abc123')"),
13
- typeInternalName: z.string().optional().describe("Type internal name (e.g., 'cf.example.myType') - no trailing dot (NOT `typeId` or `typeName`)"),
14
- localizedNames: z.record(z.string()).optional().describe("Localized type names (singular) - e.g., {\"en\": \"My Type\", \"de\": \"Mein Typ\"}"),
15
- localizedPlural: z.record(z.string()).optional().describe("Localized type names (plural) - e.g., {\"en\": \"My Types\", \"de\": \"Meine Typen\"}"),
16
- description: z.string().optional().describe("Type description"),
17
- showInExplorer: z.boolean().optional().describe("Whether to show in explorer (default: true for create)"),
18
- readers: z.array(z.string()).optional().describe("Create only: Reader principal IDs (e.g., ['person/user1', 'group/editors'])"),
19
- writers: z.array(z.string()).optional().describe("Create only: Writer principal IDs (e.g., ['person/user2'])"),
20
- readersAreDefault: z.boolean().optional().describe("Create only: Whether readers use default permissions"),
21
- writersAreDefault: z.boolean().optional().describe("Create only: Whether writers use default permissions"),
22
- editorsMayDeletePages: z.boolean().optional().describe("Whether editors can delete pages (default: false for create)"),
23
- showNewButton: z.boolean().optional().describe("Show 'New' button in UI (default: true for create)"),
24
- showInGlobalNewDialog: z.boolean().optional().describe("Include in global new dialog (default: true for create)"),
25
- showInGlobalSearch: z.boolean().optional().describe("Include in global search (default: true for create)"),
26
- namesAreUnique: z.boolean().optional().describe("Create only: Whether page names must be unique (default: false)"),
27
- enableIconLink: z.boolean().optional().describe("Enable icon linking (default: false for create)"),
28
- hideTabVersions: z.boolean().optional().describe("Hide versions tab (default: false for create)"),
29
- allowDivergentLayouts: z.boolean().optional().describe("Allow different layouts per page (default: false for create)"),
30
- iconName: z.string().optional().describe("FontAwesome icon name (e.g., 'fa-project', 'fa-list') or visual icon identifier for update"),
31
- nameGenerationPattern: z.string().optional().describe("Auto-naming pattern for pages of this type. When configured, page names can be auto-generated during creation. Angle-bracket DSL: `<attributeName>` for attribute values, `<#>` for sequential counter, `<#|numberFormat:\"0000\">` for zero-padded counter (zero-pad only via numberFormat filter, never via repeated `#`). Examples: `PROJ-<#>` → `PROJ-0`, `PROJ-1`; `PROJ-<#|numberFormat:\"000\">` → `PROJ-000`, `PROJ-001`; `<title>-<#|numberFormat:\"0000\">` → `ProjectAlpha-0001`. Pages can still override with explicit names. Leave empty to require explicit names."),
32
- displayNameGenerationPattern: z.string().optional().describe("Display name pattern for UI representation. Same angle-bracket DSL as nameGenerationPattern (`<attributeName>`, `<#>`, `<#|numberFormat:\"000\">`). Shown in UI, separate from internal page name. Cross-field rule: if this pattern uses the counter `<#>`, then nameGenerationPattern must also use `<#>` — backend validation rejects otherwise."),
33
- autocompleteDetailsPattern: z.string().optional().describe("Autocomplete display format. Angle-bracket DSL for attribute refs only (no counter — counters are instance-creation-time, autocomplete is display-only). Example: `<cf.myApp.title> - <cf.myApp.category>`. Tokens must be actual attribute internal names defined on the type."),
34
- internalAttributeNamePrefix: z.string().optional().describe("Prefix for attribute names (e.g., 'cf.mycompany.risk' - no trailing dot)"),
35
- localizedPageNamesMode: z.enum(["none", "optional", "optional_with_dialog", "mandatory"]).optional().describe("Localized naming mode")
59
+ operation: z
60
+ .enum(['create', 'update'])
61
+ .describe("Operation type: 'create' for new type definitions, 'update' for existing type definitions"),
62
+ workspaceId: z
63
+ .string()
64
+ .optional()
65
+ .describe("Required for both: Target workspace ID (e.g., 'abc123')"),
66
+ typeInternalName: z
67
+ .string()
68
+ .optional()
69
+ .describe("Type internal name (e.g., 'cf.example.myType') - no trailing dot (NOT `typeId` or `typeName`)"),
70
+ localizedNames: z
71
+ .record(z.string())
72
+ .optional()
73
+ .describe('Localized type names (singular) - e.g., {"en": "My Type", "de": "Mein Typ"}'),
74
+ localizedPlural: z
75
+ .record(z.string())
76
+ .optional()
77
+ .describe('Localized type names (plural) - e.g., {"en": "My Types", "de": "Meine Typen"}'),
78
+ description: z.string().optional().describe('Type description'),
79
+ showInExplorer: z.boolean().optional().describe('Deprecated do not use. Default: false.'),
80
+ readers: z
81
+ .array(z.string())
82
+ .optional()
83
+ .describe("Create only: Reader principal IDs (e.g., ['person/user1', 'group/editors'])"),
84
+ writers: z
85
+ .array(z.string())
86
+ .optional()
87
+ .describe("Create only: Writer principal IDs (e.g., ['person/user2'])"),
88
+ readersAreDefault: z
89
+ .boolean()
90
+ .optional()
91
+ .describe('Create only: Whether readers use default permissions'),
92
+ writersAreDefault: z
93
+ .boolean()
94
+ .optional()
95
+ .describe('Create only: Whether writers use default permissions'),
96
+ editorsMayDeletePages: z
97
+ .boolean()
98
+ .optional()
99
+ .describe('Whether editors can delete pages (default: false for create)'),
100
+ showNewButton: z
101
+ .boolean()
102
+ .optional()
103
+ .describe("Show 'New' button in UI (default: true for create)"),
104
+ showInGlobalNewDialog: z
105
+ .boolean()
106
+ .optional()
107
+ .describe('Include in global new dialog (default: true for create)'),
108
+ showInGlobalSearch: z
109
+ .boolean()
110
+ .optional()
111
+ .describe('Include in global search (default: true for create)'),
112
+ namesAreUnique: z
113
+ .boolean()
114
+ .optional()
115
+ .describe('Create only: Whether page names must be unique (default: false)'),
116
+ enableIconLink: z
117
+ .boolean()
118
+ .optional()
119
+ .describe('Enable icon linking (default: false for create)'),
120
+ hideTabVersions: z
121
+ .boolean()
122
+ .optional()
123
+ .describe('Hide versions tab (default: false for create)'),
124
+ allowDivergentLayouts: z
125
+ .boolean()
126
+ .optional()
127
+ .describe('Allow different layouts per page (default: false for create)'),
128
+ iconName: z
129
+ .string()
130
+ .optional()
131
+ .describe("FontAwesome icon name (e.g., 'fa-project', 'fa-list') or visual icon identifier for update"),
132
+ nameGenerationPattern: z
133
+ .string()
134
+ .optional()
135
+ .describe('Auto-naming pattern for pages of this type. When configured, page names can be auto-generated during creation. Angle-bracket DSL: `<attributeName>` for attribute values, `<#>` for sequential counter, `<#|numberFormat:"0000">` for zero-padded counter (zero-pad only via numberFormat filter, never via repeated `#`). Examples: `PROJ-<#>` → `PROJ-0`, `PROJ-1`; `PROJ-<#|numberFormat:"000">` → `PROJ-000`, `PROJ-001`; `<title>-<#|numberFormat:"0000">` → `ProjectAlpha-0001`. Pages can still override with explicit names. Leave empty to require explicit names.'),
136
+ displayNameGenerationPattern: z
137
+ .string()
138
+ .optional()
139
+ .describe('Display name pattern for UI representation. Same angle-bracket DSL as nameGenerationPattern (`<attributeName>`, `<#>`, `<#|numberFormat:"000">`). Shown in UI, separate from internal page name. Cross-field rule: if this pattern uses the counter `<#>`, then nameGenerationPattern must also use `<#>` — backend validation rejects otherwise.'),
140
+ autocompleteDetailsPattern: z
141
+ .string()
142
+ .optional()
143
+ .describe('Autocomplete display format. Angle-bracket DSL for attribute refs only (no counter — counters are instance-creation-time, autocomplete is display-only). Example: `<cf.myApp.title> - <cf.myApp.category>`. Tokens must be actual attribute internal names defined on the type.'),
144
+ internalAttributeNamePrefix: z
145
+ .string()
146
+ .optional()
147
+ .describe("Prefix for attribute names (e.g., 'cf.mycompany.risk' - no trailing dot)"),
148
+ localizedPageNamesMode: z
149
+ .enum(['none', 'optional', 'optional_with_dialog', 'mandatory'])
150
+ .optional()
151
+ .describe('Localized naming mode'),
36
152
  },
37
- annotations: { title: "Manage Type Definition" }
153
+ annotations: { title: 'Manage Type Definition' },
38
154
  },
39
155
  [TOOL_MANAGE_ATTRIBUTE_DEFINITION]: {
40
- description: "Create or update attribute definitions within existing type definitions. Supports all major constraint types including string, number, boolean, date, reference, enumeration, and specialized types like rich text and colors. Provides comprehensive configuration options for display properties, validation, and low-code integration.",
156
+ description: buildManageAttributeDefinitionDescription(cachedCustomConstraintTypes),
41
157
  inputSchema: {
42
- operation: z.enum(["create", "update"]).describe("Operation type: 'create' for new attribute definitions, 'update' for existing attribute definitions"),
158
+ operation: z
159
+ .enum(['create', 'update'])
160
+ .describe("Operation type: 'create' for new attribute definitions, 'update' for existing attribute definitions"),
43
161
  workspaceId: z.string().describe("Target workspace ID (e.g., 'abc123')"),
44
- typeInternalName: z.string().describe("Target type internal name (e.g., 'cf.example.myType') (NOT `typeId` or `typeName`)"),
45
- attributeName: z.string().describe("For create: short name (e.g., 'myAttribute') or full internal name — prefix auto-prepended if missing. For update: full internal name from create response (e.g., 'cf.cplace.myPlugin.myAttribute')"),
46
- multiplicity: z.enum(["exactlyOne", "maximalOne", "atLeastOne", "arbitrary"]).optional().describe("Required for create (except linkedAttribute where it must be omitted). Optional for update."),
47
- constraintConfig: z.object({
48
- constraintType: z.enum([
49
- "string", "longString", "richString", "localizedString",
50
- "number", "boolean", "date", "color", "reference",
51
- "textEnumeration", "numberEnumeration", "dynamicEnumeration", "workflow",
52
- "linkedAttribute"
53
- ]).describe("Constraint type. Note: linkedAttribute constraints cannot be updated via PATCH — delete and recreate instead."),
54
- pattern: z.string().optional().describe("Regex pattern for string validation"),
55
- patternErrorMessage: z.record(z.string()).optional().describe("Localized error messages for pattern validation"),
56
- precision: z.number().optional().describe("Decimal precision (-1 for unlimited)"),
57
- suffix: z.record(z.string()).optional().describe("Localized suffix text"),
58
- specificity: z.enum(["date", "datetime", "time"]).optional().describe("Date specificity"),
59
- withTime: z.boolean().optional().describe("Include time component"),
60
- dateFormat: z.string().optional().describe("Display format"),
61
- targetTypeNames: z.array(z.string()).optional().describe("Required for 'reference': Target type internal names (e.g., ['cf.example.targetType'])"),
62
- targetEntityKind: z.string().optional().describe("Target entity kind"),
63
- sameWorkspace: z.boolean().optional().describe("Restrict to same workspace"),
64
- isHierarchy: z.boolean().optional().describe("Whether this is a hierarchical reference"),
65
- inverseRoleName: z.record(z.string()).optional().describe("Localized inverse role name"),
66
- elements: z.array(z.object({
67
- value: z.string().describe("Enumeration value"),
68
- localizedName: z.record(z.string()).describe("Localized display names"),
69
- icon: z.string().optional().describe("Optional icon name")
70
- })).optional().describe("Required for 'textEnumeration'/'numberEnumeration': Enumeration elements"),
71
- providerClass: z.string().optional().describe("Provider class for dynamicEnumeration"),
72
- providerSimpleName: z.string().optional().describe("Provider simple name for dynamicEnumeration"),
73
- linkedReferenceName: z.string().optional().describe("Required for 'linkedAttribute': name of a reference attribute on the same type"),
74
- linkedPropertyName: z.string().optional().describe("Required for 'linkedAttribute': internal name of the property on the referenced type (e.g., 'cf.cplace.bo.name')")
75
- }).optional().describe("Required for create: Constraint configuration object. Optional for update: New constraint configuration object (replaces existing)."),
76
- localizedNames: z.record(z.string()).optional().describe("Localized attribute names - e.g., {\"en\": \"My Attribute\", \"de\": \"Mein Attribut\"}"),
77
- localizedShortNames: z.record(z.string()).optional().describe("Localized short names - e.g., {\"en\": \"My Attr\", \"de\": \"Mein Attr\"}"),
78
- localizedShortHelp: z.record(z.string()).optional().describe("Localized help text - e.g., {\"en\": \"Help text\", \"de\": \"Hilfetext\"}"),
79
- readOnly: z.boolean().optional().describe("Whether attribute is read-only"),
80
- showInTables: z.boolean().optional().describe("Show in table views"),
81
- showInNewDialog: z.boolean().optional().describe("Show in new item dialogs"),
82
- showValuesWithLineBreak: z.boolean().optional().describe("Display values with line breaks"),
83
- showInAttributesWidget: z.boolean().optional().describe("Show in attribute widgets"),
84
- showInColumnSelection: z.boolean().optional().describe("Include in column selection")
162
+ typeInternalName: z
163
+ .string()
164
+ .describe("Target type internal name (e.g., 'cf.example.myType') (NOT `typeId` or `typeName`)"),
165
+ attributeName: z
166
+ .string()
167
+ .describe("For create: short name (e.g., 'myAttribute') or full internal name — prefix auto-prepended if missing. For update: full internal name from create response (e.g., 'cf.cplace.myPlugin.myAttribute')"),
168
+ multiplicity: z
169
+ .enum(['exactlyOne', 'maximalOne', 'atLeastOne', 'arbitrary'])
170
+ .optional()
171
+ .describe('Required for create (except linkedAttribute where it must be omitted). Optional for update.'),
172
+ constraintConfig: z
173
+ .object({
174
+ constraintType: z
175
+ .string()
176
+ .describe("Built-in: 'string' | 'longString' | 'richString' | 'localizedString' | " +
177
+ "'number' | 'boolean' | 'date' | 'color' | 'reference' | 'textEnumeration'. " +
178
+ "Special: 'workflow', 'linkedAttribute'. " +
179
+ 'Custom constraints from installed plugins are also accepted by constraint name ' +
180
+ "(e.g. 'cf.cplace.timeBoundedValues.customAttributeType'). " +
181
+ 'Call cplace_list_custom_constraint_types to see installed custom constraints. ' +
182
+ 'Note: linkedAttribute constraints cannot be updated via PATCH — delete and recreate.'),
183
+ pattern: z.string().optional().describe('Regex pattern for string validation'),
184
+ patternErrorMessage: z
185
+ .record(z.string())
186
+ .optional()
187
+ .describe('Localized error messages for pattern validation'),
188
+ precision: z.number().optional().describe('Decimal precision (-1 for unlimited)'),
189
+ suffix: z.record(z.string()).optional().describe('Localized suffix text'),
190
+ specificity: z.enum(['date', 'datetime', 'time']).optional().describe('Date specificity'),
191
+ withTime: z.boolean().optional().describe('Include time component'),
192
+ dateFormat: z.string().optional().describe('Display format'),
193
+ targetTypeNames: z
194
+ .array(z.string())
195
+ .optional()
196
+ .describe("Required for 'reference': Target type internal names (e.g., ['cf.example.targetType'])"),
197
+ targetEntityKind: z.string().optional().describe('Target entity kind'),
198
+ sameWorkspace: z.boolean().optional().describe('Restrict to same workspace'),
199
+ isHierarchy: z.boolean().optional().describe('Whether this is a hierarchical reference'),
200
+ inverseRoleName: z.record(z.string()).optional().describe('Localized inverse role name'),
201
+ elements: z
202
+ .array(z.object({
203
+ value: z.string().describe('Enumeration value'),
204
+ localizedName: z.record(z.string()).describe('Localized display names'),
205
+ icon: z.string().optional().describe('Optional icon name'),
206
+ }))
207
+ .optional()
208
+ .describe("Required for 'textEnumeration'/'numberEnumeration': Enumeration elements"),
209
+ providerClass: z.string().optional().describe('Provider class for dynamicEnumeration'),
210
+ providerSimpleName: z
211
+ .string()
212
+ .optional()
213
+ .describe('Provider simple name for dynamicEnumeration'),
214
+ linkedReferenceName: z
215
+ .string()
216
+ .optional()
217
+ .describe("Required for 'linkedAttribute': name of a reference attribute on the same type"),
218
+ linkedPropertyName: z
219
+ .string()
220
+ .optional()
221
+ .describe("Required for 'linkedAttribute': internal name of the property on the referenced type (e.g., 'cf.cplace.bo.name')"),
222
+ })
223
+ .optional()
224
+ .describe('Required for create: Constraint configuration object. Optional for update: New constraint configuration object (replaces existing).'),
225
+ localizedNames: z
226
+ .record(z.string())
227
+ .optional()
228
+ .describe('Localized attribute names - e.g., {"en": "My Attribute", "de": "Mein Attribut"}'),
229
+ localizedShortNames: z
230
+ .record(z.string())
231
+ .optional()
232
+ .describe('Localized short names - e.g., {"en": "My Attr", "de": "Mein Attr"}'),
233
+ localizedShortHelp: z
234
+ .record(z.string())
235
+ .optional()
236
+ .describe('Localized help text - e.g., {"en": "Help text", "de": "Hilfetext"}'),
237
+ readOnly: z.boolean().optional().describe('Whether attribute is read-only'),
238
+ showInTables: z.boolean().optional().describe('Show in table views'),
239
+ showInNewDialog: z.boolean().optional().describe('Show in new item dialogs'),
240
+ showValuesWithLineBreak: z.boolean().optional().describe('Display values with line breaks'),
241
+ showInAttributesWidget: z.boolean().optional().describe('Show in attribute widgets'),
242
+ showInColumnSelection: z.boolean().optional().describe('Include in column selection'),
85
243
  },
86
- annotations: { title: "Manage Attribute Definition" }
244
+ annotations: { title: 'Manage Attribute Definition' },
87
245
  },
88
246
  [TOOL_DELETE_TYPE_DEFINITION]: {
89
247
  description: "Delete a type definition and all its attributes, validators, change listeners, and alternative layouts. Cannot delete types that have existing pages or are referenced by other types' attributes.",
90
248
  inputSchema: {
91
- workspaceId: z.string().describe("ID of the workspace containing the type (e.g., 'workspace/abc123')"),
92
- typeInternalName: z.string().describe("Internal name of the type definition to delete (e.g., 'cf.example.Task') (NOT `typeId` or `typeName`)")
249
+ workspaceId: z
250
+ .string()
251
+ .describe("ID of the workspace containing the type (e.g., 'workspace/abc123')"),
252
+ typeInternalName: z
253
+ .string()
254
+ .describe("Internal name of the type definition to delete (e.g., 'cf.example.Task') (NOT `typeId` or `typeName`)"),
93
255
  },
94
- annotations: { title: "Delete Type Definition" }
256
+ annotations: { title: 'Delete Type Definition' },
95
257
  },
96
258
  [TOOL_DELETE_ATTRIBUTE_DEFINITION]: {
97
- description: "Delete an attribute definition from a type. Cannot delete attributes referenced by validators or change listeners — delete those first.",
259
+ description: 'Delete an attribute definition from a type. Cannot delete attributes referenced by validators or change listeners — delete those first.',
98
260
  inputSchema: {
99
- workspaceId: z.string().describe("ID of the workspace containing the type (e.g., 'workspace/abc123')"),
100
- typeInternalName: z.string().describe("Internal name of the type definition (e.g., 'cf.example.Task') (NOT `typeId` or `typeName`)"),
101
- attributeName: z.string().describe("Internal name of the attribute to delete (e.g., 'cf.cplace.myPlugin.myAttribute')")
261
+ workspaceId: z
262
+ .string()
263
+ .describe("ID of the workspace containing the type (e.g., 'workspace/abc123')"),
264
+ typeInternalName: z
265
+ .string()
266
+ .describe("Internal name of the type definition (e.g., 'cf.example.Task') (NOT `typeId` or `typeName`)"),
267
+ attributeName: z
268
+ .string()
269
+ .describe("Internal name of the attribute to delete (e.g., 'cf.cplace.myPlugin.myAttribute')"),
102
270
  },
103
- annotations: { title: "Delete Attribute Definition" }
104
- }
271
+ annotations: { title: 'Delete Attribute Definition' },
272
+ },
273
+ [TOOL_LIST_CUSTOM_CONSTRAINT_TYPES]: {
274
+ description: "List custom constraint types registered by installed plugins. Returns each constraint's name, allowed multiplicities, and display name. Use the returned names as the 'constraintType' value when creating attributes with cplace_manage_attribute_definition.",
275
+ inputSchema: {},
276
+ annotations: { title: 'List Custom Constraint Types' },
277
+ },
105
278
  };
106
279
  export function registerTypeManagementTools(server, client) {
107
280
  server.registerTool(TOOL_MANAGE_TYPE_DEFINITION, TYPE_MANAGEMENT_TOOL_DEFINITIONS[TOOL_MANAGE_TYPE_DEFINITION], async (params) => {
108
281
  try {
109
- if (params.operation === "create") {
282
+ if (params.operation === 'create') {
110
283
  if (!params.workspaceId || !params.typeInternalName) {
111
284
  return {
112
- content: [{ type: "text", text: "Error: Create operation requires workspaceId and typeInternalName parameters" }],
113
- isError: true
285
+ content: [
286
+ {
287
+ type: 'text',
288
+ text: 'Error: Create operation requires workspaceId and typeInternalName parameters',
289
+ },
290
+ ],
291
+ isError: true,
114
292
  };
115
293
  }
116
294
  debugLogWithTag('TYPE_CREATION', `Creating type definition: ${params.typeInternalName} in workspace: ${params.workspaceId}`);
117
295
  const requestBody = {
118
296
  workspaceId: params.workspaceId,
119
- internalName: params.typeInternalName
297
+ internalName: params.typeInternalName,
120
298
  };
121
299
  if (params.localizedNames)
122
300
  requestBody.localizedNames = params.localizedNames;
@@ -124,8 +302,7 @@ export function registerTypeManagementTools(server, client) {
124
302
  requestBody.localizedPlural = params.localizedPlural;
125
303
  if (params.description)
126
304
  requestBody.description = params.description;
127
- if (params.showInExplorer !== undefined)
128
- requestBody.showInExplorer = params.showInExplorer;
305
+ requestBody.showInExplorer = params.showInExplorer ?? false;
129
306
  if (params.readers)
130
307
  requestBody.readers = params.readers;
131
308
  if (params.writers)
@@ -165,20 +342,25 @@ export function registerTypeManagementTools(server, client) {
165
342
  const result = await client.makeApiRequest('json/type-definition', 'POST', undefined, requestBody);
166
343
  debugLogWithTag('TYPE_CREATION', `Successfully created type definition: ${params.typeInternalName}`);
167
344
  return {
168
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
345
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
169
346
  };
170
347
  }
171
348
  else {
172
349
  if (!params.workspaceId || !params.typeInternalName) {
173
350
  return {
174
- content: [{ type: "text", text: "Error: Update operation requires workspaceId and typeInternalName parameters" }],
175
- isError: true
351
+ content: [
352
+ {
353
+ type: 'text',
354
+ text: 'Error: Update operation requires workspaceId and typeInternalName parameters',
355
+ },
356
+ ],
357
+ isError: true,
176
358
  };
177
359
  }
178
360
  debugLogWithTag('TYPE_UPDATE', `Updating type definition: ${params.typeInternalName} in workspace: ${params.workspaceId}`);
179
361
  const requestBody = {
180
362
  workspaceId: params.workspaceId,
181
- typeInternalName: params.typeInternalName
363
+ typeInternalName: params.typeInternalName,
182
364
  };
183
365
  if (params.localizedNames)
184
366
  requestBody.localizedNames = params.localizedNames;
@@ -217,54 +399,94 @@ export function registerTypeManagementTools(server, client) {
217
399
  const result = await client.makeApiRequest('json/type-definition', 'PATCH', undefined, requestBody);
218
400
  debugLogWithTag('TYPE_UPDATE', `Successfully updated type definition: ${params.typeInternalName}`);
219
401
  return {
220
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
402
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
221
403
  };
222
404
  }
223
405
  }
224
406
  catch (error) {
225
- const operationText = params.operation === "create" ? "creating" : "updating";
226
- debugLogWithTag(params.operation === "create" ? 'TYPE_CREATION' : 'TYPE_UPDATE', `Error ${operationText} type definition: ${error instanceof Error ? error.message : String(error)}`);
407
+ const operationText = params.operation === 'create' ? 'creating' : 'updating';
408
+ debugLogWithTag(params.operation === 'create' ? 'TYPE_CREATION' : 'TYPE_UPDATE', `Error ${operationText} type definition: ${error instanceof Error ? error.message : String(error)}`);
227
409
  return {
228
- content: [{
229
- type: "text",
230
- text: `Error ${operationText} type definition: ${error instanceof Error ? error.message : String(error)}`
231
- }],
232
- isError: true
410
+ content: [
411
+ {
412
+ type: 'text',
413
+ text: `Error ${operationText} type definition: ${error instanceof Error ? error.message : String(error)}`,
414
+ },
415
+ ],
416
+ isError: true,
233
417
  };
234
418
  }
235
419
  });
236
420
  server.registerTool(TOOL_MANAGE_ATTRIBUTE_DEFINITION, TYPE_MANAGEMENT_TOOL_DEFINITIONS[TOOL_MANAGE_ATTRIBUTE_DEFINITION], async (params) => {
237
421
  try {
238
- if (params.operation === "create") {
239
- if (!params.workspaceId || !params.typeInternalName || !params.attributeName || !params.constraintConfig) {
422
+ if (params.operation === 'create') {
423
+ if (!params.workspaceId ||
424
+ !params.typeInternalName ||
425
+ !params.attributeName ||
426
+ !params.constraintConfig) {
240
427
  return {
241
- content: [{ type: "text", text: "Error: Create operation requires workspaceId, typeInternalName, attributeName, and constraintConfig parameters" }],
242
- isError: true
428
+ content: [
429
+ {
430
+ type: 'text',
431
+ text: 'Error: Create operation requires workspaceId, typeInternalName, attributeName, and constraintConfig parameters',
432
+ },
433
+ ],
434
+ isError: true,
435
+ };
436
+ }
437
+ if (params.constraintConfig.additionalConstraintData !== undefined) {
438
+ return {
439
+ content: [
440
+ {
441
+ type: 'text',
442
+ text: 'Error: additionalConstraintData is not supported for custom constraint types in this version.',
443
+ },
444
+ ],
445
+ isError: true,
243
446
  };
244
447
  }
245
448
  const ct = params.constraintConfig.constraintType;
246
- if (ct === "reference") {
247
- const isPersonReference = params.constraintConfig.targetEntityKind === "person";
248
- if (!isPersonReference && (!params.constraintConfig.targetTypeNames || params.constraintConfig.targetTypeNames.length === 0)) {
449
+ if (ct === 'reference') {
450
+ const isPersonReference = params.constraintConfig.targetEntityKind === 'person';
451
+ if (!isPersonReference &&
452
+ (!params.constraintConfig.targetTypeNames ||
453
+ params.constraintConfig.targetTypeNames.length === 0)) {
249
454
  return {
250
- content: [{ type: "text", text: "Error: Reference attributes require 'targetTypeNames' in constraintConfig (e.g., [\"cf.example.targetType\"]). Without it, the attribute defaults to 'any content type'." }],
251
- isError: true
455
+ content: [
456
+ {
457
+ type: 'text',
458
+ text: "Error: Reference attributes require 'targetTypeNames' in constraintConfig (e.g., [\"cf.example.targetType\"]). Without it, the attribute defaults to 'any content type'.",
459
+ },
460
+ ],
461
+ isError: true,
252
462
  };
253
463
  }
254
464
  }
255
- if (ct === "textEnumeration" || ct === "numberEnumeration") {
256
- if (!params.constraintConfig.elements || params.constraintConfig.elements.length === 0) {
465
+ if (ct === 'textEnumeration' || ct === 'numberEnumeration') {
466
+ if (!params.constraintConfig.elements ||
467
+ params.constraintConfig.elements.length === 0) {
257
468
  return {
258
- content: [{ type: "text", text: "Error: Enumeration attributes require 'elements' in constraintConfig with at least one element." }],
259
- isError: true
469
+ content: [
470
+ {
471
+ type: 'text',
472
+ text: "Error: Enumeration attributes require 'elements' in constraintConfig with at least one element.",
473
+ },
474
+ ],
475
+ isError: true,
260
476
  };
261
477
  }
262
478
  }
263
- if (ct === "linkedAttribute") {
264
- if (!params.constraintConfig.linkedReferenceName || !params.constraintConfig.linkedPropertyName) {
479
+ if (ct === 'linkedAttribute') {
480
+ if (!params.constraintConfig.linkedReferenceName ||
481
+ !params.constraintConfig.linkedPropertyName) {
265
482
  return {
266
- content: [{ type: "text", text: "Error: Linked attributes require both 'linkedReferenceName' and 'linkedPropertyName' in constraintConfig." }],
267
- isError: true
483
+ content: [
484
+ {
485
+ type: 'text',
486
+ text: "Error: Linked attributes require both 'linkedReferenceName' and 'linkedPropertyName' in constraintConfig.",
487
+ },
488
+ ],
489
+ isError: true,
268
490
  };
269
491
  }
270
492
  }
@@ -273,7 +495,7 @@ export function registerTypeManagementTools(server, client) {
273
495
  workspaceId: params.workspaceId,
274
496
  typeDefinitionInternalName: params.typeInternalName,
275
497
  attributeName: params.attributeName,
276
- constraintConfig: params.constraintConfig
498
+ constraintConfig: params.constraintConfig,
277
499
  };
278
500
  if (params.multiplicity)
279
501
  requestBody.multiplicity = params.multiplicity;
@@ -298,21 +520,38 @@ export function registerTypeManagementTools(server, client) {
298
520
  const result = await client.makeApiRequest('json/attribute-definition', 'POST', undefined, requestBody);
299
521
  debugLogWithTag('ATTRIBUTE_CREATION', `Successfully created attribute: ${params.attributeName}`);
300
522
  return {
301
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
523
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
302
524
  };
303
525
  }
304
526
  else {
305
527
  if (!params.workspaceId || !params.typeInternalName || !params.attributeName) {
306
528
  return {
307
- content: [{ type: "text", text: "Error: Update operation requires workspaceId, typeInternalName and attributeName parameters" }],
308
- isError: true
529
+ content: [
530
+ {
531
+ type: 'text',
532
+ text: 'Error: Update operation requires workspaceId, typeInternalName and attributeName parameters',
533
+ },
534
+ ],
535
+ isError: true,
536
+ };
537
+ }
538
+ if (params.constraintConfig &&
539
+ params.constraintConfig.additionalConstraintData !== undefined) {
540
+ return {
541
+ content: [
542
+ {
543
+ type: 'text',
544
+ text: 'Error: additionalConstraintData is not supported for custom constraint types in this version.',
545
+ },
546
+ ],
547
+ isError: true,
309
548
  };
310
549
  }
311
550
  debugLogWithTag('ATTRIBUTE_UPDATE', `Updating attribute: ${params.attributeName} for type: ${params.typeInternalName} in workspace: ${params.workspaceId}`);
312
551
  const requestBody = {
313
552
  workspaceId: params.workspaceId,
314
553
  typeDefinitionInternalName: params.typeInternalName,
315
- attributeName: params.attributeName
554
+ attributeName: params.attributeName,
316
555
  };
317
556
  if (params.multiplicity)
318
557
  requestBody.multiplicity = params.multiplicity;
@@ -339,19 +578,39 @@ export function registerTypeManagementTools(server, client) {
339
578
  const result = await client.makeApiRequest('json/attribute-definition', 'PATCH', undefined, requestBody);
340
579
  debugLogWithTag('ATTRIBUTE_UPDATE', `Successfully updated attribute: ${params.attributeName}`);
341
580
  return {
342
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
581
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
343
582
  };
344
583
  }
345
584
  }
346
585
  catch (error) {
347
- const operationText = params.operation === "create" ? "creating" : "updating";
348
- debugLogWithTag(params.operation === "create" ? 'ATTRIBUTE_CREATION' : 'ATTRIBUTE_UPDATE', `Error ${operationText} attribute: ${error instanceof Error ? error.message : String(error)}`);
586
+ const operationText = params.operation === 'create' ? 'creating' : 'updating';
587
+ debugLogWithTag(params.operation === 'create' ? 'ATTRIBUTE_CREATION' : 'ATTRIBUTE_UPDATE', `Error ${operationText} attribute: ${error instanceof Error ? error.message : String(error)}`);
588
+ const rawText = `Error ${operationText} attribute definition: ${error instanceof Error ? error.message : String(error)}`;
349
589
  return {
350
- content: [{
351
- type: "text",
352
- text: `Error ${operationText} attribute definition: ${error instanceof Error ? error.message : String(error)}`
353
- }],
354
- isError: true
590
+ content: [
591
+ {
592
+ type: 'text',
593
+ text: appendCustomConstraintHintIfNeeded(rawText),
594
+ },
595
+ ],
596
+ isError: true,
597
+ };
598
+ }
599
+ });
600
+ server.registerTool(TOOL_LIST_CUSTOM_CONSTRAINT_TYPES, TYPE_MANAGEMENT_TOOL_DEFINITIONS[TOOL_LIST_CUSTOM_CONSTRAINT_TYPES], async () => {
601
+ try {
602
+ const result = await client.makeApiRequest('json/custom-constraint-types', 'GET');
603
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
604
+ }
605
+ catch (error) {
606
+ return {
607
+ content: [
608
+ {
609
+ type: 'text',
610
+ text: `Error listing custom constraint types: ${error instanceof Error ? error.message : String(error)}`,
611
+ },
612
+ ],
613
+ isError: true,
355
614
  };
356
615
  }
357
616
  });
@@ -360,17 +619,22 @@ export function registerTypeManagementTools(server, client) {
360
619
  try {
361
620
  const result = await client.makeApiRequest('json/type-definition', 'DELETE', {
362
621
  workspaceId,
363
- typeDefinitionInternalName: typeInternalName
622
+ typeDefinitionInternalName: typeInternalName,
364
623
  });
365
624
  debugLogWithTag('TYPE_DELETE', `Successfully deleted type definition '${typeInternalName}'`);
366
625
  return {
367
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
626
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
368
627
  };
369
628
  }
370
629
  catch (error) {
371
630
  return {
372
- content: [{ type: "text", text: `Error deleting type definition: ${error instanceof Error ? error.message : String(error)}` }],
373
- isError: true
631
+ content: [
632
+ {
633
+ type: 'text',
634
+ text: `Error deleting type definition: ${error instanceof Error ? error.message : String(error)}`,
635
+ },
636
+ ],
637
+ isError: true,
374
638
  };
375
639
  }
376
640
  });
@@ -380,17 +644,22 @@ export function registerTypeManagementTools(server, client) {
380
644
  const result = await client.makeApiRequest('json/attribute-definition', 'DELETE', {
381
645
  workspaceId,
382
646
  typeDefinitionInternalName: typeInternalName,
383
- attributeName
647
+ attributeName,
384
648
  });
385
649
  debugLogWithTag('ATTRIBUTE_DELETE', `Successfully deleted attribute '${attributeName}'`);
386
650
  return {
387
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
651
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
388
652
  };
389
653
  }
390
654
  catch (error) {
391
655
  return {
392
- content: [{ type: "text", text: `Error deleting attribute definition: ${error instanceof Error ? error.message : String(error)}` }],
393
- isError: true
656
+ content: [
657
+ {
658
+ type: 'text',
659
+ text: `Error deleting attribute definition: ${error instanceof Error ? error.message : String(error)}`,
660
+ },
661
+ ],
662
+ isError: true,
394
663
  };
395
664
  }
396
665
  });