mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2026-01-30 06:12:05 +00:00
refactor: extract metadata validation to shared utility
- Add validateMcpMetadata() utility function in tools/utils.js - Replace duplicated validation code in update-task.js and update-subtask.js - Reduces code duplication and ensures consistent validation Addresses CodeRabbit nitpick about duplicated metadata validation.
This commit is contained in:
committed by
Ralph Khreish
parent
bcee5b75dd
commit
7949faa352
@@ -7,7 +7,8 @@ import { TaskIdSchemaForMcp } from '@tm/core';
|
||||
import {
|
||||
createErrorResponse,
|
||||
handleApiResult,
|
||||
withNormalizedProjectRoot
|
||||
withNormalizedProjectRoot,
|
||||
validateMcpMetadata
|
||||
} from '@tm/mcp';
|
||||
import { z } from 'zod';
|
||||
import { resolveTag } from '../../../scripts/modules/utils.js';
|
||||
@@ -77,35 +78,14 @@ export function registerUpdateSubtaskTool(server) {
|
||||
}
|
||||
|
||||
// Validate metadata if provided
|
||||
let parsedMetadata = null;
|
||||
if (args.metadata) {
|
||||
// Check if metadata updates are allowed
|
||||
const allowMetadataUpdates =
|
||||
process.env.TASK_MASTER_ALLOW_METADATA_UPDATES === 'true';
|
||||
if (!allowMetadataUpdates) {
|
||||
return createErrorResponse(
|
||||
'Metadata updates are disabled. Set TASK_MASTER_ALLOW_METADATA_UPDATES=true in your MCP server environment to enable metadata modifications.'
|
||||
);
|
||||
}
|
||||
// Parse and validate JSON
|
||||
try {
|
||||
parsedMetadata = JSON.parse(args.metadata);
|
||||
if (
|
||||
typeof parsedMetadata !== 'object' ||
|
||||
parsedMetadata === null ||
|
||||
Array.isArray(parsedMetadata)
|
||||
) {
|
||||
return createErrorResponse(
|
||||
'Invalid metadata: must be a JSON object (not null or array)'
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
return createErrorResponse(
|
||||
`Invalid metadata JSON: ${args.metadata}. Provide a valid JSON object string.`
|
||||
);
|
||||
}
|
||||
const validationResult = validateMcpMetadata(
|
||||
args.metadata,
|
||||
createErrorResponse
|
||||
);
|
||||
if (validationResult.error) {
|
||||
return validationResult.error;
|
||||
}
|
||||
|
||||
const parsedMetadata = validationResult.parsedMetadata;
|
||||
// Validate that at least prompt or metadata is provided
|
||||
if (!args.prompt && !parsedMetadata) {
|
||||
return createErrorResponse(
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
import {
|
||||
createErrorResponse,
|
||||
handleApiResult,
|
||||
withNormalizedProjectRoot
|
||||
withNormalizedProjectRoot,
|
||||
validateMcpMetadata
|
||||
} from '@tm/mcp';
|
||||
import { z } from 'zod';
|
||||
import { resolveTag } from '../../../scripts/modules/utils.js';
|
||||
@@ -85,44 +86,23 @@ export function registerUpdateTaskTool(server) {
|
||||
);
|
||||
}
|
||||
|
||||
// 3. Validate metadata if provided
|
||||
let parsedMetadata = null;
|
||||
if (args.metadata) {
|
||||
// Check if metadata updates are allowed
|
||||
const allowMetadataUpdates =
|
||||
process.env.TASK_MASTER_ALLOW_METADATA_UPDATES === 'true';
|
||||
if (!allowMetadataUpdates) {
|
||||
return createErrorResponse(
|
||||
'Metadata updates are disabled. Set TASK_MASTER_ALLOW_METADATA_UPDATES=true in your MCP server environment to enable metadata modifications.'
|
||||
);
|
||||
}
|
||||
// Parse and validate JSON
|
||||
try {
|
||||
parsedMetadata = JSON.parse(args.metadata);
|
||||
if (
|
||||
typeof parsedMetadata !== 'object' ||
|
||||
parsedMetadata === null ||
|
||||
Array.isArray(parsedMetadata)
|
||||
) {
|
||||
return createErrorResponse(
|
||||
'Invalid metadata: must be a JSON object (not null or array)'
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
return createErrorResponse(
|
||||
`Invalid metadata JSON: ${args.metadata}. Provide a valid JSON object string.`
|
||||
);
|
||||
}
|
||||
// Validate metadata if provided
|
||||
const validationResult = validateMcpMetadata(
|
||||
args.metadata,
|
||||
createErrorResponse
|
||||
);
|
||||
if (validationResult.error) {
|
||||
return validationResult.error;
|
||||
}
|
||||
|
||||
// 4. Validate that at least prompt or metadata is provided
|
||||
const parsedMetadata = validationResult.parsedMetadata;
|
||||
// Validate that at least prompt or metadata is provided
|
||||
if (!args.prompt && !parsedMetadata) {
|
||||
return createErrorResponse(
|
||||
'Either prompt or metadata must be provided for update-task'
|
||||
);
|
||||
}
|
||||
|
||||
// 5. Call Direct Function - Include projectRoot and metadata
|
||||
// Call Direct Function - Include projectRoot and metadata
|
||||
const result = await updateTaskByIdDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
|
||||
@@ -829,6 +829,72 @@ function checkProgressCapability(reportProgress, log) {
|
||||
return reportProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and parses metadata string for MCP tools.
|
||||
* Checks environment flag, validates JSON format, and ensures metadata is a plain object.
|
||||
*
|
||||
* @param {string|null|undefined} metadataString - JSON string to parse and validate
|
||||
* @param {Function} createErrorResponse - Function to create error response
|
||||
* @returns {{parsedMetadata: Object|null, error?: Object}} Object with parsed metadata or error
|
||||
*
|
||||
* @example Success case:
|
||||
* const result = validateMcpMetadata('{"key":"value"}', createErrorResponse);
|
||||
* if (result.error) return result.error;
|
||||
* const metadata = result.parsedMetadata; // { key: "value" }
|
||||
*
|
||||
* @example Disabled case:
|
||||
* // When TASK_MASTER_ALLOW_METADATA_UPDATES !== 'true'
|
||||
* const result = validateMcpMetadata('{"key":"value"}', createErrorResponse);
|
||||
* // Returns: { error: <error response> }
|
||||
*
|
||||
* @example Invalid JSON:
|
||||
* const result = validateMcpMetadata('{invalid}', createErrorResponse);
|
||||
* // Returns: { error: <error response> }
|
||||
*/
|
||||
export function validateMcpMetadata(metadataString, createErrorResponse) {
|
||||
// Return null if no metadata provided
|
||||
if (!metadataString) {
|
||||
return { parsedMetadata: null };
|
||||
}
|
||||
|
||||
// Check if metadata updates are allowed via environment variable
|
||||
const allowMetadataUpdates =
|
||||
process.env.TASK_MASTER_ALLOW_METADATA_UPDATES === 'true';
|
||||
if (!allowMetadataUpdates) {
|
||||
return {
|
||||
error: createErrorResponse(
|
||||
'Metadata updates are disabled. Set TASK_MASTER_ALLOW_METADATA_UPDATES=true in your MCP server environment to enable metadata modifications.'
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Parse and validate JSON
|
||||
try {
|
||||
const parsedMetadata = JSON.parse(metadataString);
|
||||
|
||||
// Ensure it's a plain object (not null, not array)
|
||||
if (
|
||||
typeof parsedMetadata !== 'object' ||
|
||||
parsedMetadata === null ||
|
||||
Array.isArray(parsedMetadata)
|
||||
) {
|
||||
return {
|
||||
error: createErrorResponse(
|
||||
'Invalid metadata: must be a JSON object (not null or array)'
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
return { parsedMetadata };
|
||||
} catch {
|
||||
return {
|
||||
error: createErrorResponse(
|
||||
`Invalid metadata JSON: ${metadataString}. Provide a valid JSON object string.`
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all functions are exported
|
||||
export {
|
||||
getProjectRoot,
|
||||
|
||||
Reference in New Issue
Block a user