@vibescope/mcp-server 0.5.0 → 0.5.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.
Files changed (162) hide show
  1. package/CHANGELOG.md +84 -84
  2. package/README.md +194 -194
  3. package/dist/api-client/tasks.d.ts +1 -0
  4. package/dist/cli-init.js +21 -21
  5. package/dist/cli.js +26 -26
  6. package/dist/handlers/session.js +3 -1
  7. package/dist/handlers/tasks.js +7 -1
  8. package/dist/handlers/tool-docs.js +1216 -1216
  9. package/dist/index.js +73 -73
  10. package/dist/templates/agent-guidelines.d.ts +1 -1
  11. package/dist/templates/agent-guidelines.js +205 -205
  12. package/dist/templates/help-content.js +1621 -1621
  13. package/dist/tools/bodies-of-work.js +6 -6
  14. package/dist/tools/cloud-agents.js +22 -22
  15. package/dist/tools/milestones.js +2 -2
  16. package/dist/tools/requests.js +1 -1
  17. package/dist/tools/session.js +11 -11
  18. package/dist/tools/sprints.js +9 -9
  19. package/dist/tools/tasks.js +43 -35
  20. package/dist/tools/worktrees.js +14 -14
  21. package/dist/utils.js +11 -11
  22. package/docs/TOOLS.md +2687 -2685
  23. package/package.json +53 -53
  24. package/scripts/generate-docs.ts +212 -212
  25. package/scripts/version-bump.ts +203 -203
  26. package/src/api-client/blockers.ts +86 -86
  27. package/src/api-client/bodies-of-work.ts +194 -194
  28. package/src/api-client/chat.ts +50 -50
  29. package/src/api-client/connectors.ts +152 -152
  30. package/src/api-client/cost.ts +185 -185
  31. package/src/api-client/decisions.ts +87 -87
  32. package/src/api-client/deployment.ts +313 -313
  33. package/src/api-client/discovery.ts +81 -81
  34. package/src/api-client/fallback.ts +52 -52
  35. package/src/api-client/file-checkouts.ts +115 -115
  36. package/src/api-client/findings.ts +100 -100
  37. package/src/api-client/git-issues.ts +88 -88
  38. package/src/api-client/ideas.ts +112 -112
  39. package/src/api-client/index.ts +592 -592
  40. package/src/api-client/milestones.ts +83 -83
  41. package/src/api-client/organizations.ts +185 -185
  42. package/src/api-client/progress.ts +94 -94
  43. package/src/api-client/project.ts +181 -181
  44. package/src/api-client/requests.ts +54 -54
  45. package/src/api-client/session.ts +220 -220
  46. package/src/api-client/sprints.ts +227 -227
  47. package/src/api-client/subtasks.ts +57 -57
  48. package/src/api-client/tasks.ts +451 -450
  49. package/src/api-client/types.ts +32 -32
  50. package/src/api-client/validation.ts +60 -60
  51. package/src/api-client/worktrees.ts +53 -53
  52. package/src/api-client.test.ts +847 -847
  53. package/src/api-client.ts +2728 -2728
  54. package/src/cli-init.ts +558 -558
  55. package/src/cli.test.ts +284 -284
  56. package/src/cli.ts +204 -204
  57. package/src/handlers/__test-setup__.ts +240 -240
  58. package/src/handlers/__test-utils__.ts +89 -89
  59. package/src/handlers/blockers.test.ts +468 -468
  60. package/src/handlers/blockers.ts +172 -172
  61. package/src/handlers/bodies-of-work.test.ts +704 -704
  62. package/src/handlers/bodies-of-work.ts +526 -526
  63. package/src/handlers/chat.test.ts +185 -185
  64. package/src/handlers/chat.ts +101 -101
  65. package/src/handlers/cloud-agents.test.ts +438 -438
  66. package/src/handlers/cloud-agents.ts +156 -156
  67. package/src/handlers/connectors.test.ts +834 -834
  68. package/src/handlers/connectors.ts +229 -229
  69. package/src/handlers/cost.test.ts +462 -462
  70. package/src/handlers/cost.ts +285 -285
  71. package/src/handlers/decisions.test.ts +382 -382
  72. package/src/handlers/decisions.ts +153 -153
  73. package/src/handlers/deployment.test.ts +551 -551
  74. package/src/handlers/deployment.ts +570 -570
  75. package/src/handlers/discovery.test.ts +206 -206
  76. package/src/handlers/discovery.ts +433 -433
  77. package/src/handlers/fallback.test.ts +537 -537
  78. package/src/handlers/fallback.ts +194 -194
  79. package/src/handlers/file-checkouts.test.ts +750 -750
  80. package/src/handlers/file-checkouts.ts +185 -185
  81. package/src/handlers/findings.test.ts +633 -633
  82. package/src/handlers/findings.ts +239 -239
  83. package/src/handlers/git-issues.test.ts +631 -631
  84. package/src/handlers/git-issues.ts +136 -136
  85. package/src/handlers/ideas.test.ts +644 -644
  86. package/src/handlers/ideas.ts +207 -207
  87. package/src/handlers/index.ts +93 -93
  88. package/src/handlers/milestones.test.ts +475 -475
  89. package/src/handlers/milestones.ts +180 -180
  90. package/src/handlers/organizations.test.ts +826 -826
  91. package/src/handlers/organizations.ts +315 -315
  92. package/src/handlers/progress.test.ts +269 -269
  93. package/src/handlers/progress.ts +77 -77
  94. package/src/handlers/project.test.ts +546 -546
  95. package/src/handlers/project.ts +245 -245
  96. package/src/handlers/requests.test.ts +303 -303
  97. package/src/handlers/requests.ts +99 -99
  98. package/src/handlers/roles.test.ts +305 -305
  99. package/src/handlers/roles.ts +219 -219
  100. package/src/handlers/session.test.ts +998 -998
  101. package/src/handlers/session.ts +1107 -1105
  102. package/src/handlers/sprints.test.ts +732 -732
  103. package/src/handlers/sprints.ts +537 -537
  104. package/src/handlers/tasks.test.ts +931 -931
  105. package/src/handlers/tasks.ts +1144 -1137
  106. package/src/handlers/tool-categories.test.ts +66 -66
  107. package/src/handlers/tool-docs.test.ts +511 -511
  108. package/src/handlers/tool-docs.ts +1595 -1595
  109. package/src/handlers/types.test.ts +259 -259
  110. package/src/handlers/types.ts +176 -176
  111. package/src/handlers/validation.test.ts +582 -582
  112. package/src/handlers/validation.ts +164 -164
  113. package/src/handlers/version.ts +63 -63
  114. package/src/index.test.ts +674 -674
  115. package/src/index.ts +884 -884
  116. package/src/setup.test.ts +243 -243
  117. package/src/setup.ts +410 -410
  118. package/src/templates/agent-guidelines.ts +233 -233
  119. package/src/templates/help-content.ts +1751 -1751
  120. package/src/token-tracking.test.ts +463 -463
  121. package/src/token-tracking.ts +167 -167
  122. package/src/tools/blockers.ts +122 -122
  123. package/src/tools/bodies-of-work.ts +283 -283
  124. package/src/tools/chat.ts +72 -72
  125. package/src/tools/cloud-agents.ts +101 -101
  126. package/src/tools/connectors.ts +191 -191
  127. package/src/tools/cost.ts +111 -111
  128. package/src/tools/decisions.ts +111 -111
  129. package/src/tools/deployment.ts +455 -455
  130. package/src/tools/discovery.ts +76 -76
  131. package/src/tools/fallback.ts +111 -111
  132. package/src/tools/features.ts +154 -154
  133. package/src/tools/file-checkouts.ts +145 -145
  134. package/src/tools/findings.ts +101 -101
  135. package/src/tools/git-issues.ts +130 -130
  136. package/src/tools/ideas.ts +162 -162
  137. package/src/tools/index.ts +145 -145
  138. package/src/tools/milestones.ts +118 -118
  139. package/src/tools/organizations.ts +224 -224
  140. package/src/tools/persona-templates.ts +25 -25
  141. package/src/tools/progress.ts +73 -73
  142. package/src/tools/project.ts +210 -210
  143. package/src/tools/requests.ts +68 -68
  144. package/src/tools/roles.ts +112 -112
  145. package/src/tools/session.ts +181 -181
  146. package/src/tools/sprints.ts +298 -298
  147. package/src/tools/tasks.ts +583 -575
  148. package/src/tools/tools.test.ts +222 -222
  149. package/src/tools/types.ts +9 -9
  150. package/src/tools/validation.ts +75 -75
  151. package/src/tools/version.ts +34 -34
  152. package/src/tools/worktrees.ts +66 -66
  153. package/src/tools.test.ts +416 -416
  154. package/src/utils.test.ts +1014 -1014
  155. package/src/utils.ts +586 -586
  156. package/src/validators.test.ts +223 -223
  157. package/src/validators.ts +249 -249
  158. package/src/version.ts +162 -162
  159. package/tsconfig.json +16 -16
  160. package/vitest.config.ts +14 -14
  161. package/dist/tools.d.ts +0 -2
  162. package/dist/tools.js +0 -3602
