@vibescope/mcp-server 0.4.0 → 0.4.2
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/api-client/fallback.d.ts +33 -0
- package/dist/api-client/fallback.js +21 -0
- package/dist/api-client/findings.d.ts +69 -0
- package/dist/api-client/findings.js +36 -0
- package/dist/api-client/index.d.ts +78 -1
- package/dist/api-client/index.js +74 -4
- package/dist/api-client/milestones.d.ts +59 -0
- package/dist/api-client/milestones.js +30 -0
- package/dist/api-client/validation.d.ts +35 -0
- package/dist/api-client/validation.js +23 -0
- package/dist/api-client.d.ts +4 -0
- package/dist/cli-init.d.ts +17 -0
- package/dist/cli-init.js +497 -0
- package/dist/handlers/cloud-agents.d.ts +4 -0
- package/dist/handlers/cloud-agents.js +26 -12
- package/dist/handlers/discovery.js +15 -0
- package/dist/handlers/findings.js +1 -1
- package/dist/handlers/ideas.js +1 -1
- package/dist/handlers/index.d.ts +1 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/session.js +115 -2
- package/dist/handlers/tasks.js +7 -5
- package/dist/handlers/tool-docs.js +344 -0
- package/dist/handlers/version.d.ts +5 -0
- package/dist/handlers/version.js +53 -0
- package/dist/index.js +7 -0
- package/dist/templates/agent-guidelines.d.ts +3 -1
- package/dist/templates/agent-guidelines.js +5 -1
- package/dist/templates/help-content.js +2 -2
- package/dist/tools/chat.d.ts +7 -0
- package/dist/tools/chat.js +43 -0
- package/dist/tools/cloud-agents.js +31 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.js +6 -1
- package/dist/tools/project.js +1 -1
- package/dist/tools/tasks.js +8 -0
- package/dist/tools/version.d.ts +5 -0
- package/dist/tools/version.js +28 -0
- package/dist/version.d.ts +28 -0
- package/dist/version.js +91 -0
- package/docs/TOOLS.md +93 -3
- package/package.json +4 -2
- package/src/api-client/fallback.ts +52 -0
- package/src/api-client/findings.ts +100 -0
- package/src/api-client/index.ts +91 -9
- package/src/api-client/milestones.ts +83 -0
- package/src/api-client/validation.ts +60 -0
- package/src/api-client.ts +4 -0
- package/src/cli-init.ts +557 -0
- package/src/handlers/cloud-agents.test.ts +438 -0
- package/src/handlers/cloud-agents.ts +35 -17
- package/src/handlers/discovery.ts +15 -0
- package/src/handlers/findings.ts +1 -1
- package/src/handlers/ideas.ts +1 -1
- package/src/handlers/index.ts +3 -0
- package/src/handlers/session.ts +128 -2
- package/src/handlers/tasks.ts +7 -5
- package/src/handlers/tool-docs.test.ts +511 -0
- package/src/handlers/tool-docs.ts +382 -0
- package/src/handlers/version.ts +63 -0
- package/src/index.ts +9 -0
- package/src/templates/agent-guidelines.ts +6 -1
- package/src/templates/help-content.ts +2 -2
- package/src/tools/chat.ts +46 -0
- package/src/tools/cloud-agents.ts +31 -0
- package/src/tools/index.ts +6 -0
- package/src/tools/project.ts +1 -1
- package/src/tools/tasks.ts +8 -0
- package/src/tools/version.ts +34 -0
- package/src/version.ts +109 -0
package/src/handlers/session.ts
CHANGED
|
@@ -179,10 +179,29 @@ export const startWorkSession: Handler = async (args, ctx) => {
|
|
|
179
179
|
|
|
180
180
|
// Session info
|
|
181
181
|
result.session_id = data.session_id;
|
|
182
|
+
result.IMPORTANT_session_id_reminder = `Save this session_id ("${data.session_id}") and pass it on EVERY update_task and complete_task call. Without it, the dashboard shows "Agent" instead of your name.`;
|
|
182
183
|
result.persona = data.persona;
|
|
183
184
|
result.role = data.role;
|
|
184
185
|
result.project = data.project;
|
|
185
186
|
|
|
187
|
+
// For cloud agents: include workspace setup instructions if repo not yet cloned
|
|
188
|
+
// Cloud agents pass git_url; check if workspace needs setup
|
|
189
|
+
if (git_url && data.project?.git_url) {
|
|
190
|
+
result.workspace_setup = {
|
|
191
|
+
message: 'If the project repo is NOT already cloned to your workspace, follow these steps:',
|
|
192
|
+
steps: [
|
|
193
|
+
`git clone ${data.project.git_url} ~/workspace/project`,
|
|
194
|
+
'cd ~/workspace/project',
|
|
195
|
+
...(data.project.git_workflow === 'git-flow'
|
|
196
|
+
? [`git checkout ${data.project.git_develop_branch || 'develop'}`]
|
|
197
|
+
: []),
|
|
198
|
+
'Install dependencies (check for pnpm-lock.yaml, package-lock.json, etc.)',
|
|
199
|
+
'If using SvelteKit: run `pnpm exec svelte-kit sync` or equivalent',
|
|
200
|
+
],
|
|
201
|
+
note: 'Skip these steps if ~/workspace/project already exists and has the repo.',
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
186
205
|
// Inform agent if git_url was normalized (helps explain URL matching behavior)
|
|
187
206
|
if (gitUrlWasNormalized) {
|
|
188
207
|
result.git_url_normalized = {
|
|
@@ -302,6 +321,111 @@ export const startWorkSession: Handler = async (args, ctx) => {
|
|
|
302
321
|
}
|
|
303
322
|
}
|
|
304
323
|
|
|
324
|
+
// Build dynamic AGENT_RULES from project settings
|
|
325
|
+
const agentRules: string[] = [];
|
|
326
|
+
const projectWorkflow = data.project?.git_workflow;
|
|
327
|
+
const isBranching = projectWorkflow === 'git-flow' || projectWorkflow === 'github-flow';
|
|
328
|
+
const ruleBaseBranch = projectWorkflow === 'git-flow'
|
|
329
|
+
? (data.project?.git_develop_branch || 'develop')
|
|
330
|
+
: (data.project?.git_main_branch || 'main');
|
|
331
|
+
|
|
332
|
+
// Git workflow rules (dynamic based on project settings)
|
|
333
|
+
if (isBranching) {
|
|
334
|
+
agentRules.push(`WORKTREE REQUIRED: Create a git worktree BEFORE making ANY file edits. Command: git worktree add ../PROJECT-PERSONA-task -b feature/TASKID-desc ${ruleBaseBranch}`);
|
|
335
|
+
agentRules.push(`REBASE BEFORE PR: Always rebase onto ${ruleBaseBranch} before creating a PR. Run: git fetch origin && git rebase origin/${ruleBaseBranch} && git push --force-with-lease. This prevents overwriting other agents' work.`);
|
|
336
|
+
}
|
|
337
|
+
if (projectWorkflow && projectWorkflow !== 'none') {
|
|
338
|
+
agentRules.push(`GIT WORKFLOW: This project uses ${projectWorkflow}. Branch from ${ruleBaseBranch}. Do NOT commit directly to main or develop.`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Task lifecycle rules
|
|
342
|
+
agentRules.push('COMPLETE TASKS: Always call complete_task(task_id, summary, session_id) immediately after creating a PR. This is mandatory — it updates the dashboard and triggers validation.');
|
|
343
|
+
agentRules.push('SESSION ID: Pass session_id on EVERY update_task and complete_task call. Without it, the dashboard shows "Agent" instead of your name.');
|
|
344
|
+
agentRules.push(`STATUS UPDATES: Call update_agent_status(status_message: "Working on: TASK_TITLE", project_id: "${data.project?.id || ''}", agent_name: "${result.persona || ''}") whenever you start or finish a task.`);
|
|
345
|
+
agentRules.push('TRACK PROGRESS: Call update_task with progress_percentage (0-100) every 15-20% of task completion.');
|
|
346
|
+
|
|
347
|
+
// Validation rules (dynamic based on project settings)
|
|
348
|
+
if (data.project?.validation_required !== false) {
|
|
349
|
+
agentRules.push('REVIEW REQUIRED: All completed tasks must be reviewed/validated by another agent before merging.');
|
|
350
|
+
}
|
|
351
|
+
if (data.project?.auto_merge_on_approval !== false) {
|
|
352
|
+
agentRules.push('AUTO-MERGE: After approving a PR during validation, merge it immediately with `gh pr merge --squash`.');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Autonomy rules
|
|
356
|
+
agentRules.push('BE AUTONOMOUS: Pick up tasks without asking permission. Never ask "Should I continue?" — just continue to the next task.');
|
|
357
|
+
agentRules.push('BREAK DOWN COMPLEX TASKS: If a task is too large, create subtasks with add_subtask() and start on the first one immediately.');
|
|
358
|
+
|
|
359
|
+
result.AGENT_RULES = agentRules;
|
|
360
|
+
|
|
361
|
+
// Build WORKFLOW section — dynamic step-by-step instructions
|
|
362
|
+
// This replaces the hardcoded workflow in CLAUDE.md
|
|
363
|
+
const workflow: Record<string, unknown> = {};
|
|
364
|
+
|
|
365
|
+
// Continuous work loop
|
|
366
|
+
workflow.continuous_work = {
|
|
367
|
+
description: 'After completing a task, immediately continue to the next one.',
|
|
368
|
+
steps: [
|
|
369
|
+
'complete_task(task_id, summary, session_id) — returns next_task if available',
|
|
370
|
+
'If no next_task returned: call get_next_task(project_id)',
|
|
371
|
+
'If no tasks available: call get_pending_requests(project_id) and handle any',
|
|
372
|
+
'If still nothing: call signal_idle() then start_fallback_activity(project_id, activity: "code_review")',
|
|
373
|
+
],
|
|
374
|
+
rule: 'Never ask permission. Never stop working while tasks exist.',
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// Validation workflow (only if validation is enabled)
|
|
378
|
+
if (data.project?.validation_required !== false) {
|
|
379
|
+
workflow.validation = {
|
|
380
|
+
description: 'How to validate/review completed tasks. Review PRs in FIFO order (lowest PR number first).',
|
|
381
|
+
steps: [
|
|
382
|
+
'claim_validation(task_id) — returns worktree setup commands and PR info',
|
|
383
|
+
`Set up worktree from existing branch: git fetch origin feature/xxx && git worktree add ../PROJECT-PERSONA-validation feature/xxx`,
|
|
384
|
+
'Review code, run tests if applicable',
|
|
385
|
+
'Verify PR checks: gh pr view <PR> --json statusCheckRollup,mergeable',
|
|
386
|
+
'Approve: validate_task(task_id, approved: true, pr_checks_passing: true, validation_notes: "...")',
|
|
387
|
+
data.project?.auto_merge_on_approval !== false
|
|
388
|
+
? 'Merge immediately: gh pr merge <PR> --squash'
|
|
389
|
+
: 'Do NOT merge — wait for project owner to merge.',
|
|
390
|
+
'Reject: validate_task(task_id, approved: false, validation_notes: "...", create_fix_task: true)',
|
|
391
|
+
'Clean up worktree after validation',
|
|
392
|
+
],
|
|
393
|
+
handle_failures: {
|
|
394
|
+
tests_fail: 'Use create_fix_task: true in validate_task() to create a follow-up task',
|
|
395
|
+
merge_conflicts: 'Create a task: add_task(project_id, title: "Resolve merge conflicts in PR #XXX")',
|
|
396
|
+
minor_issues: 'Fix directly in the branch, push, and re-validate',
|
|
397
|
+
closed_pr: 'cancel_task(task_id, cancelled_reason: "pr_closed")',
|
|
398
|
+
},
|
|
399
|
+
rule: 'Every PR review MUST end with a clear action. Never leave PRs unmerged or unresolved.',
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
// Post-merge branch sync (git-flow only)
|
|
403
|
+
if (projectWorkflow === 'git-flow' && data.project) {
|
|
404
|
+
const devBranch = data.project.git_develop_branch || 'develop';
|
|
405
|
+
workflow.post_merge_sync = {
|
|
406
|
+
description: `After merging to main, sync main back to ${devBranch} to prevent divergence.`,
|
|
407
|
+
commands: [
|
|
408
|
+
`git checkout ${devBranch} && git pull origin ${devBranch}`,
|
|
409
|
+
'git merge origin/main',
|
|
410
|
+
`git push origin ${devBranch}`,
|
|
411
|
+
],
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Deployment resolution workflow
|
|
417
|
+
workflow.deployment_resolution = {
|
|
418
|
+
description: 'When a fix already exists but just needs deployment',
|
|
419
|
+
steps: [
|
|
420
|
+
'add_finding(project_id, title: "Fix exists - needs deployment", category: "other", severity: "info")',
|
|
421
|
+
'complete_task(task_id, summary: "Fix exists in [branch/commit], pending deployment", session_id)',
|
|
422
|
+
'check_deployment_status(project_id) then request_deployment(project_id) if needed',
|
|
423
|
+
],
|
|
424
|
+
rule: 'Don\'t block tasks waiting for deployment — investigation is complete when you identify the resolution.',
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
result.WORKFLOW = workflow;
|
|
428
|
+
|
|
305
429
|
// Add next action at end - pending requests take priority over validation, then regular tasks
|
|
306
430
|
if (hasUrgentQuestions) {
|
|
307
431
|
const firstQuestion = data.URGENT_QUESTIONS?.requests?.[0] || data.pending_requests?.[0];
|
|
@@ -312,9 +436,11 @@ export const startWorkSession: Handler = async (args, ctx) => {
|
|
|
312
436
|
// Validation tasks take priority over new work - use next_action from API if available
|
|
313
437
|
result.next_action = data.next_action || `claim_validation(task_id: "${data.awaiting_validation[0].id}")`;
|
|
314
438
|
} else if (data.next_task) {
|
|
315
|
-
result.next_action = `update_task(task_id: "${data.next_task.id}", status: "in_progress")`;
|
|
439
|
+
result.next_action = `update_task(task_id: "${data.next_task.id}", status: "in_progress", session_id: "${result.session_id}")`;
|
|
316
440
|
} else if (data.project) {
|
|
317
|
-
result.next_action =
|
|
441
|
+
result.next_action = data.project.fallback_activities_enabled !== false
|
|
442
|
+
? `start_fallback_activity(project_id: "${data.project.id}", activity: "code_review")`
|
|
443
|
+
: 'signal_idle() — no tasks available and fallback activities are disabled.';
|
|
318
444
|
}
|
|
319
445
|
|
|
320
446
|
return { result };
|
package/src/handlers/tasks.ts
CHANGED
|
@@ -77,11 +77,13 @@ const updateTaskSchema = {
|
|
|
77
77
|
worktree_path: { type: 'string' as const },
|
|
78
78
|
task_type: { type: 'string' as const, validate: createEnumValidator(VALID_TASK_TYPES) },
|
|
79
79
|
skip_worktree_requirement: { type: 'boolean' as const, default: false },
|
|
80
|
+
session_id: { type: 'string' as const },
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
const completeTaskSchema = {
|
|
83
84
|
task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
|
|
84
85
|
summary: { type: 'string' as const },
|
|
86
|
+
session_id: { type: 'string' as const },
|
|
85
87
|
};
|
|
86
88
|
|
|
87
89
|
const deleteTaskSchema = {
|
|
@@ -367,7 +369,7 @@ export const addTask: Handler = async (args, ctx) => {
|
|
|
367
369
|
};
|
|
368
370
|
|
|
369
371
|
export const updateTask: Handler = async (args, ctx) => {
|
|
370
|
-
const { task_id, title, description, priority, status, progress_percentage, progress_note, estimated_minutes, git_branch, worktree_path, task_type, skip_worktree_requirement } = parseArgs(args, updateTaskSchema);
|
|
372
|
+
const { task_id, title, description, priority, status, progress_percentage, progress_note, estimated_minutes, git_branch, worktree_path, task_type, skip_worktree_requirement, session_id: explicit_session_id } = parseArgs(args, updateTaskSchema);
|
|
371
373
|
const updates = { title, description, priority, status, progress_percentage, estimated_minutes, git_branch, worktree_path, task_type };
|
|
372
374
|
|
|
373
375
|
// Enforce worktree creation: require git_branch when marking task as in_progress
|
|
@@ -391,7 +393,7 @@ export const updateTask: Handler = async (args, ctx) => {
|
|
|
391
393
|
const response = await api.updateTask(task_id, {
|
|
392
394
|
...updates,
|
|
393
395
|
progress_note,
|
|
394
|
-
session_id: ctx.session.currentSessionId || undefined,
|
|
396
|
+
session_id: explicit_session_id || ctx.session.currentSessionId || undefined,
|
|
395
397
|
});
|
|
396
398
|
|
|
397
399
|
if (!response.ok) {
|
|
@@ -514,7 +516,7 @@ export const updateTask: Handler = async (args, ctx) => {
|
|
|
514
516
|
message: 'If investigation reveals the fix already exists but needs deployment:',
|
|
515
517
|
steps: [
|
|
516
518
|
'1. Add finding: add_finding(project_id, title: "Fix exists, awaits deployment", category: "other", severity: "info", description: "...", related_task_id: task_id)',
|
|
517
|
-
'2. Complete task: complete_task(task_id, summary: "Fix already exists in codebase (PR #
|
|
519
|
+
'2. Complete task: complete_task(task_id, summary: "Fix already exists in codebase (PR #{pr_number}). Needs deployment.")',
|
|
518
520
|
'3. Check deployment: check_deployment_status(project_id)',
|
|
519
521
|
'4. Request deployment if not pending: request_deployment(project_id, notes: "Includes fix for [issue]")',
|
|
520
522
|
],
|
|
@@ -526,12 +528,12 @@ export const updateTask: Handler = async (args, ctx) => {
|
|
|
526
528
|
};
|
|
527
529
|
|
|
528
530
|
export const completeTask: Handler = async (args, ctx) => {
|
|
529
|
-
const { task_id, summary } = parseArgs(args, completeTaskSchema);
|
|
531
|
+
const { task_id, summary, session_id: explicit_session_id } = parseArgs(args, completeTaskSchema);
|
|
530
532
|
|
|
531
533
|
const api = getApiClient();
|
|
532
534
|
const response = await api.completeTask(task_id, {
|
|
533
535
|
summary,
|
|
534
|
-
session_id: ctx.session.currentSessionId || undefined,
|
|
536
|
+
session_id: explicit_session_id || ctx.session.currentSessionId || undefined,
|
|
535
537
|
});
|
|
536
538
|
|
|
537
539
|
if (!response.ok) {
|