@vibescope/mcp-server 0.1.0 → 0.2.0
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/README.md +1 -1
- package/dist/api-client.d.ts +56 -1
- package/dist/api-client.js +17 -2
- package/dist/handlers/bodies-of-work.js +3 -2
- package/dist/handlers/deployment.js +3 -2
- package/dist/handlers/discovery.d.ts +3 -0
- package/dist/handlers/discovery.js +20 -652
- package/dist/handlers/fallback.js +18 -9
- package/dist/handlers/findings.d.ts +8 -1
- package/dist/handlers/findings.js +24 -3
- package/dist/handlers/session.js +23 -8
- package/dist/handlers/sprints.js +3 -2
- package/dist/handlers/tasks.js +22 -1
- package/dist/handlers/tool-docs.d.ts +4 -3
- package/dist/handlers/tool-docs.js +252 -5
- package/dist/handlers/validation.js +13 -1
- package/dist/index.js +25 -7
- package/dist/tools.js +30 -4
- package/package.json +1 -1
- package/src/api-client.ts +72 -2
- package/src/handlers/__test-setup__.ts +5 -0
- package/src/handlers/bodies-of-work.ts +27 -11
- package/src/handlers/deployment.ts +4 -2
- package/src/handlers/discovery.ts +23 -740
- package/src/handlers/fallback.test.ts +78 -0
- package/src/handlers/fallback.ts +20 -9
- package/src/handlers/findings.test.ts +129 -2
- package/src/handlers/findings.ts +32 -3
- package/src/handlers/session.test.ts +37 -2
- package/src/handlers/session.ts +29 -8
- package/src/handlers/sprints.ts +19 -6
- package/src/handlers/tasks.test.ts +61 -0
- package/src/handlers/tasks.ts +26 -1
- package/src/handlers/tool-docs.ts +1024 -0
- package/src/handlers/validation.test.ts +52 -0
- package/src/handlers/validation.ts +14 -1
- package/src/index.ts +25 -7
- package/src/tools.ts +30 -4
- package/src/knowledge.ts +0 -230
package/dist/tools.js
CHANGED
|
@@ -881,15 +881,29 @@ Returns session info, persona, role, and next task. Use mode:'full' for complete
|
|
|
881
881
|
},
|
|
882
882
|
{
|
|
883
883
|
name: 'get_findings',
|
|
884
|
-
description: `Get findings for a project, optionally filtered by category, severity, or status.`,
|
|
884
|
+
description: `Get findings for a project, optionally filtered by category, severity, or status. Use summary_only=true to reduce token usage by returning only essential fields (id, title, category, severity, status). For just counts, use get_findings_stats instead.`,
|
|
885
885
|
inputSchema: {
|
|
886
886
|
type: 'object',
|
|
887
887
|
properties: {
|
|
888
888
|
project_id: { type: 'string', description: 'Project UUID' },
|
|
889
889
|
category: { type: 'string', enum: ['performance', 'security', 'code_quality', 'accessibility', 'documentation', 'architecture', 'testing', 'other'], description: 'Filter by category (optional)' },
|
|
890
890
|
severity: { type: 'string', enum: ['info', 'low', 'medium', 'high', 'critical'], description: 'Filter by severity (optional)' },
|
|
891
|
-
status: { type: 'string', enum: ['open', 'addressed', 'dismissed', 'wontfix'], description: 'Filter by status (default:
|
|
892
|
-
limit: { type: 'number', description: 'Max number of findings to return (default 50)' },
|
|
891
|
+
status: { type: 'string', enum: ['open', 'addressed', 'dismissed', 'wontfix'], description: 'Filter by status (default: open)' },
|
|
892
|
+
limit: { type: 'number', description: 'Max number of findings to return (default 50, max 200)' },
|
|
893
|
+
offset: { type: 'number', description: 'Number of findings to skip for pagination (default 0)' },
|
|
894
|
+
search_query: { type: 'string', description: 'Search findings by title' },
|
|
895
|
+
summary_only: { type: 'boolean', description: 'When true, returns only id, title, category, severity, status (reduces tokens by ~80%). Default: false' },
|
|
896
|
+
},
|
|
897
|
+
required: ['project_id'],
|
|
898
|
+
},
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
name: 'get_findings_stats',
|
|
902
|
+
description: `Get aggregate statistics about findings for a project. Returns total count and breakdowns by status, severity, and category. Much more token-efficient than get_findings when you just need to understand the overall state.`,
|
|
903
|
+
inputSchema: {
|
|
904
|
+
type: 'object',
|
|
905
|
+
properties: {
|
|
906
|
+
project_id: { type: 'string', description: 'Project UUID' },
|
|
893
907
|
},
|
|
894
908
|
required: ['project_id'],
|
|
895
909
|
},
|
|
@@ -1100,6 +1114,10 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1100
1114
|
type: 'string',
|
|
1101
1115
|
description: 'Session ID from start_work_session (optional, uses current session if not provided)',
|
|
1102
1116
|
},
|
|
1117
|
+
current_worktree_path: {
|
|
1118
|
+
type: ['string', 'null'],
|
|
1119
|
+
description: 'Report your current git worktree path (e.g., "../project-task-abc123"). Set to null to clear.',
|
|
1120
|
+
},
|
|
1103
1121
|
},
|
|
1104
1122
|
},
|
|
1105
1123
|
},
|
|
@@ -1149,7 +1167,7 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1149
1167
|
},
|
|
1150
1168
|
{
|
|
1151
1169
|
name: 'validate_task',
|
|
1152
|
-
description: 'Validate a completed task. Include test results in validation_notes.',
|
|
1170
|
+
description: 'Validate a completed task. Include test results in validation_notes. For github-flow/git-flow projects, a PR must exist before approval (add via add_task_reference).',
|
|
1153
1171
|
inputSchema: {
|
|
1154
1172
|
type: 'object',
|
|
1155
1173
|
properties: {
|
|
@@ -1165,6 +1183,10 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1165
1183
|
type: 'boolean',
|
|
1166
1184
|
description: 'Whether the task passes validation (true = approved, false = needs more work)',
|
|
1167
1185
|
},
|
|
1186
|
+
skip_pr_check: {
|
|
1187
|
+
type: 'boolean',
|
|
1188
|
+
description: 'Skip PR existence check (use only for tasks that legitimately do not need a PR)',
|
|
1189
|
+
},
|
|
1168
1190
|
},
|
|
1169
1191
|
required: ['task_id', 'approved'],
|
|
1170
1192
|
},
|
|
@@ -1348,6 +1370,10 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1348
1370
|
type: 'boolean',
|
|
1349
1371
|
description: 'When true, converted task blocks all other work until complete',
|
|
1350
1372
|
},
|
|
1373
|
+
recurring: {
|
|
1374
|
+
type: 'boolean',
|
|
1375
|
+
description: 'When true, requirement resets to pending when a new deployment is requested',
|
|
1376
|
+
},
|
|
1351
1377
|
},
|
|
1352
1378
|
required: ['project_id', 'type', 'title'],
|
|
1353
1379
|
},
|
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -137,13 +137,16 @@ export class VibescopeApiClient {
|
|
|
137
137
|
return this.request('POST', '/api/mcp/sessions/start', params);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
async heartbeat(sessionId: string
|
|
140
|
+
async heartbeat(sessionId: string, options?: {
|
|
141
|
+
current_worktree_path?: string | null;
|
|
142
|
+
}): Promise<ApiResponse<{
|
|
141
143
|
success: boolean;
|
|
142
144
|
session_id: string;
|
|
143
145
|
timestamp: string;
|
|
144
146
|
}>> {
|
|
145
147
|
return this.request('POST', '/api/mcp/sessions/heartbeat', {
|
|
146
|
-
session_id: sessionId
|
|
148
|
+
session_id: sessionId,
|
|
149
|
+
...options
|
|
147
150
|
});
|
|
148
151
|
}
|
|
149
152
|
|
|
@@ -381,6 +384,20 @@ export class VibescopeApiClient {
|
|
|
381
384
|
}): Promise<ApiResponse<{
|
|
382
385
|
success: boolean;
|
|
383
386
|
task_id: string;
|
|
387
|
+
git_workflow?: {
|
|
388
|
+
workflow: string;
|
|
389
|
+
base_branch: string;
|
|
390
|
+
suggested_branch: string;
|
|
391
|
+
worktree_required: boolean;
|
|
392
|
+
};
|
|
393
|
+
worktree_setup?: {
|
|
394
|
+
message: string;
|
|
395
|
+
commands: string[];
|
|
396
|
+
worktree_path: string;
|
|
397
|
+
branch_name: string;
|
|
398
|
+
cleanup_command: string;
|
|
399
|
+
};
|
|
400
|
+
next_step?: string;
|
|
384
401
|
}>> {
|
|
385
402
|
return this.request('PATCH', `/api/mcp/tasks/${taskId}`, updates);
|
|
386
403
|
}
|
|
@@ -405,6 +422,7 @@ export class VibescopeApiClient {
|
|
|
405
422
|
deployment?: string;
|
|
406
423
|
};
|
|
407
424
|
next_action: string;
|
|
425
|
+
warnings?: string[];
|
|
408
426
|
}>> {
|
|
409
427
|
return this.request('POST', `/api/mcp/tasks/${taskId}/complete`, params);
|
|
410
428
|
}
|
|
@@ -642,6 +660,9 @@ export class VibescopeApiClient {
|
|
|
642
660
|
severity?: string;
|
|
643
661
|
status?: string;
|
|
644
662
|
limit?: number;
|
|
663
|
+
offset?: number;
|
|
664
|
+
search_query?: string;
|
|
665
|
+
summary_only?: boolean;
|
|
645
666
|
}): Promise<ApiResponse<{
|
|
646
667
|
findings: Array<{
|
|
647
668
|
id: string;
|
|
@@ -655,6 +676,8 @@ export class VibescopeApiClient {
|
|
|
655
676
|
resolution_note?: string;
|
|
656
677
|
created_at: string;
|
|
657
678
|
}>;
|
|
679
|
+
total_count?: number;
|
|
680
|
+
has_more?: boolean;
|
|
658
681
|
}>> {
|
|
659
682
|
return this.proxy('get_findings', {
|
|
660
683
|
project_id: projectId,
|
|
@@ -662,6 +685,17 @@ export class VibescopeApiClient {
|
|
|
662
685
|
});
|
|
663
686
|
}
|
|
664
687
|
|
|
688
|
+
async getFindingsStats(projectId: string): Promise<ApiResponse<{
|
|
689
|
+
total: number;
|
|
690
|
+
by_status: Record<string, number>;
|
|
691
|
+
by_severity: Record<string, number>;
|
|
692
|
+
by_category: Record<string, number>;
|
|
693
|
+
}>> {
|
|
694
|
+
return this.proxy('get_findings_stats', {
|
|
695
|
+
project_id: projectId
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
|
|
665
699
|
async addFinding(projectId: string, params: {
|
|
666
700
|
title: string;
|
|
667
701
|
description?: string;
|
|
@@ -839,11 +873,13 @@ export class VibescopeApiClient {
|
|
|
839
873
|
async validateTask(taskId: string, params: {
|
|
840
874
|
approved: boolean;
|
|
841
875
|
validation_notes?: string;
|
|
876
|
+
skip_pr_check?: boolean;
|
|
842
877
|
}, sessionId?: string): Promise<ApiResponse<{
|
|
843
878
|
success: boolean;
|
|
844
879
|
approved: boolean;
|
|
845
880
|
task_id: string;
|
|
846
881
|
message?: string;
|
|
882
|
+
workflow?: string;
|
|
847
883
|
}>> {
|
|
848
884
|
return this.proxy('validate_task', {
|
|
849
885
|
task_id: taskId,
|
|
@@ -858,6 +894,21 @@ export class VibescopeApiClient {
|
|
|
858
894
|
success: boolean;
|
|
859
895
|
activity: string;
|
|
860
896
|
message: string;
|
|
897
|
+
git_workflow?: {
|
|
898
|
+
workflow: string;
|
|
899
|
+
base_branch: string;
|
|
900
|
+
worktree_recommended: boolean;
|
|
901
|
+
note: string;
|
|
902
|
+
};
|
|
903
|
+
worktree_setup?: {
|
|
904
|
+
message: string;
|
|
905
|
+
commands: string[];
|
|
906
|
+
worktree_path: string;
|
|
907
|
+
branch_name: string;
|
|
908
|
+
cleanup_command: string;
|
|
909
|
+
report_worktree: string;
|
|
910
|
+
};
|
|
911
|
+
next_step?: string;
|
|
861
912
|
}>> {
|
|
862
913
|
return this.proxy('start_fallback_activity', {
|
|
863
914
|
project_id: projectId,
|
|
@@ -1591,6 +1642,7 @@ export class VibescopeApiClient {
|
|
|
1591
1642
|
file_path?: string;
|
|
1592
1643
|
stage?: string;
|
|
1593
1644
|
blocking?: boolean;
|
|
1645
|
+
recurring?: boolean;
|
|
1594
1646
|
}): Promise<ApiResponse<{
|
|
1595
1647
|
success: boolean;
|
|
1596
1648
|
requirement_id: string;
|
|
@@ -1730,6 +1782,24 @@ export class VibescopeApiClient {
|
|
|
1730
1782
|
readme_content: readmeContent
|
|
1731
1783
|
});
|
|
1732
1784
|
}
|
|
1785
|
+
|
|
1786
|
+
// ============================================================================
|
|
1787
|
+
// Help Topics (database-backed)
|
|
1788
|
+
// ============================================================================
|
|
1789
|
+
async getHelpTopic(slug: string): Promise<ApiResponse<{
|
|
1790
|
+
slug: string;
|
|
1791
|
+
title: string;
|
|
1792
|
+
content: string;
|
|
1793
|
+
} | null>> {
|
|
1794
|
+
return this.proxy('get_help_topic', { slug });
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
async getHelpTopics(): Promise<ApiResponse<Array<{
|
|
1798
|
+
slug: string;
|
|
1799
|
+
title: string;
|
|
1800
|
+
}>>> {
|
|
1801
|
+
return this.proxy('get_help_topics', {});
|
|
1802
|
+
}
|
|
1733
1803
|
}
|
|
1734
1804
|
|
|
1735
1805
|
// Singleton instance
|
|
@@ -77,6 +77,7 @@ export const mockApiClient = {
|
|
|
77
77
|
// Findings
|
|
78
78
|
addFinding: vi.fn(),
|
|
79
79
|
getFindings: vi.fn(),
|
|
80
|
+
getFindingsStats: vi.fn(),
|
|
80
81
|
updateFinding: vi.fn(),
|
|
81
82
|
deleteFinding: vi.fn(),
|
|
82
83
|
|
|
@@ -164,6 +165,10 @@ export const mockApiClient = {
|
|
|
164
165
|
claimValidation: vi.fn(),
|
|
165
166
|
validateTask: vi.fn(),
|
|
166
167
|
|
|
168
|
+
// Help Topics
|
|
169
|
+
getHelpTopic: vi.fn(),
|
|
170
|
+
getHelpTopics: vi.fn(),
|
|
171
|
+
|
|
167
172
|
// Proxy (generic)
|
|
168
173
|
proxy: vi.fn(),
|
|
169
174
|
};
|
|
@@ -134,24 +134,40 @@ export const updateBodyOfWork: Handler = async (args, ctx) => {
|
|
|
134
134
|
};
|
|
135
135
|
|
|
136
136
|
export const getBodyOfWork: Handler = async (args, ctx) => {
|
|
137
|
-
const { body_of_work_id } = args as { body_of_work_id: string };
|
|
137
|
+
const { body_of_work_id, summary_only = false } = args as { body_of_work_id: string; summary_only?: boolean };
|
|
138
138
|
|
|
139
139
|
validateRequired(body_of_work_id, 'body_of_work_id');
|
|
140
140
|
validateUUID(body_of_work_id, 'body_of_work_id');
|
|
141
141
|
|
|
142
142
|
const apiClient = getApiClient();
|
|
143
143
|
|
|
144
|
+
// Response type varies based on summary_only
|
|
144
145
|
const response = await apiClient.proxy<{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
body_of_work: {
|
|
147
|
+
id: string;
|
|
148
|
+
title: string;
|
|
149
|
+
description?: string;
|
|
150
|
+
status: string;
|
|
151
|
+
progress_percentage: number;
|
|
152
|
+
};
|
|
153
|
+
// Full response includes tasks grouped by phase
|
|
154
|
+
tasks?: {
|
|
155
|
+
pre: unknown[];
|
|
156
|
+
core: unknown[];
|
|
157
|
+
post: unknown[];
|
|
158
|
+
};
|
|
159
|
+
// Summary response includes counts and next task
|
|
160
|
+
task_counts?: {
|
|
161
|
+
pre: { total: number; completed: number };
|
|
162
|
+
core: { total: number; completed: number };
|
|
163
|
+
post: { total: number; completed: number };
|
|
164
|
+
total: number;
|
|
165
|
+
completed: number;
|
|
166
|
+
in_progress: number;
|
|
167
|
+
};
|
|
168
|
+
current_task?: { id: string; title: string } | null;
|
|
169
|
+
next_task?: { id: string; title: string; priority: number } | null;
|
|
170
|
+
}>('get_body_of_work', { body_of_work_id, summary_only });
|
|
155
171
|
|
|
156
172
|
if (!response.ok) {
|
|
157
173
|
throw new Error(`Failed to get body of work: ${response.error}`);
|
|
@@ -198,7 +198,7 @@ export const cancelDeployment: Handler = async (args, ctx) => {
|
|
|
198
198
|
};
|
|
199
199
|
|
|
200
200
|
export const addDeploymentRequirement: Handler = async (args, ctx) => {
|
|
201
|
-
const { project_id, type, title, description, file_path, stage = 'preparation', blocking = false } = args as {
|
|
201
|
+
const { project_id, type, title, description, file_path, stage = 'preparation', blocking = false, recurring = false } = args as {
|
|
202
202
|
project_id: string;
|
|
203
203
|
type: string;
|
|
204
204
|
title: string;
|
|
@@ -206,6 +206,7 @@ export const addDeploymentRequirement: Handler = async (args, ctx) => {
|
|
|
206
206
|
file_path?: string;
|
|
207
207
|
stage?: string;
|
|
208
208
|
blocking?: boolean;
|
|
209
|
+
recurring?: boolean;
|
|
209
210
|
};
|
|
210
211
|
|
|
211
212
|
validateRequired(project_id, 'project_id');
|
|
@@ -230,7 +231,8 @@ export const addDeploymentRequirement: Handler = async (args, ctx) => {
|
|
|
230
231
|
description,
|
|
231
232
|
file_path,
|
|
232
233
|
stage: stage as 'preparation' | 'deployment' | 'verification',
|
|
233
|
-
blocking
|
|
234
|
+
blocking,
|
|
235
|
+
recurring
|
|
234
236
|
});
|
|
235
237
|
|
|
236
238
|
if (!response.ok) {
|