@strapi/content-manager 5.48.0 → 5.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/dist/admin/components/ActionsDrawer.js +3 -2
  2. package/dist/admin/components/ActionsDrawer.js.map +1 -1
  3. package/dist/admin/components/ComponentIcon.js +4 -3
  4. package/dist/admin/components/ComponentIcon.js.map +1 -1
  5. package/dist/admin/components/ConfigurationForm/EditFieldForm.js +3 -2
  6. package/dist/admin/components/ConfigurationForm/EditFieldForm.js.map +1 -1
  7. package/dist/admin/components/ConfigurationForm/Fields.js +3 -2
  8. package/dist/admin/components/ConfigurationForm/Fields.js.map +1 -1
  9. package/dist/admin/components/ConfigurationForm/Form.js +7 -3
  10. package/dist/admin/components/ConfigurationForm/Form.js.map +1 -1
  11. package/dist/admin/components/LeftMenu.js +3 -2
  12. package/dist/admin/components/LeftMenu.js.map +1 -1
  13. package/dist/admin/components/RelativeTime.js +3 -2
  14. package/dist/admin/components/RelativeTime.js.map +1 -1
  15. package/dist/admin/components/Widgets.js +3 -2
  16. package/dist/admin/components/Widgets.js.map +1 -1
  17. package/dist/admin/features/DocumentRBAC.js +12 -3
  18. package/dist/admin/features/DocumentRBAC.js.map +1 -1
  19. package/dist/admin/features/DocumentRBAC.mjs +9 -1
  20. package/dist/admin/features/DocumentRBAC.mjs.map +1 -1
  21. package/dist/admin/history/components/VersionContent.js +7 -3
  22. package/dist/admin/history/components/VersionContent.js.map +1 -1
  23. package/dist/admin/history/components/VersionHeader.js +3 -2
  24. package/dist/admin/history/components/VersionHeader.js.map +1 -1
  25. package/dist/admin/history/components/VersionInputRenderer.js +3 -2
  26. package/dist/admin/history/components/VersionInputRenderer.js.map +1 -1
  27. package/dist/admin/history/pages/History.js +3 -2
  28. package/dist/admin/history/pages/History.js.map +1 -1
  29. package/dist/admin/history/routes.js +3 -2
  30. package/dist/admin/history/routes.js.map +1 -1
  31. package/dist/admin/hooks/useContentTypeSchema.js +40 -19
  32. package/dist/admin/hooks/useContentTypeSchema.js.map +1 -1
  33. package/dist/admin/hooks/useContentTypeSchema.mjs +37 -17
  34. package/dist/admin/hooks/useContentTypeSchema.mjs.map +1 -1
  35. package/dist/admin/hooks/useDocument.js +3 -2
  36. package/dist/admin/hooks/useDocument.js.map +1 -1
  37. package/dist/admin/hooks/useDocumentActions.js +3 -2
  38. package/dist/admin/hooks/useDocumentActions.js.map +1 -1
  39. package/dist/admin/hooks/useDocumentContext.js +3 -2
  40. package/dist/admin/hooks/useDocumentContext.js.map +1 -1
  41. package/dist/admin/hooks/useDocumentLayout.js +46 -6
  42. package/dist/admin/hooks/useDocumentLayout.js.map +1 -1
  43. package/dist/admin/hooks/useDocumentLayout.mjs +43 -4
  44. package/dist/admin/hooks/useDocumentLayout.mjs.map +1 -1
  45. package/dist/admin/hooks/useDragAndDrop.js +3 -2
  46. package/dist/admin/hooks/useDragAndDrop.js.map +1 -1
  47. package/dist/admin/hooks/useKeyboardDragAndDrop.js +3 -2
  48. package/dist/admin/hooks/useKeyboardDragAndDrop.js.map +1 -1
  49. package/dist/admin/hooks/useOnce.js +3 -2
  50. package/dist/admin/hooks/useOnce.js.map +1 -1
  51. package/dist/admin/hooks/usePersistentQueryParams.js +7 -2
  52. package/dist/admin/hooks/usePersistentQueryParams.js.map +1 -1
  53. package/dist/admin/pages/ComponentConfigurationPage.js +9 -5
  54. package/dist/admin/pages/ComponentConfigurationPage.js.map +1 -1
  55. package/dist/admin/pages/ComponentConfigurationPage.mjs +6 -3
  56. package/dist/admin/pages/ComponentConfigurationPage.mjs.map +1 -1
  57. package/dist/admin/pages/EditConfigurationPage.js +3 -2
  58. package/dist/admin/pages/EditConfigurationPage.js.map +1 -1
  59. package/dist/admin/pages/EditView/EditViewPage.js +3 -2
  60. package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
  61. package/dist/admin/pages/EditView/components/DocumentActions.js +80 -39
  62. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  63. package/dist/admin/pages/EditView/components/DocumentActions.mjs +67 -33
  64. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  65. package/dist/admin/pages/EditView/components/EditorToolbarObserver.js +3 -2
  66. package/dist/admin/pages/EditView/components/EditorToolbarObserver.js.map +1 -1
  67. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.js +4 -3
  68. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.js.map +1 -1
  69. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js +3 -2
  70. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Image.js.map +1 -1
  71. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.js +3 -2
  72. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/Link.js.map +1 -1
  73. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +8 -4
  74. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
  75. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +5 -2
  76. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
  77. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.js +3 -2
  78. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.js.map +1 -1
  79. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.js +3 -2
  80. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.js.map +1 -1
  81. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js +4 -3
  82. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js.map +1 -1
  83. package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js +3 -2
  84. package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js.map +1 -1
  85. package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js +3 -2
  86. package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js.map +1 -1
  87. package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js +3 -2
  88. package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js.map +1 -1
  89. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +14 -4
  90. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
  91. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +11 -2
  92. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
  93. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js +16 -7
  94. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
  95. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs +9 -4
  96. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
  97. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +3 -2
  98. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
  99. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +7 -3
  100. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  101. package/dist/admin/pages/EditView/components/FormInputs/UID.js +3 -2
  102. package/dist/admin/pages/EditView/components/FormInputs/UID.js.map +1 -1
  103. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/Editor.js +8 -4
  104. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/Editor.js.map +1 -1
  105. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/Field.js +3 -2
  106. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/Field.js.map +1 -1
  107. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.js +5 -28
  108. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.js.map +1 -1
  109. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.mjs +2 -26
  110. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/PreviewWysiwyg.mjs.map +1 -1
  111. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/continueList.js +5 -1
  112. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/continueList.js.map +1 -1
  113. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/mdRenderer.js +15 -2
  114. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/mdRenderer.js.map +1 -1
  115. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.js +76 -0
  116. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.js.map +1 -0
  117. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.mjs +70 -0
  118. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.mjs.map +1 -0
  119. package/dist/admin/pages/EditView/components/FormLayout.js +3 -2
  120. package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
  121. package/dist/admin/pages/EditView/components/Header.js +3 -2
  122. package/dist/admin/pages/EditView/components/Header.js.map +1 -1
  123. package/dist/admin/pages/EditView/components/InputRenderer.js +3 -2
  124. package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
  125. package/dist/admin/pages/EditView/components/Panels.js +3 -2
  126. package/dist/admin/pages/EditView/components/Panels.js.map +1 -1
  127. package/dist/admin/pages/EditView/utils/data.js +5 -1
  128. package/dist/admin/pages/EditView/utils/data.js.map +1 -1
  129. package/dist/admin/pages/EditView/utils/keyboardShortcuts.js +35 -0
  130. package/dist/admin/pages/EditView/utils/keyboardShortcuts.js.map +1 -0
  131. package/dist/admin/pages/EditView/utils/keyboardShortcuts.mjs +33 -0
  132. package/dist/admin/pages/EditView/utils/keyboardShortcuts.mjs.map +1 -0
  133. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js +7 -10
  134. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js.map +1 -1
  135. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs +5 -9
  136. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs.map +1 -1
  137. package/dist/admin/pages/ListConfiguration/components/DraggableCard.js +3 -2
  138. package/dist/admin/pages/ListConfiguration/components/DraggableCard.js.map +1 -1
  139. package/dist/admin/pages/ListConfiguration/components/EditFieldForm.js +3 -2
  140. package/dist/admin/pages/ListConfiguration/components/EditFieldForm.js.map +1 -1
  141. package/dist/admin/pages/ListConfiguration/components/Settings.js +3 -2
  142. package/dist/admin/pages/ListConfiguration/components/Settings.js.map +1 -1
  143. package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.js +9 -12
  144. package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.js.map +1 -1
  145. package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.mjs +6 -10
  146. package/dist/admin/pages/ListConfiguration/components/SortDisplayedFields.mjs.map +1 -1
  147. package/dist/admin/pages/ListView/ListViewPage.js +3 -2
  148. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  149. package/dist/admin/pages/ListView/components/BulkActions/Actions.js +3 -2
  150. package/dist/admin/pages/ListView/components/BulkActions/Actions.js.map +1 -1
  151. package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.js +3 -2
  152. package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.js.map +1 -1
  153. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js +3 -2
  154. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js.map +1 -1
  155. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs.map +1 -1
  156. package/dist/admin/pages/ListView/components/Filters.js +10 -11
  157. package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
  158. package/dist/admin/pages/ListView/components/Filters.mjs +7 -9
  159. package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
  160. package/dist/admin/pages/ListView/components/TableActions.js +3 -2
  161. package/dist/admin/pages/ListView/components/TableActions.js.map +1 -1
  162. package/dist/admin/pages/ListView/components/TableCells/CellContent.js +7 -3
  163. package/dist/admin/pages/ListView/components/TableCells/CellContent.js.map +1 -1
  164. package/dist/admin/pages/ListView/components/TableCells/CellValue.js +7 -2
  165. package/dist/admin/pages/ListView/components/TableCells/CellValue.js.map +1 -1
  166. package/dist/admin/pages/ListView/components/TableCells/Media.js +5 -4
  167. package/dist/admin/pages/ListView/components/TableCells/Media.js.map +1 -1
  168. package/dist/admin/pages/ListView/components/TableCells/Media.mjs +5 -4
  169. package/dist/admin/pages/ListView/components/TableCells/Media.mjs.map +1 -1
  170. package/dist/admin/pages/ListView/components/TableCells/Relations.js +3 -2
  171. package/dist/admin/pages/ListView/components/TableCells/Relations.js.map +1 -1
  172. package/dist/admin/pages/formatComponentConfigurationEditLayout.js +15 -9
  173. package/dist/admin/pages/formatComponentConfigurationEditLayout.js.map +1 -1
  174. package/dist/admin/pages/formatComponentConfigurationEditLayout.mjs +15 -9
  175. package/dist/admin/pages/formatComponentConfigurationEditLayout.mjs.map +1 -1
  176. package/dist/admin/preview/components/InputPopover.js +3 -2
  177. package/dist/admin/preview/components/InputPopover.js.map +1 -1
  178. package/dist/admin/preview/hooks/usePreviewInputManager.js +3 -2
  179. package/dist/admin/preview/hooks/usePreviewInputManager.js.map +1 -1
  180. package/dist/admin/preview/pages/Preview.js +3 -2
  181. package/dist/admin/preview/pages/Preview.js.map +1 -1
  182. package/dist/admin/preview/routes.js +3 -2
  183. package/dist/admin/preview/routes.js.map +1 -1
  184. package/dist/admin/services/components.js +3 -2
  185. package/dist/admin/services/components.js.map +1 -1
  186. package/dist/admin/services/components.mjs +3 -2
  187. package/dist/admin/services/components.mjs.map +1 -1
  188. package/dist/admin/services/contentTypes.js +4 -3
  189. package/dist/admin/services/contentTypes.js.map +1 -1
  190. package/dist/admin/services/contentTypes.mjs +4 -3
  191. package/dist/admin/services/contentTypes.mjs.map +1 -1
  192. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +1 -1
  193. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/utils/sanitizer.d.ts +2 -0
  194. package/dist/admin/src/pages/EditView/utils/keyboardShortcuts.d.ts +18 -0
  195. package/dist/admin/src/pages/ListConfiguration/components/SortDisplayedFields.d.ts +2 -2
  196. package/dist/admin/src/pages/ListView/components/TableCells/Media.d.ts +2 -2
  197. package/dist/admin/src/pages/formatComponentConfigurationEditLayout.d.ts +3 -1
  198. package/dist/admin/src/utils/layouts/normalizeContentManagerLayout.d.ts +24 -0
  199. package/dist/admin/translations/cs.json.js +2 -1
  200. package/dist/admin/translations/cs.json.js.map +1 -1
  201. package/dist/admin/translations/cs.json.mjs +2 -1
  202. package/dist/admin/translations/cs.json.mjs.map +1 -1
  203. package/dist/admin/translations/de.json.js +2 -1
  204. package/dist/admin/translations/de.json.js.map +1 -1
  205. package/dist/admin/translations/de.json.mjs +2 -1
  206. package/dist/admin/translations/de.json.mjs.map +1 -1
  207. package/dist/admin/translations/en.json.js +3 -1
  208. package/dist/admin/translations/en.json.js.map +1 -1
  209. package/dist/admin/translations/en.json.mjs +3 -1
  210. package/dist/admin/translations/en.json.mjs.map +1 -1
  211. package/dist/admin/translations/es.json.js +2 -1
  212. package/dist/admin/translations/es.json.js.map +1 -1
  213. package/dist/admin/translations/es.json.mjs +2 -1
  214. package/dist/admin/translations/es.json.mjs.map +1 -1
  215. package/dist/admin/translations/fr.json.js +2 -1
  216. package/dist/admin/translations/fr.json.js.map +1 -1
  217. package/dist/admin/translations/fr.json.mjs +2 -1
  218. package/dist/admin/translations/fr.json.mjs.map +1 -1
  219. package/dist/admin/translations/nl.json.js +2 -1
  220. package/dist/admin/translations/nl.json.js.map +1 -1
  221. package/dist/admin/translations/nl.json.mjs +2 -1
  222. package/dist/admin/translations/nl.json.mjs.map +1 -1
  223. package/dist/admin/translations/pl.json.js +2 -1
  224. package/dist/admin/translations/pl.json.js.map +1 -1
  225. package/dist/admin/translations/pl.json.mjs +2 -1
  226. package/dist/admin/translations/pl.json.mjs.map +1 -1
  227. package/dist/admin/translations/sk.json.js +2 -1
  228. package/dist/admin/translations/sk.json.js.map +1 -1
  229. package/dist/admin/translations/sk.json.mjs +2 -1
  230. package/dist/admin/translations/sk.json.mjs.map +1 -1
  231. package/dist/admin/utils/attributes.js +17 -2
  232. package/dist/admin/utils/attributes.js.map +1 -1
  233. package/dist/admin/utils/attributes.mjs +17 -2
  234. package/dist/admin/utils/attributes.mjs.map +1 -1
  235. package/dist/admin/utils/layouts/normalizeContentManagerLayout.js +329 -0
  236. package/dist/admin/utils/layouts/normalizeContentManagerLayout.js.map +1 -0
  237. package/dist/admin/utils/layouts/normalizeContentManagerLayout.mjs +321 -0
  238. package/dist/admin/utils/layouts/normalizeContentManagerLayout.mjs.map +1 -0
  239. package/dist/admin/utils/objects.js +9 -4
  240. package/dist/admin/utils/objects.js.map +1 -1
  241. package/dist/admin/utils/validation.js +7 -3
  242. package/dist/admin/utils/validation.js.map +1 -1
  243. package/dist/server/controllers/collection-types.js +7 -2
  244. package/dist/server/controllers/collection-types.js.map +1 -1
  245. package/dist/server/controllers/collection-types.mjs +7 -2
  246. package/dist/server/controllers/collection-types.mjs.map +1 -1
  247. package/dist/server/controllers/utils/clone.js +5 -1
  248. package/dist/server/controllers/utils/clone.js.map +1 -1
  249. package/dist/server/controllers/utils/clone.mjs.map +1 -1
  250. package/dist/server/controllers/validation/index.js +6 -2
  251. package/dist/server/controllers/validation/index.js.map +1 -1
  252. package/dist/server/homepage/services/homepage.js +6 -1
  253. package/dist/server/homepage/services/homepage.js.map +1 -1
  254. package/dist/server/homepage/services/homepage.mjs +6 -1
  255. package/dist/server/homepage/services/homepage.mjs.map +1 -1
  256. package/dist/server/mcp/handlers/collection-handlers.js +15 -18
  257. package/dist/server/mcp/handlers/collection-handlers.js.map +1 -1
  258. package/dist/server/mcp/handlers/collection-handlers.mjs +16 -19
  259. package/dist/server/mcp/handlers/collection-handlers.mjs.map +1 -1
  260. package/dist/server/mcp/handlers/single-type-handlers.js +12 -12
  261. package/dist/server/mcp/handlers/single-type-handlers.js.map +1 -1
  262. package/dist/server/mcp/handlers/single-type-handlers.mjs +13 -13
  263. package/dist/server/mcp/handlers/single-type-handlers.mjs.map +1 -1
  264. package/dist/server/mcp/register-content-manager-mcp-tools.js +4 -1
  265. package/dist/server/mcp/register-content-manager-mcp-tools.js.map +1 -1
  266. package/dist/server/mcp/register-content-manager-mcp-tools.mjs +4 -1
  267. package/dist/server/mcp/register-content-manager-mcp-tools.mjs.map +1 -1
  268. package/dist/server/mcp/sanitizers/shape-relations.js +108 -0
  269. package/dist/server/mcp/sanitizers/shape-relations.js.map +1 -0
  270. package/dist/server/mcp/sanitizers/shape-relations.mjs +103 -0
  271. package/dist/server/mcp/sanitizers/shape-relations.mjs.map +1 -0
  272. package/dist/server/mcp/schemas/data-schema.js +0 -3
  273. package/dist/server/mcp/schemas/data-schema.js.map +1 -1
  274. package/dist/server/mcp/schemas/data-schema.mjs +0 -3
  275. package/dist/server/mcp/schemas/data-schema.mjs.map +1 -1
  276. package/dist/server/mcp/schemas/output-schemas.js +30 -4
  277. package/dist/server/mcp/schemas/output-schemas.js.map +1 -1
  278. package/dist/server/mcp/schemas/output-schemas.mjs +30 -4
  279. package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -1
  280. package/dist/server/mcp/utils.js +30 -3
  281. package/dist/server/mcp/utils.js.map +1 -1
  282. package/dist/server/mcp/utils.mjs +30 -4
  283. package/dist/server/mcp/utils.mjs.map +1 -1
  284. package/dist/server/middlewares/routing.js +5 -1
  285. package/dist/server/middlewares/routing.js.map +1 -1
  286. package/dist/server/services/populate-builder.js.map +1 -1
  287. package/dist/server/services/populate-builder.mjs.map +1 -1
  288. package/dist/server/services/uid.js +9 -4
  289. package/dist/server/services/uid.js.map +1 -1
  290. package/dist/server/services/utils/configuration/attributes.js +14 -10
  291. package/dist/server/services/utils/configuration/attributes.js.map +1 -1
  292. package/dist/server/services/utils/configuration/layouts.js +8 -4
  293. package/dist/server/services/utils/configuration/layouts.js.map +1 -1
  294. package/dist/server/services/utils/configuration/metadatas.js +19 -15
  295. package/dist/server/services/utils/configuration/metadatas.js.map +1 -1
  296. package/dist/server/services/utils/configuration/settings.js +5 -1
  297. package/dist/server/services/utils/configuration/settings.js.map +1 -1
  298. package/dist/server/services/utils/draft.js +5 -1
  299. package/dist/server/services/utils/draft.js.map +1 -1
  300. package/dist/server/services/utils/populate.js +8 -4
  301. package/dist/server/services/utils/populate.js.map +1 -1
  302. package/dist/server/services/utils/populate.mjs.map +1 -1
  303. package/dist/server/services/utils/store.js +9 -5
  304. package/dist/server/services/utils/store.js.map +1 -1
  305. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  306. package/dist/server/src/controllers/utils/clone.d.ts +1 -1
  307. package/dist/server/src/controllers/utils/clone.d.ts.map +1 -1
  308. package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
  309. package/dist/server/src/index.d.ts +3 -1
  310. package/dist/server/src/index.d.ts.map +1 -1
  311. package/dist/server/src/mcp/handlers/collection-handlers.d.ts.map +1 -1
  312. package/dist/server/src/mcp/handlers/single-type-handlers.d.ts.map +1 -1
  313. package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts +2 -1
  314. package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts.map +1 -1
  315. package/dist/server/src/mcp/sanitizers/shape-relations.d.ts +38 -0
  316. package/dist/server/src/mcp/sanitizers/shape-relations.d.ts.map +1 -0
  317. package/dist/server/src/mcp/schemas/data-schema.d.ts +0 -3
  318. package/dist/server/src/mcp/schemas/data-schema.d.ts.map +1 -1
  319. package/dist/server/src/mcp/schemas/output-schemas.d.ts +2 -2
  320. package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -1
  321. package/dist/server/src/mcp/types.d.ts +2 -2
  322. package/dist/server/src/mcp/types.d.ts.map +1 -1
  323. package/dist/server/src/mcp/utils.d.ts +19 -1
  324. package/dist/server/src/mcp/utils.d.ts.map +1 -1
  325. package/dist/server/src/services/index.d.ts +3 -1
  326. package/dist/server/src/services/index.d.ts.map +1 -1
  327. package/dist/server/src/services/populate-builder.d.ts +3 -1
  328. package/dist/server/src/services/populate-builder.d.ts.map +1 -1
  329. package/dist/server/src/services/utils/populate.d.ts +3 -1
  330. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  331. package/package.json +8 -8
