@cplace/mcp-server 1.9.1 → 1.10.5

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 +410 -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,7 +1,7 @@
1
- import { z } from "zod";
2
- import { debugLogWithTag } from "../logger.js";
1
+ import { z } from 'zod';
2
+ import { debugLogWithTag } from '../logger.js';
3
3
  import { checkResponseSize } from '../utils.js';
4
- import { DATE_TIME_FORMAT_DESCRIPTION, jsonStringToObject } from "./common-schemas.js";
4
+ import { DATE_TIME_FORMAT_DESCRIPTION, jsonStringToObject } from './common-schemas.js';
5
5
  import { applyStrReplace } from '../str-replace-utils.js';
6
6
  const TOOL_DELETE_PAGE = 'cplace_delete_page';
7
7
  const TOOL_DELETE_PAGE_WITH_CHILDREN = 'cplace_delete_page_with_children';
@@ -10,56 +10,117 @@ const TOOL_MANAGE_PAGE = 'cplace_manage_page';
10
10
  const TOOL_EDIT_PAGE_CONTENT = 'cplace_edit_page_content';
11
11
  export const PAGE_TOOL_DEFINITIONS = {
12
12
  [TOOL_DELETE_PAGE]: {
13
- description: "⚠️ DESTRUCTIVE OPERATION: Permanently delete a single page. Only works for leaf pages (pages without children). For pages with children, use cplace_delete_page_with_children.",
13
+ description: '⚠️ DESTRUCTIVE OPERATION: Permanently delete a single page. Only works for leaf pages (pages without children). For pages with children, use cplace_delete_page_with_children.',
14
14
  inputSchema: {
15
- pageUID: z.string().describe("The unique identifier (UID) of the page to delete (e.g., 'page/abc123def456')")
15
+ pageUID: z
16
+ .string()
17
+ .describe("The unique identifier (UID) of the page to delete (e.g., 'page/abc123def456')"),
16
18
  },
17
- annotations: { title: "Delete Page" }
19
+ annotations: { title: 'Delete Page' },
18
20
  },
19
21
  [TOOL_DELETE_PAGE_WITH_CHILDREN]: {
20
- description: "⚠️ DESTRUCTIVE OPERATION: Permanently delete a page and optionally all its children. Uses a two-phase workflow: first call shows preview, second call with confirmation performs deletion.",
22
+ description: '⚠️ DESTRUCTIVE OPERATION: Permanently delete a page and optionally all its children. Uses a two-phase workflow: first call shows preview, second call with confirmation performs deletion.',
21
23
  inputSchema: {
22
- pageUID: z.string().describe("The unique identifier (UID) of the page to delete"),
23
- confirmDeleteChildren: z.boolean().optional().default(false).describe("Explicit confirmation flag for bulk deletion. Set to true to confirm deletion of page and all children.")
24
+ pageUID: z.string().describe('The unique identifier (UID) of the page to delete'),
25
+ confirmDeleteChildren: z
26
+ .boolean()
27
+ .optional()
28
+ .default(false)
29
+ .describe('Explicit confirmation flag for bulk deletion. Set to true to confirm deletion of page and all children.'),
24
30
  },
25
- annotations: { title: "Delete Page with Children" }
31
+ annotations: { title: 'Delete Page with Children' },
26
32
  },
27
33
  [TOOL_COPY_PAGE]: {
28
- description: "Copy a page with optional hierarchical copy. Set includeChildren=false for single page copy (leaf pages only), or includeChildren=true for copying page with all children. When includeChildren=true, uses a two-phase workflow: first call shows preview, second call with confirmCopyChildren=true performs the copy.",
34
+ description: 'Copy a page with optional hierarchical copy. Set includeChildren=false for single page copy (leaf pages only), or includeChildren=true for copying page with all children. When includeChildren=true, uses a two-phase workflow: first call shows preview, second call with confirmCopyChildren=true performs the copy.',
29
35
  inputSchema: {
30
36
  sourcePageUID: z.string().describe("The UID of the page to copy (e.g., 'page/abc123def456')"),
31
- includeChildren: z.boolean().describe("Whether to copy child pages. false (default) for single page copy (will fail if page has children), true for hierarchical copy with all descendants."),
32
- confirmCopyChildren: z.boolean().optional().describe("Required confirmation when includeChildren=true. Set to false (or omit) for preview showing child count, set to true to perform the actual bulk copy operation. Ignored when includeChildren=false."),
33
- targetWorkspaceId: z.string().optional().describe("Target workspace ID (e.g., 'workspace789'). Exactly one of targetWorkspaceId or targetParentUID must be provided."),
34
- targetParentUID: z.string().optional().describe("UID of target parent page (e.g., 'page/parent123xyz'). Exactly one of targetWorkspaceId or targetParentUID must be provided."),
35
- newName: z.string().optional().describe("New name for the copied page (optional). If not provided, uses original page name. When includeChildren=true, only the root page is renamed; children retain their original names."),
36
- includeComments: z.boolean().optional().default(false).describe("Whether to copy comments from the page(s). Default: false for single page copy, false for hierarchical copy. Comments add context but increase copy time significantly for large hierarchies."),
37
- includeFiles: z.boolean().optional().default(true).describe("Whether to copy files attached to the page(s). Default: true for single page copy, true for hierarchical copy. Files are typically needed for complete page copies but increase copy time and storage usage.")
37
+ includeChildren: z
38
+ .boolean()
39
+ .describe('Whether to copy child pages. false (default) for single page copy (will fail if page has children), true for hierarchical copy with all descendants.'),
40
+ confirmCopyChildren: z
41
+ .boolean()
42
+ .optional()
43
+ .describe('Required confirmation when includeChildren=true. Set to false (or omit) for preview showing child count, set to true to perform the actual bulk copy operation. Ignored when includeChildren=false.'),
44
+ targetWorkspaceId: z
45
+ .string()
46
+ .optional()
47
+ .describe("Target workspace ID (e.g., 'workspace789'). Exactly one of targetWorkspaceId or targetParentUID must be provided."),
48
+ targetParentUID: z
49
+ .string()
50
+ .optional()
51
+ .describe("UID of target parent page (e.g., 'page/parent123xyz'). Exactly one of targetWorkspaceId or targetParentUID must be provided."),
52
+ newName: z
53
+ .string()
54
+ .optional()
55
+ .describe('New name for the copied page (optional). If not provided, uses original page name. When includeChildren=true, only the root page is renamed; children retain their original names.'),
56
+ includeComments: z
57
+ .boolean()
58
+ .optional()
59
+ .default(false)
60
+ .describe('Whether to copy comments from the page(s). Default: false for single page copy, false for hierarchical copy. Comments add context but increase copy time significantly for large hierarchies.'),
61
+ includeFiles: z
62
+ .boolean()
63
+ .optional()
64
+ .default(true)
65
+ .describe('Whether to copy files attached to the page(s). Default: true for single page copy, true for hierarchical copy. Files are typically needed for complete page copies but increase copy time and storage usage.'),
38
66
  },
39
- annotations: { title: "Copy Page" }
67
+ annotations: { title: 'Copy Page' },
40
68
  },
41
69
  [TOOL_EDIT_PAGE_CONTENT]: {
42
- description: "Edit page wiki content using str_replace — find an exact text match and replace it. Reads current content, applies the replacement, and writes back. Use this instead of cplace_manage_page when making small changes to large page content to avoid reproducing the entire content.\n\nRichString content is in decoded form: embedded widgets appear as `<decoded-widget id=\"…\" type=\"…\">{\"properties\":{…}}</decoded-widget>` — no base64. `old_str` must match the decoded form exactly as returned by reads. Raw base64 `<embeddedwidget>` tags are rejected in both `old_str` and `new_str`.",
70
+ description: 'Edit page wiki content using str_replace — find an exact text match and replace it. Reads current content, applies the replacement, and writes back. Use this instead of cplace_manage_page when making small changes to large page content to avoid reproducing the entire content.\n\nRichString content is in decoded form: embedded widgets appear as `<decoded-widget id="" type="">{"properties":{…}}</decoded-widget>` — no base64. `old_str` must match the decoded form exactly as returned by reads. Raw base64 `<embeddedwidget>` tags are rejected in both `old_str` and `new_str`.\n\nIMPORTANT: cplace normalizes HTML/CSS on every save (CSS properties are alphabetized, hex colors become rgb(), whitespace is regularized). After this tool completes, the stored content may differ from what was submitted. The response includes the current stored form — use it (not your original input) when constructing the next old_str.',
43
71
  inputSchema: {
44
72
  pageUID: z.string().describe("The UID of the page to edit (e.g., 'page/abc123def456')"),
45
- old_str: z.string().describe("The exact text to find in the page content (must match exactly, including whitespace and line breaks)"),
46
- new_str: z.string().describe("The replacement text. Use empty string to delete the matched text."),
47
- replace_all: z.boolean().optional().default(false).describe("If true, replace all occurrences of old_str. If false (default), fails when old_str matches more than once.")
73
+ old_str: z
74
+ .string()
75
+ .describe('The exact text to find in the page content (must match exactly, including whitespace and line breaks)'),
76
+ new_str: z
77
+ .string()
78
+ .describe('The replacement text. Use empty string to delete the matched text.'),
79
+ replace_all: z
80
+ .boolean()
81
+ .optional()
82
+ .default(false)
83
+ .describe('If true, replace all occurrences of old_str. If false (default), fails when old_str matches more than once.'),
48
84
  },
49
- annotations: { title: "Edit Page Content" }
85
+ annotations: { title: 'Edit Page Content' },
50
86
  },
51
87
  [TOOL_MANAGE_PAGE]: {
52
- description: "Create or update a page. Use operation='create' to create new pages with workspace and type. Use operation='update' to modify existing pages by UID. 🔍 IMPORTANT: Use 'cplace_get_type_datamodel' before creating pages to understand attribute requirements.\n\nRichString content (page content and richstring attributes) uses decoded form: `<decoded-widget id=\"…\" type=\"…\">{\"properties\":{…}}</decoded-widget>` — no base64. On writes, decoded tags are auto-encoded to storage form. Raw base64 `<embeddedwidget>` tags are rejected.",
88
+ description: 'Create or update a page. Use operation=\'create\' to create new pages with workspace and type. Use operation=\'update\' to modify existing pages by UID. 🔍 IMPORTANT: Use \'cplace_get_type_datamodel\' before creating pages to understand attribute requirements.\n\nRichString content (page content and richstring attributes) uses decoded form: `<decoded-widget id="" type="">{"properties":{…}}</decoded-widget>` — no base64. On writes, decoded tags are auto-encoded to storage form. Raw base64 `<embeddedwidget>` tags are rejected.',
53
89
  inputSchema: {
54
- operation: z.enum(["create", "update"]).describe("Operation to perform: 'create' for new pages, 'update' for existing pages"),
55
- responseFormat: z.enum(["status", "full"]).optional().default("status").describe("Response format. 'status' (default): returns only operation result with pageUID — prevents token-exceeded errors. 'full': returns the complete page entity (may exceed size limits for large pages)."),
56
- workspaceId: z.string().optional().describe("Required for create: The workspace ID where the page should be created (e.g., 'abc123')"),
57
- typeInternalName: z.string().optional().describe("Required for create: The type internal name (e.g., 'cf.example.myType')"),
58
- pageUID: z.string().optional().describe("Required for update: The UID of the page to update (e.g., 'page/abc123def456')"),
59
- name: z.string().optional().describe("Page name. For create operations: optional if type has name generation pattern (auto-generates from pattern), otherwise required. For update operations: optional. Name generation pattern syntax: <attributeName> for attribute values, {###} for sequential counter, {0000} for zero-padded counter. Example: '<title>-{0000}' generates 'ProjectAlpha-0001'. Provide explicit name to override pattern. Use cplace_get_type_datamodel to check if type supports name generation."),
60
- parentUID: z.string().optional().describe("Parent page UID for hierarchy. For create: sets initial parent. For update: moves page (use empty string to remove parent)."),
61
- content: z.string().optional().describe("HTML content for the page. Use HTML markup, not markdown - e.g. '<strong>bold</strong>' not '**bold**'. Embedded widgets appear in decoded form: `<decoded-widget type=\"…\">{\"properties\":{…}}</decoded-widget>`. For update: use empty string to remove content."),
62
- attributes: jsonStringToObject(z.any().optional()).describe(`Pass as a JSON object (NOT \`customAttributes\`, NOT a JSON string). Custom attribute values as key-value pairs. 🔍 IMPORTANT: Use 'cplace_get_type_datamodel' tool first to understand attribute requirements and constraints. Supports:
90
+ operation: z
91
+ .enum(['create', 'update'])
92
+ .describe("Operation to perform: 'create' for new pages, 'update' for existing pages"),
93
+ responseFormat: z
94
+ .enum(['status', 'full'])
95
+ .optional()
96
+ .default('status')
97
+ .describe("Response format. 'status' (default): returns only operation result with pageUID prevents token-exceeded errors. 'full': returns the complete page entity (may exceed size limits for large pages)."),
98
+ workspaceId: z
99
+ .string()
100
+ .optional()
101
+ .describe("Required for create: The workspace ID where the page should be created (e.g., 'abc123')"),
102
+ typeInternalName: z
103
+ .string()
104
+ .optional()
105
+ .describe("Required for create: The type internal name (e.g., 'cf.example.myType')"),
106
+ pageUID: z
107
+ .string()
108
+ .optional()
109
+ .describe("Required for update: The UID of the page to update (e.g., 'page/abc123def456')"),
110
+ name: z
111
+ .string()
112
+ .optional()
113
+ .describe("Page name. For create operations: optional if type has name generation pattern (auto-generates from pattern), otherwise required. For update operations: optional. Name generation pattern syntax: <attributeName> for attribute values, {###} for sequential counter, {0000} for zero-padded counter. Example: '<title>-{0000}' generates 'ProjectAlpha-0001'. Provide explicit name to override pattern. Use cplace_get_type_datamodel to check if type supports name generation."),
114
+ parentUID: z
115
+ .string()
116
+ .optional()
117
+ .describe('Parent page UID for hierarchy. For create: sets initial parent. For update: moves page (use empty string to remove parent).'),
118
+ content: z
119
+ .string()
120
+ .optional()
121
+ .describe('HTML content for the page. Use HTML markup, not markdown - e.g. \'<strong>bold</strong>\' not \'**bold**\'. Embedded widgets appear in decoded form: `<decoded-widget type="…">{"properties":{…}}</decoded-widget>`. For update: use empty string to remove content.'),
122
+ attributes: jsonStringToObject(z.any().optional())
123
+ .describe(`Pass as a JSON object (NOT \`customAttributes\`, NOT a JSON string). Custom attribute values as key-value pairs. 🔍 IMPORTANT: Use 'cplace_get_type_datamodel' tool first to understand attribute requirements and constraints. Supports:
63
124
  - String values: "text"
64
125
  - Numeric values: 42 or 3.14
65
126
  - Boolean values: true/false
@@ -76,7 +137,8 @@ The system automatically detects attribute types from the page type definition a
76
137
  - Proper multiplicity validation (single vs multi-valued)
77
138
  - Automatic type conversion and validation
78
139
  - Enhanced error messages with attribute-specific details`),
79
- builtinAttributes: jsonStringToObject(z.any().optional()).describe(`Builtin/mixin-provided attributes (optional for schedules). Supports:
140
+ builtinAttributes: jsonStringToObject(z.any().optional())
141
+ .describe(`Builtin/mixin-provided attributes (optional for schedules). Supports:
80
142
  - owner: Person UID as string (e.g., "person/123abc456") - Sets/updates the page owner for schedules
81
143
  - For update only: Use null to remove builtin attribute values
82
144
 
@@ -84,19 +146,19 @@ Supported page type:
84
146
  - Schedule (cf.schedule): supports owner attribute
85
147
 
86
148
  Example for schedule:
87
- {"owner": "person/123abc456"}`)
149
+ {"owner": "person/123abc456"}`),
88
150
  },
89
- annotations: { title: "Manage Page" }
90
- }
151
+ annotations: { title: 'Manage Page' },
152
+ },
91
153
  };
