start_project
Retrieve project details and the first task's prompt using a unique three-letter project identifier to begin work or understand the starting point.
Instructions
Retrieves the project details and the prompt for the very first task of a specified project using the project's unique slug (e.g., 'CRD'). This is useful for initiating work on a new project or understanding its starting point.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | The unique three-letter uppercase identifier for the project (e.g., 'CRD') for which the first task's prompt is to be retrieved. |
Implementation Reference
- src/tools/start-project.ts:103-153 (handler)The main handler function that executes the tool logic: makes API call to retrieve project first task, sets up git repository if needed, handles errors, and returns structured response with project, task, and git setup info.async execute(input: StartProjectInput): Promise<unknown> { logger.info('Executing start-project tool', input); try { // Use the injected API client to get first task if (!this.apiClient) { throw new Error('API client not available - tool not properly initialized'); } // Get the first task of the project using the new endpoint const url = `/project/slug/${input.slug.toUpperCase()}/first-task`; logger.debug(`Making GET request to: ${url}`); const responseData = await this.apiClient.get<StartProjectApiResponse>(url) as unknown as StartProjectApiResponse; // const responseData: StartProjectApiResponse = axiosResponse.data; // This was the previous incorrect line if (!responseData || responseData.error) { const errorMessage = responseData?.error || `Failed to get first task for project '${input.slug}' (no data or error in response).`; logger.warn(`Error in start-project tool: ${errorMessage}`, { responseData }); return { isError: true, content: [{ type: "text", text: errorMessage }] }; } // Git integration: Set up repository if needed const gitSetupResult = await this.setupGitRepository(responseData.project); // Return data structured according to the new schema with git setup status return { project: { slug: responseData.project?.slug || '', name: responseData.project?.name || '' }, task: { number: responseData.task?.number || '', title: responseData.task?.title || '', prompt: responseData.task?.prompt || '' // Access 'prompt' and output as 'prompt' }, gitSetup: gitSetupResult }; } catch (error) { const errorMessage = (error instanceof Error) ? error.message : 'An unknown error occurred'; logger.error(`Error in start-project tool: ${errorMessage}`, error instanceof Error ? error : undefined); return { isError: true, content: [{ type: "text", text: errorMessage }] }; } }
- src/tools/start-project.ts:16-23 (schema)Zod input schema validation for the start_project tool, requiring a 3-letter project slug.const StartProjectSchema = z.object({ // Project slug (URL-friendly identifier) slug: z.string({ required_error: "Project slug is required" }) .regex(/^[A-Za-z]{3}$/, { message: "Project slug must be three letters (e.g., CRD or crd). Case insensitive." }) .describe("Project slug identifier (e.g., 'CRD' or 'crd'). Case insensitive"), }).strict();
- src/index.ts:315-330 (registration)Tool instantiation with dependency injection (secureApiClient) and registration to the MCP server via BaseTool.register() method.const tools: any[] = [ new StartProjectTool(secureApiClient), new GetPromptTool(secureApiClient), new GetTaskTool(secureApiClient), new GetProjectTool(secureApiClient), new UpdateTaskTool(secureApiClient), new UpdateProjectTool(secureApiClient), new ListProjectsTool(secureApiClient), new ListTasksTool(secureApiClient), new NextTaskTool(secureApiClient), ]; // Register each tool with the server tools.forEach(tool => { tool.register(server); });
- src/tools/start-project.ts:158-219 (helper)Helper method that automatically sets up git repository for the project if not already present, including init, add, commit with conventional commit message.private async setupGitRepository(projectData: any): Promise<{ status: string; message: string; actions: string[] }> { try { const projectSlug = projectData?.slug; const projectName = projectData?.name || projectSlug; // Check if we're in a git repository const { execSync } = await import('child_process'); try { execSync('git rev-parse --git-dir', { stdio: 'ignore' }); // Already in a git repository return { status: 'existing', message: 'Git repository already exists', actions: [ 'Verified existing git repository', 'Ready for project development', 'Consider creating feature branch for project work' ] }; } catch { // Not in a git repository, initialize one try { execSync('git init', { stdio: 'ignore' }); execSync('git add .', { stdio: 'ignore' }); execSync(`git commit -m "feat: initialize ${projectName} project (${projectSlug})"`, { stdio: 'ignore' }); return { status: 'initialized', message: 'Git repository initialized successfully', actions: [ 'Initialized new git repository', 'Created initial commit for project', 'Ready for feature branch creation', 'Consider setting up remote repository' ] }; } catch (gitError) { return { status: 'failed', message: `Git initialization failed: ${gitError}`, actions: [ 'Manual git setup required', 'Run: git init', 'Run: git add .', 'Run: git commit -m "feat: initialize project"' ] }; } } } catch (error) { return { status: 'error', message: `Git setup error: ${error}`, actions: [ 'Git not available or accessible', 'Install git if needed', 'Verify git is in PATH' ] }; } }