@@ -1,164 +1,164 @@
1
- /**
2
- * Validation Handlers (Migrated to API Client)
3
- *
4
- * Handles cross-agent task validation:
5
- * - get_tasks_awaiting_validation
6
- * - claim_validation
7
- * - validate_task
8
- */
9
-
10
- import type { Handler, HandlerRegistry } from './types.js';
11
- import { error, success } from './types.js';
12
- import { parseArgs, uuidValidator } from '../validators.js';
13
- import { getApiClient } from '../api-client.js';
14
-
15
- // Argument schemas for type-safe parsing
16
- const getTasksAwaitingValidationSchema = {
17
- project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
18
- };
19
-
20
- const claimValidationSchema = {
21
- task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
22
- };
23
-
24
- const validateTaskSchema = {
25
- task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
26
- approved: { type: 'boolean' as const, required: true as const },
27
- validation_notes: { type: 'string' as const },
28
- skip_pr_check: { type: 'boolean' as const },
29
- // Note: pr_checks_passing may arrive as string from some MCP clients, handled in validateTask
30
- pr_checks_passing: { type: 'boolean' as const },
31
- };
32
-
33
- export const getTasksAwaitingValidation: Handler = async (args, _ctx) => {
34
- const { project_id } = parseArgs(args, getTasksAwaitingValidationSchema);
35
-
36
- const apiClient = getApiClient();
37
- const response = await apiClient.getTasksAwaitingValidation(project_id);
38
-
39
- if (!response.ok) {
40
- return error(response.error || 'Failed to fetch tasks awaiting validation');
41
- }
42
-
43
- // Check for application-level errors (200 OK but error in body)
44
- if (response.data && typeof response.data === 'object' && 'error' in response.data) {
45
- const errMsg = typeof response.data.error === 'string' ? response.data.error : 'Unknown error';
46
- return error(errMsg);
47
- }
48
-
49
- return success(response.data);
50
- };
51
-
52
- export const claimValidation: Handler = async (args, ctx) => {
53
- const { task_id } = parseArgs(args, claimValidationSchema);
54
-
55
- const { session } = ctx;
56
- const currentSessionId = session.currentSessionId;
57
-
58
- const apiClient = getApiClient();
59
- const response = await apiClient.claimValidation(task_id, currentSessionId || undefined);
60
-
61
- if (!response.ok) {
62
- return error(response.error || 'Failed to claim task for validation');
63
- }
64
-
65
- // Check for application-level errors (200 OK but error in body)
66
- if (response.data && typeof response.data === 'object' && 'error' in response.data) {
67
- const errMsg = typeof response.data.error === 'string' ? response.data.error : 'Unknown error';
68
- return error(errMsg);
69
- }
70
-
71
- // Add VALIDATION_WORKFLOW reminder
72
- const taskData = response.data as { task?: { git_branch?: string; references?: Array<{ url: string }> } } | null;
73
- const gitBranch = taskData?.task?.git_branch;
74
- const prUrl = taskData?.task?.references?.find((ref: { url: string }) => ref.url.includes('/pull/'))?.url;
75
-
76
- const result = {
77
- ...response.data,
78
- VALIDATION_WORKFLOW: {
79
- message: 'Follow this validation workflow:',
80
- steps: [
81
- `1. Set up worktree from EXISTING branch (don't create new):`,
82
- ` git fetch origin ${gitBranch || 'feature/xxx'}`,
83
- ` git worktree add ../PROJECT-PERSONA-validation ${gitBranch || 'feature/xxx'}`,
84
- '2. Run: pnpm install && pnpm test && pnpm build',
85
- `3. Check PR is still open: gh pr view ${prUrl || '<PR_NUMBER>'} --json state`,
86
- '4. If PR closed without merge → cancel_task(cancelled_reason: "pr_closed")',
87
- '5. On approve → merge PR immediately → remove worktree',
88
- '6. On reject → use validate_task(approved: false) with notes → remove worktree',
89
- ],
90
- fifo_rule: 'IMPORTANT: Review lowest PR number first. Never skip to newer PRs.',
91
- worktree_note: 'Use EXISTING branch - do NOT create a new feature branch for validation',
92
- },
93
- };
94
-
95
- return success(result);
96
- };
97
-
98
- export const validateTask: Handler = async (args, ctx) => {
99
- const { task_id, approved, validation_notes, skip_pr_check, pr_checks_passing } = parseArgs(args, validateTaskSchema);
100
-
101
- const { session } = ctx;
102
- const currentSessionId = session.currentSessionId;
103
-
104
- // Ensure pr_checks_passing is a proper boolean (MCP may send as string)
105
- // Cast to unknown first to satisfy TypeScript
106
- const checksPassingBool = pr_checks_passing === true || (pr_checks_passing as unknown) === 'true';
107
-
108
- const apiClient = getApiClient();
109
- const response = await apiClient.validateTask(task_id, {
110
- approved,
111
- validation_notes,
112
- skip_pr_check,
113
- pr_checks_passing: pr_checks_passing !== undefined ? checksPassingBool : undefined,
114
- }, currentSessionId || undefined);
115
-
116
- if (!response.ok) {
117
- // Handle PR required error specially
118
- if (response.error === 'pr_required') {
119
- return error('pr_required', {
120
- message: response.data?.message || 'A Pull Request is required before validation approval. Create a PR and add it via add_task_reference.',
121
- workflow: response.data?.workflow,
122
- action_required: 'Create a PR for this task and add it via add_task_reference(task_id, pr_url, label: "Pull Request")',
123
- });
124
- }
125
- return error(response.error || 'Failed to validate task');
126
- }
127
-
128
- // Check for application-level errors (200 OK but error in body)
129
- if (response.data && typeof response.data === 'object' && 'error' in response.data) {
130
- const errMsg = typeof response.data.error === 'string' ? response.data.error : 'Unknown error';
131
- return error(errMsg);
132
- }
133
-
134
- // Add REJECTION_GUIDANCE when validation is rejected
135
- if (!approved) {
136
- const result = {
137
- ...response.data,
138
- REJECTION_GUIDANCE: {
139
- message: 'Task validation rejected. A fix task will be created automatically.',
140
- what_happens: [
141
- 'Uses SAME branch (no new branch needed)',
142
- 'References SAME PR',
143
- 'Includes your validation notes',
144
- 'Another agent will pick up the fix task',
145
- ],
146
- your_action: 'Clean up your validation worktree - fix agent creates their own',
147
- cleanup_command: 'git worktree remove ../PROJECT-PERSONA-validation',
148
- note: 'Your validation notes are passed to the fix task so the agent knows exactly what to fix.',
149
- },
150
- };
151
- return success(result);
152
- }
153
-
154
- return success(response.data);
155
- };
156
-
157
- /**
158
- * Validation handlers registry
159
- */
160
- export const validationHandlers: HandlerRegistry = {
161
- get_tasks_awaiting_validation: getTasksAwaitingValidation,
162
- claim_validation: claimValidation,
163
- validate_task: validateTask,
164
- };
1
+ /**
2
+ * Validation Handlers (Migrated to API Client)
3
+ *
4
+ * Handles cross-agent task validation:
5
+ * - get_tasks_awaiting_validation
6
+ * - claim_validation
7
+ * - validate_task
8
+ */
9
+
10
+ import type { Handler, HandlerRegistry } from './types.js';
11
+ import { error, success } from './types.js';
12
+ import { parseArgs, uuidValidator } from '../validators.js';
13
+ import { getApiClient } from '../api-client.js';
14
+
15
+ // Argument schemas for type-safe parsing
16
+ const getTasksAwaitingValidationSchema = {
17
+ project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
18
+ };
19
+
20
+ const claimValidationSchema = {
21
+ task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
22
+ };
23
+
24
+ const validateTaskSchema = {
25
+ task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
26
+ approved: { type: 'boolean' as const, required: true as const },
27
+ validation_notes: { type: 'string' as const },
28
+ skip_pr_check: { type: 'boolean' as const },
29
+ // Note: pr_checks_passing may arrive as string from some MCP clients, handled in validateTask
30
+ pr_checks_passing: { type: 'boolean' as const },
31
+ };
32
+
33
+ export const getTasksAwaitingValidation: Handler = async (args, _ctx) => {
34
+ const { project_id } = parseArgs(args, getTasksAwaitingValidationSchema);
35
+
36
+ const apiClient = getApiClient();
37
+ const response = await apiClient.getTasksAwaitingValidation(project_id);
38
+
39
+ if (!response.ok) {
40
+ return error(response.error || 'Failed to fetch tasks awaiting validation');
41
+ }
42
+
43
+ // Check for application-level errors (200 OK but error in body)
44
+ if (response.data && typeof response.data === 'object' && 'error' in response.data) {
45
+ const errMsg = typeof response.data.error === 'string' ? response.data.error : 'Unknown error';
46
+ return error(errMsg);
47
+ }
48
+
49
+ return success(response.data);
50
+ };
51
+
52
+ export const claimValidation: Handler = async (args, ctx) => {
53
+ const { task_id } = parseArgs(args, claimValidationSchema);
54
+
55
+ const { session } = ctx;
56
+ const currentSessionId = session.currentSessionId;
57
+
58
+ const apiClient = getApiClient();
59
+ const response = await apiClient.claimValidation(task_id, currentSessionId || undefined);
60
+
61
+ if (!response.ok) {
62
+ return error(response.error || 'Failed to claim task for validation');
63
+ }
64
+
65
+ // Check for application-level errors (200 OK but error in body)
66
+ if (response.data && typeof response.data === 'object' && 'error' in response.data) {
67
+ const errMsg = typeof response.data.error === 'string' ? response.data.error : 'Unknown error';
68
+ return error(errMsg);
69
+ }
70
+
71
+ // Add VALIDATION_WORKFLOW reminder
72
+ const taskData = response.data as { task?: { git_branch?: string; references?: Array<{ url: string }> } } | null;
73
+ const gitBranch = taskData?.task?.git_branch;
74
+ const prUrl = taskData?.task?.references?.find((ref: { url: string }) => ref.url.includes('/pull/'))?.url;
75
+
76
+ const result = {
77
+ ...response.data,
78
+ VALIDATION_WORKFLOW: {
79
+ message: 'Follow this validation workflow:',
80
+ steps: [
81
+ `1. Set up worktree from EXISTING branch (don't create new):`,
82
+ ` git fetch origin ${gitBranch || 'feature/xxx'}`,
83
+ ` git worktree add ../PROJECT-PERSONA-validation ${gitBranch || 'feature/xxx'}`,
84
+ '2. Run: pnpm install && pnpm test && pnpm build',
85
+ `3. Check PR is still open: gh pr view ${prUrl || '<PR_NUMBER>'} --json state`,
86
+ '4. If PR closed without merge → cancel_task(cancelled_reason: "pr_closed")',
87
+ '5. On approve → merge PR immediately → remove worktree',
88
+ '6. On reject → use validate_task(approved: false) with notes → remove worktree',
89
+ ],
90
+ fifo_rule: 'IMPORTANT: Review lowest PR number first. Never skip to newer PRs.',
91
+ worktree_note: 'Use EXISTING branch - do NOT create a new feature branch for validation',
92
+ },
93
+ };
94
+
95
+ return success(result);
96
+ };
97
+
98
+ export const validateTask: Handler = async (args, ctx) => {
99
+ const { task_id, approved, validation_notes, skip_pr_check, pr_checks_passing } = parseArgs(args, validateTaskSchema);
100
+
101
+ const { session } = ctx;
102
+ const currentSessionId = session.currentSessionId;
103
+
104
+ // Ensure pr_checks_passing is a proper boolean (MCP may send as string)
105
+ // Cast to unknown first to satisfy TypeScript
106
+ const checksPassingBool = pr_checks_passing === true || (pr_checks_passing as unknown) === 'true';
107
+
108
+ const apiClient = getApiClient();
109
+ const response = await apiClient.validateTask(task_id, {
110
+ approved,
111
+ validation_notes,
112
+ skip_pr_check,
113
+ pr_checks_passing: pr_checks_passing !== undefined ? checksPassingBool : undefined,
114
+ }, currentSessionId || undefined);
115
+
116
+ if (!response.ok) {
117
+ // Handle PR required error specially
118
+ if (response.error === 'pr_required') {
119
+ return error('pr_required', {
120
+ message: response.data?.message || 'A Pull Request is required before validation approval. Create a PR and add it via add_task_reference.',
121
+ workflow: response.data?.workflow,
122
+ action_required: 'Create a PR for this task and add it via add_task_reference(task_id, pr_url, label: "Pull Request")',
123
+ });
124
+ }
125
+ return error(response.error || 'Failed to validate task');
126
+ }
127
+
128
+ // Check for application-level errors (200 OK but error in body)
129
+ if (response.data && typeof response.data === 'object' && 'error' in response.data) {
130
+ const errMsg = typeof response.data.error === 'string' ? response.data.error : 'Unknown error';
131
+ return error(errMsg);
132
+ }
133
+
134
+ // Add REJECTION_GUIDANCE when validation is rejected
135
+ if (!approved) {
136
+ const result = {
137
+ ...response.data,
138
+ REJECTION_GUIDANCE: {
139
+ message: 'Task validation rejected. A fix task will be created automatically.',
140
+ what_happens: [
141
+ 'Uses SAME branch (no new branch needed)',
142
+ 'References SAME PR',
143
+ 'Includes your validation notes',
144
+ 'Another agent will pick up the fix task',
145
+ ],
146
+ your_action: 'Clean up your validation worktree - fix agent creates their own',
147
+ cleanup_command: 'git worktree remove ../PROJECT-PERSONA-validation',
148
+ note: 'Your validation notes are passed to the fix task so the agent knows exactly what to fix.',
149
+ },
150
+ };
151
+ return success(result);
152
+ }
153
+
154
+ return success(response.data);
155
+ };
156
+
157
+ /**
158
+ * Validation handlers registry
159
+ */
160
+ export const validationHandlers: HandlerRegistry = {
161
+ get_tasks_awaiting_validation: getTasksAwaitingValidation,
162
+ claim_validation: claimValidation,
163
+ validate_task: validateTask,
164
+ };
@@ -1,63 +1,63 @@
1
- /**
2
- * Version management handlers
3
- */
4
-
5
- import { execSync } from 'child_process';
6
- import type { HandlerRegistry } from './types.js';
7
- import { success, error } from './types.js';
8
- import { checkVersion, getLocalVersion } from '../version.js';
9
-
10
- const PACKAGE_NAME = '@vibescope/mcp-server';
11
-
12
- export const versionHandlers: HandlerRegistry = {
13
- check_mcp_version: async (_args, _ctx) => {
14
- const info = await checkVersion({ bypassCache: true });
15
-
16
- if (info.error) {
17
- return success({
18
- current_version: info.current,
19
- latest_version: info.latest,
20
- update_available: false,
21
- warning: info.error,
22
- });
23
- }
24
-
25
- return success({
26
- current_version: info.current,
27
- latest_version: info.latest,
28
- update_available: info.updateAvailable,
29
- message: info.updateAvailable
30
- ? `Update available! v${info.current} → v${info.latest}. Ask the user if they would like to update using the update_mcp_server tool.`
31
- : `Vibescope MCP server is up to date (v${info.current}).`,
32
- });
33
- },
34
-
35
- update_mcp_server: async (args, _ctx) => {
36
- const useGlobal = args.global !== false; // default true
37
- const flag = useGlobal ? '-g ' : '';
38
- const command = `npm install ${flag}${PACKAGE_NAME}@latest`;
39
-
40
- try {
41
- const output = execSync(command, {
42
- encoding: 'utf-8',
43
- timeout: 60000,
44
- stdio: ['pipe', 'pipe', 'pipe'],
45
- });
46
-
47
- // Check the new version
48
- const newVersion = getLocalVersion();
49
-
50
- return success({
51
- updated: true,
52
- command_run: command,
53
- output: output.trim(),
54
- new_version: newVersion,
55
- message:
56
- 'Update complete. The MCP server must be restarted to use the new version. Please ask the user to restart their editor/MCP client, or reconnect the MCP server.',
57
- });
58
- } catch (err) {
59
- const message = err instanceof Error ? err.message : String(err);
60
- return error(`Failed to update: ${message}. The user may need to run manually: ${command}`);
61
- }
62
- },
63
- };
1
+ /**
2
+ * Version management handlers
3
+ */
4
+
5
+ import { execSync } from 'child_process';
6
+ import type { HandlerRegistry } from './types.js';
7
+ import { success, error } from './types.js';
8
+ import { checkVersion, getLocalVersion } from '../version.js';
9
+
10
+ const PACKAGE_NAME = '@vibescope/mcp-server';
11
+
12
+ export const versionHandlers: HandlerRegistry = {
13
+ check_mcp_version: async (_args, _ctx) => {
14
+ const info = await checkVersion({ bypassCache: true });
15
+
16
+ if (info.error) {
17
+ return success({
18
+ current_version: info.current,
19
+ latest_version: info.latest,
20
+ update_available: false,
21
+ warning: info.error,
22
+ });
23
+ }
24
+
25
+ return success({
26
+ current_version: info.current,
27
+ latest_version: info.latest,
28
+ update_available: info.updateAvailable,
29
+ message: info.updateAvailable
30
+ ? `Update available! v${info.current} → v${info.latest}. Ask the user if they would like to update using the update_mcp_server tool.`
31
+ : `Vibescope MCP server is up to date (v${info.current}).`,
32
+ });
33
+ },
34
+
35
+ update_mcp_server: async (args, _ctx) => {
36
+ const useGlobal = args.global !== false; // default true
37
+ const flag = useGlobal ? '-g ' : '';
38
+ const command = `npm install ${flag}${PACKAGE_NAME}@latest`;
39
+
40
+ try {
41
+ const output = execSync(command, {
42
+ encoding: 'utf-8',
43
+ timeout: 60000,
44
+ stdio: ['pipe', 'pipe', 'pipe'],
45
+ });
46
+
47
+ // Check the new version
48
+ const newVersion = getLocalVersion();
49
+
50
+ return success({
51
+ updated: true,
52
+ command_run: command,
53
+ output: output.trim(),
54
+ new_version: newVersion,
55
+ message:
56
+ 'Update complete. The MCP server must be restarted to use the new version. Please ask the user to restart their editor/MCP client, or reconnect the MCP server.',
57
+ });
58
+ } catch (err) {
59
+ const message = err instanceof Error ? err.message : String(err);
60
+ return error(`Failed to update: ${message}. The user may need to run manually: ${command}`);
61
+ }
62
+ },
63
+ };