@strapi/upload 5.52.3 → 5.54.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 (220) hide show
  1. package/dist/admin/future/components/Drawer.js +6 -3
  2. package/dist/admin/future/components/Drawer.js.map +1 -1
  3. package/dist/admin/future/components/Drawer.mjs +6 -3
  4. package/dist/admin/future/components/Drawer.mjs.map +1 -1
  5. package/dist/admin/future/components/UploadProgressDialog.js +9 -8
  6. package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
  7. package/dist/admin/future/components/UploadProgressDialog.mjs +9 -8
  8. package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
  9. package/dist/admin/future/pages/Assets/AssetsPage.js +16 -4
  10. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  11. package/dist/admin/future/pages/Assets/AssetsPage.mjs +16 -4
  12. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  13. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +5 -0
  14. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -1
  15. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +5 -0
  16. package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
  17. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +19 -4
  18. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  19. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +19 -4
  20. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  21. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +35 -1
  22. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  23. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +35 -1
  24. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  25. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +10 -0
  26. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
  27. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +10 -0
  28. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  29. package/dist/admin/future/pages/Assets/components/AssetsTable.js +9 -0
  30. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
  31. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +10 -1
  32. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
  33. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +132 -88
  34. package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
  35. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +135 -91
  36. package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
  37. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +7 -0
  38. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
  39. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +7 -0
  40. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
  41. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js +4 -1
  42. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js.map +1 -1
  43. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs +4 -1
  44. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs.map +1 -1
  45. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.js +181 -0
  46. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.js.map +1 -0
  47. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.mjs +179 -0
  48. package/dist/admin/future/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -0
  49. package/dist/admin/future/pages/Assets/constants.js +22 -0
  50. package/dist/admin/future/pages/Assets/constants.js.map +1 -1
  51. package/dist/admin/future/pages/Assets/constants.mjs +19 -1
  52. package/dist/admin/future/pages/Assets/constants.mjs.map +1 -1
  53. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +65 -10
  54. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -1
  55. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +66 -11
  56. package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -1
  57. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.js +111 -0
  58. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.js.map +1 -0
  59. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.mjs +109 -0
  60. package/dist/admin/future/pages/Assets/hooks/useListScrollRestoration.mjs.map +1 -0
  61. package/dist/admin/future/services/api.js +17 -0
  62. package/dist/admin/future/services/api.js.map +1 -1
  63. package/dist/admin/future/services/api.mjs +18 -1
  64. package/dist/admin/future/services/api.mjs.map +1 -1
  65. package/dist/admin/future/store/uploadProgress.js +31 -22
  66. package/dist/admin/future/store/uploadProgress.js.map +1 -1
  67. package/dist/admin/future/store/uploadProgress.mjs +31 -22
  68. package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
  69. package/dist/admin/index.js +11 -10
  70. package/dist/admin/index.js.map +1 -1
  71. package/dist/admin/index.mjs +11 -10
  72. package/dist/admin/index.mjs.map +1 -1
  73. package/dist/admin/src/future/components/Drawer.d.ts +10 -0
  74. package/dist/admin/src/future/pages/Assets/components/MainAreaContextMenu.d.ts +28 -0
  75. package/dist/admin/src/future/pages/Assets/constants.d.ts +20 -0
  76. package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +4 -0
  77. package/dist/admin/src/future/pages/Assets/hooks/useListScrollRestoration.d.ts +15 -0
  78. package/dist/admin/src/future/store/uploadProgress.d.ts +14 -20
  79. package/dist/admin/translations/en.json.js +1 -3
  80. package/dist/admin/translations/en.json.js.map +1 -1
  81. package/dist/admin/translations/en.json.mjs +1 -3
  82. package/dist/admin/translations/en.json.mjs.map +1 -1
  83. package/dist/server/bootstrap.js +11 -0
  84. package/dist/server/bootstrap.js.map +1 -1
  85. package/dist/server/bootstrap.mjs +11 -0
  86. package/dist/server/bootstrap.mjs.map +1 -1
  87. package/dist/server/controllers/admin-upload.js +31 -1
  88. package/dist/server/controllers/admin-upload.js.map +1 -1
  89. package/dist/server/controllers/admin-upload.mjs +31 -1
  90. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  91. package/dist/server/controllers/utils/find-entity-and-check-permissions.js +15 -4
  92. package/dist/server/controllers/utils/find-entity-and-check-permissions.js.map +1 -1
  93. package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs +15 -4
  94. package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs.map +1 -1
  95. package/dist/server/controllers/utils/folders.js +1 -1
  96. package/dist/server/controllers/utils/folders.js.map +1 -1
  97. package/dist/server/controllers/utils/folders.mjs +1 -1
  98. package/dist/server/controllers/utils/folders.mjs.map +1 -1
  99. package/dist/server/mcp/ambient-instance.js +46 -0
  100. package/dist/server/mcp/ambient-instance.js.map +1 -0
  101. package/dist/server/mcp/ambient-instance.mjs +43 -0
  102. package/dist/server/mcp/ambient-instance.mjs.map +1 -0
  103. package/dist/server/mcp/handlers/constants.js +60 -0
  104. package/dist/server/mcp/handlers/constants.js.map +1 -0
  105. package/dist/server/mcp/handlers/constants.mjs +45 -0
  106. package/dist/server/mcp/handlers/constants.mjs.map +1 -0
  107. package/dist/server/mcp/handlers/folder-handlers.js +308 -0
  108. package/dist/server/mcp/handlers/folder-handlers.js.map +1 -0
  109. package/dist/server/mcp/handlers/folder-handlers.mjs +303 -0
  110. package/dist/server/mcp/handlers/folder-handlers.mjs.map +1 -0
  111. package/dist/server/mcp/handlers/read-handlers.js +134 -0
  112. package/dist/server/mcp/handlers/read-handlers.js.map +1 -0
  113. package/dist/server/mcp/handlers/read-handlers.mjs +130 -0
  114. package/dist/server/mcp/handlers/read-handlers.mjs.map +1 -0
  115. package/dist/server/mcp/handlers/write-handlers.js +315 -0
  116. package/dist/server/mcp/handlers/write-handlers.js.map +1 -0
  117. package/dist/server/mcp/handlers/write-handlers.mjs +311 -0
  118. package/dist/server/mcp/handlers/write-handlers.mjs.map +1 -0
  119. package/dist/server/mcp/permissions.js +36 -0
  120. package/dist/server/mcp/permissions.js.map +1 -0
  121. package/dist/server/mcp/permissions.mjs +33 -0
  122. package/dist/server/mcp/permissions.mjs.map +1 -0
  123. package/dist/server/mcp/register-upload-mcp-tools.js +235 -0
  124. package/dist/server/mcp/register-upload-mcp-tools.js.map +1 -0
  125. package/dist/server/mcp/register-upload-mcp-tools.mjs +232 -0
  126. package/dist/server/mcp/register-upload-mcp-tools.mjs.map +1 -0
  127. package/dist/server/mcp/sanitizers/sanitize-media.js +97 -0
  128. package/dist/server/mcp/sanitizers/sanitize-media.js.map +1 -0
  129. package/dist/server/mcp/sanitizers/sanitize-media.mjs +93 -0
  130. package/dist/server/mcp/sanitizers/sanitize-media.mjs.map +1 -0
  131. package/dist/server/mcp/schemas/input-schemas.js +206 -0
  132. package/dist/server/mcp/schemas/input-schemas.js.map +1 -0
  133. package/dist/server/mcp/schemas/input-schemas.mjs +190 -0
  134. package/dist/server/mcp/schemas/input-schemas.mjs.map +1 -0
  135. package/dist/server/mcp/schemas/output-schemas.js +158 -0
  136. package/dist/server/mcp/schemas/output-schemas.js.map +1 -0
  137. package/dist/server/mcp/schemas/output-schemas.mjs +142 -0
  138. package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -0
  139. package/dist/server/mcp/utils.js +14 -0
  140. package/dist/server/mcp/utils.js.map +1 -0
  141. package/dist/server/mcp/utils.mjs +12 -0
  142. package/dist/server/mcp/utils.mjs.map +1 -0
  143. package/dist/server/media-library-default-notice.js +42 -0
  144. package/dist/server/media-library-default-notice.js.map +1 -0
  145. package/dist/server/media-library-default-notice.mjs +40 -0
  146. package/dist/server/media-library-default-notice.mjs.map +1 -0
  147. package/dist/server/register.js +5 -0
  148. package/dist/server/register.js.map +1 -1
  149. package/dist/server/register.mjs +5 -0
  150. package/dist/server/register.mjs.map +1 -1
  151. package/dist/server/services/folder.js.map +1 -1
  152. package/dist/server/services/folder.mjs.map +1 -1
  153. package/dist/server/services/upload.js +34 -10
  154. package/dist/server/services/upload.js.map +1 -1
  155. package/dist/server/services/upload.mjs +34 -10
  156. package/dist/server/services/upload.mjs.map +1 -1
  157. package/dist/server/src/bootstrap.d.ts.map +1 -1
  158. package/dist/server/src/controllers/admin-upload.d.ts +1 -0
  159. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  160. package/dist/server/src/controllers/utils/find-entity-and-check-permissions.d.ts +14 -1
  161. package/dist/server/src/controllers/utils/find-entity-and-check-permissions.d.ts.map +1 -1
  162. package/dist/server/src/controllers/utils/folders.d.ts +2 -1
  163. package/dist/server/src/controllers/utils/folders.d.ts.map +1 -1
  164. package/dist/server/src/index.d.ts +10 -2
  165. package/dist/server/src/index.d.ts.map +1 -1
  166. package/dist/server/src/mcp/ambient-instance.d.ts +65 -0
  167. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -0
  168. package/dist/server/src/mcp/handlers/constants.d.ts +48 -0
  169. package/dist/server/src/mcp/handlers/constants.d.ts.map +1 -0
  170. package/dist/server/src/mcp/handlers/folder-handlers.d.ts +49 -0
  171. package/dist/server/src/mcp/handlers/folder-handlers.d.ts.map +1 -0
  172. package/dist/server/src/mcp/handlers/index.d.ts +5 -0
  173. package/dist/server/src/mcp/handlers/index.d.ts.map +1 -0
  174. package/dist/server/src/mcp/handlers/read-handlers.d.ts +35 -0
  175. package/dist/server/src/mcp/handlers/read-handlers.d.ts.map +1 -0
  176. package/dist/server/src/mcp/handlers/write-handlers.d.ts +66 -0
  177. package/dist/server/src/mcp/handlers/write-handlers.d.ts.map +1 -0
  178. package/dist/server/src/mcp/index.d.ts +3 -0
  179. package/dist/server/src/mcp/index.d.ts.map +1 -0
  180. package/dist/server/src/mcp/permissions.d.ts +22 -0
  181. package/dist/server/src/mcp/permissions.d.ts.map +1 -0
  182. package/dist/server/src/mcp/register-upload-mcp-tools.d.ts +29 -0
  183. package/dist/server/src/mcp/register-upload-mcp-tools.d.ts.map +1 -0
  184. package/dist/server/src/mcp/sanitizers/sanitize-media.d.ts +63 -0
  185. package/dist/server/src/mcp/sanitizers/sanitize-media.d.ts.map +1 -0
  186. package/dist/server/src/mcp/schemas/index.d.ts +3 -0
  187. package/dist/server/src/mcp/schemas/index.d.ts.map +1 -0
  188. package/dist/server/src/mcp/schemas/input-schemas.d.ts +148 -0
  189. package/dist/server/src/mcp/schemas/input-schemas.d.ts.map +1 -0
  190. package/dist/server/src/mcp/schemas/output-schemas.d.ts +276 -0
  191. package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -0
  192. package/dist/server/src/mcp/types.d.ts +19 -0
  193. package/dist/server/src/mcp/types.d.ts.map +1 -0
  194. package/dist/server/src/mcp/utils.d.ts +4 -0
  195. package/dist/server/src/mcp/utils.d.ts.map +1 -0
  196. package/dist/server/src/media-library-default-notice.d.ts +19 -0
  197. package/dist/server/src/media-library-default-notice.d.ts.map +1 -0
  198. package/dist/server/src/register.d.ts.map +1 -1
  199. package/dist/server/src/services/folder.d.ts +6 -2
  200. package/dist/server/src/services/folder.d.ts.map +1 -1
  201. package/dist/server/src/services/index.d.ts +10 -2
  202. package/dist/server/src/services/index.d.ts.map +1 -1
  203. package/dist/server/src/services/upload.d.ts +10 -1
  204. package/dist/server/src/services/upload.d.ts.map +1 -1
  205. package/dist/server/src/types.d.ts +2 -2
  206. package/dist/server/src/types.d.ts.map +1 -1
  207. package/dist/server/src/utils/index.d.ts +2 -1
  208. package/dist/server/src/utils/index.d.ts.map +1 -1
  209. package/dist/server/utils/index.js +2 -2
  210. package/dist/server/utils/index.js.map +1 -1
  211. package/dist/server/utils/index.mjs +2 -2
  212. package/dist/server/utils/index.mjs.map +1 -1
  213. package/dist/shared/contracts/files.d.ts +22 -0
  214. package/dist/shared/contracts/files.d.ts.map +1 -1
  215. package/package.json +7 -6
  216. package/dist/admin/future/components/BetaNotice.js +0 -72
  217. package/dist/admin/future/components/BetaNotice.js.map +0 -1
  218. package/dist/admin/future/components/BetaNotice.mjs +0 -70
  219. package/dist/admin/future/components/BetaNotice.mjs.map +0 -1
  220. package/dist/admin/src/future/components/BetaNotice.d.ts +0 -11