@@ -5,7 +5,8 @@ import { formatDocumentWithMetadata } from '../../controllers/utils/metadata.mjs
5
5
  import { getPopulateForLocalizations } from '../../services/utils/populate.mjs';
6
6
  import { MCP_NOT_FOUND_DOCUMENT } from './constants.mjs';
7
7
  import { isContentTypeLocalized } from '../permissions.mjs';
8
- import { ok } from '../utils.mjs';
8
+ import { shapeRelationsForMcp } from '../sanitizers/shape-relations.mjs';
9
+ import { ok, sanitizeFormatShape } from '../utils.mjs';
9
10
 
10
11
  // ---------------------------------------------------------------------------
11
12
  // Shared create-or-update logic mirroring single-types controller
@@ -33,7 +34,7 @@ import { ok } from '../utils.mjs';
33
34
  const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
34
35
  locale
35
36
  }, uid);
36
- const populate = await getService('populate-builder')(typedUid).populateFromQuery(sanitizedQuery).populateDeep(Infinity).countRelations().withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
37
+ const populate = await getService('populate-builder')(typedUid).populateFromQuery(sanitizedQuery).populateDeep(Infinity).withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
37
38
  const draftFindQuery = {
38
39
  ...sanitizedQuery,
39
40
  populate,
@@ -77,8 +78,7 @@ import { ok } from '../utils.mjs';
77
78
  locale: resolvedLocale
78
79
  });
