internaltool-mcp 1.5.0 → 1.5.1

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.
Files changed (2) hide show
  1. package/index.js +58 -40
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -448,74 +448,92 @@ Use this when the developer says "wrap up", "end of day", or "I'm done for today
448
448
 
449
449
  server.tool(
450
450
  'kickoff_task',
451
- `Kick off a task — brief the developer and move it to in_progress.
452
- Fetches the full task details plus recent project commits for context.
453
- Returns everything needed to start: task plan, what recently changed in the repo, and the git branch command to run.
454
- Use this when a developer says "start task", "brief me on", or "what do I need to do for TASK-X".
451
+ `Kick off a task — read the implementation plan (README) and brief the developer, then move the task to in_progress.
455
452
 
456
- Set confirmed=false first to preview what will happen, then confirmed=true to actually move the task to in_progress.`,
453
+ The README/implementation plan IS the brief. Always read it fully and present it to the developer
454
+ before they write a single line of code. If no README exists, warn the developer that the plan is
455
+ missing and suggest they write one before starting.
456
+
457
+ Workflow:
458
+ 1. confirmed=false → show the full README brief + subtask checklist so developer can read the plan
459
+ 2. confirmed=true → move task to in_progress, return branch name and recent repo commits
460
+
461
+ Use this when a developer says "start task", "brief me on", or "what do I need to do for TASK-X".`,
457
462
  {
458
463
  taskId: z.string().describe("Task's MongoDB ObjectId"),
459
- confirmed: z.boolean().optional().default(false).describe('Set true to move the task to in_progress'),
464
+ confirmed: z.boolean().optional().default(false).describe('Set true after reading the plan to move the task to in_progress'),
460
465
  },
461
466
  async ({ taskId, confirmed = false }) => {
462
- // Get full task
463
467
  const taskRes = await api.get(`/api/tasks/${taskId}`)
464
468
  if (!taskRes?.success) return errorText('Task not found')
465
469
  const task = taskRes.data.task
466
470
 
467
- // Get recent commits from the project
468
- let recentCommits = []
469
- try {
470
- const commitsRes = await api.get(
471
- `/api/projects/${task.project}/github/commits?per_page=10`
472
- )
473
- if (commitsRes?.success) recentCommits = commitsRes.data.commits || []
474
- } catch { /* GitHub may not be linked */ }
475
-
476
471
  const suggestedBranch = `feature/${task.key?.toLowerCase()}-${task.title
477
472
  .toLowerCase()
478
473
  .replace(/[^a-z0-9]+/g, '-')
479
474
  .slice(0, 40)}`
480
475
 
481
- // Preview mode show what will happen without touching the task
476
+ const hasReadme = !!(task.readmeMarkdown && task.readmeMarkdown.trim().length > 0)
477
+ const subtasks = (task.subtasks || []).map(s => ({
478
+ title: s.title,
479
+ done: s.done,
480
+ status: s.done ? '✅' : '⬜',
481
+ }))
482
+ const subtasksDone = subtasks.filter(s => s.done).length
483
+ const subtasksTotal = subtasks.length
484
+
485
+ // ── Preview: show the full plan before touching anything ──
482
486
  if (!confirmed) {
483
487
  return text({
484
- preview: {
485
- action: 'kickoff_task',
486
- task: { key: task.key, title: task.title, currentColumn: task.column, priority: task.priority },
487
- willMoveTo: 'in_progress',
488
+ brief: {
489
+ key: task.key,
490
+ title: task.title,
491
+ priority: task.priority,
492
+ description: task.description || '(no description)',
493
+ // The implementation plan — Claude must read and present this to the developer
494
+ implementationPlan: hasReadme
495
+ ? task.readmeMarkdown
496
+ : '⚠️ No implementation plan (README) found for this task. The developer should write one before starting work.',
497
+ subtasks: subtasksTotal > 0
498
+ ? { items: subtasks, progress: `${subtasksDone}/${subtasksTotal} done` }
499
+ : null,
500
+ approvalState: task.approval?.state || 'none',
501
+ },
502
+ meta: {
503
+ currentColumn: task.column,
504
+ willMoveTo: 'in_progress',
488
505
  suggestedBranch,
489
506
  },
490
507
  requiresConfirmation: true,
491
- message: `This will move "${task.key}: ${task.title}" to in_progress. Call kickoff_task again with confirmed=true to proceed.`,
508
+ message: hasReadme
509
+ ? `Read the implementation plan above carefully, then call kickoff_task again with confirmed=true to start the task.`
510
+ : `⚠️ This task has no implementation plan. Consider writing one first (use update_task with readmeMarkdown), then confirm to start anyway.`,
492
511
  })
493
512
  }
494
513
 
495
- // Move to in_progress
514
+ // ── Confirmed: move to in_progress and fetch recent commits ──
515
+ let recentCommits = []
516
+ try {
517
+ const commitsRes = await api.get(`/api/projects/${task.project}/github/commits?per_page=10`)
518
+ if (commitsRes?.success) recentCommits = commitsRes.data.commits || []
519
+ } catch { /* GitHub may not be linked */ }
520
+
496
521
  let moved = false
497
522
  try {
498
- const moveRes = await api.post(`/api/tasks/${taskId}/move`, {
499
- column: 'in_progress',
500
- toIndex: 0,
501
- })
523
+ const moveRes = await api.post(`/api/tasks/${taskId}/move`, { column: 'in_progress', toIndex: 0 })
502
524
  moved = moveRes?.success ?? false
503
525
  } catch { /* might already be in_progress */ }
504
526
 
505
527
  return text({
506
- task: {
507
- id: task._id,
508
- key: task.key,
509
- title: task.title,
510
- description: task.description,
511
- priority: task.priority,
512
- column: moved ? 'in_progress' : task.column,
513
- readme: task.readmeMarkdown,
514
- subtasks: task.subtasks,
515
- parkNote: task.parkNote,
516
- approval: task.approval,
528
+ started: {
529
+ key: task.key,
530
+ title: task.title,
531
+ priority: task.priority,
532
+ column: moved ? 'in_progress' : task.column,
533
+ subtasks,
517
534
  },
518
- recentCommits: recentCommits.slice(0, 5).map((c) => ({
535
+ implementationPlan: hasReadme ? task.readmeMarkdown : null,
536
+ recentCommits: recentCommits.slice(0, 5).map(c => ({
519
537
  sha: c.sha?.slice(0, 7),
520
538
  message: c.commit?.message?.split('\n')[0],
521
539
  author: c.commit?.author?.name,
@@ -523,7 +541,7 @@ Set confirmed=false first to preview what will happen, then confirmed=true to ac
523
541
  })),
524
542
  movedToInProgress: moved,
525
543
  suggestedBranch,
526
- nextStep: `Branch created? Run: git checkout -b ${suggestedBranch}\nOr use the create_branch tool to create it on GitHub automatically.`,
544
+ nextStep: `Use create_branch to create "${suggestedBranch}" on GitHub, then run:\n git fetch origin\n git checkout ${suggestedBranch}`,
527
545
  })
528
546
  }
529
547
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "internaltool-mcp",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "MCP server for InternalTool — connect AI assistants (Claude Code, Cursor) to your project and task management platform",
5
5
  "type": "module",
6
6
  "main": "index.js",