@@ -0,0 +1,190 @@
1
+ import { z } from '@strapi/utils';
2
+ import { ALLOWED_SORT_STRINGS } from '../../constants.mjs';
3
+
4
+ /**
5
+ * Media files and folders are NOT documents: they are plain entities keyed by a numeric `id`,
6
+ * so there is no `documentId` and no draft/published pair. Every media identifier in the MCP
7
+ * surface is this numeric id.
8
+ */ const mediaIdSchema = z.number().int().min(1).describe('Numeric media asset id (e.g. 42). Media files are not documents — they have no documentId and no draft/published versions.');
9
+ const folderIdSchema = z.number().int().min(1).describe('Numeric media folder id (e.g. 3). Folders are not documents — they use numeric ids.');
10
+ const pageSchema = z.number().int().min(1).optional().describe('Page number (1-indexed, default: 1).');
11
+ const pageSizeSchema = z.number().int().min(1).max(100).optional().describe('Items per page (default: 25, max: 100).');
12
+ /**
13
+ * Sort is constrained to the same whitelist the Media Library admin uses, so MCP callers
14
+ * cannot sort by private columns such as `folderPath`.
15
+ */ const sortSchema = z.enum(ALLOWED_SORT_STRINGS).optional().describe(`Sort expression. One of: ${ALLOWED_SORT_STRINGS.join(', ')}. Defaults to "createdAt:DESC".`);
16
+ const mediaListAssetsInputSchema = z.object({
17
+ folderId: folderIdSchema.optional().describe('Only return assets directly inside this folder. Omit for every folder; pass null for assets at the media library root.').nullable(),
18
+ mime: z.string().min(1).optional().describe('Filter by mime type prefix or exact value (e.g. "image", "image/png", "application/pdf").'),
19
+ name: z.string().min(1).optional().describe('Case-insensitive substring search on the asset name.'),
20
+ page: pageSchema,
21
+ pageSize: pageSizeSchema,
22
+ sort: sortSchema
23
+ });
24
+ const mediaGetAssetInputSchema = z.object({
25
+ id: mediaIdSchema
26
+ });
27
+ z.object({});
28
+ const FOLDER_INPUT_KEYS = [
29
+ 'folder',
30
+ 'folderId',
31
+ 'folderPath'
32
+ ];
33
+ /**
34
+ * `media_update_asset` input — the only writable asset metadata.
35
+ *
36
+ * `.strict()` turns an out-of-scope field into an error rather than a silent no-op. The custom
37
+ * object error directs folder-shaped inputs to `media_move_assets`; other unknown keys are named by
38
+ * Zod's default error, so the agent can correct the call without a round-trip.
39
+ *
40
+ * The "at least one field" rule is enforced in the handler, not here: a `.refine()` would turn
41
+ * this into a `ZodEffects`, which the MCP tool registry cannot expose as an input schema.
42
+ */ const mediaUpdateAssetInputSchema = z.object({
43
+ id: mediaIdSchema,
44
+ name: z.string().min(1).optional().describe('New asset name as shown in the Media Library. Renames the entry only — the stored file and its URL are unchanged.'),
45
+ alternativeText: z.string().nullable().optional().describe('Alt text used by the frontend for accessibility. Pass null to clear it; the field then reads back as an empty string.'),
46
+ caption: z.string().nullable().optional().describe('Caption shown alongside the asset. Pass null to clear it; the field then reads back as an empty string.')
47
+ }, {
48
+ error (issue) {
49
+ if (issue.code === 'unrecognized_keys' && FOLDER_INPUT_KEYS.some((key)=>issue.keys.includes(key))) {
50
+ return 'Folder changes are not supported by media_update_asset. Use media_move_assets to move an asset between folders.';
51
+ }
52
+ return undefined;
53
+ }
54
+ }).strict();
55
+ /**
56
+ * Folder name, validated to the same rules as the admin folder controller
57
+ * (`controllers/validation/admin/folder.ts`): non-empty, no slashes, no surrounding whitespace.
58
+ *
59
+ * Enforcing the shape here rather than only in the handler means the agent is corrected by the
60
+ * tool schema — before a call is made — instead of by a service-level error afterwards. The
61
+ * uniqueness rule cannot live here: it needs a DB read, so it stays in the handler.
62
+ */ const folderNameSchema = z.string().min(1).regex(/^[^/]+$/, 'Folder name cannot contain slashes.').regex(/^(?! ).+(?<! )$/, 'Folder name cannot start or end with a whitespace.').describe('Folder name as shown in the Media Library. Cannot contain slashes or start/end with a space, and must be unique among its siblings.');
63
+ /**
64
+ * `parent` is nullable-with-meaning: null is the media library root, an id nests the folder.
65
+ * The two are distinct from *omitting* the key, which `media_move_folder` forbids (a move needs a
66
+ * destination) and `media_create_folder` reads as the root.
67
+ */ const parentFolderIdSchema = folderIdSchema.nullable().describe('Numeric id of the containing folder. Pass null for the media library root. Use media_list_folders to discover folder ids.');
68
+ const mediaCreateFolderInputSchema = z.object({
69
+ name: folderNameSchema,
70
+ parent: parentFolderIdSchema.optional().describe('Numeric id of the parent folder. Omit or pass null to create the folder at the media library root.')
71
+ }).strict();
72
+ /**
73
+ * `media_rename_folder` deliberately takes no `parent`: renaming and moving are separate tools, so an
74
+ * agent picks by intent. A `parent` here is a sign the caller wanted `media_move_folder`, and the
75
+ * custom object error says so rather than letting Zod's generic "unrecognized key" stand.
76
+ */ const mediaRenameFolderInputSchema = z.object({
77
+ id: folderIdSchema,
78
+ name: folderNameSchema
79
+ }, {
80
+ error (issue) {
81
+ if (issue.code === 'unrecognized_keys' && issue.keys.includes('parent')) {
82
+ return 'media_rename_folder only changes a folder name. Use media_move_folder to change a folder location.';
83
+ }
84
+ return undefined;
85
+ }
86
+ }).strict();
87
+ /**
88
+ * `media_move_folder` requires `parent` — including an explicit null for the root. Making it required
89
+ * is what keeps a mistyped move from silently becoming a no-op update.
90
+ */ const mediaMoveFolderInputSchema = z.object({
91
+ id: folderIdSchema,
92
+ parent: parentFolderIdSchema
93
+ }, {
94
+ error (issue) {
95
+ if (issue.code === 'unrecognized_keys' && issue.keys.includes('name')) {
96
+ return 'media_move_folder only changes a folder location. Use media_rename_folder to change a folder name.';
97
+ }
98
+ return undefined;
99
+ }
100
+ }).strict();
101
+ /**
102
+ * `media_delete_folder` input.
103
+ *
104
+ * `dryRun` defaults to true: the safe branch is the one an agent gets when it omits the flag, so
105
+ * a destructive cascade is never the path of least resistance (the initiative card's mitigation
106
+ * for irreversible MCP operations). Deleting requires saying `dryRun: false` on purpose.
107
+ *
108
+ * That default lives in the handler (`folder-handlers.ts`, `dryRun = true`), NOT in this schema:
109
+ * `.default(true)` here is deliberately avoided so an omitted flag is a preview no matter how a
110
+ * client serialises the advertised schema. The `.describe()` text below is what tells an agent
111
+ * the default, so the two must be kept in step — do not "fix" this to `.default(true)`.
112
+ */ const mediaDeleteFolderInputSchema = z.object({
113
+ ids: z.array(folderIdSchema).min(1).max(100).describe('Numeric ids of the folders to delete (1-100). FOLDER ids only — asset ids are a separate namespace of integers and are rejected here; use media_delete_assets for assets.'),
114
+ dryRun: z.boolean().optional().describe('When true (the default), nothing is deleted and the tool only reports how many folders and files WOULD be removed. Pass false to actually perform the irreversible deletion.')
115
+ }).strict();
116
+ /**
117
+ * `media_move_assets` input.
118
+ *
119
+ * Bulk by design: an agent reorganising a library moves many assets at once, and one call with a
120
+ * per-id report is cheaper and easier to recover from than N sequential calls. There is no
121
+ * single-asset variant — the array length is the only difference, and a second tool would add a
122
+ * choice without removing a mistake. The admin REST API agrees: `/actions/bulk-move` is the only
123
+ * move route.
124
+ *
125
+ * `folder` is required, including an explicit null for the root, for the same reason `media_move_folder`
126
+ * requires `parent`: a move needs a destination, and an omitted key would silently become a no-op.
127
+ *
128
+ * ASSET ids only, and the schema CANNOT enforce it. Asset ids and folder ids are independently
129
+ * numbered, so the same integer routinely names both; the handler resolves ids in the file table,
130
+ * which means a folder id whose number collides with an asset moves that asset — and reports it
131
+ * as a success. Only an id matching no asset at all is reported as failed.
132
+ *
133
+ * This is an accepted risk, not an oversight: with a bare `ids: number[]` there is no way for the
134
+ * caller to say which namespace it meant, and refusing every colliding id would make those assets
135
+ * permanently unmovable over MCP. The mitigation is the tool description. The durable fix is
136
+ * namespaced handles (`asset:1` / `folder:1`) across the whole media surface, which is a breaking
137
+ * change to the read tools and belongs to its own ticket.
138
+ */ const mediaMoveAssetsInputSchema = z.object({
139
+ ids: z.array(mediaIdSchema).min(1).max(100).describe('Numeric ids of the assets to move (1-100). ASSET ids only, taken from media_list_assets or media_get_asset — never from media_list_folders. Folder ids are numbered separately and the same number often names both an asset and a folder, so a folder id here moves the asset sharing that number; use media_move_folder to move a folder.'),
140
+ folder: folderIdSchema.nullable().describe('Numeric id of the destination folder. Pass null to move the assets to the media library root. Required — including the explicit null — so a move always names a destination. Use media_list_folders to discover folder ids.')
141
+ }, {
142
+ error (issue) {
143
+ if (issue.code === 'unrecognized_keys' && issue.keys.some((key)=>key === 'id' || key === 'fileIds')) {
144
+ return 'media_move_assets moves assets in bulk: pass `ids` as an array of numeric asset ids, even for a single asset.';
145
+ }
146
+ if (issue.code === 'unrecognized_keys' && issue.keys.includes('folderIds')) {
147
+ return 'media_move_assets moves assets only. Use media_move_folder to move a folder.';
148
+ }
149
+ return undefined;
150
+ }
151
+ }).strict();
152
+ /**
153
+ * `media_delete_assets` input.
154
+ *
155
+ * Bulk-only, like `media_move_assets`: the admin REST API has no single-asset delete route either
156
+ * (`/actions/bulk-delete` is the only one), and single-vs-bulk is an array length rather than a
157
+ * distinction an agent can get wrong.
158
+ *
159
+ * `dryRun` defaults to true in the handler, not here — same reasoning as `media_delete_folder`: the
160
+ * safe branch is what an agent gets when it omits the flag, so an irreversible delete is never
161
+ * the path of least resistance. A schema-level `.default(true)` would publish as a JSON Schema
162
+ * default a client could serialise away.
163
+ *
164
+ * ASSET ids only, and the schema CANNOT enforce it. Asset ids and folder ids are independently
165
+ * numbered, so the same integer routinely names both; the handler resolves ids in the file table,
166
+ * which means a folder id whose number collides with an asset deletes that asset. Only an id
167
+ * matching no asset at all is reported as failed.
168
+ *
169
+ * This is an accepted risk, not an oversight: with a bare `ids: number[]` there is no way for the
170
+ * caller to say which namespace it meant, and refusing every colliding id would make those assets
171
+ * permanently undeletable over MCP. The mitigations are the dry run and the tool description. The
172
+ * durable fix is namespaced handles (`asset:1` / `folder:1`) across the whole media surface, which
173
+ * is a breaking change to the read tools and belongs to its own ticket.
174
+ */ const mediaDeleteAssetsInputSchema = z.object({
175
+ ids: z.array(mediaIdSchema).min(1).max(100).describe('Numeric ids of the assets to delete (1-100). ASSET ids only, taken from media_list_assets or media_get_asset — never from media_list_folders. Folder ids are numbered separately and the same number often names both an asset and a folder, so a folder id here deletes the asset sharing that number; use media_delete_folder for folders.'),
176
+ dryRun: z.boolean().optional().describe('When true (the default), NOTHING is deleted and the tool only reports which assets WOULD be permanently removed. Pass false to actually perform the irreversible deletion.')
177
+ }, {
178
+ error (issue) {
179
+ if (issue.code === 'unrecognized_keys' && issue.keys.some((key)=>key === 'id' || key === 'fileIds')) {
180
+ return 'media_delete_assets deletes assets in bulk: pass `ids` as an array of numeric asset ids, even for a single asset.';
181
+ }
182
+ if (issue.code === 'unrecognized_keys' && issue.keys.includes('folderIds')) {
183
+ return 'media_delete_assets deletes assets only. Use media_delete_folder to delete a folder.';
184
+ }
185
+ return undefined;
186
+ }
187
+ }).strict();
188
+
189
+ export { folderIdSchema, folderNameSchema, mediaCreateFolderInputSchema, mediaDeleteAssetsInputSchema, mediaDeleteFolderInputSchema, mediaGetAssetInputSchema, mediaIdSchema, mediaListAssetsInputSchema, mediaMoveAssetsInputSchema, mediaMoveFolderInputSchema, mediaRenameFolderInputSchema, mediaUpdateAssetInputSchema, pageSchema, pageSizeSchema, sortSchema };
190
+ //# sourceMappingURL=input-schemas.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-schemas.mjs","sources":["../../../../server/src/mcp/schemas/input-schemas.ts"],"sourcesContent":["import { z } from '@strapi/utils';\n\nimport { ALLOWED_SORT_STRINGS } from '../../constants';\n\n/**\n * Media files and folders are NOT documents: they are plain entities keyed by a numeric `id`,\n * so there is no `documentId` and no draft/published pair. Every media identifier in the MCP\n * surface is this numeric id.\n */\nexport const mediaIdSchema = z\n .number()\n .int()\n .min(1)\n .describe(\n 'Numeric media asset id (e.g. 42). Media files are not documents — they have no documentId and no draft/published versions.'\n );\n\nexport const folderIdSchema = z\n .number()\n .int()\n .min(1)\n .describe('Numeric media folder id (e.g. 3). Folders are not documents — they use numeric ids.');\n\nexport const pageSchema = z\n .number()\n .int()\n .min(1)\n .optional()\n .describe('Page number (1-indexed, default: 1).');\n\nexport const pageSizeSchema = z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Items per page (default: 25, max: 100).');\n\n/**\n * Sort is constrained to the same whitelist the Media Library admin uses, so MCP callers\n * cannot sort by private columns such as `folderPath`.\n */\nexport const sortSchema = z\n .enum(ALLOWED_SORT_STRINGS as [string, ...string[]])\n .optional()\n .describe(\n `Sort expression. One of: ${ALLOWED_SORT_STRINGS.join(', ')}. Defaults to \"createdAt:DESC\".`\n );\n\nexport const mediaListAssetsInputSchema = z.object({\n folderId: folderIdSchema\n .optional()\n .describe(\n 'Only return assets directly inside this folder. Omit for every folder; pass null for assets at the media library root.'\n )\n .nullable(),\n mime: z\n .string()\n .min(1)\n .optional()\n .describe(\n 'Filter by mime type prefix or exact value (e.g. \"image\", \"image/png\", \"application/pdf\").'\n ),\n name: z\n .string()\n .min(1)\n .optional()\n .describe('Case-insensitive substring search on the asset name.'),\n page: pageSchema,\n pageSize: pageSizeSchema,\n sort: sortSchema,\n});\n\nexport const mediaGetAssetInputSchema = z.object({\n id: mediaIdSchema,\n});\n\nexport const mediaListFoldersInputSchema = z.object({});\n\nconst FOLDER_INPUT_KEYS = ['folder', 'folderId', 'folderPath'] as const;\n\n/**\n * `media_update_asset` input — the only writable asset metadata.\n *\n * `.strict()` turns an out-of-scope field into an error rather than a silent no-op. The custom\n * object error directs folder-shaped inputs to `media_move_assets`; other unknown keys are named by\n * Zod's default error, so the agent can correct the call without a round-trip.\n *\n * The \"at least one field\" rule is enforced in the handler, not here: a `.refine()` would turn\n * this into a `ZodEffects`, which the MCP tool registry cannot expose as an input schema.\n */\nexport const mediaUpdateAssetInputSchema = z\n .object(\n {\n id: mediaIdSchema,\n name: z\n .string()\n .min(1)\n .optional()\n .describe(\n 'New asset name as shown in the Media Library. Renames the entry only — the stored file and its URL are unchanged.'\n ),\n alternativeText: z\n .string()\n .nullable()\n .optional()\n .describe(\n 'Alt text used by the frontend for accessibility. Pass null to clear it; the field then reads back as an empty string.'\n ),\n caption: z\n .string()\n .nullable()\n .optional()\n .describe(\n 'Caption shown alongside the asset. Pass null to clear it; the field then reads back as an empty string.'\n ),\n },\n {\n error(issue) {\n if (\n issue.code === 'unrecognized_keys' &&\n FOLDER_INPUT_KEYS.some((key) => issue.keys.includes(key))\n ) {\n return 'Folder changes are not supported by media_update_asset. Use media_move_assets to move an asset between folders.';\n }\n\n return undefined;\n },\n }\n )\n .strict();\n\n/**\n * Folder name, validated to the same rules as the admin folder controller\n * (`controllers/validation/admin/folder.ts`): non-empty, no slashes, no surrounding whitespace.\n *\n * Enforcing the shape here rather than only in the handler means the agent is corrected by the\n * tool schema — before a call is made — instead of by a service-level error afterwards. The\n * uniqueness rule cannot live here: it needs a DB read, so it stays in the handler.\n */\nexport const folderNameSchema = z\n .string()\n .min(1)\n .regex(/^[^/]+$/, 'Folder name cannot contain slashes.')\n .regex(/^(?! ).+(?<! )$/, 'Folder name cannot start or end with a whitespace.')\n .describe(\n 'Folder name as shown in the Media Library. Cannot contain slashes or start/end with a space, and must be unique among its siblings.'\n );\n\n/**\n * `parent` is nullable-with-meaning: null is the media library root, an id nests the folder.\n * The two are distinct from *omitting* the key, which `media_move_folder` forbids (a move needs a\n * destination) and `media_create_folder` reads as the root.\n */\nconst parentFolderIdSchema = folderIdSchema\n .nullable()\n .describe(\n 'Numeric id of the containing folder. Pass null for the media library root. Use media_list_folders to discover folder ids.'\n );\n\nexport const mediaCreateFolderInputSchema = z\n .object({\n name: folderNameSchema,\n parent: parentFolderIdSchema\n .optional()\n .describe(\n 'Numeric id of the parent folder. Omit or pass null to create the folder at the media library root.'\n ),\n })\n .strict();\n\n/**\n * `media_rename_folder` deliberately takes no `parent`: renaming and moving are separate tools, so an\n * agent picks by intent. A `parent` here is a sign the caller wanted `media_move_folder`, and the\n * custom object error says so rather than letting Zod's generic \"unrecognized key\" stand.\n */\nexport const mediaRenameFolderInputSchema = z\n .object(\n {\n id: folderIdSchema,\n name: folderNameSchema,\n },\n {\n error(issue) {\n if (issue.code === 'unrecognized_keys' && issue.keys.includes('parent')) {\n return 'media_rename_folder only changes a folder name. Use media_move_folder to change a folder location.';\n }\n\n return undefined;\n },\n }\n )\n .strict();\n\n/**\n * `media_move_folder` requires `parent` — including an explicit null for the root. Making it required\n * is what keeps a mistyped move from silently becoming a no-op update.\n */\nexport const mediaMoveFolderInputSchema = z\n .object(\n {\n id: folderIdSchema,\n parent: parentFolderIdSchema,\n },\n {\n error(issue) {\n if (issue.code === 'unrecognized_keys' && issue.keys.includes('name')) {\n return 'media_move_folder only changes a folder location. Use media_rename_folder to change a folder name.';\n }\n\n return undefined;\n },\n }\n )\n .strict();\n\n/**\n * `media_delete_folder` input.\n *\n * `dryRun` defaults to true: the safe branch is the one an agent gets when it omits the flag, so\n * a destructive cascade is never the path of least resistance (the initiative card's mitigation\n * for irreversible MCP operations). Deleting requires saying `dryRun: false` on purpose.\n *\n * That default lives in the handler (`folder-handlers.ts`, `dryRun = true`), NOT in this schema:\n * `.default(true)` here is deliberately avoided so an omitted flag is a preview no matter how a\n * client serialises the advertised schema. The `.describe()` text below is what tells an agent\n * the default, so the two must be kept in step — do not \"fix\" this to `.default(true)`.\n */\nexport const mediaDeleteFolderInputSchema = z\n .object({\n ids: z\n .array(folderIdSchema)\n .min(1)\n .max(100)\n .describe(\n 'Numeric ids of the folders to delete (1-100). FOLDER ids only — asset ids are a separate namespace of integers and are rejected here; use media_delete_assets for assets.'\n ),\n dryRun: z\n .boolean()\n .optional()\n .describe(\n 'When true (the default), nothing is deleted and the tool only reports how many folders and files WOULD be removed. Pass false to actually perform the irreversible deletion.'\n ),\n })\n .strict();\n\n/**\n * `media_move_assets` input.\n *\n * Bulk by design: an agent reorganising a library moves many assets at once, and one call with a\n * per-id report is cheaper and easier to recover from than N sequential calls. There is no\n * single-asset variant — the array length is the only difference, and a second tool would add a\n * choice without removing a mistake. The admin REST API agrees: `/actions/bulk-move` is the only\n * move route.\n *\n * `folder` is required, including an explicit null for the root, for the same reason `media_move_folder`\n * requires `parent`: a move needs a destination, and an omitted key would silently become a no-op.\n *\n * ASSET ids only, and the schema CANNOT enforce it. Asset ids and folder ids are independently\n * numbered, so the same integer routinely names both; the handler resolves ids in the file table,\n * which means a folder id whose number collides with an asset moves that asset — and reports it\n * as a success. Only an id matching no asset at all is reported as failed.\n *\n * This is an accepted risk, not an oversight: with a bare `ids: number[]` there is no way for the\n * caller to say which namespace it meant, and refusing every colliding id would make those assets\n * permanently unmovable over MCP. The mitigation is the tool description. The durable fix is\n * namespaced handles (`asset:1` / `folder:1`) across the whole media surface, which is a breaking\n * change to the read tools and belongs to its own ticket.\n */\nexport const mediaMoveAssetsInputSchema = z\n .object(\n {\n ids: z\n .array(mediaIdSchema)\n .min(1)\n .max(100)\n .describe(\n 'Numeric ids of the assets to move (1-100). ASSET ids only, taken from media_list_assets or media_get_asset — never from media_list_folders. Folder ids are numbered separately and the same number often names both an asset and a folder, so a folder id here moves the asset sharing that number; use media_move_folder to move a folder.'\n ),\n folder: folderIdSchema\n .nullable()\n .describe(\n 'Numeric id of the destination folder. Pass null to move the assets to the media library root. Required — including the explicit null — so a move always names a destination. Use media_list_folders to discover folder ids.'\n ),\n },\n {\n error(issue) {\n if (\n issue.code === 'unrecognized_keys' &&\n issue.keys.some((key) => key === 'id' || key === 'fileIds')\n ) {\n return 'media_move_assets moves assets in bulk: pass `ids` as an array of numeric asset ids, even for a single asset.';\n }\n\n if (issue.code === 'unrecognized_keys' && issue.keys.includes('folderIds')) {\n return 'media_move_assets moves assets only. Use media_move_folder to move a folder.';\n }\n\n return undefined;\n },\n }\n )\n .strict();\n\n/**\n * `media_delete_assets` input.\n *\n * Bulk-only, like `media_move_assets`: the admin REST API has no single-asset delete route either\n * (`/actions/bulk-delete` is the only one), and single-vs-bulk is an array length rather than a\n * distinction an agent can get wrong.\n *\n * `dryRun` defaults to true in the handler, not here — same reasoning as `media_delete_folder`: the\n * safe branch is what an agent gets when it omits the flag, so an irreversible delete is never\n * the path of least resistance. A schema-level `.default(true)` would publish as a JSON Schema\n * default a client could serialise away.\n *\n * ASSET ids only, and the schema CANNOT enforce it. Asset ids and folder ids are independently\n * numbered, so the same integer routinely names both; the handler resolves ids in the file table,\n * which means a folder id whose number collides with an asset deletes that asset. Only an id\n * matching no asset at all is reported as failed.\n *\n * This is an accepted risk, not an oversight: with a bare `ids: number[]` there is no way for the\n * caller to say which namespace it meant, and refusing every colliding id would make those assets\n * permanently undeletable over MCP. The mitigations are the dry run and the tool description. The\n * durable fix is namespaced handles (`asset:1` / `folder:1`) across the whole media surface, which\n * is a breaking change to the read tools and belongs to its own ticket.\n */\nexport const mediaDeleteAssetsInputSchema = z\n .object(\n {\n ids: z\n .array(mediaIdSchema)\n .min(1)\n .max(100)\n .describe(\n 'Numeric ids of the assets to delete (1-100). ASSET ids only, taken from media_list_assets or media_get_asset — never from media_list_folders. Folder ids are numbered separately and the same number often names both an asset and a folder, so a folder id here deletes the asset sharing that number; use media_delete_folder for folders.'\n ),\n dryRun: z\n .boolean()\n .optional()\n .describe(\n 'When true (the default), NOTHING is deleted and the tool only reports which assets WOULD be permanently removed. Pass false to actually perform the irreversible deletion.'\n ),\n },\n {\n error(issue) {\n if (\n issue.code === 'unrecognized_keys' &&\n issue.keys.some((key) => key === 'id' || key === 'fileIds')\n ) {\n return 'media_delete_assets deletes assets in bulk: pass `ids` as an array of numeric asset ids, even for a single asset.';\n }\n\n if (issue.code === 'unrecognized_keys' && issue.keys.includes('folderIds')) {\n return 'media_delete_assets deletes assets only. Use media_delete_folder to delete a folder.';\n }\n\n return undefined;\n },\n }\n )\n .strict();\n"],"names":["mediaIdSchema","z","number","int","min","describe","folderIdSchema","pageSchema","optional","pageSizeSchema","max","sortSchema","enum","ALLOWED_SORT_STRINGS","join","mediaListAssetsInputSchema","object","folderId","nullable","mime","string","name","page","pageSize","sort","mediaGetAssetInputSchema","id","FOLDER_INPUT_KEYS","mediaUpdateAssetInputSchema","alternativeText","caption","error","issue","code","some","key","keys","includes","undefined","strict","folderNameSchema","regex","parentFolderIdSchema","mediaCreateFolderInputSchema","parent","mediaRenameFolderInputSchema","mediaMoveFolderInputSchema","mediaDeleteFolderInputSchema","ids","array","dryRun","boolean","mediaMoveAssetsInputSchema","folder","mediaDeleteAssetsInputSchema"],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ 'use strict';
2
+
3
+ var utils = require('@strapi/utils');
4
+
5
+ /**
6
+ * The exhaustive set of asset fields the MCP surface may expose — an allowlist, for the reasons
7
+ * in `sanitizeMediaAsset`. A field added to the file content-type stays invisible to MCP until
8
+ * it is added both here and there.
9
+ */ const mediaAssetOutputSchema = utils.z.object({
10
+ id: utils.z.number().describe('Numeric asset id — the canonical identifier for this asset.'),
11
+ name: utils.z.string(),
12
+ alternativeText: utils.z.string().nullable().optional(),
13
+ caption: utils.z.string().nullable().optional(),
14
+ url: utils.z.string().describe('Public (or signed, for private providers) URL of the asset.'),
15
+ mime: utils.z.string().describe('Mime type, e.g. "image/png".'),
16
+ size: utils.z.number().describe('File size in kilobytes, as stored by Strapi.'),
17
+ width: utils.z.number().nullable().optional().describe('Pixel width, images only.'),
18
+ height: utils.z.number().nullable().optional().describe('Pixel height, images only.'),
19
+ ext: utils.z.string().nullable().optional().describe('File extension including the dot, e.g. ".png".'),
20
+ folder: utils.z.object({
21
+ id: utils.z.number(),
22
+ name: utils.z.string()
23
+ }).nullable().optional().describe('Containing folder, or null when the asset sits at the media library root.'),
24
+ createdAt: utils.z.string().nullable().optional(),
25
+ updatedAt: utils.z.string().nullable().optional()
26
+ });
27
+ const mediaGetAssetOutputSchema = utils.z.object({
28
+ data: mediaAssetOutputSchema.nullable()
29
+ });
30
+ const mediaListAssetsOutputSchema = utils.z.object({
31
+ results: utils.z.array(mediaAssetOutputSchema),
32
+ pagination: utils.z.object({
33
+ page: utils.z.number(),
34
+ pageSize: utils.z.number(),
35
+ pageCount: utils.z.number(),
36
+ total: utils.z.number()
37
+ })
38
+ });
39
+ const mediaFolderNodeSchema = utils.z.lazy(()=>utils.z.object({
40
+ id: utils.z.number(),
41
+ name: utils.z.string(),
42
+ children: utils.z.array(mediaFolderNodeSchema)
43
+ }));
44
+ const mediaListFoldersOutputSchema = utils.z.object({
45
+ data: utils.z.array(mediaFolderNodeSchema).describe('Nested folder structure, roots first.')
46
+ });
47
+ /**
48
+ * `media_update_asset` output — the updated asset in the same shape the read tools return,
49
+ * so an agent can confirm the write without a follow-up `media_get_asset` call.
50
+ */ const mediaUpdateAssetOutputSchema = utils.z.object({
51
+ data: mediaAssetOutputSchema
52
+ });
53
+ /**
54
+ * A folder as returned by the write tools.
55
+ *
56
+ * Like the asset schema this is an ALLOWLIST: `path` and `pathId` are internal materialized-path
57
+ * bookkeeping and stay invisible to MCP clients, matching what `media_list_folders` already exposes.
58
+ */ const mediaFolderOutputSchema = utils.z.object({
59
+ id: utils.z.number().describe('Numeric folder id — the canonical identifier for this folder.'),
60
+ name: utils.z.string(),
61
+ parent: utils.z.object({
62
+ id: utils.z.number(),
63
+ name: utils.z.string().optional()
64
+ }).nullable().optional().describe('Containing folder, or null when the folder sits at the media library root. Absent when this response did not load the relation — absent means unknown, not root.'),
65
+ createdAt: utils.z.string().nullable().optional(),
66
+ updatedAt: utils.z.string().nullable().optional()
67
+ });
68
+ const mediaCreateFolderOutputSchema = utils.z.object({
69
+ data: mediaFolderOutputSchema
70
+ });
71
+ const mediaRenameFolderOutputSchema = utils.z.object({
72
+ data: mediaFolderOutputSchema
73
+ });
74
+ const mediaMoveFolderOutputSchema = utils.z.object({
75
+ data: mediaFolderOutputSchema
76
+ });
77
+ /**
78
+ * `media_delete_folder` output — the same shape for both branches, so an agent reads one contract.
79
+ *
80
+ * `dryRun` echoes which branch ran: on true the counts are what *would* be removed and nothing
81
+ * was touched; on false they are what actually was. Echoing it back means the agent can tell a
82
+ * preview from a completed deletion without tracking what it sent.
83
+ *
84
+ * There is no "skipped ids" field: an id that does not resolve to a folder rejects the whole
85
+ * call, so every id in the request is accounted for by `folders` on any successful response.
86
+ */ const mediaDeleteFolderOutputSchema = utils.z.object({
87
+ dryRun: utils.z.boolean().describe('True when this was a preview and NOTHING was deleted. False when the deletion was performed.'),
88
+ folders: utils.z.array(mediaFolderOutputSchema).describe('The folders matched by the given ids (the roots of the cascade).'),
89
+ totalFolderNumber: utils.z.number().describe('Total folders affected, including the matched folders themselves and every descendant.'),
90
+ totalFileNumber: utils.z.number().describe('Total files affected, across the whole cascade.')
91
+ });
92
+ /**
93
+ * `media_move_assets` output — a per-id report rather than a single verdict.
94
+ *
95
+ * A bad id among good ones does not roll back the valid moves (see the handler), so the response
96
+ * has to say which ids moved and which did not: an agent that only learned "the call failed"
97
+ * would either retry moves that already happened or abandon ones that did. `moved` and `failed`
98
+ * together account for every id in the request, on every successful response — including one
99
+ * where `moved` is empty because no id resolved.
100
+ *
101
+ * `moved` carries the full asset in the same shape the read tools return, so the new folder can
102
+ * be confirmed without a follow-up `media_get_asset`.
103
+ */ const mediaMoveAssetsFailureSchema = utils.z.object({
104
+ id: utils.z.number().describe('The requested asset id that was not moved.'),
105
+ reason: utils.z.string().describe('Why this id was not moved — a missing asset, or one this token may not edit.')
106
+ });
107
+ const mediaMoveAssetsOutputSchema = utils.z.object({
108
+ destinationFolder: utils.z.object({
109
+ id: utils.z.number(),
110
+ name: utils.z.string().optional()
111
+ }).nullable().describe('The destination folder, or null when the assets were moved to the media library root.'),
112
+ moved: utils.z.array(mediaAssetOutputSchema).describe('The assets that were moved, in their new location.'),
113
+ failed: utils.z.array(mediaMoveAssetsFailureSchema).describe('The ids that were not moved, each with a reason. The moves reported in `moved` still happened — retry only these.')
114
+ });
115
+ /**
116
+ * `media_delete_assets` output — one contract for both branches, with a per-id account of every
117
+ * requested id.
118
+ *
119
+ * `dryRun` echoes which branch ran: on true `deleted` is what *would* be removed and nothing was
120
+ * touched; on false it is what actually was. Echoing it back means an agent can tell a preview
121
+ * from a completed deletion without tracking what it sent — the difference matters more here
122
+ * than anywhere else in this surface, because one branch is irreversible.
123
+ *
124
+ * `deleted` carries the full asset rather than a bare id, so the agent can report what it
125
+ * destroyed after the row is gone and no read can recover it. On a dry run it is the same shape,
126
+ * which is exactly what makes the preview a confirmation an agent can act on.
127
+ *
128
+ * Unlike `media_delete_folder`, an unresolvable id does NOT reject the call: deletions are performed
129
+ * per asset and reported per id, so a bad id among good ones neither rolls back the valid
130
+ * deletions nor stops them from happening. `deleted` and `failed` together account for every id
131
+ * in the request, on every successful response.
132
+ */ const mediaDeleteAssetsFailureSchema = utils.z.object({
133
+ id: utils.z.number().describe('The requested asset id that was not deleted.'),
134
+ reason: utils.z.string().describe('Why this id was not deleted — a missing asset (possibly a folder id), or one this token may not delete.')
135
+ });
136
+ const mediaDeleteAssetsOutputSchema = utils.z.object({
137
+ dryRun: utils.z.boolean().describe('True when this was a preview and NOTHING was deleted. False when the deletion was performed and is irreversible.'),
138
+ deleted: utils.z.array(mediaAssetOutputSchema).describe('On a dry run, the assets that WOULD be permanently deleted. On a real run, the assets that were deleted — they no longer exist and cannot be read back.'),
139
+ failed: utils.z.array(mediaDeleteAssetsFailureSchema).describe('The ids that were not deleted, each with a reason. On a real run the deletions reported in `deleted` still happened — retry only these.'),
140
+ totalFileNumber: utils.z.number().describe('How many assets are in `deleted` — the count that WOULD be removed on a dry run, or that was removed on a real one.')
141
+ });
142
+
143
+ exports.mediaAssetOutputSchema = mediaAssetOutputSchema;
144
+ exports.mediaCreateFolderOutputSchema = mediaCreateFolderOutputSchema;
145
+ exports.mediaDeleteAssetsFailureSchema = mediaDeleteAssetsFailureSchema;
146
+ exports.mediaDeleteAssetsOutputSchema = mediaDeleteAssetsOutputSchema;
147
+ exports.mediaDeleteFolderOutputSchema = mediaDeleteFolderOutputSchema;
148
+ exports.mediaFolderNodeSchema = mediaFolderNodeSchema;
149
+ exports.mediaFolderOutputSchema = mediaFolderOutputSchema;
150
+ exports.mediaGetAssetOutputSchema = mediaGetAssetOutputSchema;
151
+ exports.mediaListAssetsOutputSchema = mediaListAssetsOutputSchema;
152
+ exports.mediaListFoldersOutputSchema = mediaListFoldersOutputSchema;
153
+ exports.mediaMoveAssetsFailureSchema = mediaMoveAssetsFailureSchema;
154
+ exports.mediaMoveAssetsOutputSchema = mediaMoveAssetsOutputSchema;
155
+ exports.mediaMoveFolderOutputSchema = mediaMoveFolderOutputSchema;
156
+ exports.mediaRenameFolderOutputSchema = mediaRenameFolderOutputSchema;
157
+ exports.mediaUpdateAssetOutputSchema = mediaUpdateAssetOutputSchema;
158
+ //# sourceMappingURL=output-schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-schemas.js","sources":["../../../../server/src/mcp/schemas/output-schemas.ts"],"sourcesContent":["import { z } from '@strapi/utils';\n\n/**\n * The exhaustive set of asset fields the MCP surface may expose — an allowlist, for the reasons\n * in `sanitizeMediaAsset`. A field added to the file content-type stays invisible to MCP until\n * it is added both here and there.\n */\nexport const mediaAssetOutputSchema = z.object({\n id: z.number().describe('Numeric asset id — the canonical identifier for this asset.'),\n name: z.string(),\n alternativeText: z.string().nullable().optional(),\n caption: z.string().nullable().optional(),\n url: z.string().describe('Public (or signed, for private providers) URL of the asset.'),\n mime: z.string().describe('Mime type, e.g. \"image/png\".'),\n size: z.number().describe('File size in kilobytes, as stored by Strapi.'),\n width: z.number().nullable().optional().describe('Pixel width, images only.'),\n height: z.number().nullable().optional().describe('Pixel height, images only.'),\n ext: z.string().nullable().optional().describe('File extension including the dot, e.g. \".png\".'),\n folder: z\n .object({\n id: z.number(),\n name: z.string(),\n })\n .nullable()\n .optional()\n .describe('Containing folder, or null when the asset sits at the media library root.'),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n});\n\nexport const mediaGetAssetOutputSchema = z.object({\n data: mediaAssetOutputSchema.nullable(),\n});\n\nexport const mediaListAssetsOutputSchema = z.object({\n results: z.array(mediaAssetOutputSchema),\n pagination: z.object({\n page: z.number(),\n pageSize: z.number(),\n pageCount: z.number(),\n total: z.number(),\n }),\n});\n\n/**\n * Folder tree node. `children` is recursive and unbounded in depth, so it is typed lazily.\n */\nexport type MediaFolderNode = {\n id: number;\n name: string;\n children: MediaFolderNode[];\n};\n\nexport const mediaFolderNodeSchema: z.ZodType<MediaFolderNode> = z.lazy(() =>\n z.object({\n id: z.number(),\n name: z.string(),\n children: z.array(mediaFolderNodeSchema),\n })\n);\n\nexport const mediaListFoldersOutputSchema = z.object({\n data: z.array(mediaFolderNodeSchema).describe('Nested folder structure, roots first.'),\n});\n\n/**\n * `media_update_asset` output — the updated asset in the same shape the read tools return,\n * so an agent can confirm the write without a follow-up `media_get_asset` call.\n */\nexport const mediaUpdateAssetOutputSchema = z.object({\n data: mediaAssetOutputSchema,\n});\n\n/**\n * A folder as returned by the write tools.\n *\n * Like the asset schema this is an ALLOWLIST: `path` and `pathId` are internal materialized-path\n * bookkeeping and stay invisible to MCP clients, matching what `media_list_folders` already exposes.\n */\nexport const mediaFolderOutputSchema = z.object({\n id: z.number().describe('Numeric folder id — the canonical identifier for this folder.'),\n name: z.string(),\n parent: z\n .object({\n id: z.number(),\n name: z.string().optional(),\n })\n .nullable()\n .optional()\n .describe(\n 'Containing folder, or null when the folder sits at the media library root. Absent when this response did not load the relation — absent means unknown, not root.'\n ),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n});\n\nexport const mediaCreateFolderOutputSchema = z.object({\n data: mediaFolderOutputSchema,\n});\n\nexport const mediaRenameFolderOutputSchema = z.object({\n data: mediaFolderOutputSchema,\n});\n\nexport const mediaMoveFolderOutputSchema = z.object({\n data: mediaFolderOutputSchema,\n});\n\n/**\n * `media_delete_folder` output — the same shape for both branches, so an agent reads one contract.\n *\n * `dryRun` echoes which branch ran: on true the counts are what *would* be removed and nothing\n * was touched; on false they are what actually was. Echoing it back means the agent can tell a\n * preview from a completed deletion without tracking what it sent.\n *\n * There is no \"skipped ids\" field: an id that does not resolve to a folder rejects the whole\n * call, so every id in the request is accounted for by `folders` on any successful response.\n */\nexport const mediaDeleteFolderOutputSchema = z.object({\n dryRun: z\n .boolean()\n .describe(\n 'True when this was a preview and NOTHING was deleted. False when the deletion was performed.'\n ),\n folders: z\n .array(mediaFolderOutputSchema)\n .describe('The folders matched by the given ids (the roots of the cascade).'),\n totalFolderNumber: z\n .number()\n .describe(\n 'Total folders affected, including the matched folders themselves and every descendant.'\n ),\n totalFileNumber: z.number().describe('Total files affected, across the whole cascade.'),\n});\n\n/**\n * `media_move_assets` output — a per-id report rather than a single verdict.\n *\n * A bad id among good ones does not roll back the valid moves (see the handler), so the response\n * has to say which ids moved and which did not: an agent that only learned \"the call failed\"\n * would either retry moves that already happened or abandon ones that did. `moved` and `failed`\n * together account for every id in the request, on every successful response — including one\n * where `moved` is empty because no id resolved.\n *\n * `moved` carries the full asset in the same shape the read tools return, so the new folder can\n * be confirmed without a follow-up `media_get_asset`.\n */\nexport const mediaMoveAssetsFailureSchema = z.object({\n id: z.number().describe('The requested asset id that was not moved.'),\n reason: z\n .string()\n .describe('Why this id was not moved — a missing asset, or one this token may not edit.'),\n});\n\nexport const mediaMoveAssetsOutputSchema = z.object({\n destinationFolder: z\n .object({\n id: z.number(),\n name: z.string().optional(),\n })\n .nullable()\n .describe(\n 'The destination folder, or null when the assets were moved to the media library root.'\n ),\n moved: z\n .array(mediaAssetOutputSchema)\n .describe('The assets that were moved, in their new location.'),\n failed: z\n .array(mediaMoveAssetsFailureSchema)\n .describe(\n 'The ids that were not moved, each with a reason. The moves reported in `moved` still happened — retry only these.'\n ),\n});\n\n/**\n * `media_delete_assets` output — one contract for both branches, with a per-id account of every\n * requested id.\n *\n * `dryRun` echoes which branch ran: on true `deleted` is what *would* be removed and nothing was\n * touched; on false it is what actually was. Echoing it back means an agent can tell a preview\n * from a completed deletion without tracking what it sent — the difference matters more here\n * than anywhere else in this surface, because one branch is irreversible.\n *\n * `deleted` carries the full asset rather than a bare id, so the agent can report what it\n * destroyed after the row is gone and no read can recover it. On a dry run it is the same shape,\n * which is exactly what makes the preview a confirmation an agent can act on.\n *\n * Unlike `media_delete_folder`, an unresolvable id does NOT reject the call: deletions are performed\n * per asset and reported per id, so a bad id among good ones neither rolls back the valid\n * deletions nor stops them from happening. `deleted` and `failed` together account for every id\n * in the request, on every successful response.\n */\nexport const mediaDeleteAssetsFailureSchema = z.object({\n id: z.number().describe('The requested asset id that was not deleted.'),\n reason: z\n .string()\n .describe(\n 'Why this id was not deleted — a missing asset (possibly a folder id), or one this token may not delete.'\n ),\n});\n\nexport const mediaDeleteAssetsOutputSchema = z.object({\n dryRun: z\n .boolean()\n .describe(\n 'True when this was a preview and NOTHING was deleted. False when the deletion was performed and is irreversible.'\n ),\n deleted: z\n .array(mediaAssetOutputSchema)\n .describe(\n 'On a dry run, the assets that WOULD be permanently deleted. On a real run, the assets that were deleted — they no longer exist and cannot be read back.'\n ),\n failed: z\n .array(mediaDeleteAssetsFailureSchema)\n .describe(\n 'The ids that were not deleted, each with a reason. On a real run the deletions reported in `deleted` still happened — retry only these.'\n ),\n totalFileNumber: z\n .number()\n .describe(\n 'How many assets are in `deleted` — the count that WOULD be removed on a dry run, or that was removed on a real one.'\n ),\n});\n"],"names":["mediaAssetOutputSchema","z","object","id","number","describe","name","string","alternativeText","nullable","optional","caption","url","mime","size","width","height","ext","folder","createdAt","updatedAt","mediaGetAssetOutputSchema","data","mediaListAssetsOutputSchema","results","array","pagination","page","pageSize","pageCount","total","mediaFolderNodeSchema","lazy","children","mediaListFoldersOutputSchema","mediaUpdateAssetOutputSchema","mediaFolderOutputSchema","parent","mediaCreateFolderOutputSchema","mediaRenameFolderOutputSchema","mediaMoveFolderOutputSchema","mediaDeleteFolderOutputSchema","dryRun","boolean","folders","totalFolderNumber","totalFileNumber","mediaMoveAssetsFailureSchema","reason","mediaMoveAssetsOutputSchema","destinationFolder","moved","failed","mediaDeleteAssetsFailureSchema","mediaDeleteAssetsOutputSchema","deleted"],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import { z } from '@strapi/utils';
2
+
3
+ /**
4
+ * The exhaustive set of asset fields the MCP surface may expose — an allowlist, for the reasons
5
+ * in `sanitizeMediaAsset`. A field added to the file content-type stays invisible to MCP until
6
+ * it is added both here and there.
7
+ */ const mediaAssetOutputSchema = z.object({
8
+ id: z.number().describe('Numeric asset id — the canonical identifier for this asset.'),
9
+ name: z.string(),
10
+ alternativeText: z.string().nullable().optional(),
11
+ caption: z.string().nullable().optional(),
12
+ url: z.string().describe('Public (or signed, for private providers) URL of the asset.'),
13
+ mime: z.string().describe('Mime type, e.g. "image/png".'),
14
+ size: z.number().describe('File size in kilobytes, as stored by Strapi.'),
15
+ width: z.number().nullable().optional().describe('Pixel width, images only.'),
16
+ height: z.number().nullable().optional().describe('Pixel height, images only.'),
17
+ ext: z.string().nullable().optional().describe('File extension including the dot, e.g. ".png".'),
18
+ folder: z.object({
19
+ id: z.number(),
20
+ name: z.string()
21
+ }).nullable().optional().describe('Containing folder, or null when the asset sits at the media library root.'),
22
+ createdAt: z.string().nullable().optional(),
23
+ updatedAt: z.string().nullable().optional()
24
+ });
25
+ const mediaGetAssetOutputSchema = z.object({
26
+ data: mediaAssetOutputSchema.nullable()
27
+ });
28
+ const mediaListAssetsOutputSchema = z.object({
29
+ results: z.array(mediaAssetOutputSchema),
30
+ pagination: z.object({
31
+ page: z.number(),
32
+ pageSize: z.number(),
33
+ pageCount: z.number(),
34
+ total: z.number()
35
+ })
36
+ });
37
+ const mediaFolderNodeSchema = z.lazy(()=>z.object({
38
+ id: z.number(),
39
+ name: z.string(),
40
+ children: z.array(mediaFolderNodeSchema)
41
+ }));
42
+ const mediaListFoldersOutputSchema = z.object({
43
+ data: z.array(mediaFolderNodeSchema).describe('Nested folder structure, roots first.')
44
+ });
45
+ /**
46
+ * `media_update_asset` output — the updated asset in the same shape the read tools return,
47
+ * so an agent can confirm the write without a follow-up `media_get_asset` call.
48
+ */ const mediaUpdateAssetOutputSchema = z.object({
49
+ data: mediaAssetOutputSchema
50
+ });
51
+ /**
52
+ * A folder as returned by the write tools.
53
+ *
54
+ * Like the asset schema this is an ALLOWLIST: `path` and `pathId` are internal materialized-path
55
+ * bookkeeping and stay invisible to MCP clients, matching what `media_list_folders` already exposes.
56
+ */ const mediaFolderOutputSchema = z.object({
57
+ id: z.number().describe('Numeric folder id — the canonical identifier for this folder.'),
58
+ name: z.string(),
59
+ parent: z.object({
60
+ id: z.number(),
61
+ name: z.string().optional()
62
+ }).nullable().optional().describe('Containing folder, or null when the folder sits at the media library root. Absent when this response did not load the relation — absent means unknown, not root.'),
63
+ createdAt: z.string().nullable().optional(),
64
+ updatedAt: z.string().nullable().optional()
65
+ });
66
+ const mediaCreateFolderOutputSchema = z.object({
67
+ data: mediaFolderOutputSchema
68
+ });
69
+ const mediaRenameFolderOutputSchema = z.object({
70
+ data: mediaFolderOutputSchema
71
+ });
72
+ const mediaMoveFolderOutputSchema = z.object({
73
+ data: mediaFolderOutputSchema
74
+ });
75
+ /**
76
+ * `media_delete_folder` output — the same shape for both branches, so an agent reads one contract.
77
+ *
78
+ * `dryRun` echoes which branch ran: on true the counts are what *would* be removed and nothing
79
+ * was touched; on false they are what actually was. Echoing it back means the agent can tell a
80
+ * preview from a completed deletion without tracking what it sent.
81
+ *
82
+ * There is no "skipped ids" field: an id that does not resolve to a folder rejects the whole
83
+ * call, so every id in the request is accounted for by `folders` on any successful response.
84
+ */ const mediaDeleteFolderOutputSchema = z.object({
85
+ dryRun: z.boolean().describe('True when this was a preview and NOTHING was deleted. False when the deletion was performed.'),
86
+ folders: z.array(mediaFolderOutputSchema).describe('The folders matched by the given ids (the roots of the cascade).'),
87
+ totalFolderNumber: z.number().describe('Total folders affected, including the matched folders themselves and every descendant.'),
88
+ totalFileNumber: z.number().describe('Total files affected, across the whole cascade.')
89
+ });
90
+ /**
91
+ * `media_move_assets` output — a per-id report rather than a single verdict.
92
+ *
93
+ * A bad id among good ones does not roll back the valid moves (see the handler), so the response
94
+ * has to say which ids moved and which did not: an agent that only learned "the call failed"
95
+ * would either retry moves that already happened or abandon ones that did. `moved` and `failed`
96
+ * together account for every id in the request, on every successful response — including one
97
+ * where `moved` is empty because no id resolved.
98
+ *
99
+ * `moved` carries the full asset in the same shape the read tools return, so the new folder can
100
+ * be confirmed without a follow-up `media_get_asset`.
101
+ */ const mediaMoveAssetsFailureSchema = z.object({
102
+ id: z.number().describe('The requested asset id that was not moved.'),
103
+ reason: z.string().describe('Why this id was not moved — a missing asset, or one this token may not edit.')
104
+ });
105
+ const mediaMoveAssetsOutputSchema = z.object({
106
+ destinationFolder: z.object({
107
+ id: z.number(),
108
+ name: z.string().optional()
109
+ }).nullable().describe('The destination folder, or null when the assets were moved to the media library root.'),
110
+ moved: z.array(mediaAssetOutputSchema).describe('The assets that were moved, in their new location.'),
111
+ failed: z.array(mediaMoveAssetsFailureSchema).describe('The ids that were not moved, each with a reason. The moves reported in `moved` still happened — retry only these.')
112
+ });
113
+ /**
114
+ * `media_delete_assets` output — one contract for both branches, with a per-id account of every
115
+ * requested id.
116
+ *
117
+ * `dryRun` echoes which branch ran: on true `deleted` is what *would* be removed and nothing was
118
+ * touched; on false it is what actually was. Echoing it back means an agent can tell a preview
119
+ * from a completed deletion without tracking what it sent — the difference matters more here
120
+ * than anywhere else in this surface, because one branch is irreversible.
121
+ *
122
+ * `deleted` carries the full asset rather than a bare id, so the agent can report what it
123
+ * destroyed after the row is gone and no read can recover it. On a dry run it is the same shape,
124
+ * which is exactly what makes the preview a confirmation an agent can act on.
125
+ *
126
+ * Unlike `media_delete_folder`, an unresolvable id does NOT reject the call: deletions are performed
127
+ * per asset and reported per id, so a bad id among good ones neither rolls back the valid
128
+ * deletions nor stops them from happening. `deleted` and `failed` together account for every id
129
+ * in the request, on every successful response.
130
+ */ const mediaDeleteAssetsFailureSchema = z.object({
131
+ id: z.number().describe('The requested asset id that was not deleted.'),
132
+ reason: z.string().describe('Why this id was not deleted — a missing asset (possibly a folder id), or one this token may not delete.')
133
+ });
134
+ const mediaDeleteAssetsOutputSchema = z.object({
135
+ dryRun: z.boolean().describe('True when this was a preview and NOTHING was deleted. False when the deletion was performed and is irreversible.'),
136
+ deleted: z.array(mediaAssetOutputSchema).describe('On a dry run, the assets that WOULD be permanently deleted. On a real run, the assets that were deleted — they no longer exist and cannot be read back.'),
137
+ failed: z.array(mediaDeleteAssetsFailureSchema).describe('The ids that were not deleted, each with a reason. On a real run the deletions reported in `deleted` still happened — retry only these.'),
138
+ totalFileNumber: z.number().describe('How many assets are in `deleted` — the count that WOULD be removed on a dry run, or that was removed on a real one.')
139
+ });
140
+
141
+ export { mediaAssetOutputSchema, mediaCreateFolderOutputSchema, mediaDeleteAssetsFailureSchema, mediaDeleteAssetsOutputSchema, mediaDeleteFolderOutputSchema, mediaFolderNodeSchema, mediaFolderOutputSchema, mediaGetAssetOutputSchema, mediaListAssetsOutputSchema, mediaListFoldersOutputSchema, mediaMoveAssetsFailureSchema, mediaMoveAssetsOutputSchema, mediaMoveFolderOutputSchema, mediaRenameFolderOutputSchema, mediaUpdateAssetOutputSchema };
142
+ //# sourceMappingURL=output-schemas.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-schemas.mjs","sources":["../../../../server/src/mcp/schemas/output-schemas.ts"],"sourcesContent":["import { z } from '@strapi/utils';\n\n/**\n * The exhaustive set of asset fields the MCP surface may expose — an allowlist, for the reasons\n * in `sanitizeMediaAsset`. A field added to the file content-type stays invisible to MCP until\n * it is added both here and there.\n */\nexport const mediaAssetOutputSchema = z.object({\n id: z.number().describe('Numeric asset id — the canonical identifier for this asset.'),\n name: z.string(),\n alternativeText: z.string().nullable().optional(),\n caption: z.string().nullable().optional(),\n url: z.string().describe('Public (or signed, for private providers) URL of the asset.'),\n mime: z.string().describe('Mime type, e.g. \"image/png\".'),\n size: z.number().describe('File size in kilobytes, as stored by Strapi.'),\n width: z.number().nullable().optional().describe('Pixel width, images only.'),\n height: z.number().nullable().optional().describe('Pixel height, images only.'),\n ext: z.string().nullable().optional().describe('File extension including the dot, e.g. \".png\".'),\n folder: z\n .object({\n id: z.number(),\n name: z.string(),\n })\n .nullable()\n .optional()\n .describe('Containing folder, or null when the asset sits at the media library root.'),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n});\n\nexport const mediaGetAssetOutputSchema = z.object({\n data: mediaAssetOutputSchema.nullable(),\n});\n\nexport const mediaListAssetsOutputSchema = z.object({\n results: z.array(mediaAssetOutputSchema),\n pagination: z.object({\n page: z.number(),\n pageSize: z.number(),\n pageCount: z.number(),\n total: z.number(),\n }),\n});\n\n/**\n * Folder tree node. `children` is recursive and unbounded in depth, so it is typed lazily.\n */\nexport type MediaFolderNode = {\n id: number;\n name: string;\n children: MediaFolderNode[];\n};\n\nexport const mediaFolderNodeSchema: z.ZodType<MediaFolderNode> = z.lazy(() =>\n z.object({\n id: z.number(),\n name: z.string(),\n children: z.array(mediaFolderNodeSchema),\n })\n);\n\nexport const mediaListFoldersOutputSchema = z.object({\n data: z.array(mediaFolderNodeSchema).describe('Nested folder structure, roots first.'),\n});\n\n/**\n * `media_update_asset` output — the updated asset in the same shape the read tools return,\n * so an agent can confirm the write without a follow-up `media_get_asset` call.\n */\nexport const mediaUpdateAssetOutputSchema = z.object({\n data: mediaAssetOutputSchema,\n});\n\n/**\n * A folder as returned by the write tools.\n *\n * Like the asset schema this is an ALLOWLIST: `path` and `pathId` are internal materialized-path\n * bookkeeping and stay invisible to MCP clients, matching what `media_list_folders` already exposes.\n */\nexport const mediaFolderOutputSchema = z.object({\n id: z.number().describe('Numeric folder id — the canonical identifier for this folder.'),\n name: z.string(),\n parent: z\n .object({\n id: z.number(),\n name: z.string().optional(),\n })\n .nullable()\n .optional()\n .describe(\n 'Containing folder, or null when the folder sits at the media library root. Absent when this response did not load the relation — absent means unknown, not root.'\n ),\n createdAt: z.string().nullable().optional(),\n updatedAt: z.string().nullable().optional(),\n});\n\nexport const mediaCreateFolderOutputSchema = z.object({\n data: mediaFolderOutputSchema,\n});\n\nexport const mediaRenameFolderOutputSchema = z.object({\n data: mediaFolderOutputSchema,\n});\n\nexport const mediaMoveFolderOutputSchema = z.object({\n data: mediaFolderOutputSchema,\n});\n\n/**\n * `media_delete_folder` output — the same shape for both branches, so an agent reads one contract.\n *\n * `dryRun` echoes which branch ran: on true the counts are what *would* be removed and nothing\n * was touched; on false they are what actually was. Echoing it back means the agent can tell a\n * preview from a completed deletion without tracking what it sent.\n *\n * There is no \"skipped ids\" field: an id that does not resolve to a folder rejects the whole\n * call, so every id in the request is accounted for by `folders` on any successful response.\n */\nexport const mediaDeleteFolderOutputSchema = z.object({\n dryRun: z\n .boolean()\n .describe(\n 'True when this was a preview and NOTHING was deleted. False when the deletion was performed.'\n ),\n folders: z\n .array(mediaFolderOutputSchema)\n .describe('The folders matched by the given ids (the roots of the cascade).'),\n totalFolderNumber: z\n .number()\n .describe(\n 'Total folders affected, including the matched folders themselves and every descendant.'\n ),\n totalFileNumber: z.number().describe('Total files affected, across the whole cascade.'),\n});\n\n/**\n * `media_move_assets` output — a per-id report rather than a single verdict.\n *\n * A bad id among good ones does not roll back the valid moves (see the handler), so the response\n * has to say which ids moved and which did not: an agent that only learned \"the call failed\"\n * would either retry moves that already happened or abandon ones that did. `moved` and `failed`\n * together account for every id in the request, on every successful response — including one\n * where `moved` is empty because no id resolved.\n *\n * `moved` carries the full asset in the same shape the read tools return, so the new folder can\n * be confirmed without a follow-up `media_get_asset`.\n */\nexport const mediaMoveAssetsFailureSchema = z.object({\n id: z.number().describe('The requested asset id that was not moved.'),\n reason: z\n .string()\n .describe('Why this id was not moved — a missing asset, or one this token may not edit.'),\n});\n\nexport const mediaMoveAssetsOutputSchema = z.object({\n destinationFolder: z\n .object({\n id: z.number(),\n name: z.string().optional(),\n })\n .nullable()\n .describe(\n 'The destination folder, or null when the assets were moved to the media library root.'\n ),\n moved: z\n .array(mediaAssetOutputSchema)\n .describe('The assets that were moved, in their new location.'),\n failed: z\n .array(mediaMoveAssetsFailureSchema)\n .describe(\n 'The ids that were not moved, each with a reason. The moves reported in `moved` still happened — retry only these.'\n ),\n});\n\n/**\n * `media_delete_assets` output — one contract for both branches, with a per-id account of every\n * requested id.\n *\n * `dryRun` echoes which branch ran: on true `deleted` is what *would* be removed and nothing was\n * touched; on false it is what actually was. Echoing it back means an agent can tell a preview\n * from a completed deletion without tracking what it sent — the difference matters more here\n * than anywhere else in this surface, because one branch is irreversible.\n *\n * `deleted` carries the full asset rather than a bare id, so the agent can report what it\n * destroyed after the row is gone and no read can recover it. On a dry run it is the same shape,\n * which is exactly what makes the preview a confirmation an agent can act on.\n *\n * Unlike `media_delete_folder`, an unresolvable id does NOT reject the call: deletions are performed\n * per asset and reported per id, so a bad id among good ones neither rolls back the valid\n * deletions nor stops them from happening. `deleted` and `failed` together account for every id\n * in the request, on every successful response.\n */\nexport const mediaDeleteAssetsFailureSchema = z.object({\n id: z.number().describe('The requested asset id that was not deleted.'),\n reason: z\n .string()\n .describe(\n 'Why this id was not deleted — a missing asset (possibly a folder id), or one this token may not delete.'\n ),\n});\n\nexport const mediaDeleteAssetsOutputSchema = z.object({\n dryRun: z\n .boolean()\n .describe(\n 'True when this was a preview and NOTHING was deleted. False when the deletion was performed and is irreversible.'\n ),\n deleted: z\n .array(mediaAssetOutputSchema)\n .describe(\n 'On a dry run, the assets that WOULD be permanently deleted. On a real run, the assets that were deleted — they no longer exist and cannot be read back.'\n ),\n failed: z\n .array(mediaDeleteAssetsFailureSchema)\n .describe(\n 'The ids that were not deleted, each with a reason. On a real run the deletions reported in `deleted` still happened — retry only these.'\n ),\n totalFileNumber: z\n .number()\n .describe(\n 'How many assets are in `deleted` — the count that WOULD be removed on a dry run, or that was removed on a real one.'\n ),\n});\n"],"names":["mediaAssetOutputSchema","z","object","id","number","describe","name","string","alternativeText","nullable","optional","caption","url","mime","size","width","height","ext","folder","createdAt","updatedAt","mediaGetAssetOutputSchema","data","mediaListAssetsOutputSchema","results","array","pagination","page","pageSize","pageCount","total","mediaFolderNodeSchema","lazy","children","mediaListFoldersOutputSchema","mediaUpdateAssetOutputSchema","mediaFolderOutputSchema","parent","mediaCreateFolderOutputSchema","mediaRenameFolderOutputSchema","mediaMoveFolderOutputSchema","mediaDeleteFolderOutputSchema","dryRun","boolean","folders","totalFolderNumber","totalFileNumber","mediaMoveAssetsFailureSchema","reason","mediaMoveAssetsOutputSchema","destinationFolder","moved","failed","mediaDeleteAssetsFailureSchema","mediaDeleteAssetsOutputSchema","deleted"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ /** Wraps a plain object into the dual-representation MCP tool return value (text + structuredContent). */ const ok = (structuredContent)=>({
4
+ content: [
5
+ {
6
+ type: 'text',
7
+ text: JSON.stringify(structuredContent)
8
+ }
9
+ ],
10
+ structuredContent
11
+ });
12
+
13
+ exports.ok = ok;
14
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../../../server/src/mcp/utils.ts"],"sourcesContent":["import type { Modules } from '@strapi/types';\n\n/** Wraps a plain object into the dual-representation MCP tool return value (text + structuredContent). */\nexport const ok = (\n structuredContent: Record<string, unknown>\n): Modules.MCP.McpToolHandlerReturn => ({\n content: [{ type: 'text', text: JSON.stringify(structuredContent) }],\n structuredContent,\n});\n"],"names":["ok","structuredContent","content","type","text","JSON","stringify"],"mappings":";;AAEA,2GACO,MAAMA,EAAAA,GAAK,CAChBC,qBACsC;QACtCC,OAAAA,EAAS;AAAC,YAAA;gBAAEC,IAAAA,EAAM,MAAA;gBAAQC,IAAAA,EAAMC,IAAAA,CAAKC,SAAS,CAACL,iBAAAA;AAAmB;AAAE,SAAA;AACpEA,QAAAA;AACF,KAAA;;;;"}