79
80
  }
80
- const sanitizedDocument = await permissionChecker.sanitizeOutput(doc);
81
- return formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);
81
+ return sanitizeFormatShape(permissionChecker, typedUid, doc);
82
82
  });
83
83
  return ok(formatted);
84
84
  };
@@ -109,7 +109,7 @@ import { ok } from '../utils.mjs';
109
109
  locale,
110
110
  status
111
111
  }, uid);
112
- const populate = await getService('populate-builder')(typedUid).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
112
+ const populate = await getService('populate-builder')(typedUid).populateFromQuery(permissionQuery).populateDeep(Infinity).withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
113
113
  const versionFindQuery = {
114
114
  ...permissionQuery,
115
115
  populate,
@@ -141,8 +141,7 @@ import { ok } from '../utils.mjs';
141
141
  if (permissionChecker.cannot.read(version)) {
142
142
  throw new errors.ForbiddenError();
143
143
  }
144
- const sanitizedDocument = await permissionChecker.sanitizeOutput(version);
145
- const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);
144
+ const result = await sanitizeFormatShape(permissionChecker, typedUid, version);
146
145
  return ok(result);
147
146
  };
148
147
  /**
@@ -170,7 +169,7 @@ import { ok } from '../utils.mjs';
170
169
  const sanitizedQuery = await permissionChecker.sanitizedQuery.delete({
171
170
  locale
172
171
  });
173
- const populate = await getService('populate-builder')(typedUid).populateFromQuery(sanitizedQuery).populateDeep(Infinity).countRelations().withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
172
+ const populate = await getService('populate-builder')(typedUid).populateFromQuery(sanitizedQuery).populateDeep(Infinity).withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
174
173
  const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
175
174
  locale
176
175
  }, uid);
@@ -191,9 +190,11 @@ import { ok } from '../utils.mjs';
191
190
  const deletedEntity = await documentManager.delete(documentLocales[0].documentId, typedUid, {
192
191
  locale: localeForQuery
193
192
  });
193
+ // Delete returns `{ data }` without metadata — no status to compute, so sanitize + shape only.
194
194
  const sanitizedResult = await permissionChecker.sanitizeOutput(deletedEntity);
195
+ const shapedResult = await shapeRelationsForMcp(typedUid, sanitizedResult);
195
196
  return ok({
196
- data: sanitizedResult
197
+ data: shapedResult
197
198
  });
198
199
  };
199
200
  /**
@@ -236,8 +237,7 @@ import { ok } from '../utils.mjs';
236
237
  });
237
238
  return publishResult?.at(0);
238
239
  });
239
- const sanitizedDocument = await permissionChecker.sanitizeOutput(publishedDocument);
240
- const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);
240
+ const result = await sanitizeFormatShape(permissionChecker, typedUid, publishedDocument);
241
241
  return ok(result);
242
242
  };
243
243
  /**
@@ -288,7 +288,7 @@ import { ok } from '../utils.mjs';
288
288
  }
289
289
  return async.pipe((doc)=>documentManager.unpublish(doc.documentId, typedUid, {
290
290
  locale: resolvedLocale
291
- }), permissionChecker.sanitizeOutput, (doc)=>formatDocumentWithMetadata(permissionChecker, typedUid, doc))(document);
291
+ }), (doc)=>sanitizeFormatShape(permissionChecker, typedUid, doc))(document);
292
292
  });
293
293
  return ok(result);
294
294
  };
@@ -328,7 +328,7 @@ import { ok } from '../utils.mjs';
328
328
  }
329
329
  const discardedDocument = await async.pipe((doc)=>documentManager.discardDraft(doc.documentId, typedUid, {
330
330
  locale: resolvedLocale
331
- }), permissionChecker.sanitizeOutput, (doc)=>formatDocumentWithMetadata(permissionChecker, typedUid, doc))(document);
331
+ }), (doc)=>sanitizeFormatShape(permissionChecker, typedUid, doc))(document);
332
332
  return ok(discardedDocument);
333
333
  };
334
334
 
@@ -1 +1 @@
1
- {"version":3,"file":"single-type-handlers.mjs","sources":["../../../../server/src/mcp/handlers/single-type-handlers.ts"],"sourcesContent":["import { errors, async as asyncPipe, setCreatorFields } from '@strapi/utils';\nimport type { Core, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../../utils';\nimport { getDocumentLocaleAndStatus } from '../../controllers/validation/dimensions';\nimport { formatDocumentWithMetadata } from '../../controllers/utils/metadata';\nimport { getPopulateForLocalizations } from '../../services/utils/populate';\nimport { MCP_NOT_FOUND_DOCUMENT } from './constants';\nimport { isContentTypeLocalized } from '../permissions';\nimport { ok } from '../utils';\n\ntype McpDocumentQuery = {\n populate?: unknown;\n locale?: string;\n status?: string;\n filters?: unknown;\n sort?: unknown;\n pagination?: unknown;\n [key: string]: unknown;\n};\n\ntype McpFindManyParams = Parameters<Modules.Documents.ServiceInstance['findMany']>[0];\n\n// ---------------------------------------------------------------------------\n// Input arg schemas — used for type-safe narrowing from Record<string, unknown>\n// ---------------------------------------------------------------------------\n\ntype SingleLocaleArgs = { locale?: string };\ntype SingleGetArgs = SingleLocaleArgs & { status?: 'draft' | 'published' };\ntype SingleUnpublishArgs = SingleLocaleArgs & { discardDraft?: boolean };\ntype SingleWriteArgs = { data: Record<string, unknown>; locale?: string };\n\n// ---------------------------------------------------------------------------\n// Shared create-or-update logic mirroring single-types controller\n// ---------------------------------------------------------------------------\n\n/**\n * Core write logic shared by the single-type write handler.\n * Creates the document when none exists; updates the existing draft otherwise.\n * Enforces RBAC create/update permission and sanitizes input + output.\n */\nexport const singleCreateOrUpdate = async (\n strapi: Core.Strapi,\n uid: UID.SingleType,\n context: Modules.MCP.McpHandlerContext,\n args: SingleWriteArgs\n): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility, user } = context;\n const { data, locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.create() && permissionChecker.cannot.update()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.update({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(sanitizedQuery)\n .populateDeep(Infinity)\n .countRelations()\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const draftFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n populate,\n locale: resolvedLocale,\n status: 'draft',\n };\n const [documentVersion, otherDocumentVersion] = await Promise.all([\n documentManager\n .findMany(draftFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]),\n strapi.db.query(typedUid).findOne({ select: ['documentId'] }),\n ]);\n\n const documentId = otherDocumentVersion?.documentId;\n\n if (documentVersion) {\n if (permissionChecker.cannot.update(documentVersion)) {\n throw new errors.ForbiddenError();\n }\n } else if (permissionChecker.cannot.create()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizeInput = documentVersion\n ? permissionChecker.sanitizeUpdateInput(documentVersion)\n : permissionChecker.sanitizeCreateInput;\n\n const isEdition = documentVersion !== null && documentVersion !== undefined;\n const sanitizedData = setCreatorFields({ user, isEdition })(await sanitizeInput(data)) as Record<\n string,\n unknown\n >;\n\n const formatted = await strapi.db.transaction(async () => {\n let doc: any;\n\n if (documentId === undefined) {\n doc = await documentManager.create(typedUid, {\n data: sanitizedData,\n ...sanitizedQuery,\n locale: resolvedLocale,\n });\n } else {\n doc = await documentManager.update(documentId, typedUid, {\n data: sanitizedData,\n populate,\n locale: resolvedLocale,\n });\n }\n\n const sanitizedDocument = await permissionChecker.sanitizeOutput(doc);\n return formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);\n });\n\n return ok(formatted as Record<string, unknown>);\n};\n\n// ---------------------------------------------------------------------------\n// Handler factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a handler for reading the single-type document.\n * Returns available locale metadata when the requested locale version does not exist.\n * Enforces RBAC read permission.\n */\nexport const createSingleGetHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleGetArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale, status } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.read()) {\n throw new errors.ForbiddenError();\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read({ locale, status });\n const { locale: resolvedLocale, status: resolvedStatus } = await getDocumentLocaleAndStatus(\n { locale, status },\n uid\n );\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(permissionQuery)\n .populateDeep(Infinity)\n .countRelations()\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const versionFindQuery: McpDocumentQuery = {\n ...permissionQuery,\n populate,\n locale: resolvedLocale,\n status: resolvedStatus,\n };\n const version = await getService('document-manager')\n .findMany(versionFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!version) {\n if (permissionChecker.cannot.create()) {\n throw new errors.ForbiddenError();\n }\n\n const document = await strapi.db.query(typedUid).findOne({});\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n const { meta } = await formatDocumentWithMetadata(\n permissionChecker,\n typedUid,\n {\n documentId: document.documentId,\n locale: resolvedLocale,\n publishedAt: null,\n } as Parameters<typeof formatDocumentWithMetadata>[2],\n { availableLocales: true, availableStatus: false }\n );\n\n return ok({ data: {}, meta } as Record<string, unknown>);\n }\n\n if (permissionChecker.cannot.read(version)) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedDocument = await permissionChecker.sanitizeOutput(version);\n const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for creating or updating the single-type document.\n * Delegates to `singleCreateOrUpdate`; enforces RBAC create/update permission.\n */\nexport const createSingleWriteHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({\n args,\n }: {\n args: Record<string, unknown>;\n }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n return singleCreateOrUpdate(strapi, uid, context, args as SingleWriteArgs);\n };\n\n/**\n * Creates a handler for deleting the single-type document (or a specific locale).\n * Enforces RBAC delete permission on every locale version before deletion.\n */\nexport const createSingleDeleteHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.delete()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.delete({ locale });\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(sanitizedQuery)\n .populateDeep(Infinity)\n .countRelations()\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const isLocalized = isContentTypeLocalized(strapi, uid);\n\n const localeForQuery = isLocalized === true ? resolvedLocale : undefined;\n\n const documentLocales = await documentManager.findLocales(undefined, typedUid, {\n populate,\n locale: localeForQuery,\n });\n\n if (documentLocales.length === 0) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n for (const document of documentLocales) {\n if (permissionChecker.cannot.delete(document)) {\n throw new errors.ForbiddenError();\n }\n }\n\n const deletedEntity = await documentManager.delete(documentLocales[0].documentId, typedUid, {\n locale: localeForQuery,\n });\n\n const sanitizedResult = await permissionChecker.sanitizeOutput(deletedEntity);\n\n return ok({ data: sanitizedResult } as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for publishing the single-type document draft.\n * Enforces RBAC publish permission; throws NotFound when the draft is missing.\n */\nexport const createSinglePublishHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.publish()) {\n throw new errors.ForbiddenError();\n }\n\n const publishedDocument = await strapi.db.transaction(async () => {\n const sanitizedQuery = await permissionChecker.sanitizedQuery.publish({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const publishFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n locale: resolvedLocale,\n status: 'draft',\n };\n const document = await getService('document-manager')\n .findMany(publishFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.publish(document)) {\n throw new errors.ForbiddenError();\n }\n\n const publishResult = await documentManager.publish(document.documentId, typedUid, {\n locale: resolvedLocale,\n });\n\n return publishResult?.at(0);\n });\n\n const sanitizedDocument = await permissionChecker.sanitizeOutput(publishedDocument);\n const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for unpublishing the single-type document.\n * Optionally discards the draft in the same transaction when `discardDraft` is true.\n * Enforces RBAC unpublish (and discard) permission.\n */\nexport const createSingleUnpublishHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleUnpublishArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale, discardDraft } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.unpublish()) {\n throw new errors.ForbiddenError();\n }\n\n if (discardDraft === true && permissionChecker.cannot.discard()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.unpublish({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const unpublishFindQuery: McpDocumentQuery = { ...sanitizedQuery, locale: resolvedLocale };\n const document = await getService('document-manager')\n .findMany(unpublishFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.unpublish(document)) {\n throw new errors.ForbiddenError();\n }\n\n if (discardDraft === true && permissionChecker.cannot.discard(document)) {\n throw new errors.ForbiddenError();\n }\n\n const result = await strapi.db.transaction(async () => {\n if (discardDraft === true) {\n await documentManager.discardDraft(document.documentId, typedUid, {\n locale: resolvedLocale,\n });\n }\n\n return asyncPipe.pipe(\n (doc: any) =>\n documentManager.unpublish(doc.documentId, typedUid, { locale: resolvedLocale }),\n permissionChecker.sanitizeOutput,\n (doc: any) => formatDocumentWithMetadata(permissionChecker, typedUid, doc)\n )(document);\n });\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for discarding the draft of the single-type document.\n * Restores the published version as the draft. Enforces RBAC discard permission.\n */\nexport const createSingleDiscardDraftHandler =\n (uid: UID.SingleType) =>\n (_strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.discard()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.discard({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const discardFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n locale: resolvedLocale,\n status: 'published',\n };\n const document = await getService('document-manager')\n .findMany(discardFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.discard(document)) {\n throw new errors.ForbiddenError();\n }\n\n const discardedDocument = await asyncPipe.pipe(\n (doc: any) =>\n documentManager.discardDraft(doc.documentId, typedUid, { locale: resolvedLocale }),\n permissionChecker.sanitizeOutput,\n (doc: any) => formatDocumentWithMetadata(permissionChecker, typedUid, doc)\n )(document);\n\n return ok(discardedDocument as Record<string, unknown>);\n };\n"],"names":["singleCreateOrUpdate","strapi","uid","context","args","userAbility","user","data","locale","typedUid","documentManager","getService","permissionChecker","create","model","cannot","update","errors","ForbiddenError","sanitizedQuery","resolvedLocale","getDocumentLocaleAndStatus","populate","populateFromQuery","populateDeep","Infinity","countRelations","withPopulateOverride","getPopulateForLocalizations","build","draftFindQuery","status","documentVersion","otherDocumentVersion","Promise","all","findMany","then","docs","db","query","findOne","select","documentId","sanitizeInput","sanitizeUpdateInput","sanitizeCreateInput","isEdition","undefined","sanitizedData","setCreatorFields","formatted","transaction","doc","sanitizedDocument","sanitizeOutput","formatDocumentWithMetadata","ok","createSingleGetHandler","read","permissionQuery","resolvedStatus","versionFindQuery","version","document","NotFoundError","MCP_NOT_FOUND_DOCUMENT","meta","publishedAt","availableLocales","availableStatus","result","createSingleWriteHandler","createSingleDeleteHandler","delete","isLocalized","isContentTypeLocalized","localeForQuery","documentLocales","findLocales","length","deletedEntity","sanitizedResult","createSinglePublishHandler","publish","publishedDocument","publishFindQuery","publishResult","at","createSingleUnpublishHandler","discardDraft","unpublish","discard","unpublishFindQuery","asyncPipe","pipe","createSingleDiscardDraftHandler","_strapi","discardFindQuery","discardedDocument"],"mappings":"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"}
1
+ {"version":3,"file":"single-type-handlers.mjs","sources":["../../../../server/src/mcp/handlers/single-type-handlers.ts"],"sourcesContent":["import { errors, async as asyncPipe, setCreatorFields } from '@strapi/utils';\nimport type { Core, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../../utils';\nimport { getDocumentLocaleAndStatus } from '../../controllers/validation/dimensions';\nimport { formatDocumentWithMetadata } from '../../controllers/utils/metadata';\nimport { getPopulateForLocalizations } from '../../services/utils/populate';\nimport { MCP_NOT_FOUND_DOCUMENT } from './constants';\nimport { isContentTypeLocalized } from '../permissions';\nimport { shapeRelationsForMcp } from '../sanitizers/shape-relations';\nimport { ok, sanitizeFormatShape } from '../utils';\n\ntype McpDocumentQuery = {\n populate?: unknown;\n locale?: string;\n status?: string;\n filters?: unknown;\n sort?: unknown;\n pagination?: unknown;\n [key: string]: unknown;\n};\n\ntype McpFindManyParams = Parameters<Modules.Documents.ServiceInstance['findMany']>[0];\n\n// ---------------------------------------------------------------------------\n// Input arg schemas — used for type-safe narrowing from Record<string, unknown>\n// ---------------------------------------------------------------------------\n\ntype SingleLocaleArgs = { locale?: string };\ntype SingleGetArgs = SingleLocaleArgs & { status?: 'draft' | 'published' };\ntype SingleUnpublishArgs = SingleLocaleArgs & { discardDraft?: boolean };\ntype SingleWriteArgs = { data: Record<string, unknown>; locale?: string };\n\n// ---------------------------------------------------------------------------\n// Shared create-or-update logic mirroring single-types controller\n// ---------------------------------------------------------------------------\n\n/**\n * Core write logic shared by the single-type write handler.\n * Creates the document when none exists; updates the existing draft otherwise.\n * Enforces RBAC create/update permission and sanitizes input + output.\n */\nexport const singleCreateOrUpdate = async (\n strapi: Core.Strapi,\n uid: UID.SingleType,\n context: Modules.MCP.McpHandlerContext,\n args: SingleWriteArgs\n): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility, user } = context;\n const { data, locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.create() && permissionChecker.cannot.update()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.update({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(sanitizedQuery)\n .populateDeep(Infinity)\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const draftFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n populate,\n locale: resolvedLocale,\n status: 'draft',\n };\n const [documentVersion, otherDocumentVersion] = await Promise.all([\n documentManager\n .findMany(draftFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]),\n strapi.db.query(typedUid).findOne({ select: ['documentId'] }),\n ]);\n\n const documentId = otherDocumentVersion?.documentId;\n\n if (documentVersion) {\n if (permissionChecker.cannot.update(documentVersion)) {\n throw new errors.ForbiddenError();\n }\n } else if (permissionChecker.cannot.create()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizeInput = documentVersion\n ? permissionChecker.sanitizeUpdateInput(documentVersion)\n : permissionChecker.sanitizeCreateInput;\n\n const isEdition = documentVersion !== null && documentVersion !== undefined;\n const sanitizedData = setCreatorFields({ user, isEdition })(await sanitizeInput(data)) as Record<\n string,\n unknown\n >;\n\n const formatted = await strapi.db.transaction(async () => {\n let doc: any;\n\n if (documentId === undefined) {\n doc = await documentManager.create(typedUid, {\n data: sanitizedData,\n ...sanitizedQuery,\n locale: resolvedLocale,\n });\n } else {\n doc = await documentManager.update(documentId, typedUid, {\n data: sanitizedData,\n populate,\n locale: resolvedLocale,\n });\n }\n\n return sanitizeFormatShape(permissionChecker, typedUid, doc);\n });\n\n return ok(formatted as Record<string, unknown>);\n};\n\n// ---------------------------------------------------------------------------\n// Handler factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a handler for reading the single-type document.\n * Returns available locale metadata when the requested locale version does not exist.\n * Enforces RBAC read permission.\n */\nexport const createSingleGetHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleGetArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale, status } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.read()) {\n throw new errors.ForbiddenError();\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read({ locale, status });\n const { locale: resolvedLocale, status: resolvedStatus } = await getDocumentLocaleAndStatus(\n { locale, status },\n uid\n );\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(permissionQuery)\n .populateDeep(Infinity)\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const versionFindQuery: McpDocumentQuery = {\n ...permissionQuery,\n populate,\n locale: resolvedLocale,\n status: resolvedStatus,\n };\n const version = await getService('document-manager')\n .findMany(versionFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!version) {\n if (permissionChecker.cannot.create()) {\n throw new errors.ForbiddenError();\n }\n\n const document = await strapi.db.query(typedUid).findOne({});\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n const { meta } = await formatDocumentWithMetadata(\n permissionChecker,\n typedUid,\n {\n documentId: document.documentId,\n locale: resolvedLocale,\n publishedAt: null,\n } as Parameters<typeof formatDocumentWithMetadata>[2],\n { availableLocales: true, availableStatus: false }\n );\n\n return ok({ data: {}, meta } as Record<string, unknown>);\n }\n\n if (permissionChecker.cannot.read(version)) {\n throw new errors.ForbiddenError();\n }\n\n const result = await sanitizeFormatShape(permissionChecker, typedUid, version);\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for creating or updating the single-type document.\n * Delegates to `singleCreateOrUpdate`; enforces RBAC create/update permission.\n */\nexport const createSingleWriteHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({\n args,\n }: {\n args: Record<string, unknown>;\n }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n return singleCreateOrUpdate(strapi, uid, context, args as SingleWriteArgs);\n };\n\n/**\n * Creates a handler for deleting the single-type document (or a specific locale).\n * Enforces RBAC delete permission on every locale version before deletion.\n */\nexport const createSingleDeleteHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.delete()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.delete({ locale });\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(sanitizedQuery)\n .populateDeep(Infinity)\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const isLocalized = isContentTypeLocalized(strapi, uid);\n\n const localeForQuery = isLocalized === true ? resolvedLocale : undefined;\n\n const documentLocales = await documentManager.findLocales(undefined, typedUid, {\n populate,\n locale: localeForQuery,\n });\n\n if (documentLocales.length === 0) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n for (const document of documentLocales) {\n if (permissionChecker.cannot.delete(document)) {\n throw new errors.ForbiddenError();\n }\n }\n\n const deletedEntity = await documentManager.delete(documentLocales[0].documentId, typedUid, {\n locale: localeForQuery,\n });\n\n // Delete returns `{ data }` without metadata — no status to compute, so sanitize + shape only.\n const sanitizedResult = await permissionChecker.sanitizeOutput(deletedEntity);\n const shapedResult = await shapeRelationsForMcp(typedUid, sanitizedResult);\n\n return ok({ data: shapedResult } as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for publishing the single-type document draft.\n * Enforces RBAC publish permission; throws NotFound when the draft is missing.\n */\nexport const createSinglePublishHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.publish()) {\n throw new errors.ForbiddenError();\n }\n\n const publishedDocument = await strapi.db.transaction(async () => {\n const sanitizedQuery = await permissionChecker.sanitizedQuery.publish({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const publishFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n locale: resolvedLocale,\n status: 'draft',\n };\n const document = await getService('document-manager')\n .findMany(publishFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.publish(document)) {\n throw new errors.ForbiddenError();\n }\n\n const publishResult = await documentManager.publish(document.documentId, typedUid, {\n locale: resolvedLocale,\n });\n\n return publishResult?.at(0);\n });\n\n const result = await sanitizeFormatShape(permissionChecker, typedUid, publishedDocument);\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for unpublishing the single-type document.\n * Optionally discards the draft in the same transaction when `discardDraft` is true.\n * Enforces RBAC unpublish (and discard) permission.\n */\nexport const createSingleUnpublishHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleUnpublishArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale, discardDraft } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.unpublish()) {\n throw new errors.ForbiddenError();\n }\n\n if (discardDraft === true && permissionChecker.cannot.discard()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.unpublish({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const unpublishFindQuery: McpDocumentQuery = { ...sanitizedQuery, locale: resolvedLocale };\n const document = await getService('document-manager')\n .findMany(unpublishFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.unpublish(document)) {\n throw new errors.ForbiddenError();\n }\n\n if (discardDraft === true && permissionChecker.cannot.discard(document)) {\n throw new errors.ForbiddenError();\n }\n\n const result = await strapi.db.transaction(async () => {\n if (discardDraft === true) {\n await documentManager.discardDraft(document.documentId, typedUid, {\n locale: resolvedLocale,\n });\n }\n\n return asyncPipe.pipe(\n (doc: any) =>\n documentManager.unpublish(doc.documentId, typedUid, { locale: resolvedLocale }),\n (doc: unknown) => sanitizeFormatShape(permissionChecker, typedUid, doc)\n )(document);\n });\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for discarding the draft of the single-type document.\n * Restores the published version as the draft. Enforces RBAC discard permission.\n */\nexport const createSingleDiscardDraftHandler =\n (uid: UID.SingleType) =>\n (_strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.discard()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.discard({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const discardFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n locale: resolvedLocale,\n status: 'published',\n };\n const document = await getService('document-manager')\n .findMany(discardFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.discard(document)) {\n throw new errors.ForbiddenError();\n }\n\n const discardedDocument = await asyncPipe.pipe(\n (doc: any) =>\n documentManager.discardDraft(doc.documentId, typedUid, { locale: resolvedLocale }),\n (doc: unknown) => sanitizeFormatShape(permissionChecker, typedUid, doc)\n )(document);\n\n return ok(discardedDocument as Record<string, unknown>);\n };\n"],"names":["singleCreateOrUpdate","strapi","uid","context","args","userAbility","user","data","locale","typedUid","documentManager","getService","permissionChecker","create","model","cannot","update","errors","ForbiddenError","sanitizedQuery","resolvedLocale","getDocumentLocaleAndStatus","populate","populateFromQuery","populateDeep","Infinity","withPopulateOverride","getPopulateForLocalizations","build","draftFindQuery","status","documentVersion","otherDocumentVersion","Promise","all","findMany","then","docs","db","query","findOne","select","documentId","sanitizeInput","sanitizeUpdateInput","sanitizeCreateInput","isEdition","undefined","sanitizedData","setCreatorFields","formatted","transaction","doc","sanitizeFormatShape","ok","createSingleGetHandler","read","permissionQuery","resolvedStatus","versionFindQuery","version","document","NotFoundError","MCP_NOT_FOUND_DOCUMENT","meta","formatDocumentWithMetadata","publishedAt","availableLocales","availableStatus","result","createSingleWriteHandler","createSingleDeleteHandler","delete","isLocalized","isContentTypeLocalized","localeForQuery","documentLocales","findLocales","length","deletedEntity","sanitizedResult","sanitizeOutput","shapedResult","shapeRelationsForMcp","createSinglePublishHandler","publish","publishedDocument","publishFindQuery","publishResult","at","createSingleUnpublishHandler","discardDraft","unpublish","discard","unpublishFindQuery","asyncPipe","pipe","createSingleDiscardDraftHandler","_strapi","discardFindQuery","discardedDocument"],"mappings":"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"}
@@ -4,8 +4,11 @@ var deriveContentTypeMcpTools = require('./derive-content-type-mcp-tools.js');
4
4
  var index = require('../utils/index.js');
