@umbraco-cms/mcp-dev 17.4.0 → 17.4.2

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.
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;var __create = Object.create;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;var __create = Object.create;
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -3002,28 +3002,28 @@ var getUmbracoManagementAPI = () => {
3002
3002
  options
3003
3003
  );
3004
3004
  };
3005
- const getPartialViewByPath = (path4, options) => {
3005
+ const getPartialViewByPath = (path3, options) => {
3006
3006
  return UmbracoManagementClient(
3007
3007
  {
3008
- url: `/umbraco/management/api/v1/partial-view/${path4}`,
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 = (path4, options) => {
3014
+ const deletePartialViewByPath = (path3, options) => {
3015
3015
  return UmbracoManagementClient(
3016
3016
  {
3017
- url: `/umbraco/management/api/v1/partial-view/${path4}`,
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 = (path4, updatePartialViewRequestModel, options) => {
3023
+ const putPartialViewByPath = (path3, updatePartialViewRequestModel, options) => {
3024
3024
  return UmbracoManagementClient(
3025
3025
  {
3026
- url: `/umbraco/management/api/v1/partial-view/${path4}`,
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 = (path4, renamePartialViewRequestModel, options) => {
3034
+ const putPartialViewByPathRename = (path3, renamePartialViewRequestModel, options) => {
3035
3035
  return UmbracoManagementClient(
3036
3036
  {
3037
- url: `/umbraco/management/api/v1/partial-view/${path4}/rename`,
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 = (path4, options) => {
3056
+ const getPartialViewFolderByPath = (path3, options) => {
3057
3057
  return UmbracoManagementClient(
3058
3058
  {
3059
- url: `/umbraco/management/api/v1/partial-view/folder/${path4}`,
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 = (path4, options) => {
3065
+ const deletePartialViewFolderByPath = (path3, options) => {
3066
3066
  return UmbracoManagementClient(
3067
3067
  {
3068
- url: `/umbraco/management/api/v1/partial-view/folder/${path4}`,
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 = (path4, options) => {
3316
+ const getScriptByPath = (path3, options) => {
3317
3317
  return UmbracoManagementClient(
3318
3318
  {
3319
- url: `/umbraco/management/api/v1/script/${path4}`,
3319
+ url: `/umbraco/management/api/v1/script/${path3}`,
3320
3320
  method: "GET"
3321
3321
  },
3322
3322
  options
3323
3323
  );
3324
3324
  };
3325
- const deleteScriptByPath = (path4, options) => {
3325
+ const deleteScriptByPath = (path3, options) => {
3326
3326
  return UmbracoManagementClient(
3327
3327
  {
3328
- url: `/umbraco/management/api/v1/script/${path4}`,
3328
+ url: `/umbraco/management/api/v1/script/${path3}`,
3329
3329
  method: "DELETE"
3330
3330
  },
3331
3331
  options
3332
3332
  );
3333
3333
  };
3334
- const putScriptByPath = (path4, updateScriptRequestModel, options) => {
3334
+ const putScriptByPath = (path3, updateScriptRequestModel, options) => {
3335
3335
  return UmbracoManagementClient(
3336
3336
  {
3337
- url: `/umbraco/management/api/v1/script/${path4}`,
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 = (path4, renameScriptRequestModel, options) => {
3345
+ const putScriptByPathRename = (path3, renameScriptRequestModel, options) => {
3346
3346
  return UmbracoManagementClient(
3347
3347
  {
3348
- url: `/umbraco/management/api/v1/script/${path4}/rename`,
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 = (path4, options) => {
3367
+ const getScriptFolderByPath = (path3, options) => {
3368
3368
  return UmbracoManagementClient(
3369
3369
  {
3370
- url: `/umbraco/management/api/v1/script/folder/${path4}`,
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 = (path4, options) => {
3376
+ const deleteScriptFolderByPath = (path3, options) => {
3377
3377
  return UmbracoManagementClient(
3378
3378
  {
3379
- url: `/umbraco/management/api/v1/script/folder/${path4}`,
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 = (path4, options) => {
3603
+ const getStylesheetByPath = (path3, options) => {
3604
3604
  return UmbracoManagementClient(
3605
3605
  {
3606
- url: `/umbraco/management/api/v1/stylesheet/${path4}`,
3606
+ url: `/umbraco/management/api/v1/stylesheet/${path3}`,
3607
3607
  method: "GET"
3608
3608
  },
3609
3609
  options
3610
3610
  );
3611
3611
  };
3612
- const deleteStylesheetByPath = (path4, options) => {
3612
+ const deleteStylesheetByPath = (path3, options) => {
3613
3613
  return UmbracoManagementClient(
3614
3614
  {
3615
- url: `/umbraco/management/api/v1/stylesheet/${path4}`,
3615
+ url: `/umbraco/management/api/v1/stylesheet/${path3}`,
3616
3616
  method: "DELETE"
3617
3617
  },
3618
3618
  options
3619
3619
  );
3620
3620
  };
3621
- const putStylesheetByPath = (path4, updateStylesheetRequestModel, options) => {
3621
+ const putStylesheetByPath = (path3, updateStylesheetRequestModel, options) => {
3622
3622
  return UmbracoManagementClient(
3623
3623
  {
3624
- url: `/umbraco/management/api/v1/stylesheet/${path4}`,
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 = (path4, renameStylesheetRequestModel, options) => {
3632
+ const putStylesheetByPathRename = (path3, renameStylesheetRequestModel, options) => {
3633
3633
  return UmbracoManagementClient(
3634
3634
  {
3635
- url: `/umbraco/management/api/v1/stylesheet/${path4}/rename`,
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 = (path4, options) => {
3654
+ const getStylesheetFolderByPath = (path3, options) => {
3655
3655
  return UmbracoManagementClient(
3656
3656
  {
3657
- url: `/umbraco/management/api/v1/stylesheet/folder/${path4}`,
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 = (path4, options) => {
3663
+ const deleteStylesheetFolderByPath = (path3, options) => {
3664
3664
  return UmbracoManagementClient(
3665
3665
  {
3666
- url: `/umbraco/management/api/v1/stylesheet/folder/${path4}`,
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
 
4549
- var _formdata = require('form-data'); var _formdata2 = _interopRequireDefault(_formdata);
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) => {
4552
- const formData = new (0, _formdata2.default)();
4557
+ postTemporaryFile: async (postTemporaryFileBody2, options) => {
4558
+ const formData = new FormData();
4553
4559
  formData.append("Id", postTemporaryFileBody2.Id);
4554
- formData.append("File", postTemporaryFileBody2.File);
4555
- const headers = {
4556
- ...formData.getHeaders(),
4557
- ..._optionalChain([options, 'optionalAccess', _ => _.headers])
4558
- };
4560
+ const file = postTemporaryFileBody2.File;
4561
+ console.log("[temp-file] incoming file:", {
4562
+ typeofFile: typeof file,
4563
+ isBuffer: Buffer.isBuffer(file),
4564
+ ctorName: _optionalChain([file, 'optionalAccess', _ => _.constructor, 'optionalAccess', _2 => _2.name]),
4565
+ hasByteLength: typeof _optionalChain([file, 'optionalAccess', _3 => _3.byteLength]),
4566
+ hasLength: typeof _optionalChain([file, 'optionalAccess', _4 => _4.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" : _nullishCoalesce(_optionalChain([v, 'optionalAccess', _5 => _5.constructor, 'optionalAccess', _6 => _6.name]), () => ( typeof v)),
4581
+ valueSize: typeof v === "string" ? v.length : _nullishCoalesce(_optionalChain([v, 'optionalAccess', _7 => _7.size]), () => ( void 0))
4582
+ });
4583
+ }
4584
+ console.log("[temp-file] formData entries:", entries);
4559
4585
  return _mcpserversdk.UmbracoManagementClient.call(void 0,
4560
4586
  {
4561
4587
  url: `/umbraco/management/api/v1/temporary-file`,
4562
4588
  method: "POST",
4563
- headers,
4589
+ headers: _optionalChain([options, 'optionalAccess', _8 => _8.headers]),
4564
4590
  data: formData
4565
4591
  },
4566
4592
  options
@@ -4610,6 +4636,13 @@ var UmbracoManagementClient3 = (_class = 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 = _nullishCoalesce(version, () => ( null));
4615
4648
  }
@@ -12518,7 +12551,7 @@ async function synthesizeDataTypeSchema(id) {
12518
12551
  const client = UmbracoManagementClient3.getClient();
12519
12552
  const dataType = await client.getDataTypeById(id);
12520
12553
  const template = findTemplateByEditorAlias(dataType.editorAlias);
12521
- const valueTypeName = _nullishCoalesce(VALUE_TYPE_BY_EDITOR_ALIAS[dataType.editorAlias], () => ( (_optionalChain([template, 'optionalAccess', _2 => _2.value]) !== void 0 ? "JSON" : null)));
12554
+ const valueTypeName = _nullishCoalesce(VALUE_TYPE_BY_EDITOR_ALIAS[dataType.editorAlias], () => ( (_optionalChain([template, 'optionalAccess', _9 => _9.value]) !== void 0 ? "JSON" : null)));
12522
12555
  const jsonSchema = {
12523
12556
  $schema: "https://json-schema.org/draft/2020-12/schema",
12524
12557
  title: dataType.name,
@@ -12526,8 +12559,8 @@ async function synthesizeDataTypeSchema(id) {
12526
12559
  dataTypeId: dataType.id,
12527
12560
  editorAlias: dataType.editorAlias,
12528
12561
  editorUiAlias: dataType.editorUiAlias,
12529
- example: _optionalChain([template, 'optionalAccess', _3 => _3.value]),
12530
- notes: _optionalChain([template, 'optionalAccess', _4 => _4._notes])
12562
+ example: _optionalChain([template, 'optionalAccess', _10 => _10.value]),
12563
+ notes: _optionalChain([template, 'optionalAccess', _11 => _11._notes])
12531
12564
  };
12532
12565
  return { valueTypeName, jsonSchema };
12533
12566
  }
@@ -12648,7 +12681,7 @@ var CopyDataTypeTool = {
12648
12681
  validateStatus: () => true
12649
12682
  });
12650
12683
  if (response.status === 201) {
12651
- const location = _optionalChain([response, 'access', _5 => _5.headers, 'optionalAccess', _6 => _6.location]) || "";
12684
+ const location = _optionalChain([response, 'access', _12 => _12.headers, 'optionalAccess', _13 => _13.location]) || "";
12652
12685
  const newId = location.split("/").pop() || "";
12653
12686
  const output = {
12654
12687
  message: "Data type copied successfully",
@@ -13289,7 +13322,7 @@ var CreateDictionaryItemTool = {
13289
13322
  validateStatus: () => true
13290
13323
  });
13291
13324
  if (response.status === 201) {
13292
- const locationHeader = _optionalChain([response, 'access', _7 => _7.headers, 'optionalAccess', _8 => _8["location"]]) || _optionalChain([response, 'access', _9 => _9.headers, 'optionalAccess', _10 => _10["Location"]]);
13325
+ const locationHeader = _optionalChain([response, 'access', _14 => _14.headers, 'optionalAccess', _15 => _15["location"]]) || _optionalChain([response, 'access', _16 => _16.headers, 'optionalAccess', _17 => _17["Location"]]);
13293
13326
  let createdId = model.id || "";
13294
13327
  if (locationHeader) {
13295
13328
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -14246,8 +14279,8 @@ function buildPropertyEntry(prop, dataType, template) {
14246
14279
  editorAlias: dataType.editorAlias,
14247
14280
  dataTypeId: dataType.id,
14248
14281
  dataTypeName: dataType.name,
14249
- example: _optionalChain([template, 'optionalAccess', _11 => _11.value]),
14250
- notes: _optionalChain([template, 'optionalAccess', _12 => _12._notes])
14282
+ example: _optionalChain([template, 'optionalAccess', _18 => _18.value]),
14283
+ notes: _optionalChain([template, 'optionalAccess', _19 => _19._notes])
14251
14284
  };
14252
14285
  }
14253
14286
  async function synthesizeDocumentTypeSchema(id) {
@@ -14649,7 +14682,7 @@ var CopyDocumentTool = {
14649
14682
  validateStatus: () => true
14650
14683
  });
14651
14684
  if (response.status === 201) {
14652
- const location = _optionalChain([response, 'access', _13 => _13.headers, 'optionalAccess', _14 => _14.location]) || "";
14685
+ const location = _optionalChain([response, 'access', _20 => _20.headers, 'optionalAccess', _21 => _21.location]) || "";
14653
14686
  const newId = location.split("/").pop() || "";
14654
14687
  const output = { id: newId };
14655
14688
  return _mcpserversdk.createToolResult.call(void 0, output);
@@ -14793,7 +14826,7 @@ var CreateDocumentTool = {
14793
14826
  template = { id: model.templateId };
14794
14827
  } else {
14795
14828
  const docType = await client.getDocumentTypeById(model.documentTypeId);
14796
- template = _optionalChain([docType, 'access', _15 => _15.defaultTemplate, 'optionalAccess', _16 => _16.id]) ? { id: docType.defaultTemplate.id } : null;
14829
+ template = _optionalChain([docType, 'access', _22 => _22.defaultTemplate, 'optionalAccess', _23 => _23.id]) ? { id: docType.defaultTemplate.id } : null;
14797
14830
  }
14798
14831
  const payload = {
14799
14832
  id: documentId,
@@ -15572,7 +15605,7 @@ var UpdateDocumentPropertiesTool = {
15572
15605
  const docTypeProps = await getDocumentTypeProperties();
15573
15606
  const propsToValidate = allPropertiesToValidate.map((p) => {
15574
15607
  const def = docTypeProps.find((d) => d.alias === p.alias);
15575
- return { alias: p.alias, value: p.value, dataTypeId: _nullishCoalesce(_optionalChain([def, 'optionalAccess', _17 => _17.dataTypeId]), () => ( "")) };
15608
+ return { alias: p.alias, value: p.value, dataTypeId: _nullishCoalesce(_optionalChain([def, 'optionalAccess', _24 => _24.dataTypeId]), () => ( "")) };
15576
15609
  }).filter((p) => p.dataTypeId);
15577
15610
  if (propsToValidate.length > 0) {
15578
15611
  const valueValidation = await validatePropertiesBeforeSave(propsToValidate);
@@ -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, path4 = "root") {
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, `${path4}.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: path4
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 = `${path4}.contentData[${index}].values[${propIndex}](${prop.alias})`;
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 = `${path4}.settingsData[${index}].values[${propIndex}](${prop.alias})`;
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);
@@ -15865,7 +15898,7 @@ var UpdateBlockPropertyTool = {
15865
15898
  if (!isUmbracoAtLeast(17, 4) && elementTypeProperties.length > 0) {
15866
15899
  const propsToValidate = update.properties.map((p) => {
15867
15900
  const def = elementTypeProperties.find((d) => d.alias === p.alias);
15868
- return { alias: p.alias, value: p.value, dataTypeId: _nullishCoalesce(_optionalChain([def, 'optionalAccess', _18 => _18.dataTypeId]), () => ( "")) };
15901
+ return { alias: p.alias, value: p.value, dataTypeId: _nullishCoalesce(_optionalChain([def, 'optionalAccess', _25 => _25.dataTypeId]), () => ( "")) };
15869
15902
  }).filter((p) => p.dataTypeId);
15870
15903
  if (propsToValidate.length > 0) {
15871
15904
  const valueValidation = await validatePropertiesBeforeSave(propsToValidate);
@@ -16525,7 +16558,7 @@ var CopyDocumentTypeTool = {
16525
16558
  validateStatus: () => true
16526
16559
  });
16527
16560
  if (response.status === 201) {
16528
- const location = _optionalChain([response, 'access', _19 => _19.headers, 'optionalAccess', _20 => _20.location]) || "";
16561
+ const location = _optionalChain([response, 'access', _26 => _26.headers, 'optionalAccess', _27 => _27.location]) || "";
16529
16562
  const newId = location.split("/").pop() || "";
16530
16563
  const output = { id: newId };
16531
16564
  return _mcpserversdk.createToolResult.call(void 0, output);
@@ -18658,17 +18691,15 @@ var ManifestCollection = {
18658
18691
 
18659
18692
 
18660
18693
  // src/umb-management-api/tools/media/post/helpers/media-upload-helpers.ts
18661
- var _fs = require('fs'); var fs2 = _interopRequireWildcard(_fs); var fs = _interopRequireWildcard(_fs); var fs3 = _interopRequireWildcard(_fs);
18662
- var _os = require('os'); var os = _interopRequireWildcard(_os); var os2 = _interopRequireWildcard(_os);
18663
- var _path = require('path'); var path2 = _interopRequireWildcard(_path); var path = _interopRequireWildcard(_path); var path3 = _interopRequireWildcard(_path);
18694
+ var _fs = require('fs'); var fs2 = _interopRequireWildcard(_fs); var fs = _interopRequireWildcard(_fs);
18695
+ var _path = require('path'); var path2 = _interopRequireWildcard(_path); var path = _interopRequireWildcard(_path);
18664
18696
  var _mimetypes = require('mime-types'); var _mimetypes2 = _interopRequireDefault(_mimetypes);
18665
18697
 
18666
18698
  // src/umb-management-api/tools/media/post/helpers/validate-file-path.ts
18667
18699
 
18668
18700
 
18669
-
18670
18701
  async function validateFilePath(filePath, allowedPaths) {
18671
- const allowedMediaPaths = await _asyncNullishCoalesce(allowedPaths, async () => ( (await _mcpserversdk.getServerConfig.call(void 0, true)).config.allowedMediaPaths));
18702
+ const allowedMediaPaths = _nullishCoalesce(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
- const realAllowedPath = fs.realpathSync(allowedPath);
18680
- return normalizedPath.startsWith(allowedPath) || normalizedPath.startsWith(realAllowedPath);
18710
+ if (normalizedPath.startsWith(allowedPath)) return true;
18711
+ try {
18712
+ const realAllowedPath = fs.realpathSync(allowedPath);
18713
+ return normalizedPath.startsWith(realAllowedPath);
18714
+ } catch (e2) {
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
- const realAllowedPath = fs.realpathSync(allowedPath);
18693
- return realPath.startsWith(allowedPath) || realPath.startsWith(realAllowedPath);
18728
+ if (realPath.startsWith(allowedPath)) return true;
18729
+ try {
18730
+ const realAllowedPath = fs.realpathSync(allowedPath);
18731
+ return realPath.startsWith(realAllowedPath);
18732
+ } catch (e3) {
18733
+ return false;
18734
+ }
18694
18735
  });
18695
18736
  if (!symlinkAllowed) {
18696
18737
  throw new Error(
@@ -18715,6 +18756,7 @@ async function validateFilePath(filePath, allowedPaths) {
18715
18756
 
18716
18757
 
18717
18758
 
18759
+ var BASE64_MAX_BYTES = 10 * 1024;
18718
18760
  function getExtensionFromMimeType(mimeType) {
18719
18761
  if (!mimeType) return void 0;
18720
18762
  const baseMimeType = mimeType.split(";")[0].trim();
@@ -18722,7 +18764,7 @@ function getExtensionFromMimeType(mimeType) {
18722
18764
  return extension ? `.${extension}` : void 0;
18723
18765
  }
18724
18766
  function validateMediaTypeForSvg(filePath, fileUrl, fileName, mediaTypeName) {
18725
- const isSvg = _optionalChain([filePath, 'optionalAccess', _21 => _21.toLowerCase, 'call', _22 => _22(), 'access', _23 => _23.endsWith, 'call', _24 => _24(".svg")]) || _optionalChain([fileUrl, 'optionalAccess', _25 => _25.toLowerCase, 'call', _26 => _26(), 'access', _27 => _27.endsWith, 'call', _28 => _28(".svg")]) || fileName.toLowerCase().endsWith(".svg");
18767
+ const isSvg = _optionalChain([filePath, 'optionalAccess', _28 => _28.toLowerCase, 'call', _29 => _29(), 'access', _30 => _30.endsWith, 'call', _31 => _31(".svg")]) || _optionalChain([fileUrl, 'optionalAccess', _32 => _32.toLowerCase, 'call', _33 => _33(), 'access', _34 => _34.endsWith, 'call', _35 => _35(".svg")]) || fileName.toLowerCase().endsWith(".svg");
18726
18768
  if (isSvg && mediaTypeName === _mcpserversdk.MEDIA_TYPE_IMAGE) {
18727
18769
  console.warn(`SVG detected - using ${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS} media type instead of ${_mcpserversdk.MEDIA_TYPE_IMAGE}`);
18728
18770
  return _mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS;
@@ -18777,18 +18819,25 @@ function buildValueStructure(mediaTypeName, temporaryFileId) {
18777
18819
  value: { temporaryFileId }
18778
18820
  };
18779
18821
  }
18780
- async function createFileStream(sourceType, filePath, fileUrl, fileAsBase64, fileName) {
18781
- let tempFilePath = null;
18782
- let readStream;
18822
+ async function createFilePayload(sourceType, filePath, fileUrl, fileAsBase64, fileName) {
18783
18823
  switch (sourceType) {
18784
- case "filePath":
18824
+ case "filePath": {
18785
18825
  if (!filePath) {
18786
18826
  throw new Error("filePath is required when sourceType is 'filePath'");
18787
18827
  }
18828
+ if (typeof fs2.createReadStream !== "function") {
18829
+ throw new Error(
18830
+ "filePath source is not supported in this runtime (no filesystem). Use sourceType 'url' or 'base64' instead."
18831
+ );
18832
+ }
18788
18833
  const validatedPath = await validateFilePath(filePath);
18789
- readStream = fs2.createReadStream(validatedPath);
18790
- break;
18791
- case "url":
18834
+ const filename = fileName.includes(".") ? fileName : path2.basename(validatedPath);
18835
+ return {
18836
+ data: fs2.createReadStream(validatedPath),
18837
+ filename
18838
+ };
18839
+ }
18840
+ case "url": {
18792
18841
  if (!fileUrl) {
18793
18842
  throw new Error("fileUrl is required when sourceType is 'url'");
18794
18843
  }
@@ -18804,122 +18853,284 @@ async function createFileStream(sourceType, filePath, fileUrl, fileAsBase64, fil
18804
18853
  if (response.status >= 400) {
18805
18854
  throw new Error(`Failed to fetch file from URL: HTTP ${response.status} ${response.statusText}`);
18806
18855
  }
18807
- const arrayBuffer = await response.arrayBuffer();
18808
- let fileNameWithExtension2 = fileName;
18856
+ const buffer = Buffer.from(await response.arrayBuffer());
18857
+ let filename = fileName;
18809
18858
  if (!fileName.includes(".")) {
18810
18859
  const urlPath = new URL(fileUrl).pathname;
18811
18860
  const urlExtension = path2.extname(urlPath);
18812
18861
  if (urlExtension) {
18813
- fileNameWithExtension2 = `${fileName}${urlExtension}`;
18862
+ filename = `${fileName}${urlExtension}`;
18814
18863
  } else {
18815
18864
  const contentType = _nullishCoalesce(response.headers.get("content-type"), () => ( void 0));
18816
18865
  const extensionFromMime = getExtensionFromMimeType(contentType);
18817
- if (extensionFromMime) {
18818
- fileNameWithExtension2 = `${fileName}${extensionFromMime}`;
18819
- } else {
18820
- fileNameWithExtension2 = `${fileName}.bin`;
18821
- }
18866
+ filename = extensionFromMime ? `${fileName}${extensionFromMime}` : `${fileName}.bin`;
18822
18867
  }
18823
18868
  }
18824
- tempFilePath = path2.join(os.tmpdir(), fileNameWithExtension2);
18825
- fs2.writeFileSync(tempFilePath, Buffer.from(arrayBuffer));
18826
- readStream = fs2.createReadStream(tempFilePath);
18869
+ return { data: buffer, filename };
18827
18870
  } catch (error) {
18828
18871
  if (error.name === "AbortError") {
18829
18872
  throw new Error(`Request timeout after 30s fetching URL: ${fileUrl}`);
18830
18873
  }
18831
18874
  throw new Error(`Failed to fetch URL: ${fileUrl} - ${error.message}`);
18832
18875
  }
18833
- break;
18834
- case "base64":
18876
+ }
18877
+ case "base64": {
18835
18878
  if (!fileAsBase64) {
18836
18879
  throw new Error("fileAsBase64 is required when sourceType is 'base64'");
18837
18880
  }
18838
- const fileContent = Buffer.from(fileAsBase64, "base64");
18839
- let fileNameWithExtension = fileName;
18881
+ const padding = fileAsBase64.endsWith("==") ? 2 : fileAsBase64.endsWith("=") ? 1 : 0;
18882
+ const estimatedBytes = Math.floor(fileAsBase64.length * 3 / 4) - padding;
18883
+ if (estimatedBytes > BASE64_MAX_BYTES) {
18884
+ throw new Error(
18885
+ `base64 upload rejected: decoded payload is ~${estimatedBytes.toLocaleString()} bytes (limit is ${BASE64_MAX_BYTES.toLocaleString()} bytes). Use sourceType="url" with a public direct-download URL, or sourceType="file" if the file is attached to the chat.`
18886
+ );
18887
+ }
18888
+ const buffer = Buffer.from(fileAsBase64, "base64");
18889
+ let filename = fileName;
18840
18890
  if (!fileName.includes(".")) {
18841
- const extension = _mcpserversdk.detectFileExtensionFromBuffer.call(void 0, fileContent);
18842
- fileNameWithExtension = `${fileName}${extension}`;
18891
+ const extension = _mcpserversdk.detectFileExtensionFromBuffer.call(void 0, buffer);
18892
+ filename = `${fileName}${extension}`;
18843
18893
  }
18844
- tempFilePath = path2.join(os.tmpdir(), fileNameWithExtension);
18845
- fs2.writeFileSync(tempFilePath, fileContent);
18846
- readStream = fs2.createReadStream(tempFilePath);
18847
- break;
18894
+ return { data: buffer, filename };
18895
+ }
18848
18896
  }
18849
- return { readStream, tempFilePath };
18850
18897
  }
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);
18898
+ async function uploadMediaFile(client, params) {
18899
+ const validatedMediaTypeName = validateMediaTypeForSvg(
18900
+ params.filePath,
18901
+ params.fileUrl,
18902
+ params.name,
18903
+ params.mediaTypeName
18904
+ );
18905
+ const mediaTypeId = await fetchMediaTypeId(client, validatedMediaTypeName);
18906
+ const { data, filename } = await createFilePayload(
18907
+ params.sourceType,
18908
+ params.filePath,
18909
+ params.fileUrl,
18910
+ params.fileAsBase64,
18911
+ params.name
18912
+ );
18913
+ try {
18914
+ await client.postTemporaryFile({
18915
+ Id: params.temporaryFileId,
18916
+ File: data,
18917
+ FileName: filename
18918
+ });
18919
+ } catch (error) {
18920
+ const err = error;
18921
+ const errorData = _optionalChain([err, 'access', _36 => _36.response, 'optionalAccess', _37 => _37.data]) ? typeof err.response.data === "string" ? err.response.data : JSON.stringify(err.response.data) : err.message;
18922
+ throw new Error(`Failed to upload temporary file: ${_optionalChain([err, 'access', _38 => _38.response, 'optionalAccess', _39 => _39.status]) || "Unknown error"} - ${errorData}`);
18923
+ }
18924
+ const valueStructure = buildValueStructure(validatedMediaTypeName, params.temporaryFileId);
18925
+ let response;
18926
+ try {
18927
+ response = await client.postMedia({
18928
+ mediaType: { id: mediaTypeId },
18929
+ variants: [
18930
+ {
18931
+ culture: null,
18932
+ segment: null,
18933
+ name: params.name
18934
+ // Use original name provided by user
18935
+ }
18936
+ ],
18937
+ values: [valueStructure],
18938
+ parent: params.parentId ? { id: params.parentId } : null
18939
+ }, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE);
18940
+ } catch (error) {
18941
+ const err = error;
18942
+ throw new Error(`Failed to create media item: ${_optionalChain([err, 'access', _40 => _40.response, 'optionalAccess', _41 => _41.status]) || "Unknown error"} - ${JSON.stringify(_optionalChain([err, 'access', _42 => _42.response, 'optionalAccess', _43 => _43.data])) || err.message}`);
18943
+ }
18944
+ if (response.status < 200 || response.status >= 300) {
18945
+ throw new Error(`Request failed with status code ${response.status}`);
18946
+ }
18947
+ const locationHeader = _optionalChain([response, 'access', _44 => _44.headers, 'optionalAccess', _45 => _45.location]) || _optionalChain([response, 'access', _46 => _46.headers, 'optionalAccess', _47 => _47.Location]);
18948
+ if (!locationHeader) {
18949
+ throw new Error("No Location header in response - cannot determine created media ID");
18950
+ }
18951
+ const idMatch = locationHeader.match(/\/([a-f0-9-]{36})$/i);
18952
+ if (!idMatch) {
18953
+ throw new Error(`Could not extract ID from Location header: ${locationHeader}`);
18954
+ }
18955
+ const mediaId = idMatch[1];
18956
+ return { name: params.name, id: mediaId };
18957
+ }
18958
+
18959
+ // src/umb-management-api/tools/media/post/helpers/source-type-helpers.ts
18960
+ var FILE_PATH_ENTRY = `filePath - Most efficient for local files, works with any size
18961
+ SECURITY: Requires UMBRACO_ALLOWED_MEDIA_PATHS environment variable
18962
+ to be configured with comma-separated allowed directories.
18963
+ Example: UMBRACO_ALLOWED_MEDIA_PATHS="/tmp/uploads,/var/media"`;
18964
+ function buildSourceTypeSection(allowFilePath, otherSources) {
18965
+ const sources = allowFilePath ? [FILE_PATH_ENTRY, ...otherSources] : otherSources;
18966
+ return sources.map((s, i) => ` ${i + 1}. ${s}`).join("\n");
18967
+ }
18968
+
18969
+ // src/umb-management-api/tools/media/post/helpers/streaming-upload.ts
18970
+
18971
+
18972
+ var _mcphosted = require('@umbraco-cms/mcp-hosted');
18973
+
18974
+
18975
+
18976
+
18977
+
18978
+
18979
+ var authContext = null;
18980
+ function isStreamingAuthContextConfigured() {
18981
+ return authContext !== null;
18982
+ }
18983
+ async function resolveAuth() {
18984
+ if (!authContext) {
18985
+ throw new Error(
18986
+ "Streaming auth context not configured. setStreamingAuthContext() must be called in worker init()."
18987
+ );
18988
+ }
18989
+ const entry = await _mcphosted.getStoredUmbracoToken.call(void 0, authContext.env.OAUTH_KV, authContext.tokenKey);
18990
+ if (!_optionalChain([entry, 'optionalAccess', _48 => _48.tokens, 'optionalAccess', _49 => _49.access_token])) {
18991
+ throw new Error("No Umbraco access token in KV. Reconnect the MCP connector.");
18992
+ }
18993
+ const baseUrl = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([entry, 'access', _50 => _50.site, 'optionalAccess', _51 => _51.serverUrl]), () => ( _optionalChain([entry, 'access', _52 => _52.site, 'optionalAccess', _53 => _53.baseUrl]))), () => ( authContext.env.UMBRACO_SERVER_URL)), () => ( authContext.env.UMBRACO_BASE_URL));
18994
+ if (!baseUrl) {
18995
+ throw new Error("No Umbraco base URL resolvable from site or env.");
18996
+ }
18997
+ return { accessToken: entry.tokens.access_token, baseUrl: _mcpserversdk.normalizeBaseUrl.call(void 0, baseUrl) };
18998
+ }
18999
+ function ensureExtension(name, contentType, urlPath) {
19000
+ if (name.includes(".")) return name;
19001
+ const fromUrl = _optionalChain([urlPath, 'access', _54 => _54.match, 'call', _55 => _55(/\.([a-z0-9]{1,8})$/i), 'optionalAccess', _56 => _56[0]]);
19002
+ if (fromUrl) return `${name}${fromUrl}`;
19003
+ if (contentType) {
19004
+ const subtype = contentType.split(";")[0].split("/")[1];
19005
+ if (subtype && /^[a-z0-9]{1,8}$/i.test(subtype)) {
19006
+ return `${name}.${subtype === "jpeg" ? "jpg" : subtype}`;
18857
19007
  }
18858
19008
  }
19009
+ return `${name}.bin`;
18859
19010
  }
18860
- async function uploadMediaFile(client, params) {
18861
- let tempFilePath = null;
19011
+ async function streamingUploadFromUrl(params) {
19012
+ const client = UmbracoManagementClient3.getClient();
19013
+ const validatedMediaTypeName = validateMediaTypeForSvg(
19014
+ void 0,
19015
+ params.sourceUrl,
19016
+ params.name,
19017
+ params.mediaTypeName
19018
+ );
19019
+ const [mediaTypeId, auth] = await Promise.all([
19020
+ fetchMediaTypeId(client, validatedMediaTypeName),
19021
+ (async () => {
19022
+ await client.getTemporaryFileConfiguration().catch(() => void 0);
19023
+ return resolveAuth();
19024
+ })()
19025
+ ]);
19026
+ const { accessToken, baseUrl } = auth;
19027
+ const ctl = new AbortController();
19028
+ const overallTimeout = setTimeout(() => ctl.abort(), 6e4);
18862
19029
  try {
18863
- const validatedMediaTypeName = validateMediaTypeForSvg(
18864
- params.filePath,
18865
- params.fileUrl,
18866
- params.name,
18867
- params.mediaTypeName
18868
- );
18869
- const mediaTypeId = await fetchMediaTypeId(client, validatedMediaTypeName);
18870
- const { readStream, tempFilePath: createdTempPath } = await createFileStream(
18871
- params.sourceType,
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 = _optionalChain([err, 'access', _29 => _29.response, 'optionalAccess', _30 => _30.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: ${_optionalChain([err, 'access', _31 => _31.response, 'optionalAccess', _32 => _32.status]) || "Unknown error"} - ${errorData}`);
19030
+ const sourceResp = await fetch(params.sourceUrl, { signal: ctl.signal });
19031
+ if (!sourceResp.ok || !sourceResp.body) {
19032
+ throw new Error(
19033
+ `Failed to fetch source URL: HTTP ${sourceResp.status} ${sourceResp.statusText}`
19034
+ );
18887
19035
  }
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
19036
+ const sourceContentType = _nullishCoalesce(sourceResp.headers.get("content-type"), () => ( "application/octet-stream"));
19037
+ const sourceUrl = new URL(params.sourceUrl);
19038
+ const filename = ensureExtension(params.name, sourceContentType, sourceUrl.pathname);
19039
+ const temporaryFileId = crypto.randomUUID();
19040
+ const boundary = `----mcp-stream-${crypto.randomUUID()}`;
19041
+ const encoder = new TextEncoder();
19042
+ const prefix = encoder.encode(
19043
+ `--${boundary}\r
19044
+ Content-Disposition: form-data; name="Id"\r
19045
+ \r
19046
+ ${temporaryFileId}\r
19047
+ --${boundary}\r
19048
+ Content-Disposition: form-data; name="File"; filename="${filename}"\r
19049
+ Content-Type: ${sourceContentType}\r
19050
+ \r
19051
+ `
19052
+ );
19053
+ const suffix = encoder.encode(`\r
19054
+ --${boundary}--\r
19055
+ `);
19056
+ const sourceBody = sourceResp.body;
19057
+ const multipartBody = new ReadableStream({
19058
+ async start(controller) {
19059
+ const reader = sourceBody.getReader();
19060
+ try {
19061
+ controller.enqueue(prefix);
19062
+ while (true) {
19063
+ const { done, value } = await reader.read();
19064
+ if (done) break;
19065
+ if (value) controller.enqueue(value);
18899
19066
  }
18900
- ],
19067
+ controller.enqueue(suffix);
19068
+ controller.close();
19069
+ } catch (e) {
19070
+ controller.error(e);
19071
+ } finally {
19072
+ reader.releaseLock();
19073
+ }
19074
+ },
19075
+ cancel(reason) {
19076
+ sourceBody.cancel(reason).catch(() => void 0);
19077
+ }
19078
+ });
19079
+ const tempResp = await fetch(`${baseUrl}/umbraco/management/api/v1/temporary-file`, {
19080
+ method: "POST",
19081
+ body: multipartBody,
19082
+ // @ts-expect-error — `duplex` is required by Workers/undici for streaming bodies
19083
+ duplex: "half",
19084
+ signal: ctl.signal,
19085
+ headers: {
19086
+ "Content-Type": `multipart/form-data; boundary=${boundary}`,
19087
+ Authorization: `Bearer ${accessToken}`,
19088
+ Accept: "application/json"
19089
+ }
19090
+ });
19091
+ if (!tempResp.ok) {
19092
+ const errBody = await tempResp.text().catch(() => "");
19093
+ throw new Error(
19094
+ `Umbraco temporary-file POST failed: HTTP ${tempResp.status} ${tempResp.statusText} - ${errBody}`
19095
+ );
19096
+ }
19097
+ const valueStructure = buildValueStructure(validatedMediaTypeName, temporaryFileId);
19098
+ const response = await client.postMedia(
19099
+ {
19100
+ mediaType: { id: mediaTypeId },
19101
+ variants: [{ culture: null, segment: null, name: params.name }],
18901
19102
  values: [valueStructure],
18902
19103
  parent: params.parentId ? { id: params.parentId } : null
18903
- }, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE);
18904
- } catch (error) {
18905
- const err = error;
18906
- throw new Error(`Failed to create media item: ${_optionalChain([err, 'access', _33 => _33.response, 'optionalAccess', _34 => _34.status]) || "Unknown error"} - ${JSON.stringify(_optionalChain([err, 'access', _35 => _35.response, 'optionalAccess', _36 => _36.data])) || err.message}`);
18907
- }
19104
+ },
19105
+ _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE
19106
+ );
18908
19107
  if (response.status < 200 || response.status >= 300) {
18909
- throw new Error(`Request failed with status code ${response.status}`);
18910
- }
18911
- const locationHeader = _optionalChain([response, 'access', _37 => _37.headers, 'optionalAccess', _38 => _38.location]) || _optionalChain([response, 'access', _39 => _39.headers, 'optionalAccess', _40 => _40.Location]);
18912
- if (!locationHeader) {
18913
- throw new Error("No Location header in response - cannot determine created media ID");
19108
+ throw new Error(`postMedia failed with status ${response.status}`);
18914
19109
  }
18915
- const idMatch = locationHeader.match(/\/([a-f0-9-]{36})$/i);
19110
+ const locationHeader = _nullishCoalesce(_optionalChain([response, 'access', _57 => _57.headers, 'optionalAccess', _58 => _58.location]), () => ( _optionalChain([response, 'access', _59 => _59.headers, 'optionalAccess', _60 => _60.Location])));
19111
+ const idMatch = _optionalChain([locationHeader, 'optionalAccess', _61 => _61.match, 'call', _62 => _62(/\/([a-f0-9-]{36})$/i)]);
18916
19112
  if (!idMatch) {
18917
- throw new Error(`Could not extract ID from Location header: ${locationHeader}`);
19113
+ throw new Error(
19114
+ `Could not extract media id from Location header: ${_nullishCoalesce(locationHeader, () => ( "(missing)"))}`
19115
+ );
18918
19116
  }
18919
- const mediaId = idMatch[1];
18920
- return { name: params.name, id: mediaId };
19117
+ return { name: params.name, id: idMatch[1] };
18921
19118
  } finally {
18922
- cleanupTempFile(tempFilePath);
19119
+ clearTimeout(overallTimeout);
19120
+ }
19121
+ }
19122
+ async function streamingUploadToToolResult(params) {
19123
+ try {
19124
+ const { name, id } = await streamingUploadFromUrl(params);
19125
+ return _mcpserversdk.createToolResult.call(void 0, {
19126
+ message: `Media "${name}" created successfully`,
19127
+ name,
19128
+ id
19129
+ });
19130
+ } catch (error) {
19131
+ return _mcpserversdk.createToolResultError.call(void 0, {
19132
+ detail: `Error creating media: ${error.message}`
19133
+ });
18923
19134
  }
18924
19135
  }
18925
19136
 
@@ -18935,23 +19146,47 @@ async function uploadMediaFile(client, params) {
18935
19146
 
18936
19147
 
18937
19148
 
18938
- var createMediaSchema = _zod.z.object({
18939
- sourceType: _zod.z.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: _zod.z.string().describe("The name of the media item"),
18941
- mediaTypeName: _zod.z.string().describe(`Media type: '${_mcpserversdk.MEDIA_TYPE_IMAGE}', '${_mcpserversdk.MEDIA_TYPE_ARTICLE}', '${_mcpserversdk.MEDIA_TYPE_AUDIO}', '${_mcpserversdk.MEDIA_TYPE_VIDEO}', '${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS}', '${_mcpserversdk.MEDIA_TYPE_FILE}', or custom media type name`),
18942
- filePath: _zod.z.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
18943
- fileUrl: _zod.z.string().url().optional().describe("[raw] URL to fetch the file from (required if sourceType is 'url')"),
18944
- fileAsBase64: _zod.z.string().optional().describe("Base64 encoded file data (required if sourceType is 'base64')"),
18945
- parentId: _zod.z.string().uuid().optional().describe("Parent folder ID (defaults to root)")
19149
+ var fileObjectSchema = _zod.z.object({
19150
+ download_url: _zod.z.string().describe("Temporary URL the host provides to fetch the file bytes"),
19151
+ file_id: _zod.z.string().describe("Persistent file identifier from the host"),
19152
+ mime_type: _zod.z.string().optional().describe("MIME type if the host knows it"),
19153
+ file_name: _zod.z.string().optional().describe("Original file name if the host knows it")
18946
19154
  });
18947
19155
  var createMediaOutputSchema = _zod.z.object({
18948
19156
  message: _zod.z.string(),
18949
19157
  name: _zod.z.string(),
18950
19158
  id: _zod.z.string().guid()
18951
19159
  });
18952
- var CreateMediaTool = {
18953
- name: "create-media",
18954
- description: `Upload any media file to Umbraco (images, documents, audio, video, SVG, or custom types).
19160
+ function createCreateMediaTool(options) {
19161
+ const sourceTypeValues = options.allowFilePath ? ["filePath", "url", "file", "base64"] : ["url", "file", "base64"];
19162
+ const base64Kib = BASE64_MAX_BYTES / 1024;
19163
+ const filePathPrefix = options.allowFilePath ? "'filePath' for local files (Node stdio only), " : "";
19164
+ const sourceTypeDescription = `Media source type: ${filePathPrefix}'url' for public direct-download URLs (streamed; preferred for everything not already attached to the chat), 'file' for host-injected attachments \u2014 the connector populates the 'file' object automatically when the user attached a file or you generated one in this chat, 'base64' for TINY inline payloads only \u2014 the server rejects base64 above ${base64Kib} KiB decoded to stop LLM-truncated or thumbnail-preview base64 from persisting as corrupt files`;
19165
+ const schema = _zod.z.object({
19166
+ sourceType: _zod.z.enum(sourceTypeValues).describe(sourceTypeDescription),
19167
+ name: _zod.z.string().describe("The name of the media item"),
19168
+ mediaTypeName: _zod.z.string().describe(`Media type: '${_mcpserversdk.MEDIA_TYPE_IMAGE}', '${_mcpserversdk.MEDIA_TYPE_ARTICLE}', '${_mcpserversdk.MEDIA_TYPE_AUDIO}', '${_mcpserversdk.MEDIA_TYPE_VIDEO}', '${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS}', '${_mcpserversdk.MEDIA_TYPE_FILE}', or custom media type name`),
19169
+ filePath: _zod.z.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
19170
+ fileUrl: _zod.z.string().url().optional().describe("[raw] Public, direct-download URL to fetch the file from (required if sourceType is 'url'). Must be reachable without authentication. Share/viewer links (e.g. drive.google.com/file/d/<id>/view, Dropbox ?dl=0, OneDrive view URLs) must be converted to their direct-download equivalent first \u2014 Google Drive: drive.google.com/uc?export=download&id=<id>. Uploads are streamed, so multi-MB files round-trip without timing out."),
19171
+ file: fileObjectSchema.optional().describe(
19172
+ "[raw] Host-injected file object (required if sourceType is 'file'). ChatGPT's connector populates this automatically when the user attached a file or you generated one in this chat \u2014 leave it for the host to fill, do not synthesise it yourself."
19173
+ ),
19174
+ fileAsBase64: _zod.z.string().optional().describe(`Base64-encoded file data (required if sourceType is 'base64'). HARD LIMIT: decoded payload must be \u2264${base64Kib} KiB; the server rejects anything larger because LLMs reliably truncate big base64 strings or substitute thumbnail previews, both producing corrupt files. Use sourceType='url' or 'file' for everything bigger.`),
19175
+ parentId: _zod.z.string().uuid().optional().describe("Parent folder ID (defaults to root)")
19176
+ });
19177
+ const filePathSection = buildSourceTypeSection(options.allowFilePath, [
19178
+ `url - Stream from any public direct-download URL (Drive / Dropbox / etc.). Use this for anything above ${base64Kib} KiB that isn't already attached to the chat.`,
19179
+ `file - Stream a host-attached file. The connector injects { download_url, file_id, mime_type, file_name } on the 'file' field automatically when the user attached a file or you generated one in this chat \u2014 prefer this over url for chat-bound files.`,
19180
+ `base64 - ONLY for tiny inline payloads; server hard-rejects decoded base64 over ${base64Kib} KiB to prevent LLM-truncated corrupt files.`
19181
+ ]);
19182
+ const tool = {
19183
+ name: "create-media",
19184
+ description: `Upload any media file to Umbraco (images, documents, audio, video, SVG, or custom types).
19185
+
19186
+ Pick the sourceType that matches where the file lives:
19187
+ - If the file is attached to this chat or you just generated it \u2192 sourceType="file" (the host fills in the file reference automatically).
19188
+ - If you have a public direct-download URL \u2192 sourceType="url".
19189
+ - For tiny inline payloads (\u2264${base64Kib} KiB decoded) \u2192 sourceType="base64".
18955
19190
 
18956
19191
  Media Types:
18957
19192
  - ${_mcpserversdk.MEDIA_TYPE_IMAGE}: jpg, png, gif, webp, etc. (supports cropping)
@@ -18963,48 +19198,72 @@ var CreateMediaTool = {
18963
19198
  - Custom: any custom media type created in Umbraco
18964
19199
 
18965
19200
  Source Types:
18966
- 1. filePath - Most efficient for local files, works with any size
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
19201
+ ${filePathSection}
18972
19202
 
18973
19203
  The tool automatically:
18974
19204
  - Creates temporary files
18975
19205
  - Detects and validates media types (auto-corrects SVG vs Image)
18976
19206
  - Configures correct property editors (ImageCropper vs UploadField)
18977
19207
  - Cleans up temporary files`,
18978
- inputSchema: createMediaSchema.shape,
18979
- outputSchema: createMediaOutputSchema.shape,
18980
- slices: ["create"],
18981
- handler: (async (model) => {
18982
- try {
18983
- const client = UmbracoManagementClient3.getClient();
18984
- const temporaryFileId = _uuid.v4.call(void 0, );
18985
- const { name: actualName, id } = await uploadMediaFile(client, {
18986
- sourceType: model.sourceType,
18987
- name: model.name,
18988
- mediaTypeName: model.mediaTypeName,
18989
- filePath: model.filePath,
18990
- fileUrl: model.fileUrl,
18991
- fileAsBase64: model.fileAsBase64,
18992
- parentId: model.parentId,
18993
- temporaryFileId
18994
- });
18995
- return _mcpserversdk.createToolResult.call(void 0, {
18996
- message: `Media "${actualName}" created successfully`,
18997
- name: actualName,
18998
- id
18999
- });
19000
- } catch (error) {
19001
- return _mcpserversdk.createToolResultError.call(void 0, {
19002
- detail: `Error creating media: ${error.message}`
19003
- });
19004
- }
19005
- })
19006
- };
19007
- var create_media_default = _mcpserversdk.withStandardDecorators.call(void 0, CreateMediaTool);
19208
+ inputSchema: schema.shape,
19209
+ outputSchema: createMediaOutputSchema.shape,
19210
+ slices: ["create"],
19211
+ _meta: { "openai/fileParams": ["file"] },
19212
+ handler: (async (model) => {
19213
+ let effectiveSourceType;
19214
+ let effectiveFileUrl = model.fileUrl;
19215
+ if (model.sourceType === "file") {
19216
+ if (!_optionalChain([model, 'access', _63 => _63.file, 'optionalAccess', _64 => _64.download_url])) {
19217
+ return _mcpserversdk.createToolResultError.call(void 0, {
19218
+ detail: "Error creating media: sourceType is 'file' but no file object was provided. ChatGPT's connector should inject this automatically when a file is attached \u2014 if it didn't, the user has nothing attached or your client doesn't support openai/fileParams."
19219
+ });
19220
+ }
19221
+ effectiveSourceType = "url";
19222
+ effectiveFileUrl = model.file.download_url;
19223
+ } else {
19224
+ effectiveSourceType = model.sourceType;
19225
+ }
19226
+ if (effectiveSourceType === "url" && isStreamingAuthContextConfigured()) {
19227
+ if (!effectiveFileUrl) {
19228
+ return _mcpserversdk.createToolResultError.call(void 0, {
19229
+ detail: "Error creating media: fileUrl is required when sourceType is 'url'"
19230
+ });
19231
+ }
19232
+ return streamingUploadToToolResult({
19233
+ sourceUrl: effectiveFileUrl,
19234
+ name: model.name,
19235
+ mediaTypeName: model.mediaTypeName,
19236
+ parentId: model.parentId
19237
+ });
19238
+ }
19239
+ try {
19240
+ const client = UmbracoManagementClient3.getClient();
19241
+ const temporaryFileId = _uuid.v4.call(void 0, );
19242
+ const { name: actualName, id } = await uploadMediaFile(client, {
19243
+ sourceType: effectiveSourceType,
19244
+ name: model.name,
19245
+ mediaTypeName: model.mediaTypeName,
19246
+ filePath: model.filePath,
19247
+ fileUrl: effectiveFileUrl,
19248
+ fileAsBase64: model.fileAsBase64,
19249
+ parentId: model.parentId,
19250
+ temporaryFileId
19251
+ });
19252
+ return _mcpserversdk.createToolResult.call(void 0, {
19253
+ message: `Media "${actualName}" created successfully`,
19254
+ name: actualName,
19255
+ id
19256
+ });
19257
+ } catch (error) {
19258
+ return _mcpserversdk.createToolResultError.call(void 0, {
19259
+ detail: `Error creating media: ${error.message}`
19260
+ });
19261
+ }
19262
+ })
19263
+ };
19264
+ return _mcpserversdk.withStandardDecorators.call(void 0, tool);
19265
+ }
19266
+ var create_media_default = createCreateMediaTool({ allowFilePath: true });
19008
19267
 
19009
19268
  // src/umb-management-api/tools/media/post/create-media-multiple.ts
19010
19269
 
@@ -19020,16 +19279,6 @@ var create_media_default = _mcpserversdk.withStandardDecorators.call(void 0, Cre
19020
19279
 
19021
19280
 
19022
19281
 
19023
- var createMediaMultipleSchema = _zod.z.object({
19024
- sourceType: _zod.z.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: _zod.z.array(_zod.z.object({
19026
- name: _zod.z.string().describe("The name of the media item"),
19027
- filePath: _zod.z.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
19028
- fileUrl: _zod.z.string().url().optional().describe("URL to fetch the file from (required if sourceType is 'url')"),
19029
- mediaTypeName: _zod.z.string().optional().describe(`Optional override: '${_mcpserversdk.MEDIA_TYPE_IMAGE}', '${_mcpserversdk.MEDIA_TYPE_ARTICLE}', '${_mcpserversdk.MEDIA_TYPE_AUDIO}', '${_mcpserversdk.MEDIA_TYPE_VIDEO}', '${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS}', '${_mcpserversdk.MEDIA_TYPE_FILE}', or custom media type name. If not specified, defaults to '${_mcpserversdk.MEDIA_TYPE_FILE}'`)
19030
- })).describe("Array of files to upload (maximum 20 files per batch)"),
19031
- parentId: _zod.z.string().uuid().optional().describe("Parent folder ID (defaults to root)")
19032
- });
19033
19282
  var createMediaMultipleOutputSchema = _zod.z.object({
19034
19283
  summary: _zod.z.string(),
19035
19284
  results: _zod.z.array(_zod.z.object({
@@ -19039,70 +19288,136 @@ var createMediaMultipleOutputSchema = _zod.z.object({
19039
19288
  error: _zod.z.string().optional()
19040
19289
  }))
19041
19290
  });
19042
- var CreateMediaMultipleTool = {
19043
- name: "create-media-multiple",
19044
- description: `Batch upload multiple media files to Umbraco (maximum 20 files per batch).
19291
+ var fileObjectSchema2 = _zod.z.object({
19292
+ download_url: _zod.z.string().describe("Temporary URL the host provides to fetch the file bytes"),
19293
+ file_id: _zod.z.string().describe("Persistent file identifier from the host"),
19294
+ mime_type: _zod.z.string().optional().describe("MIME type if the host knows it"),
19295
+ file_name: _zod.z.string().optional().describe("Original file name if the host knows it")
19296
+ });
19297
+ var UPLOAD_CONCURRENCY = 4;
19298
+ var MAX_BATCH_SIZE = 20;
19299
+ async function mapWithConcurrency(items, concurrency, producer) {
19300
+ const results = new Array(items.length);
19301
+ let nextIndex = 0;
19302
+ async function worker() {
19303
+ while (true) {
19304
+ const current = nextIndex++;
19305
+ if (current >= items.length) return;
19306
+ results[current] = await producer(items[current], current);
19307
+ }
19308
+ }
19309
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
19310
+ await Promise.all(workers);
19311
+ return results;
19312
+ }
19313
+ function createCreateMediaMultipleTool(options) {
19314
+ const sourceTypeValues = options.allowFilePath ? ["filePath", "url", "file"] : ["url", "file"];
19315
+ const filePathPrefix = options.allowFilePath ? "'filePath' for local files (most efficient, Node stdio only), " : "";
19316
+ const sourceTypeDescription = `Media source type: ${filePathPrefix}'url' for public direct-download URLs (streamed), 'file' for host-injected attachments \u2014 the connector populates each entry's 'file' object automatically when the user attached or generated files in this chat. Base64 is not supported for batch uploads due to token usage \u2014 use single-file create-media for tiny inline payloads.`;
19317
+ const schema = _zod.z.object({
19318
+ sourceType: _zod.z.enum(sourceTypeValues).describe(sourceTypeDescription),
19319
+ files: _zod.z.array(_zod.z.object({
19320
+ name: _zod.z.string().describe("The name of the media item"),
19321
+ filePath: _zod.z.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
19322
+ fileUrl: _zod.z.string().url().optional().describe("[raw] Public direct-download URL (required if sourceType is 'url'). Drive / Dropbox share links must be converted to their direct-download equivalent first \u2014 see the create-media tool description for the format. Streamed, so multi-MB files round-trip without timing out."),
19323
+ file: fileObjectSchema2.optional().describe("[raw] Host-injected file reference (required if sourceType is 'file'). ChatGPT's connector populates this per entry automatically when files are attached."),
19324
+ mediaTypeName: _zod.z.string().optional().describe(`Optional override: '${_mcpserversdk.MEDIA_TYPE_IMAGE}', '${_mcpserversdk.MEDIA_TYPE_ARTICLE}', '${_mcpserversdk.MEDIA_TYPE_AUDIO}', '${_mcpserversdk.MEDIA_TYPE_VIDEO}', '${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS}', '${_mcpserversdk.MEDIA_TYPE_FILE}', or custom media type name. If not specified, defaults to '${_mcpserversdk.MEDIA_TYPE_FILE}'`)
19325
+ })).max(MAX_BATCH_SIZE).describe(`Array of files to upload (maximum ${MAX_BATCH_SIZE} files per batch)`),
19326
+ parentId: _zod.z.string().uuid().optional().describe("Parent folder ID (defaults to root)")
19327
+ });
19328
+ const filePathSection = buildSourceTypeSection(options.allowFilePath, [
19329
+ "url - Stream from any public direct-download URL (Drive / Dropbox / etc.).",
19330
+ "file - Stream a host-attached file. The connector injects { download_url, file_id, ... } per entry automatically when the user attached or generated files in this chat \u2014 prefer this over 'url' for chat-bound files."
19331
+ ]);
19332
+ const tool = {
19333
+ name: "create-media-multiple",
19334
+ description: `Batch upload multiple media files to Umbraco (maximum ${MAX_BATCH_SIZE} files per batch).
19045
19335
 
19046
- Supports any file type: images, documents, audio, video, SVG, or custom types.
19336
+ Use this \u2014 not several separate create-media calls \u2014 when the user attached or generated multiple files in this chat (sourceType="file"), or has a list of public URLs to upload (sourceType="url"). ChatGPT's connector populates each entry's 'file' field automatically.
19047
19337
 
19048
19338
  Source Types:
19049
- 1. filePath - Most efficient for local files, works with any size
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
19339
+ ${filePathSection}
19054
19340
 
19055
19341
  Note: base64 is not supported for batch uploads due to token usage.
19056
19342
 
19057
- The tool processes files sequentially and returns detailed results for each file.
19058
- If some files fail, others will continue processing (continue-on-error strategy).`,
19059
- inputSchema: createMediaMultipleSchema.shape,
19060
- outputSchema: createMediaMultipleOutputSchema.shape,
19061
- slices: ["create"],
19062
- handler: (async (model) => {
19063
- if (model.files.length > 20) {
19064
- return _mcpserversdk.createToolResultError.call(void 0, {
19065
- detail: `Batch upload limited to 20 files per call. You provided ${model.files.length} files. Please split into multiple batches.`
19066
- });
19067
- }
19068
- const results = [];
19069
- const client = UmbracoManagementClient3.getClient();
19070
- for (const file of model.files) {
19071
- try {
19072
- const temporaryFileId = _uuid.v4.call(void 0, );
19073
- const defaultMediaType = file.mediaTypeName || _mcpserversdk.MEDIA_TYPE_FILE;
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
19343
+ The tool processes up to ${UPLOAD_CONCURRENCY} uploads in parallel and returns detailed results for each file in input order. If some files fail, others continue processing (continue-on-error strategy).`,
19344
+ inputSchema: schema.shape,
19345
+ outputSchema: createMediaMultipleOutputSchema.shape,
19346
+ slices: ["create"],
19347
+ _meta: { "openai/fileParams": ["files"] },
19348
+ handler: (async (model) => {
19349
+ if (model.files.length > MAX_BATCH_SIZE) {
19350
+ return _mcpserversdk.createToolResultError.call(void 0, {
19351
+ detail: `Batch upload limited to ${MAX_BATCH_SIZE} files per call. You provided ${model.files.length} files. Please split into multiple batches.`
19094
19352
  });
19095
19353
  }
19096
- }
19097
- const successCount = results.filter((r) => r.success).length;
19098
- const failureCount = results.filter((r) => !r.success).length;
19099
- return _mcpserversdk.createToolResult.call(void 0, {
19100
- summary: `Processed ${model.files.length} files: ${successCount} succeeded, ${failureCount} failed`,
19101
- results
19102
- });
19103
- })
19104
- };
19105
- var create_media_multiple_default = _mcpserversdk.withStandardDecorators.call(void 0, CreateMediaMultipleTool);
19354
+ const client = UmbracoManagementClient3.getClient();
19355
+ const streamingAvailable = isStreamingAuthContextConfigured();
19356
+ const results = await mapWithConcurrency(
19357
+ model.files,
19358
+ UPLOAD_CONCURRENCY,
19359
+ async (file) => {
19360
+ try {
19361
+ const mediaTypeName = file.mediaTypeName || _mcpserversdk.MEDIA_TYPE_FILE;
19362
+ let effectiveSourceType;
19363
+ let effectiveFileUrl = file.fileUrl;
19364
+ if (model.sourceType === "file") {
19365
+ if (!_optionalChain([file, 'access', _65 => _65.file, 'optionalAccess', _66 => _66.download_url])) {
19366
+ return {
19367
+ success: false,
19368
+ name: file.name,
19369
+ error: "sourceType is 'file' but no file object was provided for this entry. The host connector should inject this automatically when a file is attached."
19370
+ };
19371
+ }
19372
+ effectiveSourceType = "url";
19373
+ effectiveFileUrl = file.file.download_url;
19374
+ } else {
19375
+ effectiveSourceType = model.sourceType;
19376
+ }
19377
+ if (effectiveSourceType === "url" && streamingAvailable) {
19378
+ if (!effectiveFileUrl) {
19379
+ return {
19380
+ success: false,
19381
+ name: file.name,
19382
+ error: "fileUrl is required when sourceType is 'url'."
19383
+ };
19384
+ }
19385
+ const { name: actualName2, id: mediaId2 } = await streamingUploadFromUrl({
19386
+ sourceUrl: effectiveFileUrl,
19387
+ name: file.name,
19388
+ mediaTypeName,
19389
+ parentId: model.parentId
19390
+ });
19391
+ return { success: true, name: actualName2, id: mediaId2 };
19392
+ }
19393
+ const temporaryFileId = _uuid.v4.call(void 0, );
19394
+ const { name: actualName, id: mediaId } = await uploadMediaFile(client, {
19395
+ sourceType: effectiveSourceType,
19396
+ name: file.name,
19397
+ mediaTypeName,
19398
+ filePath: file.filePath,
19399
+ fileUrl: effectiveFileUrl,
19400
+ fileAsBase64: void 0,
19401
+ parentId: model.parentId,
19402
+ temporaryFileId
19403
+ });
19404
+ return { success: true, name: actualName, id: mediaId };
19405
+ } catch (error) {
19406
+ return { success: false, name: file.name, error: error.message };
19407
+ }
19408
+ }
19409
+ );
19410
+ const successCount = results.filter((r) => r.success).length;
19411
+ const failureCount = results.filter((r) => !r.success).length;
19412
+ return _mcpserversdk.createToolResult.call(void 0, {
19413
+ summary: `Processed ${model.files.length} files: ${successCount} succeeded, ${failureCount} failed`,
19414
+ results
19415
+ });
19416
+ })
19417
+ };
19418
+ return _mcpserversdk.withStandardDecorators.call(void 0, tool);
19419
+ }
19420
+ var create_media_multiple_default = createCreateMediaMultipleTool({ allowFilePath: true });
19106
19421
 
19107
19422
  // src/umb-management-api/tools/media/post/create-media-folder.ts
19108
19423
 
@@ -19146,7 +19461,7 @@ var CreateMediaFolderTool = {
19146
19461
  if (response.status < 200 || response.status >= 300) {
19147
19462
  throw new Error(`Request failed with status code ${response.status}`);
19148
19463
  }
19149
- const locationHeader = _optionalChain([response, 'access', _41 => _41.headers, 'optionalAccess', _42 => _42.location]) || _optionalChain([response, 'access', _43 => _43.headers, 'optionalAccess', _44 => _44.Location]);
19464
+ const locationHeader = _optionalChain([response, 'access', _67 => _67.headers, 'optionalAccess', _68 => _68.location]) || _optionalChain([response, 'access', _69 => _69.headers, 'optionalAccess', _70 => _70.Location]);
19150
19465
  if (!locationHeader) {
19151
19466
  throw new Error("No Location header in response - cannot determine created folder ID");
19152
19467
  }
@@ -19921,8 +20236,9 @@ var MediaCollection = {
19921
20236
  tools.push(get_root_default6);
19922
20237
  }
19923
20238
  if (AuthorizationPolicies.SectionAccessMedia(user)) {
19924
- tools.push(create_media_default);
19925
- tools.push(create_media_multiple_default);
20239
+ const allowFilePath = isFilePathUploadAllowed();
20240
+ tools.push(createCreateMediaTool({ allowFilePath }));
20241
+ tools.push(createCreateMediaMultipleTool({ allowFilePath }));
19926
20242
  tools.push(create_media_folder_default);
19927
20243
  tools.push(delete_media_default);
19928
20244
  tools.push(update_media_default);
@@ -20382,7 +20698,7 @@ var CreateMediaTypeFolderTool = {
20382
20698
  validateStatus: () => true
20383
20699
  });
20384
20700
  if (response.status === 201) {
20385
- const locationHeader = _optionalChain([response, 'access', _45 => _45.headers, 'optionalAccess', _46 => _46["location"]]) || _optionalChain([response, 'access', _47 => _47.headers, 'optionalAccess', _48 => _48["Location"]]);
20701
+ const locationHeader = _optionalChain([response, 'access', _71 => _71.headers, 'optionalAccess', _72 => _72["location"]]) || _optionalChain([response, 'access', _73 => _73.headers, 'optionalAccess', _74 => _74["Location"]]);
20386
20702
  let createdId = model.id || "";
20387
20703
  if (locationHeader) {
20388
20704
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -20516,7 +20832,7 @@ var CreateMediaTypeTool = {
20516
20832
  validateStatus: () => true
20517
20833
  });
20518
20834
  if (response.status === 201) {
20519
- const locationHeader = _optionalChain([response, 'access', _49 => _49.headers, 'optionalAccess', _50 => _50["location"]]) || _optionalChain([response, 'access', _51 => _51.headers, 'optionalAccess', _52 => _52["Location"]]);
20835
+ const locationHeader = _optionalChain([response, 'access', _75 => _75.headers, 'optionalAccess', _76 => _76["location"]]) || _optionalChain([response, 'access', _77 => _77.headers, 'optionalAccess', _78 => _78["Location"]]);
20520
20836
  let createdId = model.id || "";
20521
20837
  if (locationHeader) {
20522
20838
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -20567,7 +20883,7 @@ var CopyMediaTypeTool = {
20567
20883
  validateStatus: () => true
20568
20884
  });
20569
20885
  if (response.status === 201) {
20570
- const locationHeader = _optionalChain([response, 'access', _53 => _53.headers, 'optionalAccess', _54 => _54["location"]]) || _optionalChain([response, 'access', _55 => _55.headers, 'optionalAccess', _56 => _56["Location"]]);
20886
+ const locationHeader = _optionalChain([response, 'access', _79 => _79.headers, 'optionalAccess', _80 => _80["location"]]) || _optionalChain([response, 'access', _81 => _81.headers, 'optionalAccess', _82 => _82["Location"]]);
20571
20887
  let createdId = "";
20572
20888
  if (locationHeader) {
20573
20889
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -20777,7 +21093,7 @@ var CreateMemberTool = {
20777
21093
  validateStatus: () => true
20778
21094
  });
20779
21095
  if (response.status === 201) {
20780
- const locationHeader = _optionalChain([response, 'access', _57 => _57.headers, 'optionalAccess', _58 => _58["location"]]) || _optionalChain([response, 'access', _59 => _59.headers, 'optionalAccess', _60 => _60["Location"]]);
21096
+ const locationHeader = _optionalChain([response, 'access', _83 => _83.headers, 'optionalAccess', _84 => _84["location"]]) || _optionalChain([response, 'access', _85 => _85.headers, 'optionalAccess', _86 => _86["Location"]]);
20781
21097
  let createdId = model.id || "";
20782
21098
  if (locationHeader) {
20783
21099
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -21328,7 +21644,7 @@ var CreateMemberTypeTool = {
21328
21644
  validateStatus: () => true
21329
21645
  });
21330
21646
  if (response.status === 201) {
21331
- const locationHeader = _optionalChain([response, 'access', _61 => _61.headers, 'optionalAccess', _62 => _62["location"]]) || _optionalChain([response, 'access', _63 => _63.headers, 'optionalAccess', _64 => _64["Location"]]);
21647
+ const locationHeader = _optionalChain([response, 'access', _87 => _87.headers, 'optionalAccess', _88 => _88["location"]]) || _optionalChain([response, 'access', _89 => _89.headers, 'optionalAccess', _90 => _90["Location"]]);
21332
21648
  let createdId = model.id || "";
21333
21649
  if (locationHeader) {
21334
21650
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -21498,7 +21814,7 @@ var CopyMemberTypeTool = {
21498
21814
  validateStatus: () => true
21499
21815
  });
21500
21816
  if (response.status === 201) {
21501
- const locationHeader = _optionalChain([response, 'access', _65 => _65.headers, 'optionalAccess', _66 => _66["location"]]) || _optionalChain([response, 'access', _67 => _67.headers, 'optionalAccess', _68 => _68["Location"]]);
21817
+ const locationHeader = _optionalChain([response, 'access', _91 => _91.headers, 'optionalAccess', _92 => _92["location"]]) || _optionalChain([response, 'access', _93 => _93.headers, 'optionalAccess', _94 => _94["Location"]]);
21502
21818
  let createdId = "";
21503
21819
  if (locationHeader) {
21504
21820
  const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
@@ -21858,7 +22174,7 @@ var CreatePartialViewTool = {
21858
22174
  validateStatus: () => true
21859
22175
  });
21860
22176
  if (response.status === 201) {
21861
- const locationHeader = _optionalChain([response, 'access', _69 => _69.headers, 'optionalAccess', _70 => _70["location"]]) || _optionalChain([response, 'access', _71 => _71.headers, 'optionalAccess', _72 => _72["Location"]]);
22177
+ const locationHeader = _optionalChain([response, 'access', _95 => _95.headers, 'optionalAccess', _96 => _96["location"]]) || _optionalChain([response, 'access', _97 => _97.headers, 'optionalAccess', _98 => _98["Location"]]);
21862
22178
  let createdPath = "";
21863
22179
  if (locationHeader) {
21864
22180
  const pathMatch = locationHeader.match(/partial-view\/(.+)$/);
@@ -21905,7 +22221,7 @@ var CreatePartialViewFolderTool = {
21905
22221
  validateStatus: () => true
21906
22222
  });
21907
22223
  if (response.status === 201) {
21908
- const locationHeader = _optionalChain([response, 'access', _73 => _73.headers, 'optionalAccess', _74 => _74["location"]]) || _optionalChain([response, 'access', _75 => _75.headers, 'optionalAccess', _76 => _76["Location"]]);
22224
+ const locationHeader = _optionalChain([response, 'access', _99 => _99.headers, 'optionalAccess', _100 => _100["location"]]) || _optionalChain([response, 'access', _101 => _101.headers, 'optionalAccess', _102 => _102["Location"]]);
21909
22225
  let createdPath = "";
21910
22226
  if (locationHeader) {
21911
22227
  const pathMatch = locationHeader.match(/partial-view\/folder\/(.+)$/);
@@ -21941,9 +22257,9 @@ var GetPartialViewByPathTool = {
21941
22257
  outputSchema: getPartialViewByPathResponse.shape,
21942
22258
  annotations: { readOnlyHint: true },
21943
22259
  slices: ["read"],
21944
- handler: (async ({ path: path4 }) => {
22260
+ handler: (async ({ path: path3 }) => {
21945
22261
  return _mcpserversdk.executeGetApiCall.call(void 0,
21946
- (client) => client.getPartialViewByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22262
+ (client) => client.getPartialViewByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
21947
22263
  );
21948
22264
  })
21949
22265
  };
@@ -21962,9 +22278,9 @@ var GetPartialViewFolderByPathTool = {
21962
22278
  outputSchema: getPartialViewFolderByPathResponse.shape,
21963
22279
  annotations: { readOnlyHint: true },
21964
22280
  slices: ["read", "folders"],
21965
- handler: (async ({ path: path4 }) => {
22281
+ handler: (async ({ path: path3 }) => {
21966
22282
  return _mcpserversdk.executeGetApiCall.call(void 0,
21967
- (client) => client.getPartialViewFolderByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22283
+ (client) => client.getPartialViewFolderByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
21968
22284
  );
21969
22285
  })
21970
22286
  };
@@ -22039,9 +22355,9 @@ var DeletePartialViewTool = {
22039
22355
  destructiveHint: true
22040
22356
  },
22041
22357
  slices: ["delete"],
22042
- handler: (async ({ path: path4 }) => {
22358
+ handler: (async ({ path: path3 }) => {
22043
22359
  return _mcpserversdk.executeVoidApiCall.call(void 0,
22044
- (client) => client.deletePartialViewByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22360
+ (client) => client.deletePartialViewByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22045
22361
  );
22046
22362
  })
22047
22363
  };
@@ -22061,9 +22377,9 @@ var DeletePartialViewFolderTool = {
22061
22377
  destructiveHint: true
22062
22378
  },
22063
22379
  slices: ["delete", "folders"],
22064
- handler: (async ({ path: path4 }) => {
22380
+ handler: (async ({ path: path3 }) => {
22065
22381
  return _mcpserversdk.executeVoidApiCall.call(void 0,
22066
- (client) => client.deletePartialViewFolderByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22382
+ (client) => client.deletePartialViewFolderByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22067
22383
  );
22068
22384
  })
22069
22385
  };
@@ -22549,9 +22865,9 @@ var GetScriptByPathTool = {
22549
22865
  outputSchema: getScriptByPathResponse.shape,
22550
22866
  annotations: { readOnlyHint: true },
22551
22867
  slices: ["read"],
22552
- handler: (async ({ path: path4 }) => {
22868
+ handler: (async ({ path: path3 }) => {
22553
22869
  return _mcpserversdk.executeGetApiCall.call(void 0,
22554
- (client) => client.getScriptByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22870
+ (client) => client.getScriptByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22555
22871
  );
22556
22872
  })
22557
22873
  };
@@ -22570,9 +22886,9 @@ var GetScriptFolderByPathTool = {
22570
22886
  outputSchema: getScriptFolderByPathResponse.shape,
22571
22887
  annotations: { readOnlyHint: true },
22572
22888
  slices: ["read", "folders"],
22573
- handler: (async ({ path: path4 }) => {
22889
+ handler: (async ({ path: path3 }) => {
22574
22890
  return _mcpserversdk.executeGetApiCall.call(void 0,
22575
- (client) => client.getScriptFolderByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22891
+ (client) => client.getScriptFolderByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22576
22892
  );
22577
22893
  })
22578
22894
  };
@@ -22727,7 +23043,7 @@ var CreateScriptTool = {
22727
23043
  validateStatus: () => true
22728
23044
  });
22729
23045
  if (response.status === 201) {
22730
- const locationHeader = _optionalChain([response, 'access', _77 => _77.headers, 'optionalAccess', _78 => _78["location"]]) || _optionalChain([response, 'access', _79 => _79.headers, 'optionalAccess', _80 => _80["Location"]]);
23046
+ const locationHeader = _optionalChain([response, 'access', _103 => _103.headers, 'optionalAccess', _104 => _104["location"]]) || _optionalChain([response, 'access', _105 => _105.headers, 'optionalAccess', _106 => _106["Location"]]);
22731
23047
  let createdPath = "";
22732
23048
  if (locationHeader) {
22733
23049
  const pathMatch = locationHeader.match(/script\/(.+)$/);
@@ -22774,7 +23090,7 @@ var CreateScriptFolderTool = {
22774
23090
  validateStatus: () => true
22775
23091
  });
22776
23092
  if (response.status === 201) {
22777
- const locationHeader = _optionalChain([response, 'access', _81 => _81.headers, 'optionalAccess', _82 => _82["location"]]) || _optionalChain([response, 'access', _83 => _83.headers, 'optionalAccess', _84 => _84["Location"]]);
23093
+ const locationHeader = _optionalChain([response, 'access', _107 => _107.headers, 'optionalAccess', _108 => _108["location"]]) || _optionalChain([response, 'access', _109 => _109.headers, 'optionalAccess', _110 => _110["Location"]]);
22778
23094
  let createdPath = "";
22779
23095
  if (locationHeader) {
22780
23096
  const pathMatch = locationHeader.match(/script\/folder\/(.+)$/);
@@ -22870,9 +23186,9 @@ var DeleteScriptTool = {
22870
23186
  destructiveHint: true
22871
23187
  },
22872
23188
  slices: ["delete"],
22873
- handler: (async ({ path: path4 }) => {
23189
+ handler: (async ({ path: path3 }) => {
22874
23190
  return _mcpserversdk.executeVoidApiCall.call(void 0,
22875
- (client) => client.deleteScriptByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
23191
+ (client) => client.deleteScriptByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22876
23192
  );
22877
23193
  })
22878
23194
  };
@@ -22892,9 +23208,9 @@ var DeleteScriptFolderTool = {
22892
23208
  destructiveHint: true
22893
23209
  },
22894
23210
  slices: ["delete", "folders"],
22895
- handler: (async ({ path: path4 }) => {
23211
+ handler: (async ({ path: path3 }) => {
22896
23212
  return _mcpserversdk.executeVoidApiCall.call(void 0,
22897
- (client) => client.deleteScriptFolderByPath(path4, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
23213
+ (client) => client.deleteScriptFolderByPath(path3, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
22898
23214
  );
22899
23215
  })
22900
23216
  };
@@ -23371,7 +23687,7 @@ var CreateStylesheetTool = {
23371
23687
  validateStatus: () => true
23372
23688
  });
23373
23689
  if (response.status === 201) {
23374
- const locationHeader = _optionalChain([response, 'access', _85 => _85.headers, 'optionalAccess', _86 => _86["location"]]) || _optionalChain([response, 'access', _87 => _87.headers, 'optionalAccess', _88 => _88["Location"]]);
23690
+ const locationHeader = _optionalChain([response, 'access', _111 => _111.headers, 'optionalAccess', _112 => _112["location"]]) || _optionalChain([response, 'access', _113 => _113.headers, 'optionalAccess', _114 => _114["Location"]]);
23375
23691
  let createdPath = "";
23376
23692
  if (locationHeader) {
23377
23693
  const pathMatch = locationHeader.match(/stylesheet\/(.+)$/);
@@ -23418,7 +23734,7 @@ var CreateStylesheetFolderTool = {
23418
23734
  validateStatus: () => true
23419
23735
  });
23420
23736
  if (response.status === 201) {
23421
- const locationHeader = _optionalChain([response, 'access', _89 => _89.headers, 'optionalAccess', _90 => _90["location"]]) || _optionalChain([response, 'access', _91 => _91.headers, 'optionalAccess', _92 => _92["Location"]]);
23737
+ const locationHeader = _optionalChain([response, 'access', _115 => _115.headers, 'optionalAccess', _116 => _116["location"]]) || _optionalChain([response, 'access', _117 => _117.headers, 'optionalAccess', _118 => _118["Location"]]);
23422
23738
  let createdPath = "";
23423
23739
  if (locationHeader) {
23424
23740
  const pathMatch = locationHeader.match(/stylesheet\/folder\/(.+)$/);
@@ -23502,9 +23818,9 @@ var UpdateStylesheetTool = {
23502
23818
  annotations: { idempotentHint: true },
23503
23819
  slices: ["update"],
23504
23820
  handler: (async (model) => {
23505
- const { path: path4, ...updateModel } = model;
23821
+ const { path: path3, ...updateModel } = model;
23506
23822
  return _mcpserversdk.executeVoidApiCall.call(void 0,
23507
- (client) => client.putStylesheetByPath(path4, updateModel, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
23823
+ (client) => client.putStylesheetByPath(path3, updateModel, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
23508
23824
  );
23509
23825
  })
23510
23826
  };
@@ -23528,8 +23844,8 @@ var RenameStylesheetTool = {
23528
23844
  annotations: { idempotentHint: true },
23529
23845
  slices: ["rename"],
23530
23846
  handler: (async (model) => {
23531
- const { path: path4, ...renameModel } = model;
23532
- const normalizedPath = encodeURIComponent(path4);
23847
+ const { path: path3, ...renameModel } = model;
23848
+ const normalizedPath = encodeURIComponent(path3);
23533
23849
  return _mcpserversdk.executeVoidApiCall.call(void 0,
23534
23850
  (client) => client.putStylesheetByPathRename(normalizedPath, renameModel, _mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE)
23535
23851
  );
@@ -23782,7 +24098,7 @@ var CreateTemplateTool = {
23782
24098
  validateStatus: () => true
23783
24099
  });
23784
24100
  if (response.status === 201) {
23785
- const locationHeader = _optionalChain([response, 'access', _93 => _93.headers, 'optionalAccess', _94 => _94["location"]]) || _optionalChain([response, 'access', _95 => _95.headers, 'optionalAccess', _96 => _96["Location"]]);
24101
+ const locationHeader = _optionalChain([response, 'access', _119 => _119.headers, 'optionalAccess', _120 => _120["location"]]) || _optionalChain([response, 'access', _121 => _121.headers, 'optionalAccess', _122 => _122["Location"]]);
23786
24102
  let createdId = "";
23787
24103
  if (locationHeader) {
23788
24104
  const idMatch = locationHeader.match(/template\/([a-f0-9-]+)$/i);
@@ -24146,9 +24462,6 @@ var TemplateCollection = {
24146
24462
 
24147
24463
 
24148
24464
 
24149
-
24150
-
24151
-
24152
24465
  var createTemporaryFileSchema = _zod.z.object({
24153
24466
  id: _zod.z.string().uuid().describe("Unique identifier for the temporary file"),
24154
24467
  fileName: _zod.z.string().describe("Name of the file"),
@@ -24171,7 +24484,6 @@ var CreateTemporaryFileTool = {
24171
24484
  outputSchema: createTemporaryFileOutputSchema.shape,
24172
24485
  slices: ["create"],
24173
24486
  handler: (async (model) => {
24174
- let tempFilePath = null;
24175
24487
  try {
24176
24488
  const fileContent = Buffer.from(model.fileAsBase64, "base64");
24177
24489
  let fileName = model.fileName;
@@ -24179,13 +24491,11 @@ var CreateTemporaryFileTool = {
24179
24491
  const extension = _mcpserversdk.detectFileExtensionFromBuffer.call(void 0, fileContent);
24180
24492
  fileName = `${fileName}${extension}`;
24181
24493
  }
24182
- tempFilePath = path3.join(os2.tmpdir(), `umbraco-upload-${model.id}-${fileName}`);
24183
- fs3.writeFileSync(tempFilePath, fileContent);
24184
- const readStream = fs3.createReadStream(tempFilePath);
24185
24494
  const client = UmbracoManagementClient3.getClient();
24186
24495
  await client.postTemporaryFile({
24187
24496
  Id: model.id,
24188
- File: readStream
24497
+ File: fileContent,
24498
+ FileName: fileName
24189
24499
  });
24190
24500
  return _mcpserversdk.createToolResult.call(void 0, {
24191
24501
  message: "Temporary file created successfully",
@@ -24195,14 +24505,6 @@ var CreateTemporaryFileTool = {
24195
24505
  return _mcpserversdk.createToolResultError.call(void 0, {
24196
24506
  detail: `Error creating temporary file: ${error.message}`
24197
24507
  });
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
24508
  }
24207
24509
  })
24208
24510
  };
@@ -24213,14 +24515,15 @@ var create_temporary_file_default = _mcpserversdk.withStandardDecorators.call(vo
24213
24515
 
24214
24516
  var postTemporaryFileBody = _zod.z.object({
24215
24517
  Id: _zod.z.string().uuid(),
24216
- File: _zod.z.instanceof(_fs.ReadStream)
24518
+ File: _zod.z.union([_zod.z.instanceof(Buffer), _zod.z.instanceof(_fs.ReadStream)]),
24519
+ FileName: _zod.z.string().min(1)
24217
24520
  });
24218
24521
  var getTemporaryFileByIdParams = _zod.z.object({
24219
24522
  id: _zod.z.string().uuid()
24220
24523
  });
24221
24524
  var getTemporaryFileByIdResponse = _zod.z.object({
24222
24525
  id: _zod.z.string().guid(),
24223
- availableUntil: _zod.z.string().datetime({ local: true }).nullish(),
24526
+ availableUntil: _zod.z.string().datetime({ local: true, offset: true }).nullish(),
24224
24527
  fileName: _zod.z.string().min(1)
24225
24528
  });
24226
24529
  var deleteTemporaryFileByIdParams = _zod.z.object({
@@ -24705,7 +25008,7 @@ var CreateUserDataTool = {
24705
25008
  validateStatus: () => true
24706
25009
  });
24707
25010
  if (response.status === 201) {
24708
- const locationHeader = _optionalChain([response, 'access', _97 => _97.headers, 'optionalAccess', _98 => _98["location"]]) || _optionalChain([response, 'access', _99 => _99.headers, 'optionalAccess', _100 => _100["Location"]]);
25011
+ const locationHeader = _optionalChain([response, 'access', _123 => _123.headers, 'optionalAccess', _124 => _124["location"]]) || _optionalChain([response, 'access', _125 => _125.headers, 'optionalAccess', _126 => _126["Location"]]);
24709
25012
  let createdId = "";
24710
25013
  if (locationHeader) {
24711
25014
  const idMatch = locationHeader.match(/user-data\/([a-f0-9-]+)$/i);
@@ -24943,7 +25246,7 @@ var CreateUserGroupTool = {
24943
25246
  validateStatus: () => true
24944
25247
  });
24945
25248
  if (response.status === 201) {
24946
- const locationHeader = _optionalChain([response, 'access', _101 => _101.headers, 'optionalAccess', _102 => _102["location"]]) || _optionalChain([response, 'access', _103 => _103.headers, 'optionalAccess', _104 => _104["Location"]]);
25249
+ const locationHeader = _optionalChain([response, 'access', _127 => _127.headers, 'optionalAccess', _128 => _128["location"]]) || _optionalChain([response, 'access', _129 => _129.headers, 'optionalAccess', _130 => _130["Location"]]);
24947
25250
  let createdId = "";
24948
25251
  if (locationHeader) {
24949
25252
  const idMatch = locationHeader.match(/user-group\/([a-f0-9-]+)$/i);
@@ -25241,7 +25544,7 @@ var CreateWebhookTool = {
25241
25544
  validateStatus: () => true
25242
25545
  });
25243
25546
  if (response.status === 201) {
25244
- const locationHeader = _optionalChain([response, 'access', _105 => _105.headers, 'optionalAccess', _106 => _106["location"]]) || _optionalChain([response, 'access', _107 => _107.headers, 'optionalAccess', _108 => _108["Location"]]);
25547
+ const locationHeader = _optionalChain([response, 'access', _131 => _131.headers, 'optionalAccess', _132 => _132["location"]]) || _optionalChain([response, 'access', _133 => _133.headers, 'optionalAccess', _134 => _134["Location"]]);
25245
25548
  let createdId = "";
25246
25549
  if (locationHeader) {
25247
25550
  const idMatch = locationHeader.match(/webhook\/([a-f0-9-]+)$/i);
@@ -25475,5 +25778,6 @@ var allSliceNames = [...toolSliceNames, "other"];
25475
25778
 
25476
25779
 
25477
25780
 
25478
- exports.__commonJS = __commonJS; exports.__toESM = __toESM; exports.UmbracoManagementClient = UmbracoManagementClient3; exports.setUmbracoVersion = setUmbracoVersion; exports.availableCollections = availableCollections; exports.allModes = allModes; exports.allModeNames = allModeNames; exports.allSliceNames = allSliceNames;
25479
- //# sourceMappingURL=chunk-OBOSCZYR.cjs.map
25781
+
25782
+ exports.__commonJS = __commonJS; exports.__toESM = __toESM; exports.UmbracoManagementClient = UmbracoManagementClient3; exports.setAllowFilePathUploads = setAllowFilePathUploads; exports.setUmbracoVersion = setUmbracoVersion; exports.availableCollections = availableCollections; exports.allModes = allModes; exports.allModeNames = allModeNames; exports.allSliceNames = allSliceNames;
25783
+ //# sourceMappingURL=chunk-Q4LCXM42.cjs.map