@umbraco-cms/mcp-dev 17.4.0 → 17.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-OBOSCZYR.cjs → chunk-H5ZIS43M.cjs} +373 -341
- package/dist/chunk-H5ZIS43M.cjs.map +1 -0
- package/dist/{chunk-6NEKTCPS.js → chunk-XVBYRUFE.js} +338 -306
- package/dist/chunk-XVBYRUFE.js.map +1 -0
- package/dist/collections.cjs +7 -2
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +7 -2
- package/dist/collections.js.map +1 -1
- package/dist/index.cjs +91 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/tool-types.d.ts +4 -4
- package/package.json +3 -3
- package/dist/chunk-6NEKTCPS.js.map +0 -1
- package/dist/chunk-OBOSCZYR.cjs.map +0 -1
|
@@ -3002,28 +3002,28 @@ var getUmbracoManagementAPI = () => {
|
|
|
3002
3002
|
options
|
|
3003
3003
|
);
|
|
3004
3004
|
};
|
|
3005
|
-
const getPartialViewByPath = (
|
|
3005
|
+
const getPartialViewByPath = (path3, options) => {
|
|
3006
3006
|
return UmbracoManagementClient(
|
|
3007
3007
|
{
|
|
3008
|
-
url: `/umbraco/management/api/v1/partial-view/${
|
|
3008
|
+
url: `/umbraco/management/api/v1/partial-view/${path3}`,
|
|
3009
3009
|
method: "GET"
|
|
3010
3010
|
},
|
|
3011
3011
|
options
|
|
3012
3012
|
);
|
|
3013
3013
|
};
|
|
3014
|
-
const deletePartialViewByPath = (
|
|
3014
|
+
const deletePartialViewByPath = (path3, options) => {
|
|
3015
3015
|
return UmbracoManagementClient(
|
|
3016
3016
|
{
|
|
3017
|
-
url: `/umbraco/management/api/v1/partial-view/${
|
|
3017
|
+
url: `/umbraco/management/api/v1/partial-view/${path3}`,
|
|
3018
3018
|
method: "DELETE"
|
|
3019
3019
|
},
|
|
3020
3020
|
options
|
|
3021
3021
|
);
|
|
3022
3022
|
};
|
|
3023
|
-
const putPartialViewByPath = (
|
|
3023
|
+
const putPartialViewByPath = (path3, updatePartialViewRequestModel, options) => {
|
|
3024
3024
|
return UmbracoManagementClient(
|
|
3025
3025
|
{
|
|
3026
|
-
url: `/umbraco/management/api/v1/partial-view/${
|
|
3026
|
+
url: `/umbraco/management/api/v1/partial-view/${path3}`,
|
|
3027
3027
|
method: "PUT",
|
|
3028
3028
|
headers: { "Content-Type": "application/json" },
|
|
3029
3029
|
data: updatePartialViewRequestModel
|
|
@@ -3031,10 +3031,10 @@ var getUmbracoManagementAPI = () => {
|
|
|
3031
3031
|
options
|
|
3032
3032
|
);
|
|
3033
3033
|
};
|
|
3034
|
-
const putPartialViewByPathRename = (
|
|
3034
|
+
const putPartialViewByPathRename = (path3, renamePartialViewRequestModel, options) => {
|
|
3035
3035
|
return UmbracoManagementClient(
|
|
3036
3036
|
{
|
|
3037
|
-
url: `/umbraco/management/api/v1/partial-view/${
|
|
3037
|
+
url: `/umbraco/management/api/v1/partial-view/${path3}/rename`,
|
|
3038
3038
|
method: "PUT",
|
|
3039
3039
|
headers: { "Content-Type": "application/json" },
|
|
3040
3040
|
data: renamePartialViewRequestModel
|
|
@@ -3053,19 +3053,19 @@ var getUmbracoManagementAPI = () => {
|
|
|
3053
3053
|
options
|
|
3054
3054
|
);
|
|
3055
3055
|
};
|
|
3056
|
-
const getPartialViewFolderByPath = (
|
|
3056
|
+
const getPartialViewFolderByPath = (path3, options) => {
|
|
3057
3057
|
return UmbracoManagementClient(
|
|
3058
3058
|
{
|
|
3059
|
-
url: `/umbraco/management/api/v1/partial-view/folder/${
|
|
3059
|
+
url: `/umbraco/management/api/v1/partial-view/folder/${path3}`,
|
|
3060
3060
|
method: "GET"
|
|
3061
3061
|
},
|
|
3062
3062
|
options
|
|
3063
3063
|
);
|
|
3064
3064
|
};
|
|
3065
|
-
const deletePartialViewFolderByPath = (
|
|
3065
|
+
const deletePartialViewFolderByPath = (path3, options) => {
|
|
3066
3066
|
return UmbracoManagementClient(
|
|
3067
3067
|
{
|
|
3068
|
-
url: `/umbraco/management/api/v1/partial-view/folder/${
|
|
3068
|
+
url: `/umbraco/management/api/v1/partial-view/folder/${path3}`,
|
|
3069
3069
|
method: "DELETE"
|
|
3070
3070
|
},
|
|
3071
3071
|
options
|
|
@@ -3313,28 +3313,28 @@ var getUmbracoManagementAPI = () => {
|
|
|
3313
3313
|
options
|
|
3314
3314
|
);
|
|
3315
3315
|
};
|
|
3316
|
-
const getScriptByPath = (
|
|
3316
|
+
const getScriptByPath = (path3, options) => {
|
|
3317
3317
|
return UmbracoManagementClient(
|
|
3318
3318
|
{
|
|
3319
|
-
url: `/umbraco/management/api/v1/script/${
|
|
3319
|
+
url: `/umbraco/management/api/v1/script/${path3}`,
|
|
3320
3320
|
method: "GET"
|
|
3321
3321
|
},
|
|
3322
3322
|
options
|
|
3323
3323
|
);
|
|
3324
3324
|
};
|
|
3325
|
-
const deleteScriptByPath = (
|
|
3325
|
+
const deleteScriptByPath = (path3, options) => {
|
|
3326
3326
|
return UmbracoManagementClient(
|
|
3327
3327
|
{
|
|
3328
|
-
url: `/umbraco/management/api/v1/script/${
|
|
3328
|
+
url: `/umbraco/management/api/v1/script/${path3}`,
|
|
3329
3329
|
method: "DELETE"
|
|
3330
3330
|
},
|
|
3331
3331
|
options
|
|
3332
3332
|
);
|
|
3333
3333
|
};
|
|
3334
|
-
const putScriptByPath = (
|
|
3334
|
+
const putScriptByPath = (path3, updateScriptRequestModel, options) => {
|
|
3335
3335
|
return UmbracoManagementClient(
|
|
3336
3336
|
{
|
|
3337
|
-
url: `/umbraco/management/api/v1/script/${
|
|
3337
|
+
url: `/umbraco/management/api/v1/script/${path3}`,
|
|
3338
3338
|
method: "PUT",
|
|
3339
3339
|
headers: { "Content-Type": "application/json" },
|
|
3340
3340
|
data: updateScriptRequestModel
|
|
@@ -3342,10 +3342,10 @@ var getUmbracoManagementAPI = () => {
|
|
|
3342
3342
|
options
|
|
3343
3343
|
);
|
|
3344
3344
|
};
|
|
3345
|
-
const putScriptByPathRename = (
|
|
3345
|
+
const putScriptByPathRename = (path3, renameScriptRequestModel, options) => {
|
|
3346
3346
|
return UmbracoManagementClient(
|
|
3347
3347
|
{
|
|
3348
|
-
url: `/umbraco/management/api/v1/script/${
|
|
3348
|
+
url: `/umbraco/management/api/v1/script/${path3}/rename`,
|
|
3349
3349
|
method: "PUT",
|
|
3350
3350
|
headers: { "Content-Type": "application/json" },
|
|
3351
3351
|
data: renameScriptRequestModel
|
|
@@ -3364,19 +3364,19 @@ var getUmbracoManagementAPI = () => {
|
|
|
3364
3364
|
options
|
|
3365
3365
|
);
|
|
3366
3366
|
};
|
|
3367
|
-
const getScriptFolderByPath = (
|
|
3367
|
+
const getScriptFolderByPath = (path3, options) => {
|
|
3368
3368
|
return UmbracoManagementClient(
|
|
3369
3369
|
{
|
|
3370
|
-
url: `/umbraco/management/api/v1/script/folder/${
|
|
3370
|
+
url: `/umbraco/management/api/v1/script/folder/${path3}`,
|
|
3371
3371
|
method: "GET"
|
|
3372
3372
|
},
|
|
3373
3373
|
options
|
|
3374
3374
|
);
|
|
3375
3375
|
};
|
|
3376
|
-
const deleteScriptFolderByPath = (
|
|
3376
|
+
const deleteScriptFolderByPath = (path3, options) => {
|
|
3377
3377
|
return UmbracoManagementClient(
|
|
3378
3378
|
{
|
|
3379
|
-
url: `/umbraco/management/api/v1/script/folder/${
|
|
3379
|
+
url: `/umbraco/management/api/v1/script/folder/${path3}`,
|
|
3380
3380
|
method: "DELETE"
|
|
3381
3381
|
},
|
|
3382
3382
|
options
|
|
@@ -3600,28 +3600,28 @@ var getUmbracoManagementAPI = () => {
|
|
|
3600
3600
|
options
|
|
3601
3601
|
);
|
|
3602
3602
|
};
|
|
3603
|
-
const getStylesheetByPath = (
|
|
3603
|
+
const getStylesheetByPath = (path3, options) => {
|
|
3604
3604
|
return UmbracoManagementClient(
|
|
3605
3605
|
{
|
|
3606
|
-
url: `/umbraco/management/api/v1/stylesheet/${
|
|
3606
|
+
url: `/umbraco/management/api/v1/stylesheet/${path3}`,
|
|
3607
3607
|
method: "GET"
|
|
3608
3608
|
},
|
|
3609
3609
|
options
|
|
3610
3610
|
);
|
|
3611
3611
|
};
|
|
3612
|
-
const deleteStylesheetByPath = (
|
|
3612
|
+
const deleteStylesheetByPath = (path3, options) => {
|
|
3613
3613
|
return UmbracoManagementClient(
|
|
3614
3614
|
{
|
|
3615
|
-
url: `/umbraco/management/api/v1/stylesheet/${
|
|
3615
|
+
url: `/umbraco/management/api/v1/stylesheet/${path3}`,
|
|
3616
3616
|
method: "DELETE"
|
|
3617
3617
|
},
|
|
3618
3618
|
options
|
|
3619
3619
|
);
|
|
3620
3620
|
};
|
|
3621
|
-
const putStylesheetByPath = (
|
|
3621
|
+
const putStylesheetByPath = (path3, updateStylesheetRequestModel, options) => {
|
|
3622
3622
|
return UmbracoManagementClient(
|
|
3623
3623
|
{
|
|
3624
|
-
url: `/umbraco/management/api/v1/stylesheet/${
|
|
3624
|
+
url: `/umbraco/management/api/v1/stylesheet/${path3}`,
|
|
3625
3625
|
method: "PUT",
|
|
3626
3626
|
headers: { "Content-Type": "application/json" },
|
|
3627
3627
|
data: updateStylesheetRequestModel
|
|
@@ -3629,10 +3629,10 @@ var getUmbracoManagementAPI = () => {
|
|
|
3629
3629
|
options
|
|
3630
3630
|
);
|
|
3631
3631
|
};
|
|
3632
|
-
const putStylesheetByPathRename = (
|
|
3632
|
+
const putStylesheetByPathRename = (path3, renameStylesheetRequestModel, options) => {
|
|
3633
3633
|
return UmbracoManagementClient(
|
|
3634
3634
|
{
|
|
3635
|
-
url: `/umbraco/management/api/v1/stylesheet/${
|
|
3635
|
+
url: `/umbraco/management/api/v1/stylesheet/${path3}/rename`,
|
|
3636
3636
|
method: "PUT",
|
|
3637
3637
|
headers: { "Content-Type": "application/json" },
|
|
3638
3638
|
data: renameStylesheetRequestModel
|
|
@@ -3651,19 +3651,19 @@ var getUmbracoManagementAPI = () => {
|
|
|
3651
3651
|
options
|
|
3652
3652
|
);
|
|
3653
3653
|
};
|
|
3654
|
-
const getStylesheetFolderByPath = (
|
|
3654
|
+
const getStylesheetFolderByPath = (path3, options) => {
|
|
3655
3655
|
return UmbracoManagementClient(
|
|
3656
3656
|
{
|
|
3657
|
-
url: `/umbraco/management/api/v1/stylesheet/folder/${
|
|
3657
|
+
url: `/umbraco/management/api/v1/stylesheet/folder/${path3}`,
|
|
3658
3658
|
method: "GET"
|
|
3659
3659
|
},
|
|
3660
3660
|
options
|
|
3661
3661
|
);
|
|
3662
3662
|
};
|
|
3663
|
-
const deleteStylesheetFolderByPath = (
|
|
3663
|
+
const deleteStylesheetFolderByPath = (path3, options) => {
|
|
3664
3664
|
return UmbracoManagementClient(
|
|
3665
3665
|
{
|
|
3666
|
-
url: `/umbraco/management/api/v1/stylesheet/folder/${
|
|
3666
|
+
url: `/umbraco/management/api/v1/stylesheet/folder/${path3}`,
|
|
3667
3667
|
method: "DELETE"
|
|
3668
3668
|
},
|
|
3669
3669
|
options
|
|
@@ -4546,21 +4546,47 @@ var getUmbracoManagementAPI = () => {
|
|
|
4546
4546
|
|
|
4547
4547
|
// src/umb-management-api/api/temporary-file/index.ts
|
|
4548
4548
|
import { UmbracoManagementClient as UmbracoManagementClient2 } from "@umbraco-cms/mcp-server-sdk";
|
|
4549
|
-
|
|
4549
|
+
async function readStreamToBuffer(stream) {
|
|
4550
|
+
const chunks = [];
|
|
4551
|
+
for await (const chunk of stream) {
|
|
4552
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
4553
|
+
}
|
|
4554
|
+
return Buffer.concat(chunks);
|
|
4555
|
+
}
|
|
4550
4556
|
var getTemporaryFileAPI = () => ({
|
|
4551
|
-
postTemporaryFile: (postTemporaryFileBody2, options) => {
|
|
4557
|
+
postTemporaryFile: async (postTemporaryFileBody2, options) => {
|
|
4552
4558
|
const formData = new FormData();
|
|
4553
4559
|
formData.append("Id", postTemporaryFileBody2.Id);
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4560
|
+
const file = postTemporaryFileBody2.File;
|
|
4561
|
+
console.log("[temp-file] incoming file:", {
|
|
4562
|
+
typeofFile: typeof file,
|
|
4563
|
+
isBuffer: Buffer.isBuffer(file),
|
|
4564
|
+
ctorName: file?.constructor?.name,
|
|
4565
|
+
hasByteLength: typeof file?.byteLength,
|
|
4566
|
+
hasLength: typeof file?.length,
|
|
4567
|
+
keys: file ? Object.keys(file).slice(0, 10) : []
|
|
4568
|
+
});
|
|
4569
|
+
const buffer = Buffer.isBuffer(file) ? file : await readStreamToBuffer(file);
|
|
4570
|
+
console.log("[temp-file] buffer:", { length: buffer.byteLength });
|
|
4571
|
+
const bytes = new Uint8Array(buffer.byteLength);
|
|
4572
|
+
bytes.set(buffer);
|
|
4573
|
+
const blob = new Blob([bytes]);
|
|
4574
|
+
console.log("[temp-file] blob:", { size: blob.size, type: blob.type, fileName: postTemporaryFileBody2.FileName });
|
|
4575
|
+
formData.append("File", blob, postTemporaryFileBody2.FileName);
|
|
4576
|
+
const entries = [];
|
|
4577
|
+
for (const [k, v] of formData.entries()) {
|
|
4578
|
+
entries.push({
|
|
4579
|
+
name: k,
|
|
4580
|
+
valueKind: typeof v === "string" ? "string" : v?.constructor?.name ?? typeof v,
|
|
4581
|
+
valueSize: typeof v === "string" ? v.length : v?.size ?? void 0
|
|
4582
|
+
});
|
|
4583
|
+
}
|
|
4584
|
+
console.log("[temp-file] formData entries:", entries);
|
|
4559
4585
|
return UmbracoManagementClient2(
|
|
4560
4586
|
{
|
|
4561
4587
|
url: `/umbraco/management/api/v1/temporary-file`,
|
|
4562
4588
|
method: "POST",
|
|
4563
|
-
headers,
|
|
4589
|
+
headers: options?.headers,
|
|
4564
4590
|
data: formData
|
|
4565
4591
|
},
|
|
4566
4592
|
options
|
|
@@ -4610,6 +4636,13 @@ var UmbracoManagementClient3 = class {
|
|
|
4610
4636
|
|
|
4611
4637
|
// src/umb-management-api/runtime-context.ts
|
|
4612
4638
|
var umbracoVersion = null;
|
|
4639
|
+
var allowFilePathUploads = false;
|
|
4640
|
+
function setAllowFilePathUploads(allow) {
|
|
4641
|
+
allowFilePathUploads = allow;
|
|
4642
|
+
}
|
|
4643
|
+
function isFilePathUploadAllowed() {
|
|
4644
|
+
return allowFilePathUploads;
|
|
4645
|
+
}
|
|
4613
4646
|
function setUmbracoVersion(version) {
|
|
4614
4647
|
umbracoVersion = version ?? null;
|
|
4615
4648
|
}
|
|
@@ -15675,13 +15708,13 @@ function isBlockStructure(value) {
|
|
|
15675
15708
|
}
|
|
15676
15709
|
return Array.isArray(value.contentData) && Array.isArray(value.settingsData);
|
|
15677
15710
|
}
|
|
15678
|
-
function discoverAllBlockArrays(value,
|
|
15711
|
+
function discoverAllBlockArrays(value, path3 = "root") {
|
|
15679
15712
|
const results = [];
|
|
15680
15713
|
if (!value || typeof value !== "object") {
|
|
15681
15714
|
return results;
|
|
15682
15715
|
}
|
|
15683
15716
|
if (isRichTextValue(value)) {
|
|
15684
|
-
const nestedResults = discoverAllBlockArrays(value.blocks, `${
|
|
15717
|
+
const nestedResults = discoverAllBlockArrays(value.blocks, `${path3}.blocks`);
|
|
15685
15718
|
results.push(...nestedResults);
|
|
15686
15719
|
return results;
|
|
15687
15720
|
}
|
|
@@ -15689,12 +15722,12 @@ function discoverAllBlockArrays(value, path4 = "root") {
|
|
|
15689
15722
|
results.push({
|
|
15690
15723
|
contentData: value.contentData,
|
|
15691
15724
|
settingsData: value.settingsData,
|
|
15692
|
-
path:
|
|
15725
|
+
path: path3
|
|
15693
15726
|
});
|
|
15694
15727
|
value.contentData.forEach((block, index) => {
|
|
15695
15728
|
if (block.values && Array.isArray(block.values)) {
|
|
15696
15729
|
block.values.forEach((prop, propIndex) => {
|
|
15697
|
-
const propPath = `${
|
|
15730
|
+
const propPath = `${path3}.contentData[${index}].values[${propIndex}](${prop.alias})`;
|
|
15698
15731
|
if (isRichTextValue(prop.value)) {
|
|
15699
15732
|
const nestedResults = discoverAllBlockArrays(prop.value.blocks, `${propPath}.blocks`);
|
|
15700
15733
|
results.push(...nestedResults);
|
|
@@ -15708,7 +15741,7 @@ function discoverAllBlockArrays(value, path4 = "root") {
|
|
|
15708
15741
|
value.settingsData.forEach((block, index) => {
|
|
15709
15742
|
if (block.values && Array.isArray(block.values)) {
|
|
15710
15743
|
block.values.forEach((prop, propIndex) => {
|
|
15711
|
-
const propPath = `${
|
|
15744
|
+
const propPath = `${path3}.settingsData[${index}].values[${propIndex}](${prop.alias})`;
|
|
15712
15745
|
if (isRichTextValue(prop.value)) {
|
|
15713
15746
|
const nestedResults = discoverAllBlockArrays(prop.value.blocks, `${propPath}.blocks`);
|
|
15714
15747
|
results.push(...nestedResults);
|
|
@@ -18659,16 +18692,14 @@ import { v4 as uuidv46 } from "uuid";
|
|
|
18659
18692
|
|
|
18660
18693
|
// src/umb-management-api/tools/media/post/helpers/media-upload-helpers.ts
|
|
18661
18694
|
import * as fs2 from "fs";
|
|
18662
|
-
import * as os from "os";
|
|
18663
18695
|
import * as path2 from "path";
|
|
18664
18696
|
import mime from "mime-types";
|
|
18665
18697
|
|
|
18666
18698
|
// src/umb-management-api/tools/media/post/helpers/validate-file-path.ts
|
|
18667
18699
|
import * as path from "path";
|
|
18668
18700
|
import * as fs from "fs";
|
|
18669
|
-
import { getServerConfig } from "@umbraco-cms/mcp-server-sdk";
|
|
18670
18701
|
async function validateFilePath(filePath, allowedPaths) {
|
|
18671
|
-
const allowedMediaPaths = allowedPaths ?? (
|
|
18702
|
+
const allowedMediaPaths = allowedPaths ?? (process.env.UMBRACO_ALLOWED_MEDIA_PATHS ? process.env.UMBRACO_ALLOWED_MEDIA_PATHS.split(",").map((p) => p.trim()).filter(Boolean) : void 0);
|
|
18672
18703
|
if (!allowedMediaPaths || allowedMediaPaths.length === 0) {
|
|
18673
18704
|
throw new Error(
|
|
18674
18705
|
'File path uploads are disabled. To enable, set UMBRACO_ALLOWED_MEDIA_PATHS environment variable with comma-separated allowed directory paths (e.g., UMBRACO_ALLOWED_MEDIA_PATHS="/tmp/uploads,/var/media")'
|
|
@@ -18676,8 +18707,13 @@ async function validateFilePath(filePath, allowedPaths) {
|
|
|
18676
18707
|
}
|
|
18677
18708
|
const normalizedPath = path.resolve(filePath);
|
|
18678
18709
|
const isAllowed = allowedMediaPaths.some((allowedPath) => {
|
|
18679
|
-
|
|
18680
|
-
|
|
18710
|
+
if (normalizedPath.startsWith(allowedPath)) return true;
|
|
18711
|
+
try {
|
|
18712
|
+
const realAllowedPath = fs.realpathSync(allowedPath);
|
|
18713
|
+
return normalizedPath.startsWith(realAllowedPath);
|
|
18714
|
+
} catch {
|
|
18715
|
+
return false;
|
|
18716
|
+
}
|
|
18681
18717
|
});
|
|
18682
18718
|
if (!isAllowed) {
|
|
18683
18719
|
throw new Error(
|
|
@@ -18689,8 +18725,13 @@ async function validateFilePath(filePath, allowedPaths) {
|
|
|
18689
18725
|
if (stats.isSymbolicLink()) {
|
|
18690
18726
|
const realPath = fs.realpathSync(normalizedPath);
|
|
18691
18727
|
const symlinkAllowed = allowedMediaPaths.some((allowedPath) => {
|
|
18692
|
-
|
|
18693
|
-
|
|
18728
|
+
if (realPath.startsWith(allowedPath)) return true;
|
|
18729
|
+
try {
|
|
18730
|
+
const realAllowedPath = fs.realpathSync(allowedPath);
|
|
18731
|
+
return realPath.startsWith(realAllowedPath);
|
|
18732
|
+
} catch {
|
|
18733
|
+
return false;
|
|
18734
|
+
}
|
|
18694
18735
|
});
|
|
18695
18736
|
if (!symlinkAllowed) {
|
|
18696
18737
|
throw new Error(
|
|
@@ -18777,18 +18818,25 @@ function buildValueStructure(mediaTypeName, temporaryFileId) {
|
|
|
18777
18818
|
value: { temporaryFileId }
|
|
18778
18819
|
};
|
|
18779
18820
|
}
|
|
18780
|
-
async function
|
|
18781
|
-
let tempFilePath = null;
|
|
18782
|
-
let readStream;
|
|
18821
|
+
async function createFilePayload(sourceType, filePath, fileUrl, fileAsBase64, fileName) {
|
|
18783
18822
|
switch (sourceType) {
|
|
18784
|
-
case "filePath":
|
|
18823
|
+
case "filePath": {
|
|
18785
18824
|
if (!filePath) {
|
|
18786
18825
|
throw new Error("filePath is required when sourceType is 'filePath'");
|
|
18787
18826
|
}
|
|
18827
|
+
if (typeof fs2.createReadStream !== "function") {
|
|
18828
|
+
throw new Error(
|
|
18829
|
+
"filePath source is not supported in this runtime (no filesystem). Use sourceType 'url' or 'base64' instead."
|
|
18830
|
+
);
|
|
18831
|
+
}
|
|
18788
18832
|
const validatedPath = await validateFilePath(filePath);
|
|
18789
|
-
|
|
18790
|
-
|
|
18791
|
-
|
|
18833
|
+
const filename = fileName.includes(".") ? fileName : path2.basename(validatedPath);
|
|
18834
|
+
return {
|
|
18835
|
+
data: fs2.createReadStream(validatedPath),
|
|
18836
|
+
filename
|
|
18837
|
+
};
|
|
18838
|
+
}
|
|
18839
|
+
case "url": {
|
|
18792
18840
|
if (!fileUrl) {
|
|
18793
18841
|
throw new Error("fileUrl is required when sourceType is 'url'");
|
|
18794
18842
|
}
|
|
@@ -18804,123 +18852,110 @@ async function createFileStream(sourceType, filePath, fileUrl, fileAsBase64, fil
|
|
|
18804
18852
|
if (response.status >= 400) {
|
|
18805
18853
|
throw new Error(`Failed to fetch file from URL: HTTP ${response.status} ${response.statusText}`);
|
|
18806
18854
|
}
|
|
18807
|
-
const
|
|
18808
|
-
let
|
|
18855
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
18856
|
+
let filename = fileName;
|
|
18809
18857
|
if (!fileName.includes(".")) {
|
|
18810
18858
|
const urlPath = new URL(fileUrl).pathname;
|
|
18811
18859
|
const urlExtension = path2.extname(urlPath);
|
|
18812
18860
|
if (urlExtension) {
|
|
18813
|
-
|
|
18861
|
+
filename = `${fileName}${urlExtension}`;
|
|
18814
18862
|
} else {
|
|
18815
18863
|
const contentType = response.headers.get("content-type") ?? void 0;
|
|
18816
18864
|
const extensionFromMime = getExtensionFromMimeType(contentType);
|
|
18817
|
-
|
|
18818
|
-
fileNameWithExtension2 = `${fileName}${extensionFromMime}`;
|
|
18819
|
-
} else {
|
|
18820
|
-
fileNameWithExtension2 = `${fileName}.bin`;
|
|
18821
|
-
}
|
|
18865
|
+
filename = extensionFromMime ? `${fileName}${extensionFromMime}` : `${fileName}.bin`;
|
|
18822
18866
|
}
|
|
18823
18867
|
}
|
|
18824
|
-
|
|
18825
|
-
fs2.writeFileSync(tempFilePath, Buffer.from(arrayBuffer));
|
|
18826
|
-
readStream = fs2.createReadStream(tempFilePath);
|
|
18868
|
+
return { data: buffer, filename };
|
|
18827
18869
|
} catch (error) {
|
|
18828
18870
|
if (error.name === "AbortError") {
|
|
18829
18871
|
throw new Error(`Request timeout after 30s fetching URL: ${fileUrl}`);
|
|
18830
18872
|
}
|
|
18831
18873
|
throw new Error(`Failed to fetch URL: ${fileUrl} - ${error.message}`);
|
|
18832
18874
|
}
|
|
18833
|
-
|
|
18834
|
-
case "base64":
|
|
18875
|
+
}
|
|
18876
|
+
case "base64": {
|
|
18835
18877
|
if (!fileAsBase64) {
|
|
18836
18878
|
throw new Error("fileAsBase64 is required when sourceType is 'base64'");
|
|
18837
18879
|
}
|
|
18838
|
-
const
|
|
18839
|
-
let
|
|
18880
|
+
const buffer = Buffer.from(fileAsBase64, "base64");
|
|
18881
|
+
let filename = fileName;
|
|
18840
18882
|
if (!fileName.includes(".")) {
|
|
18841
|
-
const extension = detectFileExtensionFromBuffer(
|
|
18842
|
-
|
|
18883
|
+
const extension = detectFileExtensionFromBuffer(buffer);
|
|
18884
|
+
filename = `${fileName}${extension}`;
|
|
18843
18885
|
}
|
|
18844
|
-
|
|
18845
|
-
fs2.writeFileSync(tempFilePath, fileContent);
|
|
18846
|
-
readStream = fs2.createReadStream(tempFilePath);
|
|
18847
|
-
break;
|
|
18848
|
-
}
|
|
18849
|
-
return { readStream, tempFilePath };
|
|
18850
|
-
}
|
|
18851
|
-
function cleanupTempFile(tempFilePath) {
|
|
18852
|
-
if (tempFilePath && fs2.existsSync(tempFilePath)) {
|
|
18853
|
-
try {
|
|
18854
|
-
fs2.unlinkSync(tempFilePath);
|
|
18855
|
-
} catch (e) {
|
|
18856
|
-
console.error("Failed to cleanup temp file:", e);
|
|
18886
|
+
return { data: buffer, filename };
|
|
18857
18887
|
}
|
|
18858
18888
|
}
|
|
18859
18889
|
}
|
|
18860
18890
|
async function uploadMediaFile(client, params) {
|
|
18861
|
-
|
|
18891
|
+
const validatedMediaTypeName = validateMediaTypeForSvg(
|
|
18892
|
+
params.filePath,
|
|
18893
|
+
params.fileUrl,
|
|
18894
|
+
params.name,
|
|
18895
|
+
params.mediaTypeName
|
|
18896
|
+
);
|
|
18897
|
+
const mediaTypeId = await fetchMediaTypeId(client, validatedMediaTypeName);
|
|
18898
|
+
const { data, filename } = await createFilePayload(
|
|
18899
|
+
params.sourceType,
|
|
18900
|
+
params.filePath,
|
|
18901
|
+
params.fileUrl,
|
|
18902
|
+
params.fileAsBase64,
|
|
18903
|
+
params.name
|
|
18904
|
+
);
|
|
18862
18905
|
try {
|
|
18863
|
-
|
|
18864
|
-
params.
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
const
|
|
18870
|
-
const
|
|
18871
|
-
|
|
18872
|
-
params.filePath,
|
|
18873
|
-
params.fileUrl,
|
|
18874
|
-
params.fileAsBase64,
|
|
18875
|
-
params.name
|
|
18876
|
-
);
|
|
18877
|
-
tempFilePath = createdTempPath;
|
|
18878
|
-
try {
|
|
18879
|
-
await client.postTemporaryFile({
|
|
18880
|
-
Id: params.temporaryFileId,
|
|
18881
|
-
File: readStream
|
|
18882
|
-
});
|
|
18883
|
-
} catch (error) {
|
|
18884
|
-
const err = error;
|
|
18885
|
-
const errorData = err.response?.data ? typeof err.response.data === "string" ? err.response.data : JSON.stringify(err.response.data) : err.message;
|
|
18886
|
-
throw new Error(`Failed to upload temporary file: ${err.response?.status || "Unknown error"} - ${errorData}`);
|
|
18887
|
-
}
|
|
18888
|
-
const valueStructure = buildValueStructure(validatedMediaTypeName, params.temporaryFileId);
|
|
18889
|
-
let response;
|
|
18890
|
-
try {
|
|
18891
|
-
response = await client.postMedia({
|
|
18892
|
-
mediaType: { id: mediaTypeId },
|
|
18893
|
-
variants: [
|
|
18894
|
-
{
|
|
18895
|
-
culture: null,
|
|
18896
|
-
segment: null,
|
|
18897
|
-
name: params.name
|
|
18898
|
-
// Use original name provided by user
|
|
18899
|
-
}
|
|
18900
|
-
],
|
|
18901
|
-
values: [valueStructure],
|
|
18902
|
-
parent: params.parentId ? { id: params.parentId } : null
|
|
18903
|
-
}, CAPTURE_RAW_HTTP_RESPONSE146);
|
|
18904
|
-
} catch (error) {
|
|
18905
|
-
const err = error;
|
|
18906
|
-
throw new Error(`Failed to create media item: ${err.response?.status || "Unknown error"} - ${JSON.stringify(err.response?.data) || err.message}`);
|
|
18907
|
-
}
|
|
18908
|
-
if (response.status < 200 || response.status >= 300) {
|
|
18909
|
-
throw new Error(`Request failed with status code ${response.status}`);
|
|
18910
|
-
}
|
|
18911
|
-
const locationHeader = response.headers?.location || response.headers?.Location;
|
|
18912
|
-
if (!locationHeader) {
|
|
18913
|
-
throw new Error("No Location header in response - cannot determine created media ID");
|
|
18914
|
-
}
|
|
18915
|
-
const idMatch = locationHeader.match(/\/([a-f0-9-]{36})$/i);
|
|
18916
|
-
if (!idMatch) {
|
|
18917
|
-
throw new Error(`Could not extract ID from Location header: ${locationHeader}`);
|
|
18918
|
-
}
|
|
18919
|
-
const mediaId = idMatch[1];
|
|
18920
|
-
return { name: params.name, id: mediaId };
|
|
18921
|
-
} finally {
|
|
18922
|
-
cleanupTempFile(tempFilePath);
|
|
18906
|
+
await client.postTemporaryFile({
|
|
18907
|
+
Id: params.temporaryFileId,
|
|
18908
|
+
File: data,
|
|
18909
|
+
FileName: filename
|
|
18910
|
+
});
|
|
18911
|
+
} catch (error) {
|
|
18912
|
+
const err = error;
|
|
18913
|
+
const errorData = err.response?.data ? typeof err.response.data === "string" ? err.response.data : JSON.stringify(err.response.data) : err.message;
|
|
18914
|
+
throw new Error(`Failed to upload temporary file: ${err.response?.status || "Unknown error"} - ${errorData}`);
|
|
18923
18915
|
}
|
|
18916
|
+
const valueStructure = buildValueStructure(validatedMediaTypeName, params.temporaryFileId);
|
|
18917
|
+
let response;
|
|
18918
|
+
try {
|
|
18919
|
+
response = await client.postMedia({
|
|
18920
|
+
mediaType: { id: mediaTypeId },
|
|
18921
|
+
variants: [
|
|
18922
|
+
{
|
|
18923
|
+
culture: null,
|
|
18924
|
+
segment: null,
|
|
18925
|
+
name: params.name
|
|
18926
|
+
// Use original name provided by user
|
|
18927
|
+
}
|
|
18928
|
+
],
|
|
18929
|
+
values: [valueStructure],
|
|
18930
|
+
parent: params.parentId ? { id: params.parentId } : null
|
|
18931
|
+
}, CAPTURE_RAW_HTTP_RESPONSE146);
|
|
18932
|
+
} catch (error) {
|
|
18933
|
+
const err = error;
|
|
18934
|
+
throw new Error(`Failed to create media item: ${err.response?.status || "Unknown error"} - ${JSON.stringify(err.response?.data) || err.message}`);
|
|
18935
|
+
}
|
|
18936
|
+
if (response.status < 200 || response.status >= 300) {
|
|
18937
|
+
throw new Error(`Request failed with status code ${response.status}`);
|
|
18938
|
+
}
|
|
18939
|
+
const locationHeader = response.headers?.location || response.headers?.Location;
|
|
18940
|
+
if (!locationHeader) {
|
|
18941
|
+
throw new Error("No Location header in response - cannot determine created media ID");
|
|
18942
|
+
}
|
|
18943
|
+
const idMatch = locationHeader.match(/\/([a-f0-9-]{36})$/i);
|
|
18944
|
+
if (!idMatch) {
|
|
18945
|
+
throw new Error(`Could not extract ID from Location header: ${locationHeader}`);
|
|
18946
|
+
}
|
|
18947
|
+
const mediaId = idMatch[1];
|
|
18948
|
+
return { name: params.name, id: mediaId };
|
|
18949
|
+
}
|
|
18950
|
+
|
|
18951
|
+
// src/umb-management-api/tools/media/post/helpers/source-type-helpers.ts
|
|
18952
|
+
var FILE_PATH_ENTRY = `filePath - Most efficient for local files, works with any size
|
|
18953
|
+
SECURITY: Requires UMBRACO_ALLOWED_MEDIA_PATHS environment variable
|
|
18954
|
+
to be configured with comma-separated allowed directories.
|
|
18955
|
+
Example: UMBRACO_ALLOWED_MEDIA_PATHS="/tmp/uploads,/var/media"`;
|
|
18956
|
+
function buildSourceTypeSection(allowFilePath, otherSources) {
|
|
18957
|
+
const sources = allowFilePath ? [FILE_PATH_ENTRY, ...otherSources] : otherSources;
|
|
18958
|
+
return sources.map((s, i) => ` ${i + 1}. ${s}`).join("\n");
|
|
18924
18959
|
}
|
|
18925
18960
|
|
|
18926
18961
|
// src/umb-management-api/tools/media/post/create-media.ts
|
|
@@ -18935,23 +18970,30 @@ import {
|
|
|
18935
18970
|
MEDIA_TYPE_VIDEO,
|
|
18936
18971
|
withStandardDecorators as withStandardDecorators160
|
|
18937
18972
|
} from "@umbraco-cms/mcp-server-sdk";
|
|
18938
|
-
var createMediaSchema = z71.object({
|
|
18939
|
-
sourceType: z71.enum(["filePath", "url", "base64"]).describe("Media source type: 'filePath' for local files (most efficient), 'url' for web files, 'base64' for embedded data (small files only)"),
|
|
18940
|
-
name: z71.string().describe("The name of the media item"),
|
|
18941
|
-
mediaTypeName: z71.string().describe(`Media type: '${MEDIA_TYPE_IMAGE2}', '${MEDIA_TYPE_ARTICLE}', '${MEDIA_TYPE_AUDIO}', '${MEDIA_TYPE_VIDEO}', '${MEDIA_TYPE_VECTOR_GRAPHICS2}', '${MEDIA_TYPE_FILE}', or custom media type name`),
|
|
18942
|
-
filePath: z71.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
|
|
18943
|
-
fileUrl: z71.string().url().optional().describe("[raw] URL to fetch the file from (required if sourceType is 'url')"),
|
|
18944
|
-
fileAsBase64: z71.string().optional().describe("Base64 encoded file data (required if sourceType is 'base64')"),
|
|
18945
|
-
parentId: z71.string().uuid().optional().describe("Parent folder ID (defaults to root)")
|
|
18946
|
-
});
|
|
18947
18973
|
var createMediaOutputSchema = z71.object({
|
|
18948
18974
|
message: z71.string(),
|
|
18949
18975
|
name: z71.string(),
|
|
18950
18976
|
id: z71.string().guid()
|
|
18951
18977
|
});
|
|
18952
|
-
|
|
18953
|
-
|
|
18954
|
-
|
|
18978
|
+
function createCreateMediaTool(options) {
|
|
18979
|
+
const sourceTypeValues = options.allowFilePath ? ["filePath", "url", "base64"] : ["url", "base64"];
|
|
18980
|
+
const sourceTypeDescription = options.allowFilePath ? "Media source type: 'filePath' for local files (most efficient), 'url' for web files, 'base64' for embedded data (small files only)" : "Media source type: 'url' for web files, 'base64' for embedded data (small files only)";
|
|
18981
|
+
const schema = z71.object({
|
|
18982
|
+
sourceType: z71.enum(sourceTypeValues).describe(sourceTypeDescription),
|
|
18983
|
+
name: z71.string().describe("The name of the media item"),
|
|
18984
|
+
mediaTypeName: z71.string().describe(`Media type: '${MEDIA_TYPE_IMAGE2}', '${MEDIA_TYPE_ARTICLE}', '${MEDIA_TYPE_AUDIO}', '${MEDIA_TYPE_VIDEO}', '${MEDIA_TYPE_VECTOR_GRAPHICS2}', '${MEDIA_TYPE_FILE}', or custom media type name`),
|
|
18985
|
+
filePath: z71.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
|
|
18986
|
+
fileUrl: z71.string().url().optional().describe("[raw] URL to fetch the file from (required if sourceType is 'url')"),
|
|
18987
|
+
fileAsBase64: z71.string().optional().describe("Base64 encoded file data (required if sourceType is 'base64')"),
|
|
18988
|
+
parentId: z71.string().uuid().optional().describe("Parent folder ID (defaults to root)")
|
|
18989
|
+
});
|
|
18990
|
+
const filePathSection = buildSourceTypeSection(options.allowFilePath, [
|
|
18991
|
+
"url - Fetch from web URL",
|
|
18992
|
+
"base64 - Only for small files (<10KB) due to token usage"
|
|
18993
|
+
]);
|
|
18994
|
+
const tool = {
|
|
18995
|
+
name: "create-media",
|
|
18996
|
+
description: `Upload any media file to Umbraco (images, documents, audio, video, SVG, or custom types).
|
|
18955
18997
|
|
|
18956
18998
|
Media Types:
|
|
18957
18999
|
- ${MEDIA_TYPE_IMAGE2}: jpg, png, gif, webp, etc. (supports cropping)
|
|
@@ -18963,48 +19005,45 @@ var CreateMediaTool = {
|
|
|
18963
19005
|
- Custom: any custom media type created in Umbraco
|
|
18964
19006
|
|
|
18965
19007
|
Source Types:
|
|
18966
|
-
|
|
18967
|
-
SECURITY: Requires UMBRACO_ALLOWED_MEDIA_PATHS environment variable
|
|
18968
|
-
to be configured with comma-separated allowed directories.
|
|
18969
|
-
Example: UMBRACO_ALLOWED_MEDIA_PATHS="/tmp/uploads,/var/media"
|
|
18970
|
-
2. url - Fetch from web URL
|
|
18971
|
-
3. base64 - Only for small files (<10KB) due to token usage
|
|
19008
|
+
${filePathSection}
|
|
18972
19009
|
|
|
18973
19010
|
The tool automatically:
|
|
18974
19011
|
- Creates temporary files
|
|
18975
19012
|
- Detects and validates media types (auto-corrects SVG vs Image)
|
|
18976
19013
|
- Configures correct property editors (ImageCropper vs UploadField)
|
|
18977
19014
|
- Cleans up temporary files`,
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
|
|
18995
|
-
|
|
18996
|
-
|
|
18997
|
-
|
|
18998
|
-
|
|
18999
|
-
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
};
|
|
19007
|
-
|
|
19015
|
+
inputSchema: schema.shape,
|
|
19016
|
+
outputSchema: createMediaOutputSchema.shape,
|
|
19017
|
+
slices: ["create"],
|
|
19018
|
+
handler: (async (model) => {
|
|
19019
|
+
try {
|
|
19020
|
+
const client = UmbracoManagementClient3.getClient();
|
|
19021
|
+
const temporaryFileId = uuidv46();
|
|
19022
|
+
const { name: actualName, id } = await uploadMediaFile(client, {
|
|
19023
|
+
sourceType: model.sourceType,
|
|
19024
|
+
name: model.name,
|
|
19025
|
+
mediaTypeName: model.mediaTypeName,
|
|
19026
|
+
filePath: model.filePath,
|
|
19027
|
+
fileUrl: model.fileUrl,
|
|
19028
|
+
fileAsBase64: model.fileAsBase64,
|
|
19029
|
+
parentId: model.parentId,
|
|
19030
|
+
temporaryFileId
|
|
19031
|
+
});
|
|
19032
|
+
return createToolResult20({
|
|
19033
|
+
message: `Media "${actualName}" created successfully`,
|
|
19034
|
+
name: actualName,
|
|
19035
|
+
id
|
|
19036
|
+
});
|
|
19037
|
+
} catch (error) {
|
|
19038
|
+
return createToolResultError10({
|
|
19039
|
+
detail: `Error creating media: ${error.message}`
|
|
19040
|
+
});
|
|
19041
|
+
}
|
|
19042
|
+
})
|
|
19043
|
+
};
|
|
19044
|
+
return withStandardDecorators160(tool);
|
|
19045
|
+
}
|
|
19046
|
+
var create_media_default = createCreateMediaTool({ allowFilePath: true });
|
|
19008
19047
|
|
|
19009
19048
|
// src/umb-management-api/tools/media/post/create-media-multiple.ts
|
|
19010
19049
|
import { z as z72 } from "zod";
|
|
@@ -19020,16 +19059,6 @@ import {
|
|
|
19020
19059
|
MEDIA_TYPE_VIDEO as MEDIA_TYPE_VIDEO2,
|
|
19021
19060
|
withStandardDecorators as withStandardDecorators161
|
|
19022
19061
|
} from "@umbraco-cms/mcp-server-sdk";
|
|
19023
|
-
var createMediaMultipleSchema = z72.object({
|
|
19024
|
-
sourceType: z72.enum(["filePath", "url"]).describe("Media source type: 'filePath' for local files (most efficient), 'url' for web files. Base64 not supported for batch uploads due to token usage."),
|
|
19025
|
-
files: z72.array(z72.object({
|
|
19026
|
-
name: z72.string().describe("The name of the media item"),
|
|
19027
|
-
filePath: z72.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
|
|
19028
|
-
fileUrl: z72.string().url().optional().describe("URL to fetch the file from (required if sourceType is 'url')"),
|
|
19029
|
-
mediaTypeName: z72.string().optional().describe(`Optional override: '${MEDIA_TYPE_IMAGE3}', '${MEDIA_TYPE_ARTICLE2}', '${MEDIA_TYPE_AUDIO2}', '${MEDIA_TYPE_VIDEO2}', '${MEDIA_TYPE_VECTOR_GRAPHICS3}', '${MEDIA_TYPE_FILE2}', or custom media type name. If not specified, defaults to '${MEDIA_TYPE_FILE2}'`)
|
|
19030
|
-
})).describe("Array of files to upload (maximum 20 files per batch)"),
|
|
19031
|
-
parentId: z72.string().uuid().optional().describe("Parent folder ID (defaults to root)")
|
|
19032
|
-
});
|
|
19033
19062
|
var createMediaMultipleOutputSchema = z72.object({
|
|
19034
19063
|
summary: z72.string(),
|
|
19035
19064
|
results: z72.array(z72.object({
|
|
@@ -19039,70 +19068,84 @@ var createMediaMultipleOutputSchema = z72.object({
|
|
|
19039
19068
|
error: z72.string().optional()
|
|
19040
19069
|
}))
|
|
19041
19070
|
});
|
|
19042
|
-
|
|
19043
|
-
|
|
19044
|
-
|
|
19071
|
+
function createCreateMediaMultipleTool(options) {
|
|
19072
|
+
const sourceTypeValues = options.allowFilePath ? ["filePath", "url"] : ["url"];
|
|
19073
|
+
const sourceTypeDescription = options.allowFilePath ? "Media source type: 'filePath' for local files (most efficient), 'url' for web files. Base64 not supported for batch uploads due to token usage." : "Media source type: 'url' for web files. Base64 not supported for batch uploads due to token usage.";
|
|
19074
|
+
const schema = z72.object({
|
|
19075
|
+
sourceType: z72.enum(sourceTypeValues).describe(sourceTypeDescription),
|
|
19076
|
+
files: z72.array(z72.object({
|
|
19077
|
+
name: z72.string().describe("The name of the media item"),
|
|
19078
|
+
filePath: z72.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
|
|
19079
|
+
fileUrl: z72.string().url().optional().describe("URL to fetch the file from (required if sourceType is 'url')"),
|
|
19080
|
+
mediaTypeName: z72.string().optional().describe(`Optional override: '${MEDIA_TYPE_IMAGE3}', '${MEDIA_TYPE_ARTICLE2}', '${MEDIA_TYPE_AUDIO2}', '${MEDIA_TYPE_VIDEO2}', '${MEDIA_TYPE_VECTOR_GRAPHICS3}', '${MEDIA_TYPE_FILE2}', or custom media type name. If not specified, defaults to '${MEDIA_TYPE_FILE2}'`)
|
|
19081
|
+
})).describe("Array of files to upload (maximum 20 files per batch)"),
|
|
19082
|
+
parentId: z72.string().uuid().optional().describe("Parent folder ID (defaults to root)")
|
|
19083
|
+
});
|
|
19084
|
+
const filePathSection = buildSourceTypeSection(options.allowFilePath, [
|
|
19085
|
+
"url - Fetch from web URL"
|
|
19086
|
+
]);
|
|
19087
|
+
const tool = {
|
|
19088
|
+
name: "create-media-multiple",
|
|
19089
|
+
description: `Batch upload multiple media files to Umbraco (maximum 20 files per batch).
|
|
19045
19090
|
|
|
19046
19091
|
Supports any file type: images, documents, audio, video, SVG, or custom types.
|
|
19047
19092
|
|
|
19048
19093
|
Source Types:
|
|
19049
|
-
|
|
19050
|
-
SECURITY: Requires UMBRACO_ALLOWED_MEDIA_PATHS environment variable
|
|
19051
|
-
to be configured with comma-separated allowed directories.
|
|
19052
|
-
Example: UMBRACO_ALLOWED_MEDIA_PATHS="/tmp/uploads,/var/media"
|
|
19053
|
-
2. url - Fetch from web URL
|
|
19094
|
+
${filePathSection}
|
|
19054
19095
|
|
|
19055
19096
|
Note: base64 is not supported for batch uploads due to token usage.
|
|
19056
19097
|
|
|
19057
19098
|
The tool processes files sequentially and returns detailed results for each file.
|
|
19058
19099
|
If some files fail, others will continue processing (continue-on-error strategy).`,
|
|
19059
|
-
|
|
19060
|
-
|
|
19061
|
-
|
|
19062
|
-
|
|
19063
|
-
|
|
19064
|
-
|
|
19065
|
-
|
|
19066
|
-
});
|
|
19067
|
-
}
|
|
19068
|
-
const results = [];
|
|
19069
|
-
const client = UmbracoManagementClient3.getClient();
|
|
19070
|
-
for (const file of model.files) {
|
|
19071
|
-
try {
|
|
19072
|
-
const temporaryFileId = uuidv47();
|
|
19073
|
-
const defaultMediaType = file.mediaTypeName || MEDIA_TYPE_FILE2;
|
|
19074
|
-
const { name: actualName, id: mediaId } = await uploadMediaFile(client, {
|
|
19075
|
-
sourceType: model.sourceType,
|
|
19076
|
-
name: file.name,
|
|
19077
|
-
mediaTypeName: defaultMediaType,
|
|
19078
|
-
filePath: file.filePath,
|
|
19079
|
-
fileUrl: file.fileUrl,
|
|
19080
|
-
fileAsBase64: void 0,
|
|
19081
|
-
parentId: model.parentId,
|
|
19082
|
-
temporaryFileId
|
|
19083
|
-
});
|
|
19084
|
-
results.push({
|
|
19085
|
-
success: true,
|
|
19086
|
-
name: actualName,
|
|
19087
|
-
id: mediaId
|
|
19088
|
-
});
|
|
19089
|
-
} catch (error) {
|
|
19090
|
-
results.push({
|
|
19091
|
-
success: false,
|
|
19092
|
-
name: file.name,
|
|
19093
|
-
error: error.message
|
|
19100
|
+
inputSchema: schema.shape,
|
|
19101
|
+
outputSchema: createMediaMultipleOutputSchema.shape,
|
|
19102
|
+
slices: ["create"],
|
|
19103
|
+
handler: (async (model) => {
|
|
19104
|
+
if (model.files.length > 20) {
|
|
19105
|
+
return createToolResultError11({
|
|
19106
|
+
detail: `Batch upload limited to 20 files per call. You provided ${model.files.length} files. Please split into multiple batches.`
|
|
19094
19107
|
});
|
|
19095
19108
|
}
|
|
19096
|
-
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19109
|
+
const results = [];
|
|
19110
|
+
const client = UmbracoManagementClient3.getClient();
|
|
19111
|
+
for (const file of model.files) {
|
|
19112
|
+
try {
|
|
19113
|
+
const temporaryFileId = uuidv47();
|
|
19114
|
+
const defaultMediaType = file.mediaTypeName || MEDIA_TYPE_FILE2;
|
|
19115
|
+
const { name: actualName, id: mediaId } = await uploadMediaFile(client, {
|
|
19116
|
+
sourceType: model.sourceType,
|
|
19117
|
+
name: file.name,
|
|
19118
|
+
mediaTypeName: defaultMediaType,
|
|
19119
|
+
filePath: file.filePath,
|
|
19120
|
+
fileUrl: file.fileUrl,
|
|
19121
|
+
fileAsBase64: void 0,
|
|
19122
|
+
parentId: model.parentId,
|
|
19123
|
+
temporaryFileId
|
|
19124
|
+
});
|
|
19125
|
+
results.push({
|
|
19126
|
+
success: true,
|
|
19127
|
+
name: actualName,
|
|
19128
|
+
id: mediaId
|
|
19129
|
+
});
|
|
19130
|
+
} catch (error) {
|
|
19131
|
+
results.push({
|
|
19132
|
+
success: false,
|
|
19133
|
+
name: file.name,
|
|
19134
|
+
error: error.message
|
|
19135
|
+
});
|
|
19136
|
+
}
|
|
19137
|
+
}
|
|
19138
|
+
const successCount = results.filter((r) => r.success).length;
|
|
19139
|
+
const failureCount = results.filter((r) => !r.success).length;
|
|
19140
|
+
return createToolResult21({
|
|
19141
|
+
summary: `Processed ${model.files.length} files: ${successCount} succeeded, ${failureCount} failed`,
|
|
19142
|
+
results
|
|
19143
|
+
});
|
|
19144
|
+
})
|
|
19145
|
+
};
|
|
19146
|
+
return withStandardDecorators161(tool);
|
|
19147
|
+
}
|
|
19148
|
+
var create_media_multiple_default = createCreateMediaMultipleTool({ allowFilePath: true });
|
|
19106
19149
|
|
|
19107
19150
|
// src/umb-management-api/tools/media/post/create-media-folder.ts
|
|
19108
19151
|
import { z as z73 } from "zod";
|
|
@@ -19921,8 +19964,9 @@ var MediaCollection = {
|
|
|
19921
19964
|
tools.push(get_root_default6);
|
|
19922
19965
|
}
|
|
19923
19966
|
if (AuthorizationPolicies.SectionAccessMedia(user)) {
|
|
19924
|
-
|
|
19925
|
-
tools.push(
|
|
19967
|
+
const allowFilePath = isFilePathUploadAllowed();
|
|
19968
|
+
tools.push(createCreateMediaTool({ allowFilePath }));
|
|
19969
|
+
tools.push(createCreateMediaMultipleTool({ allowFilePath }));
|
|
19926
19970
|
tools.push(create_media_folder_default);
|
|
19927
19971
|
tools.push(delete_media_default);
|
|
19928
19972
|
tools.push(update_media_default);
|
|
@@ -21941,9 +21985,9 @@ var GetPartialViewByPathTool = {
|
|
|
21941
21985
|
outputSchema: getPartialViewByPathResponse.shape,
|
|
21942
21986
|
annotations: { readOnlyHint: true },
|
|
21943
21987
|
slices: ["read"],
|
|
21944
|
-
handler: (async ({ path:
|
|
21988
|
+
handler: (async ({ path: path3 }) => {
|
|
21945
21989
|
return executeGetApiCall117(
|
|
21946
|
-
(client) => client.getPartialViewByPath(
|
|
21990
|
+
(client) => client.getPartialViewByPath(path3, CAPTURE_RAW_HTTP_RESPONSE235)
|
|
21947
21991
|
);
|
|
21948
21992
|
})
|
|
21949
21993
|
};
|
|
@@ -21962,9 +22006,9 @@ var GetPartialViewFolderByPathTool = {
|
|
|
21962
22006
|
outputSchema: getPartialViewFolderByPathResponse.shape,
|
|
21963
22007
|
annotations: { readOnlyHint: true },
|
|
21964
22008
|
slices: ["read", "folders"],
|
|
21965
|
-
handler: (async ({ path:
|
|
22009
|
+
handler: (async ({ path: path3 }) => {
|
|
21966
22010
|
return executeGetApiCall118(
|
|
21967
|
-
(client) => client.getPartialViewFolderByPath(
|
|
22011
|
+
(client) => client.getPartialViewFolderByPath(path3, CAPTURE_RAW_HTTP_RESPONSE236)
|
|
21968
22012
|
);
|
|
21969
22013
|
})
|
|
21970
22014
|
};
|
|
@@ -22039,9 +22083,9 @@ var DeletePartialViewTool = {
|
|
|
22039
22083
|
destructiveHint: true
|
|
22040
22084
|
},
|
|
22041
22085
|
slices: ["delete"],
|
|
22042
|
-
handler: (async ({ path:
|
|
22086
|
+
handler: (async ({ path: path3 }) => {
|
|
22043
22087
|
return executeVoidApiCall76(
|
|
22044
|
-
(client) => client.deletePartialViewByPath(
|
|
22088
|
+
(client) => client.deletePartialViewByPath(path3, CAPTURE_RAW_HTTP_RESPONSE239)
|
|
22045
22089
|
);
|
|
22046
22090
|
})
|
|
22047
22091
|
};
|
|
@@ -22061,9 +22105,9 @@ var DeletePartialViewFolderTool = {
|
|
|
22061
22105
|
destructiveHint: true
|
|
22062
22106
|
},
|
|
22063
22107
|
slices: ["delete", "folders"],
|
|
22064
|
-
handler: (async ({ path:
|
|
22108
|
+
handler: (async ({ path: path3 }) => {
|
|
22065
22109
|
return executeVoidApiCall77(
|
|
22066
|
-
(client) => client.deletePartialViewFolderByPath(
|
|
22110
|
+
(client) => client.deletePartialViewFolderByPath(path3, CAPTURE_RAW_HTTP_RESPONSE240)
|
|
22067
22111
|
);
|
|
22068
22112
|
})
|
|
22069
22113
|
};
|
|
@@ -22549,9 +22593,9 @@ var GetScriptByPathTool = {
|
|
|
22549
22593
|
outputSchema: getScriptByPathResponse.shape,
|
|
22550
22594
|
annotations: { readOnlyHint: true },
|
|
22551
22595
|
slices: ["read"],
|
|
22552
|
-
handler: (async ({ path:
|
|
22596
|
+
handler: (async ({ path: path3 }) => {
|
|
22553
22597
|
return executeGetApiCall130(
|
|
22554
|
-
(client) => client.getScriptByPath(
|
|
22598
|
+
(client) => client.getScriptByPath(path3, CAPTURE_RAW_HTTP_RESPONSE257)
|
|
22555
22599
|
);
|
|
22556
22600
|
})
|
|
22557
22601
|
};
|
|
@@ -22570,9 +22614,9 @@ var GetScriptFolderByPathTool = {
|
|
|
22570
22614
|
outputSchema: getScriptFolderByPathResponse.shape,
|
|
22571
22615
|
annotations: { readOnlyHint: true },
|
|
22572
22616
|
slices: ["read", "folders"],
|
|
22573
|
-
handler: (async ({ path:
|
|
22617
|
+
handler: (async ({ path: path3 }) => {
|
|
22574
22618
|
return executeGetApiCall131(
|
|
22575
|
-
(client) => client.getScriptFolderByPath(
|
|
22619
|
+
(client) => client.getScriptFolderByPath(path3, CAPTURE_RAW_HTTP_RESPONSE258)
|
|
22576
22620
|
);
|
|
22577
22621
|
})
|
|
22578
22622
|
};
|
|
@@ -22870,9 +22914,9 @@ var DeleteScriptTool = {
|
|
|
22870
22914
|
destructiveHint: true
|
|
22871
22915
|
},
|
|
22872
22916
|
slices: ["delete"],
|
|
22873
|
-
handler: (async ({ path:
|
|
22917
|
+
handler: (async ({ path: path3 }) => {
|
|
22874
22918
|
return executeVoidApiCall82(
|
|
22875
|
-
(client) => client.deleteScriptByPath(
|
|
22919
|
+
(client) => client.deleteScriptByPath(path3, CAPTURE_RAW_HTTP_RESPONSE266)
|
|
22876
22920
|
);
|
|
22877
22921
|
})
|
|
22878
22922
|
};
|
|
@@ -22892,9 +22936,9 @@ var DeleteScriptFolderTool = {
|
|
|
22892
22936
|
destructiveHint: true
|
|
22893
22937
|
},
|
|
22894
22938
|
slices: ["delete", "folders"],
|
|
22895
|
-
handler: (async ({ path:
|
|
22939
|
+
handler: (async ({ path: path3 }) => {
|
|
22896
22940
|
return executeVoidApiCall83(
|
|
22897
|
-
(client) => client.deleteScriptFolderByPath(
|
|
22941
|
+
(client) => client.deleteScriptFolderByPath(path3, CAPTURE_RAW_HTTP_RESPONSE267)
|
|
22898
22942
|
);
|
|
22899
22943
|
})
|
|
22900
22944
|
};
|
|
@@ -23502,9 +23546,9 @@ var UpdateStylesheetTool = {
|
|
|
23502
23546
|
annotations: { idempotentHint: true },
|
|
23503
23547
|
slices: ["update"],
|
|
23504
23548
|
handler: (async (model) => {
|
|
23505
|
-
const { path:
|
|
23549
|
+
const { path: path3, ...updateModel } = model;
|
|
23506
23550
|
return executeVoidApiCall84(
|
|
23507
|
-
(client) => client.putStylesheetByPath(
|
|
23551
|
+
(client) => client.putStylesheetByPath(path3, updateModel, CAPTURE_RAW_HTTP_RESPONSE281)
|
|
23508
23552
|
);
|
|
23509
23553
|
})
|
|
23510
23554
|
};
|
|
@@ -23528,8 +23572,8 @@ var RenameStylesheetTool = {
|
|
|
23528
23572
|
annotations: { idempotentHint: true },
|
|
23529
23573
|
slices: ["rename"],
|
|
23530
23574
|
handler: (async (model) => {
|
|
23531
|
-
const { path:
|
|
23532
|
-
const normalizedPath = encodeURIComponent(
|
|
23575
|
+
const { path: path3, ...renameModel } = model;
|
|
23576
|
+
const normalizedPath = encodeURIComponent(path3);
|
|
23533
23577
|
return executeVoidApiCall85(
|
|
23534
23578
|
(client) => client.putStylesheetByPathRename(normalizedPath, renameModel, CAPTURE_RAW_HTTP_RESPONSE282)
|
|
23535
23579
|
);
|
|
@@ -24140,9 +24184,6 @@ var TemplateCollection = {
|
|
|
24140
24184
|
|
|
24141
24185
|
// src/umb-management-api/tools/temporary-file/post/create-temporary-file.ts
|
|
24142
24186
|
import { z as z143 } from "zod";
|
|
24143
|
-
import * as fs3 from "fs";
|
|
24144
|
-
import * as os2 from "os";
|
|
24145
|
-
import * as path3 from "path";
|
|
24146
24187
|
import {
|
|
24147
24188
|
createToolResult as createToolResult42,
|
|
24148
24189
|
createToolResultError as createToolResultError27,
|
|
@@ -24171,7 +24212,6 @@ var CreateTemporaryFileTool = {
|
|
|
24171
24212
|
outputSchema: createTemporaryFileOutputSchema.shape,
|
|
24172
24213
|
slices: ["create"],
|
|
24173
24214
|
handler: (async (model) => {
|
|
24174
|
-
let tempFilePath = null;
|
|
24175
24215
|
try {
|
|
24176
24216
|
const fileContent = Buffer.from(model.fileAsBase64, "base64");
|
|
24177
24217
|
let fileName = model.fileName;
|
|
@@ -24179,13 +24219,11 @@ var CreateTemporaryFileTool = {
|
|
|
24179
24219
|
const extension = detectFileExtensionFromBuffer2(fileContent);
|
|
24180
24220
|
fileName = `${fileName}${extension}`;
|
|
24181
24221
|
}
|
|
24182
|
-
tempFilePath = path3.join(os2.tmpdir(), `umbraco-upload-${model.id}-${fileName}`);
|
|
24183
|
-
fs3.writeFileSync(tempFilePath, fileContent);
|
|
24184
|
-
const readStream = fs3.createReadStream(tempFilePath);
|
|
24185
24222
|
const client = UmbracoManagementClient3.getClient();
|
|
24186
24223
|
await client.postTemporaryFile({
|
|
24187
24224
|
Id: model.id,
|
|
24188
|
-
File:
|
|
24225
|
+
File: fileContent,
|
|
24226
|
+
FileName: fileName
|
|
24189
24227
|
});
|
|
24190
24228
|
return createToolResult42({
|
|
24191
24229
|
message: "Temporary file created successfully",
|
|
@@ -24195,14 +24233,6 @@ var CreateTemporaryFileTool = {
|
|
|
24195
24233
|
return createToolResultError27({
|
|
24196
24234
|
detail: `Error creating temporary file: ${error.message}`
|
|
24197
24235
|
});
|
|
24198
|
-
} finally {
|
|
24199
|
-
if (tempFilePath && fs3.existsSync(tempFilePath)) {
|
|
24200
|
-
try {
|
|
24201
|
-
fs3.unlinkSync(tempFilePath);
|
|
24202
|
-
} catch (e) {
|
|
24203
|
-
console.error("Failed to cleanup temp file:", e);
|
|
24204
|
-
}
|
|
24205
|
-
}
|
|
24206
24236
|
}
|
|
24207
24237
|
})
|
|
24208
24238
|
};
|
|
@@ -24213,14 +24243,15 @@ import { ReadStream } from "fs";
|
|
|
24213
24243
|
import { z as zod2 } from "zod";
|
|
24214
24244
|
var postTemporaryFileBody = zod2.object({
|
|
24215
24245
|
Id: zod2.string().uuid(),
|
|
24216
|
-
File: zod2.instanceof(ReadStream)
|
|
24246
|
+
File: zod2.union([zod2.instanceof(Buffer), zod2.instanceof(ReadStream)]),
|
|
24247
|
+
FileName: zod2.string().min(1)
|
|
24217
24248
|
});
|
|
24218
24249
|
var getTemporaryFileByIdParams = zod2.object({
|
|
24219
24250
|
id: zod2.string().uuid()
|
|
24220
24251
|
});
|
|
24221
24252
|
var getTemporaryFileByIdResponse = zod2.object({
|
|
24222
24253
|
id: zod2.string().guid(),
|
|
24223
|
-
availableUntil: zod2.string().datetime({ local: true }).nullish(),
|
|
24254
|
+
availableUntil: zod2.string().datetime({ local: true, offset: true }).nullish(),
|
|
24224
24255
|
fileName: zod2.string().min(1)
|
|
24225
24256
|
});
|
|
24226
24257
|
var deleteTemporaryFileByIdParams = zod2.object({
|
|
@@ -25470,10 +25501,11 @@ export {
|
|
|
25470
25501
|
__commonJS,
|
|
25471
25502
|
__toESM,
|
|
25472
25503
|
UmbracoManagementClient3 as UmbracoManagementClient,
|
|
25504
|
+
setAllowFilePathUploads,
|
|
25473
25505
|
setUmbracoVersion,
|
|
25474
25506
|
availableCollections,
|
|
25475
25507
|
allModes,
|
|
25476
25508
|
allModeNames,
|
|
25477
25509
|
allSliceNames
|
|
25478
25510
|
};
|
|
25479
|
-
//# sourceMappingURL=chunk-
|
|
25511
|
+
//# sourceMappingURL=chunk-XVBYRUFE.js.map
|