5
5
 
6
6
  /**
7
- * Registers derived content-type MCP tools during plugin bootstrap, before the MCP HTTP server starts.
7
+ * Registers derived content-type MCP tools via strapi.ai.mcp.registerTool().
8
+ * Must be called from the plugin register phase, before the MCP HTTP server starts.
8
9
  */ const registerContentManagerMcpTools = async ({ strapi })=>{
10
+ // Performance only: registerTool() is safe when MCP is disabled (definitions are stored but
11
+ // never exposed). Skip the expensive derivation below when the MCP server will not start.
9
12
  if (strapi.ai.mcp.isEnabled() !== true) {
10
13
  return;
11
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"register-content-manager-mcp-tools.js","sources":["../../../server/src/mcp/register-content-manager-mcp-tools.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { deriveDisplayedContentTypeMcpToolDefinitions } from './derive-content-type-mcp-tools';\nimport { getService } from '../utils';\n\n/**\n * Registers derived content-type MCP tools during plugin bootstrap, before the MCP HTTP server starts.\n */\nexport const registerContentManagerMcpTools = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<void> => {\n if (strapi.ai.mcp.isEnabled() !== true) {\n return;\n }\n\n const i18nPlugin = strapi.plugin('i18n');\n\n let localeCodes = null;\n let defaultLocale: string | null = null;\n if (i18nPlugin !== undefined) {\n localeCodes = (await i18nPlugin.service('locales').find()).map(\n (locale: { code: string }) => locale.code\n ) as [string, ...string[]];\n defaultLocale = await i18nPlugin.service('locales').getDefaultLocale();\n }\n\n const models = getService('content-types').findDisplayedContentTypes();\n const tools = deriveDisplayedContentTypeMcpToolDefinitions(strapi, models, {\n localeCodes,\n defaultLocale,\n });\n\n for (const tool of tools) {\n strapi.ai.mcp.registerTool(tool);\n }\n};\n"],"names":["registerContentManagerMcpTools","strapi","ai","mcp","isEnabled","i18nPlugin","plugin","localeCodes","defaultLocale","undefined","service","find","map","locale","code","getDefaultLocale","models","getService","findDisplayedContentTypes","tools","deriveDisplayedContentTypeMcpToolDefinitions","tool","registerTool"],"mappings":";;;;;AAKA;;AAEC,IACM,MAAMA,8BAAAA,GAAiC,OAAO,EACnDC,MAAM,EAGP,GAAA;AACC,IAAA,IAAIA,OAAOC,EAAE,CAACC,GAAG,CAACC,SAAS,OAAO,IAAA,EAAM;AACtC,QAAA;AACF,IAAA;IAEA,MAAMC,UAAAA,GAAaJ,MAAAA,CAAOK,MAAM,CAAC,MAAA,CAAA;AAEjC,IAAA,IAAIC,WAAAA,GAAc,IAAA;AAClB,IAAA,IAAIC,aAAAA,GAA+B,IAAA;AACnC,IAAA,IAAIH,eAAeI,SAAAA,EAAW;AAC5BF,QAAAA,WAAAA,GAAc,CAAC,MAAMF,UAAAA,CAAWK,OAAO,CAAC,SAAA,CAAA,CAAWC,IAAI,EAAC,EAAGC,GAAG,CAC5D,CAACC,MAAAA,GAA6BA,OAAOC,IAAI,CAAA;AAE3CN,QAAAA,aAAAA,GAAgB,MAAMH,UAAAA,CAAWK,OAAO,CAAC,WAAWK,gBAAgB,EAAA;AACtE,IAAA;IAEA,MAAMC,MAAAA,GAASC,gBAAAA,CAAW,eAAA,CAAA,CAAiBC,yBAAyB,EAAA;IACpE,MAAMC,KAAAA,GAAQC,sEAAAA,CAA6CnB,MAAAA,EAAQe,MAAAA,EAAQ;AACzET,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA,CAAA;IAEA,KAAK,MAAMa,QAAQF,KAAAA,CAAO;AACxBlB,QAAAA,MAAAA,CAAOC,EAAE,CAACC,GAAG,CAACmB,YAAY,CAACD,IAAAA,CAAAA;AAC7B,IAAA;AACF;;;;"}
1
+ {"version":3,"file":"register-content-manager-mcp-tools.js","sources":["../../../server/src/mcp/register-content-manager-mcp-tools.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { deriveDisplayedContentTypeMcpToolDefinitions } from './derive-content-type-mcp-tools';\nimport { getService } from '../utils';\n\n/**\n * Registers derived content-type MCP tools via strapi.ai.mcp.registerTool().\n * Must be called from the plugin register phase, before the MCP HTTP server starts.\n */\nexport const registerContentManagerMcpTools = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<void> => {\n // Performance only: registerTool() is safe when MCP is disabled (definitions are stored but\n // never exposed). Skip the expensive derivation below when the MCP server will not start.\n if (strapi.ai.mcp.isEnabled() !== true) {\n return;\n }\n\n const i18nPlugin = strapi.plugin('i18n');\n\n let localeCodes = null;\n let defaultLocale: string | null = null;\n if (i18nPlugin !== undefined) {\n localeCodes = (await i18nPlugin.service('locales').find()).map(\n (locale: { code: string }) => locale.code\n ) as [string, ...string[]];\n defaultLocale = await i18nPlugin.service('locales').getDefaultLocale();\n }\n\n const models = getService('content-types').findDisplayedContentTypes();\n const tools = deriveDisplayedContentTypeMcpToolDefinitions(strapi, models, {\n localeCodes,\n defaultLocale,\n });\n\n for (const tool of tools) {\n strapi.ai.mcp.registerTool(tool);\n }\n};\n"],"names":["registerContentManagerMcpTools","strapi","ai","mcp","isEnabled","i18nPlugin","plugin","localeCodes","defaultLocale","undefined","service","find","map","locale","code","getDefaultLocale","models","getService","findDisplayedContentTypes","tools","deriveDisplayedContentTypeMcpToolDefinitions","tool","registerTool"],"mappings":";;;;;AAKA;;;AAGC,IACM,MAAMA,8BAAAA,GAAiC,OAAO,EACnDC,MAAM,EAGP,GAAA;;;AAGC,IAAA,IAAIA,OAAOC,EAAE,CAACC,GAAG,CAACC,SAAS,OAAO,IAAA,EAAM;AACtC,QAAA;AACF,IAAA;IAEA,MAAMC,UAAAA,GAAaJ,MAAAA,CAAOK,MAAM,CAAC,MAAA,CAAA;AAEjC,IAAA,IAAIC,WAAAA,GAAc,IAAA;AAClB,IAAA,IAAIC,aAAAA,GAA+B,IAAA;AACnC,IAAA,IAAIH,eAAeI,SAAAA,EAAW;AAC5BF,QAAAA,WAAAA,GAAc,CAAC,MAAMF,UAAAA,CAAWK,OAAO,CAAC,SAAA,CAAA,CAAWC,IAAI,EAAC,EAAGC,GAAG,CAC5D,CAACC,MAAAA,GAA6BA,OAAOC,IAAI,CAAA;AAE3CN,QAAAA,aAAAA,GAAgB,MAAMH,UAAAA,CAAWK,OAAO,CAAC,WAAWK,gBAAgB,EAAA;AACtE,IAAA;IAEA,MAAMC,MAAAA,GAASC,gBAAAA,CAAW,eAAA,CAAA,CAAiBC,yBAAyB,EAAA;IACpE,MAAMC,KAAAA,GAAQC,sEAAAA,CAA6CnB,MAAAA,EAAQe,MAAAA,EAAQ;AACzET,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA,CAAA;IAEA,KAAK,MAAMa,QAAQF,KAAAA,CAAO;AACxBlB,QAAAA,MAAAA,CAAOC,EAAE,CAACC,GAAG,CAACmB,YAAY,CAACD,IAAAA,CAAAA;AAC7B,IAAA;AACF;;;;"}
@@ -2,8 +2,11 @@ import { deriveDisplayedContentTypeMcpToolDefinitions } from './derive-content-t
2
2
  import { getService } from '../utils/index.mjs';
3
3
 
4
4
  /**
5
- * Registers derived content-type MCP tools during plugin bootstrap, before the MCP HTTP server starts.
5
+ * Registers derived content-type MCP tools via strapi.ai.mcp.registerTool().
6
+ * Must be called from the plugin register phase, before the MCP HTTP server starts.
6
7
  */ const registerContentManagerMcpTools = async ({ strapi })=>{
8
+ // Performance only: registerTool() is safe when MCP is disabled (definitions are stored but
9
+ // never exposed). Skip the expensive derivation below when the MCP server will not start.
7
10
  if (strapi.ai.mcp.isEnabled() !== true) {
8
11
  return;
9
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"register-content-manager-mcp-tools.mjs","sources":["../../../server/src/mcp/register-content-manager-mcp-tools.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { deriveDisplayedContentTypeMcpToolDefinitions } from './derive-content-type-mcp-tools';\nimport { getService } from '../utils';\n\n/**\n * Registers derived content-type MCP tools during plugin bootstrap, before the MCP HTTP server starts.\n */\nexport const registerContentManagerMcpTools = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<void> => {\n if (strapi.ai.mcp.isEnabled() !== true) {\n return;\n }\n\n const i18nPlugin = strapi.plugin('i18n');\n\n let localeCodes = null;\n let defaultLocale: string | null = null;\n if (i18nPlugin !== undefined) {\n localeCodes = (await i18nPlugin.service('locales').find()).map(\n (locale: { code: string }) => locale.code\n ) as [string, ...string[]];\n defaultLocale = await i18nPlugin.service('locales').getDefaultLocale();\n }\n\n const models = getService('content-types').findDisplayedContentTypes();\n const tools = deriveDisplayedContentTypeMcpToolDefinitions(strapi, models, {\n localeCodes,\n defaultLocale,\n });\n\n for (const tool of tools) {\n strapi.ai.mcp.registerTool(tool);\n }\n};\n"],"names":["registerContentManagerMcpTools","strapi","ai","mcp","isEnabled","i18nPlugin","plugin","localeCodes","defaultLocale","undefined","service","find","map","locale","code","getDefaultLocale","models","getService","findDisplayedContentTypes","tools","deriveDisplayedContentTypeMcpToolDefinitions","tool","registerTool"],"mappings":";;;AAKA;;AAEC,IACM,MAAMA,8BAAAA,GAAiC,OAAO,EACnDC,MAAM,EAGP,GAAA;AACC,IAAA,IAAIA,OAAOC,EAAE,CAACC,GAAG,CAACC,SAAS,OAAO,IAAA,EAAM;AACtC,QAAA;AACF,IAAA;IAEA,MAAMC,UAAAA,GAAaJ,MAAAA,CAAOK,MAAM,CAAC,MAAA,CAAA;AAEjC,IAAA,IAAIC,WAAAA,GAAc,IAAA;AAClB,IAAA,IAAIC,aAAAA,GAA+B,IAAA;AACnC,IAAA,IAAIH,eAAeI,SAAAA,EAAW;AAC5BF,QAAAA,WAAAA,GAAc,CAAC,MAAMF,UAAAA,CAAWK,OAAO,CAAC,SAAA,CAAA,CAAWC,IAAI,EAAC,EAAGC,GAAG,CAC5D,CAACC,MAAAA,GAA6BA,OAAOC,IAAI,CAAA;AAE3CN,QAAAA,aAAAA,GAAgB,MAAMH,UAAAA,CAAWK,OAAO,CAAC,WAAWK,gBAAgB,EAAA;AACtE,IAAA;IAEA,MAAMC,MAAAA,GAASC,UAAAA,CAAW,eAAA,CAAA,CAAiBC,yBAAyB,EAAA;IACpE,MAAMC,KAAAA,GAAQC,4CAAAA,CAA6CnB,MAAAA,EAAQe,MAAAA,EAAQ;AACzET,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA,CAAA;IAEA,KAAK,MAAMa,QAAQF,KAAAA,CAAO;AACxBlB,QAAAA,MAAAA,CAAOC,EAAE,CAACC,GAAG,CAACmB,YAAY,CAACD,IAAAA,CAAAA;AAC7B,IAAA;AACF;;;;"}
1
+ {"version":3,"file":"register-content-manager-mcp-tools.mjs","sources":["../../../server/src/mcp/register-content-manager-mcp-tools.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { deriveDisplayedContentTypeMcpToolDefinitions } from './derive-content-type-mcp-tools';\nimport { getService } from '../utils';\n\n/**\n * Registers derived content-type MCP tools via strapi.ai.mcp.registerTool().\n * Must be called from the plugin register phase, before the MCP HTTP server starts.\n */\nexport const registerContentManagerMcpTools = async ({\n strapi,\n}: {\n strapi: Core.Strapi;\n}): Promise<void> => {\n // Performance only: registerTool() is safe when MCP is disabled (definitions are stored but\n // never exposed). Skip the expensive derivation below when the MCP server will not start.\n if (strapi.ai.mcp.isEnabled() !== true) {\n return;\n }\n\n const i18nPlugin = strapi.plugin('i18n');\n\n let localeCodes = null;\n let defaultLocale: string | null = null;\n if (i18nPlugin !== undefined) {\n localeCodes = (await i18nPlugin.service('locales').find()).map(\n (locale: { code: string }) => locale.code\n ) as [string, ...string[]];\n defaultLocale = await i18nPlugin.service('locales').getDefaultLocale();\n }\n\n const models = getService('content-types').findDisplayedContentTypes();\n const tools = deriveDisplayedContentTypeMcpToolDefinitions(strapi, models, {\n localeCodes,\n defaultLocale,\n });\n\n for (const tool of tools) {\n strapi.ai.mcp.registerTool(tool);\n }\n};\n"],"names":["registerContentManagerMcpTools","strapi","ai","mcp","isEnabled","i18nPlugin","plugin","localeCodes","defaultLocale","undefined","service","find","map","locale","code","getDefaultLocale","models","getService","findDisplayedContentTypes","tools","deriveDisplayedContentTypeMcpToolDefinitions","tool","registerTool"],"mappings":";;;AAKA;;;AAGC,IACM,MAAMA,8BAAAA,GAAiC,OAAO,EACnDC,MAAM,EAGP,GAAA;;;AAGC,IAAA,IAAIA,OAAOC,EAAE,CAACC,GAAG,CAACC,SAAS,OAAO,IAAA,EAAM;AACtC,QAAA;AACF,IAAA;IAEA,MAAMC,UAAAA,GAAaJ,MAAAA,CAAOK,MAAM,CAAC,MAAA,CAAA;AAEjC,IAAA,IAAIC,WAAAA,GAAc,IAAA;AAClB,IAAA,IAAIC,aAAAA,GAA+B,IAAA;AACnC,IAAA,IAAIH,eAAeI,SAAAA,EAAW;AAC5BF,QAAAA,WAAAA,GAAc,CAAC,MAAMF,UAAAA,CAAWK,OAAO,CAAC,SAAA,CAAA,CAAWC,IAAI,EAAC,EAAGC,GAAG,CAC5D,CAACC,MAAAA,GAA6BA,OAAOC,IAAI,CAAA;AAE3CN,QAAAA,aAAAA,GAAgB,MAAMH,UAAAA,CAAWK,OAAO,CAAC,WAAWK,gBAAgB,EAAA;AACtE,IAAA;IAEA,MAAMC,MAAAA,GAASC,UAAAA,CAAW,eAAA,CAAA,CAAiBC,yBAAyB,EAAA;IACpE,MAAMC,KAAAA,GAAQC,4CAAAA,CAA6CnB,MAAAA,EAAQe,MAAAA,EAAQ;AACzET,QAAAA,WAAAA;AACAC,QAAAA;AACF,KAAA,CAAA;IAEA,KAAK,MAAMa,QAAQF,KAAAA,CAAO;AACxBlB,QAAAA,MAAAA,CAAOC,EAAE,CAACC,GAAG,CAACmB,YAAY,CAACD,IAAAA,CAAAA;AAC7B,IAAA;AACF;;;;"}
@@ -0,0 +1,108 @@
1
+ 'use strict';
2
+
3
+ var strapiUtils = require('@strapi/utils');
4
+
5
+ // Relations whose cardinality is "many" — maps to Array output.
6
+ // Includes non-owning variants and morph-many.
7
+ const MANY_RELATION_TYPES = new Set([
8
+ 'oneToMany',
9
+ 'manyToMany',
10
+ 'manyWay',
11
+ 'morphToMany',
12
+ 'morphMany'
13
+ ]);
14
+ /**
15
+ * Canonical "is this relation a list" predicate for the MCP output boundary.
16
+ * Both the runtime shaping (reduceToIdentity) and the registered output schemas
17
+ * (output-schemas.ts) MUST use this single definition — the MCP SDK validates
18
+ * structuredContent against the schema, so any divergence fails the tool call.
19
+ * Intentionally broader than `relations.isAnyToMany` from @strapi/utils, which
20
+ * ignores `manyWay` and the morph variants.
21
+ */ const isManyRelationForMcp = (attribute)=>MANY_RELATION_TYPES.has(attribute.relation ?? '');
22
+ /**
23
+ * Extracts identity fields from a single relation entry.
24
+ * Returns undefined when the entry has no documentId (e.g. a bare {count} object).
25
+ */ const pickIdentity = (entry)=>{
26
+ if (entry === null || typeof entry !== 'object') {
27
+ return undefined;
28
+ }
29
+ const obj = entry;
30
+ if (typeof obj.documentId !== 'string') {
31
+ return undefined;
32
+ }
33
+ const identity = {
34
+ documentId: obj.documentId
35
+ };
36
+ if (typeof obj.locale === 'string') {
37
+ identity.locale = obj.locale;
38
+ }
39
+ if (typeof obj.__type === 'string') {
40
+ identity.__type = obj.__type;
41
+ }
42
+ // Preserve the computed publish status on `localizations` entries — it is
43
+ // calculated by formatDocumentWithMetadata BEFORE shaping (calculate, then strip).
44
+ // Non-localization relation entries never carry a string `status`, so this is a no-op for them.
45
+ if (typeof obj.status === 'string') {
46
+ identity.status = obj.status;
47
+ }
48
+ return identity;
49
+ };
50
+ /**
51
+ * Reduces a populated relation value to identity-only shape.
52
+ *
53
+ * to-one → { documentId, locale?, __type? } | null
54
+ * to-many → Array<{ documentId, locale?, __type? }> ([] when empty)
55
+ */ const reduceToIdentity = (attribute, value)=>{
56
+ const isMany = isManyRelationForMcp(attribute);
57
+ if (isMany) {
58
+ if (Array.isArray(value)) {
59
+ return value.map(pickIdentity).filter((v)=>v !== undefined);
60
+ }
61
+ // defensive: { count: N } or null/undefined → empty array
62
+ return [];
63
+ }
64
+ // to-one
65
+ if (value === null || value === undefined) {
66
+ return null;
67
+ }
68
+ if (Array.isArray(value)) {
69
+ // should not happen, but guard: treat first element
70
+ return pickIdentity(value[0]) ?? null;
71
+ }
72
+ return pickIdentity(value) ?? null;
73
+ };
74
+ /**
75
+ * Post-sanitize shaping visitor.
76
+ * Reduces every relation attribute to identity-only (documentId + locale? + __type?).
77
+ * Skips admin::user relations — those are out of scope and preserved as-is.
78
+ */ const shapeRelationToIdentity = ({ key, value, attribute }, { set })=>{
79
+ if (attribute?.type !== 'relation') {
80
+ return;
81
+ }
82
+ const target = attribute.target;
83
+ // Out of scope — admin user records are preserved untouched (tracked separately).
84
+ if (target === 'admin::user') {
85
+ return;
86
+ }
87
+ // @ts-expect-error — reduceToIdentity returns a narrower type; traverseEntity Data allows unknown
88
+ set(key, reduceToIdentity(attribute, value));
89
+ };
90
+ /**
91
+ * Applies identity shaping to all relation fields in a document, including
92
+ * nested fields inside components, dynamic zones, and `localizations`.
93
+ *
94
+ * This covers leak family #1 (relation targets) and #2 (localizations full draft rows)
95
+ * with the same single mechanism.
96
+ */ const shapeRelationsForMcp = async (uid, data)=>{
97
+ return strapiUtils.traverseEntity(shapeRelationToIdentity, {
98
+ schema: strapi.getModel(uid),
99
+ getModel: strapi.getModel.bind(strapi)
100
+ }, // @ts-expect-error — traverseEntity expects Data; post-sanitize documents are compatible at runtime
101
+ data);
102
+ };
103
+
104
+ exports.MANY_RELATION_TYPES = MANY_RELATION_TYPES;
105
+ exports.isManyRelationForMcp = isManyRelationForMcp;
106
+ exports.reduceToIdentity = reduceToIdentity;
107
+ exports.shapeRelationsForMcp = shapeRelationsForMcp;
108
+ //# sourceMappingURL=shape-relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape-relations.js","sources":["../../../../server/src/mcp/sanitizers/shape-relations.ts"],"sourcesContent":["import { traverseEntity } from '@strapi/utils';\nimport type { UID } from '@strapi/types';\n\n// Relations whose cardinality is \"many\" — maps to Array output.\n// Includes non-owning variants and morph-many.\nconst MANY_RELATION_TYPES = new Set([\n 'oneToMany',\n 'manyToMany',\n 'manyWay',\n 'morphToMany',\n 'morphMany',\n]);\n\n/**\n * Canonical \"is this relation a list\" predicate for the MCP output boundary.\n * Both the runtime shaping (reduceToIdentity) and the registered output schemas\n * (output-schemas.ts) MUST use this single definition — the MCP SDK validates\n * structuredContent against the schema, so any divergence fails the tool call.\n * Intentionally broader than `relations.isAnyToMany` from @strapi/utils, which\n * ignores `manyWay` and the morph variants.\n */\nexport const isManyRelationForMcp = (attribute: { relation?: string }): boolean =>\n MANY_RELATION_TYPES.has(attribute.relation ?? '');\n\ntype RelationIdentity = {\n documentId: string;\n locale?: string;\n __type?: string;\n status?: string;\n};\n\n/**\n * Extracts identity fields from a single relation entry.\n * Returns undefined when the entry has no documentId (e.g. a bare {count} object).\n */\nconst pickIdentity = (entry: unknown): RelationIdentity | undefined => {\n if (entry === null || typeof entry !== 'object') {\n return undefined;\n }\n\n const obj = entry as Record<string, unknown>;\n\n if (typeof obj.documentId !== 'string') {\n return undefined;\n }\n\n const identity: RelationIdentity = { documentId: obj.documentId };\n\n if (typeof obj.locale === 'string') {\n identity.locale = obj.locale;\n }\n\n if (typeof obj.__type === 'string') {\n identity.__type = obj.__type;\n }\n\n // Preserve the computed publish status on `localizations` entries — it is\n // calculated by formatDocumentWithMetadata BEFORE shaping (calculate, then strip).\n // Non-localization relation entries never carry a string `status`, so this is a no-op for them.\n if (typeof obj.status === 'string') {\n identity.status = obj.status;\n }\n\n return identity;\n};\n\n/**\n * Reduces a populated relation value to identity-only shape.\n *\n * to-one → { documentId, locale?, __type? } | null\n * to-many → Array<{ documentId, locale?, __type? }> ([] when empty)\n */\nconst reduceToIdentity = (\n attribute: { relation?: string },\n value: unknown\n): RelationIdentity | RelationIdentity[] | null => {\n const isMany = isManyRelationForMcp(attribute);\n\n if (isMany) {\n if (Array.isArray(value)) {\n return value.map(pickIdentity).filter((v): v is RelationIdentity => v !== undefined);\n }\n // defensive: { count: N } or null/undefined → empty array\n return [];\n }\n\n // to-one\n if (value === null || value === undefined) {\n return null;\n }\n\n if (Array.isArray(value)) {\n // should not happen, but guard: treat first element\n return pickIdentity(value[0]) ?? null;\n }\n\n return pickIdentity(value) ?? null;\n};\n\n/**\n * Post-sanitize shaping visitor.\n * Reduces every relation attribute to identity-only (documentId + locale? + __type?).\n * Skips admin::user relations — those are out of scope and preserved as-is.\n */\nconst shapeRelationToIdentity: Parameters<typeof traverseEntity>[0] = (\n { key, value, attribute },\n { set }\n) => {\n if (attribute?.type !== 'relation') {\n return;\n }\n\n const target = (attribute as { target?: string }).target;\n\n // Out of scope — admin user records are preserved untouched (tracked separately).\n if (target === 'admin::user') {\n return;\n }\n\n // @ts-expect-error — reduceToIdentity returns a narrower type; traverseEntity Data allows unknown\n set(key, reduceToIdentity(attribute as { relation?: string }, value));\n};\n\n/**\n * Applies identity shaping to all relation fields in a document, including\n * nested fields inside components, dynamic zones, and `localizations`.\n *\n * This covers leak family #1 (relation targets) and #2 (localizations full draft rows)\n * with the same single mechanism.\n */\nexport const shapeRelationsForMcp = async (\n uid: UID.Schema,\n data: Record<string, unknown>\n): Promise<Record<string, unknown>> => {\n return traverseEntity(\n shapeRelationToIdentity,\n {\n schema: strapi.getModel(uid),\n getModel: strapi.getModel.bind(strapi),\n },\n // @ts-expect-error — traverseEntity expects Data; post-sanitize documents are compatible at runtime\n data\n );\n};\n\n// Export for unit-testing without a full strapi instance\nexport { reduceToIdentity, MANY_RELATION_TYPES };\n"],"names":["MANY_RELATION_TYPES","Set","isManyRelationForMcp","attribute","has","relation","pickIdentity","entry","undefined","obj","documentId","identity","locale","__type","status","reduceToIdentity","value","isMany","Array","isArray","map","filter","v","shapeRelationToIdentity","key","set","type","target","shapeRelationsForMcp","uid","data","traverseEntity","schema","strapi","getModel","bind"],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ import { traverseEntity } from '@strapi/utils';
2
+
3
+ // Relations whose cardinality is "many" — maps to Array output.
4
+ // Includes non-owning variants and morph-many.
5
+ const MANY_RELATION_TYPES = new Set([
6
+ 'oneToMany',
7
+ 'manyToMany',
8
+ 'manyWay',
9
+ 'morphToMany',
10
+ 'morphMany'
11
+ ]);
12
+ /**
13
+ * Canonical "is this relation a list" predicate for the MCP output boundary.
14
+ * Both the runtime shaping (reduceToIdentity) and the registered output schemas
15
+ * (output-schemas.ts) MUST use this single definition — the MCP SDK validates
16
+ * structuredContent against the schema, so any divergence fails the tool call.
17
+ * Intentionally broader than `relations.isAnyToMany` from @strapi/utils, which
18
+ * ignores `manyWay` and the morph variants.
19
+ */ const isManyRelationForMcp = (attribute)=>MANY_RELATION_TYPES.has(attribute.relation ?? '');
20
+ /**
21
+ * Extracts identity fields from a single relation entry.
22
+ * Returns undefined when the entry has no documentId (e.g. a bare {count} object).
23
+ */ const pickIdentity = (entry)=>{
24
+ if (entry === null || typeof entry !== 'object') {
25
+ return undefined;
26
+ }
27
+ const obj = entry;
28
+ if (typeof obj.documentId !== 'string') {
29
+ return undefined;
30
+ }
31
+ const identity = {
32
+ documentId: obj.documentId
33
+ };
34
+ if (typeof obj.locale === 'string') {
35
+ identity.locale = obj.locale;
36
+ }
37
+ if (typeof obj.__type === 'string') {
38
+ identity.__type = obj.__type;
39
+ }
40
+ // Preserve the computed publish status on `localizations` entries — it is
41
+ // calculated by formatDocumentWithMetadata BEFORE shaping (calculate, then strip).
42
+ // Non-localization relation entries never carry a string `status`, so this is a no-op for them.
43
+ if (typeof obj.status === 'string') {
44
+ identity.status = obj.status;
45
+ }
46
+ return identity;
47
+ };
48
+ /**
49
+ * Reduces a populated relation value to identity-only shape.
50
+ *
51
+ * to-one → { documentId, locale?, __type? } | null
52
+ * to-many → Array<{ documentId, locale?, __type? }> ([] when empty)
53
+ */ const reduceToIdentity = (attribute, value)=>{
54
+ const isMany = isManyRelationForMcp(attribute);
55
+ if (isMany) {
56
+ if (Array.isArray(value)) {
57
+ return value.map(pickIdentity).filter((v)=>v !== undefined);
58
+ }
59
+ // defensive: { count: N } or null/undefined → empty array
60
+ return [];
61
+ }
62
+ // to-one
63
+ if (value === null || value === undefined) {
64
+ return null;
65
+ }
66
+ if (Array.isArray(value)) {
67
+ // should not happen, but guard: treat first element
68
+ return pickIdentity(value[0]) ?? null;
69
+ }
70
+ return pickIdentity(value) ?? null;
71
+ };
72
+ /**
73
+ * Post-sanitize shaping visitor.
74
+ * Reduces every relation attribute to identity-only (documentId + locale? + __type?).
75
+ * Skips admin::user relations — those are out of scope and preserved as-is.
76
+ */ const shapeRelationToIdentity = ({ key, value, attribute }, { set })=>{
77
+ if (attribute?.type !== 'relation') {
78
+ return;
79
+ }
80
+ const target = attribute.target;
81
+ // Out of scope — admin user records are preserved untouched (tracked separately).
82
+ if (target === 'admin::user') {
83
+ return;
84
+ }
85
+ // @ts-expect-error — reduceToIdentity returns a narrower type; traverseEntity Data allows unknown
86
+ set(key, reduceToIdentity(attribute, value));
87
+ };
88
+ /**
89
+ * Applies identity shaping to all relation fields in a document, including
90
+ * nested fields inside components, dynamic zones, and `localizations`.
91
+ *
92
+ * This covers leak family #1 (relation targets) and #2 (localizations full draft rows)
93
+ * with the same single mechanism.
94
+ */ const shapeRelationsForMcp = async (uid, data)=>{
95
+ return traverseEntity(shapeRelationToIdentity, {
96
+ schema: strapi.getModel(uid),
97
+ getModel: strapi.getModel.bind(strapi)
98
+ }, // @ts-expect-error — traverseEntity expects Data; post-sanitize documents are compatible at runtime
99
+ data);
100
+ };
101
+
102
+ export { MANY_RELATION_TYPES, isManyRelationForMcp, reduceToIdentity, shapeRelationsForMcp };
103
+ //# sourceMappingURL=shape-relations.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape-relations.mjs","sources":["../../../../server/src/mcp/sanitizers/shape-relations.ts"],"sourcesContent":["import { traverseEntity } from '@strapi/utils';\nimport type { UID } from '@strapi/types';\n\n// Relations whose cardinality is \"many\" — maps to Array output.\n// Includes non-owning variants and morph-many.\nconst MANY_RELATION_TYPES = new Set([\n 'oneToMany',\n 'manyToMany',\n 'manyWay',\n 'morphToMany',\n 'morphMany',\n]);\n\n/**\n * Canonical \"is this relation a list\" predicate for the MCP output boundary.\n * Both the runtime shaping (reduceToIdentity) and the registered output schemas\n * (output-schemas.ts) MUST use this single definition — the MCP SDK validates\n * structuredContent against the schema, so any divergence fails the tool call.\n * Intentionally broader than `relations.isAnyToMany` from @strapi/utils, which\n * ignores `manyWay` and the morph variants.\n */\nexport const isManyRelationForMcp = (attribute: { relation?: string }): boolean =>\n MANY_RELATION_TYPES.has(attribute.relation ?? '');\n\ntype RelationIdentity = {\n documentId: string;\n locale?: string;\n __type?: string;\n status?: string;\n};\n\n/**\n * Extracts identity fields from a single relation entry.\n * Returns undefined when the entry has no documentId (e.g. a bare {count} object).\n */\nconst pickIdentity = (entry: unknown): RelationIdentity | undefined => {\n if (entry === null || typeof entry !== 'object') {\n return undefined;\n }\n\n const obj = entry as Record<string, unknown>;\n\n if (typeof obj.documentId !== 'string') {\n return undefined;\n }\n\n const identity: RelationIdentity = { documentId: obj.documentId };\n\n if (typeof obj.locale === 'string') {\n identity.locale = obj.locale;\n }\n\n if (typeof obj.__type === 'string') {\n identity.__type = obj.__type;\n }\n\n // Preserve the computed publish status on `localizations` entries — it is\n // calculated by formatDocumentWithMetadata BEFORE shaping (calculate, then strip).\n // Non-localization relation entries never carry a string `status`, so this is a no-op for them.\n if (typeof obj.status === 'string') {\n identity.status = obj.status;\n }\n\n return identity;\n};\n\n/**\n * Reduces a populated relation value to identity-only shape.\n *\n * to-one → { documentId, locale?, __type? } | null\n * to-many → Array<{ documentId, locale?, __type? }> ([] when empty)\n */\nconst reduceToIdentity = (\n attribute: { relation?: string },\n value: unknown\n): RelationIdentity | RelationIdentity[] | null => {\n const isMany = isManyRelationForMcp(attribute);\n\n if (isMany) {\n if (Array.isArray(value)) {\n return value.map(pickIdentity).filter((v): v is RelationIdentity => v !== undefined);\n }\n // defensive: { count: N } or null/undefined → empty array\n return [];\n }\n\n // to-one\n if (value === null || value === undefined) {\n return null;\n }\n\n if (Array.isArray(value)) {\n // should not happen, but guard: treat first element\n return pickIdentity(value[0]) ?? null;\n }\n\n return pickIdentity(value) ?? null;\n};\n\n/**\n * Post-sanitize shaping visitor.\n * Reduces every relation attribute to identity-only (documentId + locale? + __type?).\n * Skips admin::user relations — those are out of scope and preserved as-is.\n */\nconst shapeRelationToIdentity: Parameters<typeof traverseEntity>[0] = (\n { key, value, attribute },\n { set }\n) => {\n if (attribute?.type !== 'relation') {\n return;\n }\n\n const target = (attribute as { target?: string }).target;\n\n // Out of scope — admin user records are preserved untouched (tracked separately).\n if (target === 'admin::user') {\n return;\n }\n\n // @ts-expect-error — reduceToIdentity returns a narrower type; traverseEntity Data allows unknown\n set(key, reduceToIdentity(attribute as { relation?: string }, value));\n};\n\n/**\n * Applies identity shaping to all relation fields in a document, including\n * nested fields inside components, dynamic zones, and `localizations`.\n *\n * This covers leak family #1 (relation targets) and #2 (localizations full draft rows)\n * with the same single mechanism.\n */\nexport const shapeRelationsForMcp = async (\n uid: UID.Schema,\n data: Record<string, unknown>\n): Promise<Record<string, unknown>> => {\n return traverseEntity(\n shapeRelationToIdentity,\n {\n schema: strapi.getModel(uid),\n getModel: strapi.getModel.bind(strapi),\n },\n // @ts-expect-error — traverseEntity expects Data; post-sanitize documents are compatible at runtime\n data\n );\n};\n\n// Export for unit-testing without a full strapi instance\nexport { reduceToIdentity, MANY_RELATION_TYPES };\n"],"names":["MANY_RELATION_TYPES","Set","isManyRelationForMcp","attribute","has","relation","pickIdentity","entry","undefined","obj","documentId","identity","locale","__type","status","reduceToIdentity","value","isMany","Array","isArray","map","filter","v","shapeRelationToIdentity","key","set","type","target","shapeRelationsForMcp","uid","data","traverseEntity","schema","strapi","getModel","bind"],"mappings":";;AAGA;AACA;AACA,MAAMA,mBAAAA,GAAsB,IAAIC,GAAAA,CAAI;AAClC,IAAA,WAAA;AACA,IAAA,YAAA;AACA,IAAA,SAAA;AACA,IAAA,aAAA;AACA,IAAA;AACD,CAAA;AAED;;;;;;;IAQO,MAAMC,oBAAAA,GAAuB,CAACC,SAAAA,GACnCH,mBAAAA,CAAoBI,GAAG,CAACD,SAAAA,CAAUE,QAAQ,IAAI,EAAA;AAShD;;;IAIA,MAAMC,eAAe,CAACC,KAAAA,GAAAA;AACpB,IAAA,IAAIA,KAAAA,KAAU,IAAA,IAAQ,OAAOA,KAAAA,KAAU,QAAA,EAAU;QAC/C,OAAOC,SAAAA;AACT,IAAA;AAEA,IAAA,MAAMC,GAAAA,GAAMF,KAAAA;AAEZ,IAAA,IAAI,OAAOE,GAAAA,CAAIC,UAAU,KAAK,QAAA,EAAU;QACtC,OAAOF,SAAAA;AACT,IAAA;AAEA,IAAA,MAAMG,QAAAA,GAA6B;AAAED,QAAAA,UAAAA,EAAYD,IAAIC;AAAW,KAAA;AAEhE,IAAA,IAAI,OAAOD,GAAAA,CAAIG,MAAM,KAAK,QAAA,EAAU;QAClCD,QAAAA,CAASC,MAAM,GAAGH,GAAAA,CAAIG,MAAM;AAC9B,IAAA;AAEA,IAAA,IAAI,OAAOH,GAAAA,CAAII,MAAM,KAAK,QAAA,EAAU;QAClCF,QAAAA,CAASE,MAAM,GAAGJ,GAAAA,CAAII,MAAM;AAC9B,IAAA;;;;AAKA,IAAA,IAAI,OAAOJ,GAAAA,CAAIK,MAAM,KAAK,QAAA,EAAU;QAClCH,QAAAA,CAASG,MAAM,GAAGL,GAAAA,CAAIK,MAAM;AAC9B,IAAA;IAEA,OAAOH,QAAAA;AACT,CAAA;AAEA;;;;;IAMA,MAAMI,gBAAAA,GAAmB,CACvBZ,SAAAA,EACAa,KAAAA,GAAAA;AAEA,IAAA,MAAMC,SAASf,oBAAAA,CAAqBC,SAAAA,CAAAA;AAEpC,IAAA,IAAIc,MAAAA,EAAQ;QACV,IAAIC,KAAAA,CAAMC,OAAO,CAACH,KAAAA,CAAAA,EAAQ;YACxB,OAAOA,KAAAA,CAAMI,GAAG,CAACd,YAAAA,CAAAA,CAAce,MAAM,CAAC,CAACC,IAA6BA,CAAAA,KAAMd,SAAAA,CAAAA;AAC5E,QAAA;;AAEA,QAAA,OAAO,EAAE;AACX,IAAA;;IAGA,IAAIQ,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAUR,SAAAA,EAAW;QACzC,OAAO,IAAA;AACT,IAAA;IAEA,IAAIU,KAAAA,CAAMC,OAAO,CAACH,KAAAA,CAAAA,EAAQ;;AAExB,QAAA,OAAOV,YAAAA,CAAaU,KAAK,CAAC,CAAA,CAAE,CAAA,IAAK,IAAA;AACnC,IAAA;AAEA,IAAA,OAAOV,aAAaU,KAAAA,CAAAA,IAAU,IAAA;AAChC;AAEA;;;;AAIC,IACD,MAAMO,uBAAAA,GAAgE,CACpE,EAAEC,GAAG,EAAER,KAAK,EAAEb,SAAS,EAAE,EACzB,EAAEsB,GAAG,EAAE,GAAA;IAEP,IAAItB,SAAAA,EAAWuB,SAAS,UAAA,EAAY;AAClC,QAAA;AACF,IAAA;IAEA,MAAMC,MAAAA,GAAS,SAACxB,CAAkCwB,MAAM;;AAGxD,IAAA,IAAIA,WAAW,aAAA,EAAe;AAC5B,QAAA;AACF,IAAA;;IAGAF,GAAAA,CAAID,GAAAA,EAAKT,iBAAiBZ,SAAAA,EAAoCa,KAAAA,CAAAA,CAAAA;AAChE,CAAA;AAEA;;;;;;AAMC,IACM,MAAMY,oBAAAA,GAAuB,OAClCC,GAAAA,EACAC,IAAAA,GAAAA;AAEA,IAAA,OAAOC,eACLR,uBAAAA,EACA;QACES,MAAAA,EAAQC,MAAAA,CAAOC,QAAQ,CAACL,GAAAA,CAAAA;AACxBK,QAAAA,QAAAA,EAAUD,MAAAA,CAAOC,QAAQ,CAACC,IAAI,CAACF,MAAAA;AACjC,KAAA;AAEAH,IAAAA,IAAAA,CAAAA;AAEJ;;;;"}
@@ -43,9 +43,6 @@ const isCustomFieldAttribute = (attr)=>typeof attr === 'object' && attr !== null
43
43
  * here to avoid a cross-package import from @strapi/content-manager into
44
44
  * @strapi/core (which is not a listed dependency).
45
45
  *
46
- * TODO — custom fields call `strapi.get('custom-fields')` at schema-build
47
- * time; confirm with an integration test that the registry is populated when MCP
48
- * tools are registered (post-bootstrap).
49
46
  */ const attributeToInputSchema = (strapi, attr, visited = new Set())=>{
50
47
  switch(attr.type){
51
48
  case 'string':