@payloadcms/plugin-mcp 3.78.0-internal-debug.f663370 → 3.78.0-internal.ab11ffa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/getMcpHandler.d.ts.map +1 -1
- package/dist/mcp/getMcpHandler.js +8 -2
- package/dist/mcp/getMcpHandler.js.map +1 -1
- package/dist/mcp/helpers/config.d.ts +1 -9
- package/dist/mcp/helpers/config.d.ts.map +1 -1
- package/dist/mcp/helpers/config.js +0 -62
- package/dist/mcp/helpers/config.js.map +1 -1
- package/dist/mcp/helpers/fields.d.ts +6 -25
- package/dist/mcp/helpers/fields.d.ts.map +1 -1
- package/dist/mcp/helpers/fields.js +35 -29
- package/dist/mcp/helpers/fields.js.map +1 -1
- package/dist/mcp/helpers/fileValidation.d.ts +0 -2
- package/dist/mcp/helpers/fileValidation.d.ts.map +1 -1
- package/dist/mcp/helpers/fileValidation.js +44 -82
- package/dist/mcp/helpers/fileValidation.js.map +1 -1
- package/dist/mcp/tools/collection/create.d.ts.map +1 -1
- package/dist/mcp/tools/collection/create.js +2 -25
- package/dist/mcp/tools/collection/create.js.map +1 -1
- package/dist/mcp/tools/collection/delete.d.ts.map +1 -1
- package/dist/mcp/tools/collection/delete.js +1 -12
- package/dist/mcp/tools/collection/delete.js.map +1 -1
- package/dist/mcp/tools/config/update.d.ts +1 -1
- package/dist/mcp/tools/config/update.d.ts.map +1 -1
- package/dist/mcp/tools/config/update.js +3 -3
- package/dist/mcp/tools/config/update.js.map +1 -1
- package/dist/mcp/tools/global/update.d.ts.map +1 -1
- package/dist/mcp/tools/global/update.js +3 -0
- package/dist/mcp/tools/global/update.js.map +1 -1
- package/dist/mcp/tools/job/create.d.ts.map +1 -1
- package/dist/mcp/tools/job/create.js +3 -6
- package/dist/mcp/tools/job/create.js.map +1 -1
- package/dist/mcp/tools/job/run.d.ts +1 -1
- package/dist/mcp/tools/job/run.d.ts.map +1 -1
- package/dist/mcp/tools/job/run.js +5 -26
- package/dist/mcp/tools/job/run.js.map +1 -1
- package/dist/mcp/tools/job/update.d.ts.map +1 -1
- package/dist/mcp/tools/job/update.js +10 -38
- package/dist/mcp/tools/job/update.js.map +1 -1
- package/dist/mcp/tools/resource/create.d.ts.map +1 -1
- package/dist/mcp/tools/resource/create.js +3 -0
- package/dist/mcp/tools/resource/create.js.map +1 -1
- package/dist/mcp/tools/resource/update.d.ts.map +1 -1
- package/dist/mcp/tools/resource/update.js +3 -0
- package/dist/mcp/tools/resource/update.js.map +1 -1
- package/dist/mcp/tools/schemas.d.ts +2 -5
- package/dist/mcp/tools/schemas.d.ts.map +1 -1
- package/dist/mcp/tools/schemas.js +0 -1
- package/dist/mcp/tools/schemas.js.map +1 -1
- package/dist/utils/getVirtualFieldNames.d.ts +14 -0
- package/dist/utils/getVirtualFieldNames.d.ts.map +1 -0
- package/dist/utils/getVirtualFieldNames.js +35 -0
- package/dist/utils/getVirtualFieldNames.js.map +1 -0
- package/dist/utils/schemaConversion/convertCollectionSchemaToZod.d.ts.map +1 -1
- package/dist/utils/schemaConversion/convertCollectionSchemaToZod.js +1 -2
- package/dist/utils/schemaConversion/convertCollectionSchemaToZod.js.map +1 -1
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts +7 -0
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.d.ts.map +1 -0
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js +20 -0
- package/dist/utils/schemaConversion/removeVirtualFieldsFromSchema.js.map +1 -0
- package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts +5 -0
- package/dist/utils/schemaConversion/sanitizeJsonSchema.d.ts.map +1 -1
- package/dist/utils/schemaConversion/sanitizeJsonSchema.js +38 -0
- package/dist/utils/schemaConversion/sanitizeJsonSchema.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +0 -1
- package/src/mcp/getMcpHandler.ts +22 -2
- package/src/mcp/helpers/config.ts +1 -114
- package/src/mcp/helpers/fields.ts +46 -50
- package/src/mcp/helpers/fileValidation.ts +38 -93
- package/src/mcp/tools/collection/create.ts +2 -30
- package/src/mcp/tools/collection/delete.ts +1 -19
- package/src/mcp/tools/config/update.ts +0 -4
- package/src/mcp/tools/global/update.ts +8 -0
- package/src/mcp/tools/job/create.ts +5 -11
- package/src/mcp/tools/job/run.ts +14 -38
- package/src/mcp/tools/job/update.ts +29 -77
- package/src/mcp/tools/resource/create.ts +7 -0
- package/src/mcp/tools/resource/update.ts +7 -0
- package/src/mcp/tools/schemas.ts +0 -1
- package/src/utils/getVirtualFieldNames.ts +53 -0
- package/src/utils/schemaConversion/convertCollectionSchemaToZod.ts +1 -3
- package/src/utils/schemaConversion/removeVirtualFieldsFromSchema.ts +27 -0
- package/src/utils/schemaConversion/sanitizeJsonSchema.ts +41 -0
- package/dist/mcp/helpers/conversion.d.ts +0 -2
- package/dist/mcp/helpers/conversion.d.ts.map +0 -1
- package/dist/mcp/helpers/conversion.js +0 -5
- package/dist/mcp/helpers/conversion.js.map +0 -1
- package/dist/mcp/helpers/validation.d.ts +0 -9
- package/dist/mcp/helpers/validation.d.ts.map +0 -1
- package/dist/mcp/helpers/validation.js +0 -22
- package/dist/mcp/helpers/validation.js.map +0 -1
- package/src/mcp/helpers/conversion.ts +0 -3
- package/src/mcp/helpers/validation.ts +0 -32
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AdminConfig,
|
|
3
|
-
CollectionConfigUpdates,
|
|
4
|
-
DatabaseConfig,
|
|
5
|
-
GeneralConfig,
|
|
6
|
-
PluginUpdates,
|
|
7
|
-
} from '../../types.js'
|
|
1
|
+
import type { AdminConfig, DatabaseConfig, PluginUpdates } from '../../types.js'
|
|
8
2
|
|
|
9
3
|
/**
|
|
10
4
|
* Adds a collection to the payload.config.ts file
|
|
@@ -217,110 +211,3 @@ export function updatePluginsConfig(content: string, pluginUpdates: PluginUpdate
|
|
|
217
211
|
|
|
218
212
|
return content
|
|
219
213
|
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Updates general configuration options in payload.config.ts
|
|
223
|
-
*/
|
|
224
|
-
export function updateGeneralConfig(content: string, generalConfig: GeneralConfig): string {
|
|
225
|
-
// Update various general configuration options
|
|
226
|
-
Object.entries(generalConfig).forEach(([key, value]) => {
|
|
227
|
-
if (value !== undefined && value !== null) {
|
|
228
|
-
const configRegex = new RegExp(`${key}:\\s*[^,}]*`, 'g')
|
|
229
|
-
|
|
230
|
-
if (content.match(configRegex)) {
|
|
231
|
-
if (typeof value === 'string') {
|
|
232
|
-
content = content.replace(configRegex, `${key}: '${value}'`)
|
|
233
|
-
} else if (typeof value === 'boolean') {
|
|
234
|
-
content = content.replace(configRegex, `${key}: ${value}`)
|
|
235
|
-
} else if (typeof value === 'object') {
|
|
236
|
-
content = content.replace(configRegex, `${key}: ${JSON.stringify(value, null, 2)}`)
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
// Add new config option
|
|
240
|
-
const configValue =
|
|
241
|
-
typeof value === 'string'
|
|
242
|
-
? `'${value}'`
|
|
243
|
-
: typeof value === 'object'
|
|
244
|
-
? JSON.stringify(value, null, 2)
|
|
245
|
-
: value
|
|
246
|
-
content = content.replace(
|
|
247
|
-
/export default buildConfig\(\{/,
|
|
248
|
-
`export default buildConfig({\n ${key}: ${configValue},`,
|
|
249
|
-
)
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
return content
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Updates collection-level configuration in a collection file
|
|
259
|
-
*/
|
|
260
|
-
export function updateCollectionConfig(
|
|
261
|
-
content: string,
|
|
262
|
-
updates: CollectionConfigUpdates,
|
|
263
|
-
collectionName: string,
|
|
264
|
-
): string {
|
|
265
|
-
let updatedContent = content
|
|
266
|
-
|
|
267
|
-
if (updates.slug) {
|
|
268
|
-
updatedContent = updatedContent.replace(/slug:\s*'[^']*'/, `slug: '${updates.slug}'`)
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (updates.access) {
|
|
272
|
-
const accessRegex = /access:\s*\{[^}]*\}/
|
|
273
|
-
if (updatedContent.match(accessRegex)) {
|
|
274
|
-
// Update existing access config
|
|
275
|
-
Object.entries(updates.access).forEach(([key, value]) => {
|
|
276
|
-
if (value !== undefined) {
|
|
277
|
-
updatedContent = updatedContent.replace(
|
|
278
|
-
new RegExp(`${key}:\\s*[^,}]*`),
|
|
279
|
-
`${key}: ${value}`,
|
|
280
|
-
)
|
|
281
|
-
}
|
|
282
|
-
})
|
|
283
|
-
} else {
|
|
284
|
-
// Add access config
|
|
285
|
-
const accessConfig = Object.entries(updates.access)
|
|
286
|
-
.filter(([, value]) => value !== undefined)
|
|
287
|
-
.map(([key, value]) => ` ${key}: ${value}`)
|
|
288
|
-
.join(',\n')
|
|
289
|
-
|
|
290
|
-
updatedContent = updatedContent.replace(
|
|
291
|
-
/slug:\s*'[^']*',/,
|
|
292
|
-
`slug: '${collectionName}',\n access: {\n${accessConfig}\n },`,
|
|
293
|
-
)
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (updates.timestamps !== undefined) {
|
|
298
|
-
if (updatedContent.includes('timestamps:')) {
|
|
299
|
-
updatedContent = updatedContent.replace(
|
|
300
|
-
/timestamps:[^,}]*/,
|
|
301
|
-
`timestamps: ${updates.timestamps}`,
|
|
302
|
-
)
|
|
303
|
-
} else {
|
|
304
|
-
updatedContent = updatedContent.replace(
|
|
305
|
-
/fields:\s*\[/,
|
|
306
|
-
`timestamps: ${updates.timestamps},\n fields: [`,
|
|
307
|
-
)
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (updates.versioning !== undefined) {
|
|
312
|
-
if (updatedContent.includes('versioning:')) {
|
|
313
|
-
updatedContent = updatedContent.replace(
|
|
314
|
-
/versioning:[^,}]*/,
|
|
315
|
-
`versioning: ${updates.versioning}`,
|
|
316
|
-
)
|
|
317
|
-
} else {
|
|
318
|
-
updatedContent = updatedContent.replace(
|
|
319
|
-
/fields:\s*\[/,
|
|
320
|
-
`versioning: ${updates.versioning},\n fields: [`,
|
|
321
|
-
)
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return updatedContent
|
|
326
|
-
}
|
|
@@ -1,21 +1,51 @@
|
|
|
1
|
-
type FieldDefinition
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import type { FieldDefinition, FieldModification } from '../../types.js'
|
|
2
|
+
|
|
3
|
+
/** Escapes a value for safe embedding inside a single-quoted TypeScript string literal. */
|
|
4
|
+
function escapeSingleQuotedString(value: string): string {
|
|
5
|
+
return value
|
|
6
|
+
.replace(/\\/g, '\\\\')
|
|
7
|
+
.replace(/'/g, "\\'")
|
|
8
|
+
.replace(/\r/g, '\\r')
|
|
9
|
+
.replace(/\n/g, '\\n')
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Generates the TypeScript source string for a single field definition block.
|
|
14
|
+
* Used when writing collection files to disk.
|
|
15
|
+
*/
|
|
16
|
+
export function generateFieldDefinitionString(field: FieldDefinition): string {
|
|
17
|
+
const lines: string[] = []
|
|
18
|
+
lines.push(` {`)
|
|
19
|
+
lines.push(` name: '${escapeSingleQuotedString(field.name)}',`)
|
|
20
|
+
lines.push(` type: '${escapeSingleQuotedString(field.type)}',`)
|
|
21
|
+
|
|
22
|
+
if (field.required) {
|
|
23
|
+
lines.push(` required: true,`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (field.description || field.position) {
|
|
27
|
+
lines.push(` admin: {`)
|
|
28
|
+
if (field.description) {
|
|
29
|
+
lines.push(` description: '${escapeSingleQuotedString(field.description)}',`)
|
|
30
|
+
}
|
|
31
|
+
if (field.position) {
|
|
32
|
+
lines.push(` position: '${escapeSingleQuotedString(field.position)}',`)
|
|
33
|
+
}
|
|
34
|
+
lines.push(` },`)
|
|
17
35
|
}
|
|
18
|
-
|
|
36
|
+
|
|
37
|
+
if (field.options && field.type === 'select') {
|
|
38
|
+
lines.push(` options: [`)
|
|
39
|
+
field.options.forEach((option) => {
|
|
40
|
+
lines.push(
|
|
41
|
+
` { label: '${escapeSingleQuotedString(option.label)}', value: '${escapeSingleQuotedString(option.value)}' },`,
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
lines.push(` ],`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
lines.push(` },`)
|
|
48
|
+
return lines.join('\n')
|
|
19
49
|
}
|
|
20
50
|
|
|
21
51
|
/**
|
|
@@ -30,41 +60,7 @@ export function addFieldsToCollection(content: string, newFields: FieldDefinitio
|
|
|
30
60
|
throw new Error('Could not find fields array in collection file')
|
|
31
61
|
}
|
|
32
62
|
|
|
33
|
-
|
|
34
|
-
const newFieldDefinitions = newFields
|
|
35
|
-
.map((field) => {
|
|
36
|
-
const fieldConfig = []
|
|
37
|
-
fieldConfig.push(` {`)
|
|
38
|
-
fieldConfig.push(` name: '${field.name}',`)
|
|
39
|
-
fieldConfig.push(` type: '${field.type}',`)
|
|
40
|
-
|
|
41
|
-
if (field.required) {
|
|
42
|
-
fieldConfig.push(` required: true,`)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (field.description || field.position) {
|
|
46
|
-
fieldConfig.push(` admin: {`)
|
|
47
|
-
if (field.description) {
|
|
48
|
-
fieldConfig.push(` description: '${field.description}',`)
|
|
49
|
-
}
|
|
50
|
-
if (field.position) {
|
|
51
|
-
fieldConfig.push(` position: '${field.position}',`)
|
|
52
|
-
}
|
|
53
|
-
fieldConfig.push(` },`)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (field.options && field.type === 'select') {
|
|
57
|
-
fieldConfig.push(` options: [`)
|
|
58
|
-
field.options.forEach((option: { label: string; value: string }) => {
|
|
59
|
-
fieldConfig.push(` { label: '${option.label}', value: '${option.value}' },`)
|
|
60
|
-
})
|
|
61
|
-
fieldConfig.push(` ],`)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
fieldConfig.push(` },`)
|
|
65
|
-
return fieldConfig.join('\n')
|
|
66
|
-
})
|
|
67
|
-
.join('\n')
|
|
63
|
+
const newFieldDefinitions = newFields.map(generateFieldDefinitionString).join('\n')
|
|
68
64
|
|
|
69
65
|
// Add new fields before the closing bracket
|
|
70
66
|
const existingFields = match[1] || ''
|
|
@@ -219,8 +219,8 @@ function validateCollectionConfig(config: CollectionConfig): ValidationResult<Co
|
|
|
219
219
|
// Validate each field has required properties
|
|
220
220
|
if (config.fields) {
|
|
221
221
|
for (let i = 0; i < config.fields.length; i++) {
|
|
222
|
-
const field = config.fields[i]
|
|
223
|
-
if (!field) {
|
|
222
|
+
const field = config.fields[i]
|
|
223
|
+
if (!field || typeof field !== 'object') {
|
|
224
224
|
return {
|
|
225
225
|
error: `Field at index ${i} is not a valid object`,
|
|
226
226
|
success: false,
|
|
@@ -228,9 +228,9 @@ function validateCollectionConfig(config: CollectionConfig): ValidationResult<Co
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
// Check if field has type property
|
|
231
|
-
if ('type' in field
|
|
231
|
+
if (!('type' in field) || !field.type) {
|
|
232
232
|
return {
|
|
233
|
-
error: `Field at index ${i}
|
|
233
|
+
error: `Field at index ${i} is missing a valid type property`,
|
|
234
234
|
success: false,
|
|
235
235
|
}
|
|
236
236
|
}
|
|
@@ -240,6 +240,29 @@ function validateCollectionConfig(config: CollectionConfig): ValidationResult<Co
|
|
|
240
240
|
return { config, success: true }
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Validates an array of schema fields (inputSchema / outputSchema).
|
|
245
|
+
* Returns an error string on the first invalid field, or null if all fields are valid.
|
|
246
|
+
*/
|
|
247
|
+
function validateSchemaFields(fields: TaskConfig['inputSchema'], label: string): null | string {
|
|
248
|
+
if (!fields || !Array.isArray(fields)) {
|
|
249
|
+
return null
|
|
250
|
+
}
|
|
251
|
+
for (let i = 0; i < fields.length; i++) {
|
|
252
|
+
const field = fields[i]
|
|
253
|
+
if (!field) {
|
|
254
|
+
return `${label} field at index ${i} is not a valid object`
|
|
255
|
+
}
|
|
256
|
+
if (!field.name) {
|
|
257
|
+
return `${label} field at index ${i} must have a valid name property`
|
|
258
|
+
}
|
|
259
|
+
if (!field.type) {
|
|
260
|
+
return `${label} field at index ${i} must have a valid type property`
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return null
|
|
264
|
+
}
|
|
265
|
+
|
|
243
266
|
/**
|
|
244
267
|
* Validate task configuration structure
|
|
245
268
|
*/
|
|
@@ -265,7 +288,6 @@ function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
|
265
288
|
}
|
|
266
289
|
}
|
|
267
290
|
|
|
268
|
-
// Validate optional properties
|
|
269
291
|
if (config.retries !== undefined && config.retries < 0) {
|
|
270
292
|
return {
|
|
271
293
|
error: 'Task config retries must be a non-negative number',
|
|
@@ -273,57 +295,14 @@ function validateTaskConfig(config: TaskConfig): ValidationResult<TaskConfig> {
|
|
|
273
295
|
}
|
|
274
296
|
}
|
|
275
297
|
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
const field = config.inputSchema[i]
|
|
280
|
-
if (!field) {
|
|
281
|
-
return {
|
|
282
|
-
error: `Input schema field at index ${i} is not a valid object`,
|
|
283
|
-
success: false,
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (!field.name) {
|
|
288
|
-
return {
|
|
289
|
-
error: `Input schema field at index ${i} must have a valid name property`,
|
|
290
|
-
success: false,
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (!field.type) {
|
|
295
|
-
return {
|
|
296
|
-
error: `Input schema field at index ${i} must have a valid type property`,
|
|
297
|
-
success: false,
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
298
|
+
const inputError = validateSchemaFields(config.inputSchema, 'Input schema')
|
|
299
|
+
if (inputError) {
|
|
300
|
+
return { error: inputError, success: false }
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (!field) {
|
|
307
|
-
return {
|
|
308
|
-
error: `Output schema field at index ${i} is not a valid object`,
|
|
309
|
-
success: false,
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (!field.name) {
|
|
314
|
-
return {
|
|
315
|
-
error: `Output schema field at index ${i} must have a valid name property`,
|
|
316
|
-
success: false,
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (!field.type) {
|
|
321
|
-
return {
|
|
322
|
-
error: `Output schema field at index ${i} must have a valid type property`,
|
|
323
|
-
success: false,
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
303
|
+
const outputError = validateSchemaFields(config.outputSchema, 'Output schema')
|
|
304
|
+
if (outputError) {
|
|
305
|
+
return { error: outputError, success: false }
|
|
327
306
|
}
|
|
328
307
|
|
|
329
308
|
return { config, success: true }
|
|
@@ -354,10 +333,9 @@ function validateWorkflowConfig(config: WorkflowConfig): ValidationResult<Workfl
|
|
|
354
333
|
}
|
|
355
334
|
}
|
|
356
335
|
|
|
357
|
-
|
|
358
|
-
if (config.queue) {
|
|
336
|
+
if (config.queue !== undefined && typeof config.queue !== 'string') {
|
|
359
337
|
return {
|
|
360
|
-
error: 'Workflow config queue must be a string',
|
|
338
|
+
error: 'Workflow config queue must be a string if provided',
|
|
361
339
|
success: false,
|
|
362
340
|
}
|
|
363
341
|
}
|
|
@@ -369,49 +347,16 @@ function validateWorkflowConfig(config: WorkflowConfig): ValidationResult<Workfl
|
|
|
369
347
|
}
|
|
370
348
|
}
|
|
371
349
|
|
|
372
|
-
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
const field = config.inputSchema[i]
|
|
376
|
-
if (!field) {
|
|
377
|
-
return {
|
|
378
|
-
error: `Input schema field at index ${i} is not a valid object`,
|
|
379
|
-
success: false,
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (!field.name) {
|
|
384
|
-
return {
|
|
385
|
-
error: `Input schema field at index ${i} must have a valid name property`,
|
|
386
|
-
success: false,
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (!field.type) {
|
|
391
|
-
return {
|
|
392
|
-
error: `Input schema field at index ${i} must have a valid type property`,
|
|
393
|
-
success: false,
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
350
|
+
const inputError = validateSchemaFields(config.inputSchema, 'Input schema')
|
|
351
|
+
if (inputError) {
|
|
352
|
+
return { error: inputError, success: false }
|
|
397
353
|
}
|
|
398
354
|
|
|
399
355
|
return { config, success: true }
|
|
400
356
|
}
|
|
401
357
|
|
|
402
|
-
// Convenience functions for backward compatibility
|
|
403
358
|
export const validateCollectionFile = async (
|
|
404
359
|
fileName: string,
|
|
405
360
|
): Promise<ValidationResult<CollectionConfig>> => {
|
|
406
361
|
return validatePayloadFile<CollectionConfig>(fileName, 'collection')
|
|
407
362
|
}
|
|
408
|
-
|
|
409
|
-
export const validateTaskFile = async (fileName: string): Promise<ValidationResult<TaskConfig>> => {
|
|
410
|
-
return validatePayloadFile<TaskConfig>(fileName, 'task')
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
export const validateWorkflowFile = async (
|
|
414
|
-
fileName: string,
|
|
415
|
-
): Promise<ValidationResult<WorkflowConfig>> => {
|
|
416
|
-
return validatePayloadFile<WorkflowConfig>(fileName, 'workflow')
|
|
417
|
-
}
|
|
@@ -4,6 +4,7 @@ import type { PayloadRequest } from 'payload'
|
|
|
4
4
|
import { writeFileSync } from 'fs'
|
|
5
5
|
import { join } from 'path'
|
|
6
6
|
|
|
7
|
+
import { generateFieldDefinitionString } from '../../helpers/fields.js'
|
|
7
8
|
import { validateCollectionFile } from '../../helpers/fileValidation.js'
|
|
8
9
|
import { toolSchemas } from '../schemas.js'
|
|
9
10
|
|
|
@@ -34,36 +35,7 @@ export const createCollection = async (
|
|
|
34
35
|
payload.logger.info(`[payload-mcp] Generated slug: ${slug} for collection: ${collectionName}`)
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
const generateFieldDefinition = (field: any) => {
|
|
39
|
-
const fieldConfig = []
|
|
40
|
-
fieldConfig.push(` {`)
|
|
41
|
-
fieldConfig.push(` name: '${field.name}',`)
|
|
42
|
-
fieldConfig.push(` type: '${field.type}',`)
|
|
43
|
-
|
|
44
|
-
if (field.required) {
|
|
45
|
-
fieldConfig.push(` required: true,`)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (field.description) {
|
|
49
|
-
fieldConfig.push(` admin: {`)
|
|
50
|
-
fieldConfig.push(` description: '${field.description}',`)
|
|
51
|
-
fieldConfig.push(` },`)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (field.options && field.type === 'select') {
|
|
55
|
-
fieldConfig.push(` options: [`)
|
|
56
|
-
field.options.forEach((option: { label: string; value: string }) => {
|
|
57
|
-
fieldConfig.push(` { label: '${option.label}', value: '${option.value}' },`)
|
|
58
|
-
})
|
|
59
|
-
fieldConfig.push(` ],`)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
fieldConfig.push(` },`)
|
|
63
|
-
return fieldConfig.join('\n')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const fieldDefinitions = fields.map(generateFieldDefinition).join('\n')
|
|
38
|
+
const fieldDefinitions = fields.map(generateFieldDefinitionString).join('\n')
|
|
67
39
|
|
|
68
40
|
// Generate collection file content
|
|
69
41
|
const collectionContent = `import type { CollectionConfig } from 'payload'
|
|
@@ -4,27 +4,9 @@ import type { PayloadRequest } from 'payload'
|
|
|
4
4
|
import { readFileSync, unlinkSync, writeFileSync } from 'fs'
|
|
5
5
|
import { join } from 'path'
|
|
6
6
|
|
|
7
|
+
import { removeCollectionFromConfig } from '../../helpers/config.js'
|
|
7
8
|
import { toolSchemas } from '../schemas.js'
|
|
8
9
|
|
|
9
|
-
// Helper function for removing collection from config
|
|
10
|
-
const removeCollectionFromConfig = (configContent: string, collectionName: string): string => {
|
|
11
|
-
// Simple implementation - find and remove the collection import and reference
|
|
12
|
-
let updatedContent = configContent
|
|
13
|
-
|
|
14
|
-
// Remove import statement
|
|
15
|
-
const importRegex = new RegExp(
|
|
16
|
-
`import\\s*{\\s*${collectionName}\\s*}\\s*from\\s*['"]\\./collections/${collectionName}['"];?\\s*\\n?`,
|
|
17
|
-
'g',
|
|
18
|
-
)
|
|
19
|
-
updatedContent = updatedContent.replace(importRegex, '')
|
|
20
|
-
|
|
21
|
-
// Remove from collections array
|
|
22
|
-
const collectionsRegex = new RegExp(`\\s*${collectionName},?\\s*`, 'g')
|
|
23
|
-
updatedContent = updatedContent.replace(collectionsRegex, '')
|
|
24
|
-
|
|
25
|
-
return updatedContent
|
|
26
|
-
}
|
|
27
|
-
|
|
28
10
|
export const deleteCollection = (
|
|
29
11
|
req: PayloadRequest,
|
|
30
12
|
verboseLogs: boolean,
|
|
@@ -21,7 +21,6 @@ export const updateConfig = (
|
|
|
21
21
|
adminConfig?: any,
|
|
22
22
|
databaseConfig?: any,
|
|
23
23
|
pluginUpdates?: any,
|
|
24
|
-
generalConfig?: any,
|
|
25
24
|
newContent?: string,
|
|
26
25
|
) => {
|
|
27
26
|
const payload = req.payload
|
|
@@ -218,7 +217,6 @@ export const updateConfigTool = (
|
|
|
218
217
|
adminConfig,
|
|
219
218
|
collectionName,
|
|
220
219
|
databaseConfig,
|
|
221
|
-
generalConfig,
|
|
222
220
|
newContent,
|
|
223
221
|
pluginUpdates,
|
|
224
222
|
updateType,
|
|
@@ -226,7 +224,6 @@ export const updateConfigTool = (
|
|
|
226
224
|
adminConfig?: any
|
|
227
225
|
collectionName?: string
|
|
228
226
|
databaseConfig?: any
|
|
229
|
-
generalConfig?: any
|
|
230
227
|
newContent?: string
|
|
231
228
|
pluginUpdates?: any
|
|
232
229
|
updateType: string
|
|
@@ -247,7 +244,6 @@ export const updateConfigTool = (
|
|
|
247
244
|
adminConfig,
|
|
248
245
|
databaseConfig,
|
|
249
246
|
pluginUpdates,
|
|
250
|
-
generalConfig,
|
|
251
247
|
newContent,
|
|
252
248
|
)
|
|
253
249
|
|
|
@@ -7,6 +7,10 @@ import { z } from 'zod'
|
|
|
7
7
|
import type { PluginMCPServerConfig } from '../../../types.js'
|
|
8
8
|
|
|
9
9
|
import { toCamelCase } from '../../../utils/camelCase.js'
|
|
10
|
+
import {
|
|
11
|
+
getGlobalVirtualFieldNames,
|
|
12
|
+
stripVirtualFields,
|
|
13
|
+
} from '../../../utils/getVirtualFieldNames.js'
|
|
10
14
|
import { convertCollectionSchemaToZod } from '../../../utils/schemaConversion/convertCollectionSchemaToZod.js'
|
|
11
15
|
import { toolSchemas } from '../schemas.js'
|
|
12
16
|
|
|
@@ -45,6 +49,10 @@ export const updateGlobalTool = (
|
|
|
45
49
|
let parsedData: Record<string, unknown>
|
|
46
50
|
try {
|
|
47
51
|
parsedData = JSON.parse(data)
|
|
52
|
+
|
|
53
|
+
const virtualFieldNames = getGlobalVirtualFieldNames(payload.config, globalSlug)
|
|
54
|
+
parsedData = stripVirtualFields(parsedData, virtualFieldNames)
|
|
55
|
+
|
|
48
56
|
if (verboseLogs) {
|
|
49
57
|
payload.logger.info(
|
|
50
58
|
`[payload-mcp] Parsed data for ${globalSlug}: ${JSON.stringify(parsedData)}`,
|
|
@@ -4,6 +4,7 @@ import type { PayloadRequest } from 'payload'
|
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
|
|
5
5
|
import { join } from 'path'
|
|
6
6
|
|
|
7
|
+
import { toCamelCase } from '../../../utils/camelCase.js'
|
|
7
8
|
import { validatePayloadFile } from '../../helpers/fileValidation.js'
|
|
8
9
|
import { toolSchemas } from '../schemas.js'
|
|
9
10
|
|
|
@@ -271,12 +272,12 @@ ${jobContent}
|
|
|
271
272
|
|
|
272
273
|
// Helper function to generate task content
|
|
273
274
|
function generateTaskContent(
|
|
274
|
-
|
|
275
|
+
_jobName: string,
|
|
275
276
|
jobSlug: string,
|
|
276
277
|
description: string,
|
|
277
278
|
inputSchema: any,
|
|
278
279
|
outputSchema: any,
|
|
279
|
-
|
|
280
|
+
_jobData: Record<string, any>,
|
|
280
281
|
): string {
|
|
281
282
|
const camelCaseJobSlug = toCamelCase(jobSlug)
|
|
282
283
|
|
|
@@ -307,12 +308,12 @@ export const ${camelCaseJobSlug}Task: Task = {
|
|
|
307
308
|
|
|
308
309
|
// Helper function to generate workflow content
|
|
309
310
|
function generateWorkflowContent(
|
|
310
|
-
|
|
311
|
+
_jobName: string,
|
|
311
312
|
jobSlug: string,
|
|
312
313
|
description: string,
|
|
313
314
|
inputSchema: any,
|
|
314
315
|
outputSchema: any,
|
|
315
|
-
|
|
316
|
+
_jobData: Record<string, any>,
|
|
316
317
|
): string {
|
|
317
318
|
const camelCaseJobSlug = toCamelCase(jobSlug)
|
|
318
319
|
|
|
@@ -339,13 +340,6 @@ export const ${camelCaseJobSlug}Workflow: Workflow = {
|
|
|
339
340
|
`
|
|
340
341
|
}
|
|
341
342
|
|
|
342
|
-
// Helper function to convert to camel case
|
|
343
|
-
function toCamelCase(str: string): string {
|
|
344
|
-
return str
|
|
345
|
-
.replace(/[-_\s]+(.)?/g, (_, chr) => (chr ? chr.toUpperCase() : ''))
|
|
346
|
-
.replace(/^(.)/, (_, chr) => chr.toLowerCase())
|
|
347
|
-
}
|
|
348
|
-
|
|
349
343
|
export const createJobTool = (
|
|
350
344
|
server: McpServer,
|
|
351
345
|
req: PayloadRequest,
|
package/src/mcp/tools/job/run.ts
CHANGED
|
@@ -8,7 +8,7 @@ export const runJob = async (
|
|
|
8
8
|
req: PayloadRequest,
|
|
9
9
|
verboseLogs: boolean,
|
|
10
10
|
jobSlug: string,
|
|
11
|
-
input: Record<string,
|
|
11
|
+
input: Record<string, unknown>,
|
|
12
12
|
queue?: string,
|
|
13
13
|
priority?: number,
|
|
14
14
|
delay?: number,
|
|
@@ -143,49 +143,25 @@ ${JSON.stringify(input, null, 2)}
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
export const runJobTool = (server: McpServer, req: PayloadRequest, verboseLogs: boolean) => {
|
|
146
|
-
const tool = async (
|
|
147
|
-
jobSlug: string,
|
|
148
|
-
input: Record<string, any>,
|
|
149
|
-
queue?: string,
|
|
150
|
-
priority?: number,
|
|
151
|
-
delay?: number,
|
|
152
|
-
) => {
|
|
153
|
-
if (verboseLogs) {
|
|
154
|
-
req.payload.logger.info(`[payload-mcp] Run Job Tool called with: ${jobSlug}`)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
const result = await runJob(req, verboseLogs, jobSlug, input, queue, priority, delay)
|
|
159
|
-
|
|
160
|
-
if (verboseLogs) {
|
|
161
|
-
req.payload.logger.info(`[payload-mcp] Run Job Tool completed successfully`)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return result
|
|
165
|
-
} catch (error) {
|
|
166
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
167
|
-
req.payload.logger.error(`[payload-mcp] Error in Run Job Tool: ${errorMessage}`)
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
content: [
|
|
171
|
-
{
|
|
172
|
-
type: 'text' as const,
|
|
173
|
-
text: `❌ **Error in Run Job Tool**: ${errorMessage}`,
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
146
|
server.registerTool(
|
|
181
147
|
'runJob',
|
|
182
148
|
{
|
|
183
149
|
description: 'Runs a Payload job with specified input data and queue options',
|
|
184
150
|
inputSchema: toolSchemas.runJob.parameters.shape,
|
|
185
151
|
},
|
|
186
|
-
async (
|
|
187
|
-
|
|
188
|
-
|
|
152
|
+
async ({ delay, input, jobSlug, priority, queue }) => {
|
|
153
|
+
if (verboseLogs) {
|
|
154
|
+
req.payload.logger.info(`[payload-mcp] Run Job Tool called with: ${jobSlug}`)
|
|
155
|
+
}
|
|
156
|
+
return runJob(
|
|
157
|
+
req,
|
|
158
|
+
verboseLogs,
|
|
159
|
+
jobSlug,
|
|
160
|
+
input as Record<string, unknown>,
|
|
161
|
+
queue,
|
|
162
|
+
priority,
|
|
163
|
+
delay,
|
|
164
|
+
)
|
|
189
165
|
},
|
|
190
166
|
)
|
|
191
167
|
}
|