92
154
  export function registerPageTools(server, client) {
93
155
  function buildStatusResponse(operation, result) {
94
156
  const response = {
95
- status: "SUCCESS",
157
+ status: 'SUCCESS',
96
158
  operation,
97
- pageUID: result.uid || result.pageUID || result.id
159
+ pageUID: result.uid || result.pageUID || result.id,
98
160
  };
99
- if (operation === "create" && result.name) {
161
+ if (operation === 'create' && result.name) {
100
162
  response.name = result.name;
101
163
  }
102
164
  return JSON.stringify(response, null, 2);
@@ -105,21 +167,23 @@ export function registerPageTools(server, client) {
105
167
  const { operation } = params;
106
168
  debugLogWithTag('MANAGE_PAGE', `${operation} page operation`);
107
169
  try {
108
- if (operation === "create") {
170
+ if (operation === 'create') {
109
171
  if (!params.workspaceId || !params.typeInternalName) {
110
172
  return {
111
- content: [{
112
- type: "text",
113
- text: "Error: workspaceId and typeInternalName are required when operation='create'."
114
- }],
115
- isError: true
173
+ content: [
174
+ {
175
+ type: 'text',
176
+ text: "Error: workspaceId and typeInternalName are required when operation='create'.",
177
+ },
178
+ ],
179
+ isError: true,
116
180
  };
117
181
  }
118
182
  const requestBody = {
119
183
  workspaceId: params.workspaceId,
120
- typeInternalName: params.typeInternalName
184
+ typeInternalName: params.typeInternalName,
121
185
  };
122
- if (params.name !== undefined && params.name !== null && params.name !== "") {
186
+ if (params.name !== undefined && params.name !== null && params.name !== '') {
123
187
  requestBody.name = params.name;
124
188
  }
125
189
  if (params.parentUID) {
@@ -141,35 +205,37 @@ export function registerPageTools(server, client) {
141
205
  debugLogWithTag('MANAGE_PAGE', `Request body: ${JSON.stringify(requestBody, null, 2)}`);
142
206
  const result = await client.makeApiRequest('json/page/create', 'POST', undefined, requestBody);
143
207
  debugLogWithTag('MANAGE_PAGE', `Successfully created page: ${params.name}`);
144
- if (params.responseFormat === "full") {
208
+ if (params.responseFormat === 'full') {
145
209
  const sizeCheck = checkResponseSize(result);
146
210
  if (sizeCheck.tooLarge) {
147
- const statusJson = JSON.parse(buildStatusResponse("create", result));
211
+ const statusJson = JSON.parse(buildStatusResponse('create', result));
148
212
  statusJson.note = `Full response omitted (${sizeCheck.actualSize} chars exceeds limit). Use cplace_get_by_uid to inspect, or use responseFormat='status'.`;
149
213
  return {
150
- content: [{ type: "text", text: JSON.stringify(statusJson, null, 2) }]
214
+ content: [{ type: 'text', text: JSON.stringify(statusJson, null, 2) }],
151
215
  };
152
216
  }
153
217
  return {
154
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
218
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
155
219
  };
156
220
  }
157
221
  return {
158
- content: [{ type: "text", text: buildStatusResponse("create", result) }]
222
+ content: [{ type: 'text', text: buildStatusResponse('create', result) }],
159
223
  };
160
224
  }
161
225
  else {
162
226
  if (!params.pageUID) {
163
227
  return {
164
- content: [{
165
- type: "text",
166
- text: "Error: pageUID is required when operation='update'. Specify the UID of the page to update."
167
- }],
168
- isError: true
228
+ content: [
229
+ {
230
+ type: 'text',
231
+ text: "Error: pageUID is required when operation='update'. Specify the UID of the page to update.",
232
+ },
233
+ ],
234
+ isError: true,
169
235
  };
170
236
  }
171
237
  const requestBody = {
172
- pageUID: params.pageUID
238
+ pageUID: params.pageUID,
173
239
  };
174
240
  if (params.name !== undefined)
175
241
  requestBody.name = params.name;
@@ -185,37 +251,44 @@ export function registerPageTools(server, client) {
185
251
  }
186
252
  if (Object.keys(requestBody).length === 1) {
187
253
  return {
188
- content: [{ type: "text", text: "No updates specified. At least one of name, content, parentUID, attributes, or builtinAttributes must be provided." }]
254
+ content: [
255
+ {
256
+ type: 'text',
257
+ text: 'No updates specified. At least one of name, content, parentUID, attributes, or builtinAttributes must be provided.',
258
+ },
259
+ ],
189
260
  };
190
261
  }
191
262
  const result = await client.makeApiRequest('json/page', 'PATCH', undefined, requestBody);
192
263
  debugLogWithTag('MANAGE_PAGE', `Successfully updated page: ${params.pageUID}`);
193
- if (params.responseFormat === "full") {
264
+ if (params.responseFormat === 'full') {
194
265
  const sizeCheck = checkResponseSize(result);
195
266
  if (sizeCheck.tooLarge) {
196
- const statusJson = JSON.parse(buildStatusResponse("update", result));
267
+ const statusJson = JSON.parse(buildStatusResponse('update', result));
197
268
  statusJson.note = `Full response omitted (${sizeCheck.actualSize} chars exceeds limit). Use cplace_get_by_uid to inspect, or use responseFormat='status'.`;
198
269
  return {
199
- content: [{ type: "text", text: JSON.stringify(statusJson, null, 2) }]
270
+ content: [{ type: 'text', text: JSON.stringify(statusJson, null, 2) }],
200
271
  };
201
272
  }
202
273
  return {
203
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
274
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
204
275
  };
205
276
  }
206
277
  return {
207
- content: [{ type: "text", text: buildStatusResponse("update", result) }]
278
+ content: [{ type: 'text', text: buildStatusResponse('update', result) }],
208
279
  };
209
280
  }
210
281
  }
211
282
  catch (error) {
212
283
  debugLogWithTag('MANAGE_PAGE', `Error ${operation} page: ${error instanceof Error ? error.message : String(error)}`);
213
284
  return {
214
- content: [{
215
- type: "text",
216
- text: `Error ${operation} page: ${error instanceof Error ? error.message : String(error)}`
217
- }],
218
- isError: true
285
+ content: [
286
+ {
287
+ type: 'text',
288
+ text: `Error ${operation} page: ${error instanceof Error ? error.message : String(error)}`,
289
+ },
290
+ ],
291
+ isError: true,
219
292
  };
220
293
  }
221
294
  });
@@ -237,14 +310,26 @@ export function registerPageTools(server, client) {
237
310
  }
238
311
  debugLogWithTag('DELETE_PAGE', `Successfully deleted page: ${pageUID}`);
239
312
  return {
240
- content: [{ type: "text", text: typeof parsedResult === 'object' ? JSON.stringify(parsedResult, null, 2) : String(parsedResult) }]
313
+ content: [
314
+ {
315
+ type: 'text',
316
+ text: typeof parsedResult === 'object'
317
+ ? JSON.stringify(parsedResult, null, 2)
318
+ : String(parsedResult),
319
+ },
320
+ ],
241
321
  };
242
322
  }
243
323
  catch (error) {
244
324
  debugLogWithTag('DELETE_PAGE', `Error deleting page: ${error instanceof Error ? error.message : String(error)}`);
245
325
  return {
246
- content: [{ type: "text", text: `Error deleting page: ${error instanceof Error ? error.message : String(error)}` }],
247
- isError: true
326
+ content: [
327
+ {
328
+ type: 'text',
329
+ text: `Error deleting page: ${error instanceof Error ? error.message : String(error)}`,
330
+ },
331
+ ],
332
+ isError: true,
248
333
  };
249
334
  }
250
335
  });
@@ -253,7 +338,7 @@ export function registerPageTools(server, client) {
253
338
  try {
254
339
  const requestBody = {
255
340
  pageUID,
256
- confirmDeleteChildren
341
+ confirmDeleteChildren,
257
342
  };
258
343
  const result = await client.makeApiRequest('json/page/with-children', 'DELETE', undefined, requestBody);
259
344
  let parsedResult;
@@ -270,14 +355,26 @@ export function registerPageTools(server, client) {
270
355
  }
271
356
  debugLogWithTag('DELETE_PAGE_WITH_CHILDREN', `Deletion operation completed for: ${pageUID}`);
272
357
  return {
273
- content: [{ type: "text", text: typeof parsedResult === 'object' ? JSON.stringify(parsedResult, null, 2) : String(parsedResult) }]
358
+ content: [
359
+ {
360
+ type: 'text',
361
+ text: typeof parsedResult === 'object'
362
+ ? JSON.stringify(parsedResult, null, 2)
363
+ : String(parsedResult),
364
+ },
365
+ ],
274
366
  };
275
367
  }
276
368
  catch (error) {
277
369
  debugLogWithTag('DELETE_PAGE_WITH_CHILDREN', `Error deleting page with children: ${error instanceof Error ? error.message : String(error)}`);
278
370
  return {
279
- content: [{ type: "text", text: `Error deleting page with children: ${error instanceof Error ? error.message : String(error)}` }],
280
- isError: true
371
+ content: [
372
+ {
373
+ type: 'text',
374
+ text: `Error deleting page with children: ${error instanceof Error ? error.message : String(error)}`,
375
+ },
376
+ ],
377
+ isError: true,
281
378
  };
282
379
  }
283
380
  });
@@ -290,30 +387,32 @@ export function registerPageTools(server, client) {
290
387
  if (!hasWorkspace && !hasParent) {
291
388
  debugLogWithTag('COPY_PAGE', 'Validation failed: No target specified');
292
389
  return {
293
- content: [{
294
- type: "text",
295
- text: "Error: Either targetWorkspaceId or targetParentUID must be provided. Specify exactly one target location for the copied page."
296
- }],
297
- isError: true
390
+ content: [
391
+ {
392
+ type: 'text',
393
+ text: 'Error: Either targetWorkspaceId or targetParentUID must be provided. Specify exactly one target location for the copied page.',
394
+ },
395
+ ],
396
+ isError: true,
298
397
  };
299
398
  }
300
399
  if (hasWorkspace && hasParent) {
301
400
  debugLogWithTag('COPY_PAGE', 'Validation failed: Both targets specified');
302
401
  return {
303
- content: [{
304
- type: "text",
305
- text: "Error: Only one of targetWorkspaceId or targetParentUID can be provided, not both. Choose a single target location."
306
- }],
307
- isError: true
402
+ content: [
403
+ {
404
+ type: 'text',
405
+ text: 'Error: Only one of targetWorkspaceId or targetParentUID can be provided, not both. Choose a single target location.',
406
+ },
407
+ ],
408
+ isError: true,
308
409
  };
309
410
  }
310
- const endpoint = includeChildren
311
- ? 'json/page/copy-with-children'
312
- : 'json/page/copy';
411
+ const endpoint = includeChildren ? 'json/page/copy-with-children' : 'json/page/copy';
313
412
  const requestBody = {
314
413
  sourcePageUID: params.sourcePageUID,
315
414
  includeComments: params.includeComments ?? false,
316
- includeFiles: params.includeFiles ?? true
415
+ includeFiles: params.includeFiles ?? true,
317
416
  };
318
417
  if (params.targetWorkspaceId)
319
418
  requestBody.targetWorkspaceId = params.targetWorkspaceId;
@@ -338,7 +437,7 @@ export function registerPageTools(server, client) {
338
437
  debugLogWithTag('COPY_PAGE', `Successfully copied page: ${params.sourcePageUID}`);
339
438
  }
340
439
  return {
341
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
440
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
342
441
  };
343
442
  }
344
443
  catch (error) {
@@ -348,54 +447,80 @@ export function registerPageTools(server, client) {
348
447
  if (childMatch) {
349
448
  const childCount = childMatch[1];
350
449
  return {
351
- content: [{
352
- type: "text",
353
- text: `This page has ${childCount} children. Retry with includeChildren: true and confirmCopyChildren: false to preview.`
354
- }],
355
- isError: true
450
+ content: [
451
+ {
452
+ type: 'text',
453
+ text: `This page has ${childCount} children. Retry with includeChildren: true and confirmCopyChildren: false to preview.`,
454
+ },
455
+ ],
456
+ isError: true,
356
457
  };
357
458
  }
358
459
  return {
359
- content: [{
360
- type: "text",
361
- text: `Error copying page: ${errorMessage}`
362
- }],
363
- isError: true
460
+ content: [
461
+ {
462
+ type: 'text',
463
+ text: `Error copying page: ${errorMessage}`,
464
+ },
465
+ ],
466
+ isError: true,
364
467
  };
365
468
  }
366
469
  });
367
470
  server.registerTool(TOOL_EDIT_PAGE_CONTENT, PAGE_TOOL_DEFINITIONS[TOOL_EDIT_PAGE_CONTENT], async ({ pageUID, old_str, new_str, replace_all = false }) => {
368
471
  debugLogWithTag('EDIT_PAGE_CONTENT', `Editing content of page ${pageUID}`);
369
472
  try {
370
- const page = await client.makeApiRequest('json/page', 'GET', { pageUID });
473
+ const page = (await client.makeApiRequest('json/page', 'GET', { pageUID }));
371
474
  const content = page.wikiMarkup;
372
475
  if (content === undefined || content === null) {
373
476
  return {
374
- content: [{ type: "text", text: `Error: Page ${pageUID} has no wiki content to edit.` }],
375
- isError: true
477
+ content: [
478
+ { type: 'text', text: `Error: Page ${pageUID} has no wiki content to edit.` },
479
+ ],
480
+ isError: true,
376
481
  };
377
482
  }
378
483
  const result = applyStrReplace(content, old_str, new_str, replace_all);
379
484
  if (!result.success) {
380
485
  return {
381
- content: [{ type: "text", text: `Error: ${result.error}` }],
382
- isError: true
486
+ content: [{ type: 'text', text: `Error: ${result.error}` }],
487
+ isError: true,
383
488
  };
384
489
  }
385
490
  await client.makeApiRequest('json/page', 'PATCH', undefined, {
386
491
  pageUID,
387
- content: result.newContent
492
+ content: result.newContent,
388
493
  });
494
+ const reReadPage = (await client.makeApiRequest('json/page', 'GET', { pageUID }));
495
+ const storedContent = reReadPage.wikiMarkup;
496
+ const storedPreview = storedContent
497
+ ? storedContent.length > 500
498
+ ? storedContent.substring(0, 500) + '...'
499
+ : storedContent
500
+ : null;
501
+ const normalizationNote = storedPreview
502
+ ? `\n\nNote: The stored content may differ from what was submitted due to server-side CSS normalization (properties alphabetized, hex→rgb, whitespace regularized). Current stored form (first 500 chars):\n${storedPreview}`
503
+ : '';
389
504
  debugLogWithTag('EDIT_PAGE_CONTENT', `Successfully edited page content (${result.replacementCount} replacement(s))`);
390
505
  return {
391
- content: [{ type: "text", text: `Successfully edited page content. Replaced ${result.replacementCount} occurrence(s).` }]
506
+ content: [
507
+ {
508
+ type: 'text',
509
+ text: `Successfully edited page content. Replaced ${result.replacementCount} occurrence(s).${normalizationNote}`,
510
+ },
511
+ ],
392
512
  };
393
513
  }
394
514
  catch (error) {
395
515
  debugLogWithTag('EDIT_PAGE_CONTENT', `Error: ${error instanceof Error ? error.message : String(error)}`);
396
516
  return {
397
- content: [{ type: "text", text: `Error editing page content: ${error instanceof Error ? error.message : String(error)}` }],
398
- isError: true
517
+ content: [
518
+ {
519
+ type: 'text',
520
+ text: `Error editing page content: ${error instanceof Error ? error.message : String(error)}`,
521
+ },
522
+ ],
523
+ isError: true,
399
524
  };
400
525
  }
401
526
  });