Files
claude-task-master/mcp-server/src/tools/parse-prd.js
Joe Danziger e3ed4d7c14 feat: CLI & MCP progress tracking for parse-prd command (#1048)
* initial cutover

* update log to debug

* update tracker to pass units

* update test to match new base tracker format

* add streamTextService mocks

* remove unused imports

* Ensure the CLI waits for async main() completion

* refactor to reduce code duplication

* update comment

* reuse function

* ensure targetTag is defined in streaming mode

* avoid throwing inside process.exit spy

* check for null

* remove reference to generate

* fix formatting

* fix textStream assignment

* ensure no division by 0

* fix jest chalk mocks

* refactor for maintainability

* Improve bar chart calculation logic for consistent visual representation

* use custom streaming error types; fix mocks

* Update streamText extraction in parse-prd.js to match actual service response

* remove check - doesn't belong here

* update mocks

* remove streaming test that wasn't really doing anything

* add comment

* make parsing logic more DRY

* fix formatting

* Fix textStream extraction to match actual service response

* fix mock

* Add a cleanup method to ensure proper resource disposal and prevent memory leaks

* debounce progress updates to reduce UI flicker during rapid updates

* Implement timeout protection for streaming operations (60-second timeout) with automatic fallback to non-streaming mode.

* clear timeout properly

* Add a maximum buffer size limit (1MB) to prevent unbounded memory growth with very large streaming responses.

* fix formatting

* remove duplicate mock

* better docs

* fix formatting

* sanitize the dynamic property name

* Fix incorrect remaining progress calculation

* Use onError callback instead of console.warn

* Remove unused chalk import

* Add missing custom validator in fallback parsing configuration

* add custom validator parameter in fallback parsing

* chore: fix package-lock.json

* chore: large code refactor

* chore: increase timeout from 1 minute to 3 minutes

* fix: refactor and fix streaming

* Merge remote-tracking branch 'origin/next' into joedanz/parse-prd-progress

* fix: cleanup and fix unit tests

* chore: fix unit tests

* chore: fix format

* chore: run format

* chore: fix weird CI unit test error

* chore: fix format

---------

Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
2025-08-12 22:37:07 +02:00

102 lines
3.0 KiB
JavaScript

/**
* tools/parsePRD.js
* Tool to parse PRD document and generate tasks
*/
import { z } from 'zod';
import {
handleApiResult,
withNormalizedProjectRoot,
createErrorResponse,
checkProgressCapability
} from './utils.js';
import { parsePRDDirect } from '../core/task-master-core.js';
import {
PRD_FILE,
TASKMASTER_DOCS_DIR,
TASKMASTER_TASKS_FILE
} from '../../../src/constants/paths.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
/**
* Register the parse_prd tool
* @param {Object} server - FastMCP server instance
*/
export function registerParsePRDTool(server) {
server.addTool({
name: 'parse_prd',
description: `Parse a Product Requirements Document (PRD) text file to automatically generate initial tasks. Reinitializing the project is not necessary to run this tool. It is recommended to run parse-prd after initializing the project and creating/importing a prd.txt file in the project root's ${TASKMASTER_DOCS_DIR} directory.`,
parameters: z.object({
input: z
.string()
.optional()
.default(PRD_FILE)
.describe('Absolute path to the PRD document file (.txt, .md, etc.)'),
projectRoot: z
.string()
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on'),
output: z
.string()
.optional()
.describe(
`Output path for tasks.json file (default: ${TASKMASTER_TASKS_FILE})`
),
numTasks: z
.string()
.optional()
.describe(
'Approximate number of top-level tasks to generate (default: 10). As the agent, if you have enough information, ensure to enter a number of tasks that would logically scale with project complexity. Setting to 0 will allow Taskmaster to determine the appropriate number of tasks based on the complexity of the PRD. Avoid entering numbers above 50 due to context window limitations.'
),
force: z
.boolean()
.optional()
.default(false)
.describe('Overwrite existing output file without prompting.'),
research: z
.boolean()
.optional()
.describe(
'Enable Taskmaster to use the research role for potentially more informed task generation. Requires appropriate API key.'
),
append: z
.boolean()
.optional()
.describe('Append generated tasks to existing file.')
}),
execute: withNormalizedProjectRoot(
async (args, { log, session, reportProgress }) => {
try {
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
const progressCapability = checkProgressCapability(
reportProgress,
log
);
const result = await parsePRDDirect(
{
...args,
tag: resolvedTag
},
log,
{ session, reportProgress: progressCapability }
);
return handleApiResult(
result,
log,
'Error parsing PRD',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in parse_prd: ${error.message}`);
return createErrorResponse(`Failed to parse PRD: ${error.message}`);
}
}
)
});
}