@vibescope/mcp-server 0.2.9 → 0.3.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +84 -84
  2. package/README.md +194 -194
  3. package/dist/api-client.d.ts +36 -0
  4. package/dist/api-client.js +34 -0
  5. package/dist/cli.d.ts +1 -1
  6. package/dist/cli.js +30 -38
  7. package/dist/handlers/discovery.js +2 -0
  8. package/dist/handlers/session.d.ts +11 -0
  9. package/dist/handlers/session.js +101 -0
  10. package/dist/handlers/tasks.d.ts +8 -0
  11. package/dist/handlers/tasks.js +163 -3
  12. package/dist/handlers/tool-docs.js +840 -828
  13. package/dist/handlers/validation.js +45 -2
  14. package/dist/index.js +73 -73
  15. package/dist/setup.js +6 -6
  16. package/dist/templates/agent-guidelines.js +185 -185
  17. package/dist/templates/help-content.js +1622 -1544
  18. package/dist/tools.js +126 -74
  19. package/dist/utils.d.ts +15 -11
  20. package/dist/utils.js +53 -28
  21. package/docs/TOOLS.md +2406 -2053
  22. package/package.json +51 -51
  23. package/scripts/generate-docs.ts +212 -212
  24. package/scripts/version-bump.ts +203 -203
  25. package/src/api-client.test.ts +723 -723
  26. package/src/api-client.ts +2561 -2499
  27. package/src/cli.test.ts +24 -8
  28. package/src/cli.ts +204 -212
  29. package/src/handlers/__test-setup__.ts +236 -236
  30. package/src/handlers/__test-utils__.ts +87 -87
  31. package/src/handlers/blockers.test.ts +468 -468
  32. package/src/handlers/blockers.ts +163 -163
  33. package/src/handlers/bodies-of-work.test.ts +704 -704
  34. package/src/handlers/bodies-of-work.ts +526 -526
  35. package/src/handlers/connectors.test.ts +834 -834
  36. package/src/handlers/connectors.ts +229 -229
  37. package/src/handlers/cost.test.ts +462 -462
  38. package/src/handlers/cost.ts +285 -285
  39. package/src/handlers/decisions.test.ts +382 -382
  40. package/src/handlers/decisions.ts +153 -153
  41. package/src/handlers/deployment.test.ts +551 -551
  42. package/src/handlers/deployment.ts +541 -541
  43. package/src/handlers/discovery.test.ts +206 -206
  44. package/src/handlers/discovery.ts +392 -390
  45. package/src/handlers/fallback.test.ts +537 -537
  46. package/src/handlers/fallback.ts +194 -194
  47. package/src/handlers/file-checkouts.test.ts +750 -750
  48. package/src/handlers/file-checkouts.ts +185 -185
  49. package/src/handlers/findings.test.ts +633 -633
  50. package/src/handlers/findings.ts +239 -239
  51. package/src/handlers/git-issues.test.ts +631 -631
  52. package/src/handlers/git-issues.ts +136 -136
  53. package/src/handlers/ideas.test.ts +644 -644
  54. package/src/handlers/ideas.ts +207 -207
  55. package/src/handlers/index.ts +84 -84
  56. package/src/handlers/milestones.test.ts +475 -475
  57. package/src/handlers/milestones.ts +180 -180
  58. package/src/handlers/organizations.test.ts +826 -826
  59. package/src/handlers/organizations.ts +315 -315
  60. package/src/handlers/progress.test.ts +269 -269
  61. package/src/handlers/progress.ts +77 -77
  62. package/src/handlers/project.test.ts +546 -546
  63. package/src/handlers/project.ts +239 -239
  64. package/src/handlers/requests.test.ts +303 -303
  65. package/src/handlers/requests.ts +99 -99
  66. package/src/handlers/roles.test.ts +305 -305
  67. package/src/handlers/roles.ts +219 -219
  68. package/src/handlers/session.test.ts +998 -875
  69. package/src/handlers/session.ts +839 -730
  70. package/src/handlers/sprints.test.ts +732 -732
  71. package/src/handlers/sprints.ts +537 -537
  72. package/src/handlers/tasks.test.ts +931 -907
  73. package/src/handlers/tasks.ts +1121 -945
  74. package/src/handlers/tool-categories.test.ts +66 -66
  75. package/src/handlers/tool-docs.ts +1109 -1096
  76. package/src/handlers/types.test.ts +259 -259
  77. package/src/handlers/types.ts +175 -175
  78. package/src/handlers/validation.test.ts +582 -582
  79. package/src/handlers/validation.ts +159 -113
  80. package/src/index.test.ts +674 -0
  81. package/src/index.ts +792 -792
  82. package/src/setup.test.ts +233 -233
  83. package/src/setup.ts +404 -403
  84. package/src/templates/agent-guidelines.ts +210 -210
  85. package/src/templates/help-content.ts +1751 -1673
  86. package/src/token-tracking.test.ts +463 -463
  87. package/src/token-tracking.ts +166 -166
  88. package/src/tools.test.ts +416 -0
  89. package/src/tools.ts +3607 -3555
  90. package/src/utils.test.ts +785 -683
  91. package/src/utils.ts +469 -436
  92. package/src/validators.test.ts +223 -223
  93. package/src/validators.ts +249 -249
  94. package/tsconfig.json +16 -16
  95. package/vitest.config.ts +14 -14
package/src/cli.test.ts CHANGED
@@ -23,24 +23,40 @@ describe('CLI verification logic', () => {
23
23
  });
24
24
 
25
25
  describe('normalizeGitUrl', () => {
26
- it('should remove .git suffix', () => {
27
- expect(normalizeGitUrl('https://github.com/user/repo.git')).toBe('https://github.com/user/repo');
26
+ it('should remove .git suffix and lowercase', () => {
27
+ expect(normalizeGitUrl('https://github.com/User/Repo.git')).toBe('https://github.com/user/repo');
28
28
  });
29
29
 
30
- it('should convert SSH to HTTPS format', () => {
31
- expect(normalizeGitUrl('git@github.com:user/repo.git')).toBe('https://github.com/user/repo');
30
+ it('should convert SSH to HTTPS format and lowercase', () => {
31
+ expect(normalizeGitUrl('git@github.com:User/Repo.git')).toBe('https://github.com/user/repo');
32
32
  });
33
33
 
34
34
  it('should handle HTTPS URLs without .git suffix', () => {
35
35
  expect(normalizeGitUrl('https://github.com/user/repo')).toBe('https://github.com/user/repo');
36
36
  });
37
37
 
38
- it('should handle GitLab SSH URLs', () => {
39
- expect(normalizeGitUrl('git@gitlab.com:user/repo.git')).toBe('https://gitlab.com/user/repo');
38
+ it('should handle GitLab SSH URLs and lowercase', () => {
39
+ expect(normalizeGitUrl('git@gitlab.com:User/Repo.git')).toBe('https://gitlab.com/user/repo');
40
40
  });
41
41
 
42
- it('should handle Bitbucket SSH URLs', () => {
43
- expect(normalizeGitUrl('git@bitbucket.org:user/repo.git')).toBe('https://bitbucket.org/user/repo');
42
+ it('should handle Bitbucket SSH URLs and lowercase', () => {
43
+ expect(normalizeGitUrl('git@bitbucket.org:User/Repo.git')).toBe('https://bitbucket.org/user/repo');
44
+ });
45
+
46
+ it('should return null for empty string', () => {
47
+ expect(normalizeGitUrl('')).toBe(null);
48
+ });
49
+
50
+ it('should handle http and upgrade to https', () => {
51
+ expect(normalizeGitUrl('http://github.com/user/repo')).toBe('https://github.com/user/repo');
52
+ });
53
+
54
+ it('should handle trailing slashes', () => {
55
+ expect(normalizeGitUrl('https://github.com/user/repo/')).toBe('https://github.com/user/repo');
56
+ });
57
+
58
+ it('should add https protocol to bare URLs', () => {
59
+ expect(normalizeGitUrl('github.com/user/repo')).toBe('https://github.com/user/repo');
44
60
  });
45
61
  });
46
62
 
package/src/cli.ts CHANGED
@@ -1,212 +1,204 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Vibescope CLI - Setup wizard and enforcement verification tool
5
- *
6
- * Commands:
7
- * setup - Interactive wizard to configure Vibescope for your IDE
8
- * verify - Check agent compliance with Vibescope tracking (used by hooks)
9
- *
10
- * Exit codes (for verify command):
11
- * 0 = Compliant (allow exit)
12
- * 1 = Non-compliant (block exit, loop back)
13
- * 2 = Error (allow exit with warning)
14
- */
15
-
16
- import { execSync } from 'child_process';
17
- import { runSetup } from './setup.js';
18
-
19
- // ============================================================================
20
- // Types
21
- // ============================================================================
22
-
23
- export interface VerificationResult {
24
- status: 'compliant' | 'non_compliant' | 'no_session' | 'error';
25
- reason: string;
26
- continuation_prompt?: string;
27
- details?: {
28
- session_started: boolean;
29
- project_id: string | null;
30
- project_name: string | null;
31
- git_url: string | null;
32
- in_progress_tasks: number;
33
- tasks_completed_this_session: number;
34
- progress_logs_this_session: number;
35
- blockers_logged_this_session: number;
36
- session_duration_minutes: number | null;
37
- };
38
- }
39
-
40
- // ============================================================================
41
- // Configuration (read at runtime for testability)
42
- // ============================================================================
43
-
44
- function getApiKey(): string | undefined {
45
- return process.env.VIBESCOPE_API_KEY;
46
- }
47
-
48
- function getApiUrl(): string {
49
- return process.env.VIBESCOPE_API_URL || 'https://vibescope.dev';
50
- }
51
-
52
- // ============================================================================
53
- // Git URL Detection
54
- // ============================================================================
55
-
56
- export function normalizeGitUrl(url: string): string {
57
- // Remove .git suffix
58
- let normalized = url.replace(/\.git$/, '');
59
- // Convert SSH to HTTPS format
60
- if (normalized.startsWith('git@')) {
61
- normalized = normalized
62
- .replace(/^git@/, 'https://')
63
- .replace(/:([^/])/, '/$1');
64
- }
65
- return normalized;
66
- }
67
-
68
- export function detectGitUrl(): string | null {
69
- try {
70
- const url = execSync('git config --get remote.origin.url', {
71
- encoding: 'utf8',
72
- timeout: 5000,
73
- stdio: ['pipe', 'pipe', 'pipe'],
74
- }).trim();
75
-
76
- return normalizeGitUrl(url);
77
- } catch {
78
- return null;
79
- }
80
- }
81
-
82
- // ============================================================================
83
- // Verification Logic
84
- // ============================================================================
85
-
86
- export async function verify(
87
- gitUrl?: string,
88
- projectId?: string
89
- ): Promise<VerificationResult> {
90
- // Check environment (read at runtime for testability)
91
- const apiKey = getApiKey();
92
- if (!apiKey) {
93
- return {
94
- status: 'error',
95
- reason: 'VIBESCOPE_API_KEY environment variable not set',
96
- };
97
- }
98
-
99
- // Auto-detect git URL if not provided
100
- if (!gitUrl && !projectId) {
101
- gitUrl = detectGitUrl() || undefined;
102
- }
103
-
104
- try {
105
- const response = await fetch(`${getApiUrl()}/api/mcp/verify`, {
106
- method: 'POST',
107
- headers: {
108
- 'Content-Type': 'application/json',
109
- },
110
- body: JSON.stringify({
111
- api_key: apiKey,
112
- git_url: gitUrl,
113
- project_id: projectId,
114
- }),
115
- });
116
-
117
- const result = await response.json() as VerificationResult;
118
- return result;
119
- } catch (err) {
120
- return {
121
- status: 'error',
122
- reason: err instanceof Error ? err.message : 'Network error',
123
- };
124
- }
125
- }
126
-
127
- // ============================================================================
128
- // CLI Entry Point
129
- // ============================================================================
130
-
131
- async function main() {
132
- const args = process.argv.slice(2);
133
- const command = args[0];
134
-
135
- if (command === 'setup') {
136
- // Run interactive setup wizard
137
- await runSetup();
138
- process.exit(0);
139
- } else if (command === 'verify') {
140
- // Parse --git-url and --project-id flags
141
- let gitUrl: string | undefined;
142
- let projectId: string | undefined;
143
-
144
- for (let i = 1; i < args.length; i++) {
145
- if (args[i] === '--git-url' && args[i + 1]) {
146
- gitUrl = args[++i];
147
- } else if (args[i] === '--project-id' && args[i + 1]) {
148
- projectId = args[++i];
149
- }
150
- }
151
-
152
- const result = await verify(gitUrl, projectId);
153
- console.log(JSON.stringify(result, null, 2));
154
-
155
- // Exit codes: 0=compliant, 1=non-compliant, 2=error
156
- if (result.status === 'compliant') {
157
- process.exit(0);
158
- } else if (result.status === 'error') {
159
- process.exit(2);
160
- } else {
161
- process.exit(1);
162
- }
163
- } else if (command === 'help' || command === '--help' || command === '-h') {
164
- console.log(`
165
- Vibescope CLI - Setup wizard and enforcement verification tool
166
-
167
- Usage:
168
- vibescope-cli setup Interactive setup wizard for your IDE
169
- vibescope-cli verify [options] Check Vibescope compliance before exit
170
-
171
- Setup:
172
- Configures Vibescope MCP integration for:
173
- - Claude Code (CLI)
174
- - Claude Desktop
175
- - Cursor
176
- - Gemini CLI
177
-
178
- Verify Options:
179
- --git-url <url> Git repository URL (auto-detected if not provided)
180
- --project-id <id> Vibescope project UUID
181
-
182
- Exit Codes (verify):
183
- 0 Compliant - agent can exit
184
- 1 Non-compliant - agent should continue work
185
- 2 Error - allow exit with warning
186
-
187
- Environment Variables:
188
- VIBESCOPE_API_KEY Required for verify - Your Vibescope API key
189
- VIBESCOPE_API_URL Optional - API URL (default: https://vibescope.dev)
190
- `);
191
- process.exit(0);
192
- } else {
193
- console.error('Usage: vibescope-cli setup');
194
- console.error(' vibescope-cli verify [--git-url <url>] [--project-id <id>]');
195
- console.error(' vibescope-cli --help');
196
- process.exit(2);
197
- }
198
- }
199
-
200
- // Only run main when executed directly (not when imported for testing)
201
- const isMainModule = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, '/')}`;
202
- if (isMainModule || process.argv[1]?.endsWith('cli.js')) {
203
- main().catch((err) => {
204
- console.error(
205
- JSON.stringify({
206
- status: 'error',
207
- reason: err instanceof Error ? err.message : 'Unknown error',
208
- })
209
- );
210
- process.exit(2);
211
- });
212
- }
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Vibescope CLI - Setup wizard and enforcement verification tool
5
+ *
6
+ * Commands:
7
+ * setup - Interactive wizard to configure Vibescope for your IDE
8
+ * verify - Check agent compliance with Vibescope tracking (used by hooks)
9
+ *
10
+ * Exit codes (for verify command):
11
+ * 0 = Compliant (allow exit)
12
+ * 1 = Non-compliant (block exit, loop back)
13
+ * 2 = Error (allow exit with warning)
14
+ */
15
+
16
+ import { execSync } from 'child_process';
17
+ import { runSetup } from './setup.js';
18
+ import { normalizeGitUrl as normalizeGitUrlFn } from './utils.js';
19
+
20
+ // ============================================================================
21
+ // Types
22
+ // ============================================================================
23
+
24
+ export interface VerificationResult {
25
+ status: 'compliant' | 'non_compliant' | 'no_session' | 'error';
26
+ reason: string;
27
+ continuation_prompt?: string;
28
+ details?: {
29
+ session_started: boolean;
30
+ project_id: string | null;
31
+ project_name: string | null;
32
+ git_url: string | null;
33
+ in_progress_tasks: number;
34
+ tasks_completed_this_session: number;
35
+ progress_logs_this_session: number;
36
+ blockers_logged_this_session: number;
37
+ session_duration_minutes: number | null;
38
+ };
39
+ }
40
+
41
+ // ============================================================================
42
+ // Configuration (read at runtime for testability)
43
+ // ============================================================================
44
+
45
+ function getApiKey(): string | undefined {
46
+ return process.env.VIBESCOPE_API_KEY;
47
+ }
48
+
49
+ function getApiUrl(): string {
50
+ return process.env.VIBESCOPE_API_URL || 'https://vibescope.dev';
51
+ }
52
+
53
+ // ============================================================================
54
+ // Git URL Detection
55
+ // ============================================================================
56
+
57
+ // Re-export normalizeGitUrl from utils for backwards compatibility with tests
58
+ export { normalizeGitUrl } from './utils.js';
59
+
60
+ export function detectGitUrl(): string | null {
61
+ try {
62
+ const url = execSync('git config --get remote.origin.url', {
63
+ encoding: 'utf8',
64
+ timeout: 5000,
65
+ stdio: ['pipe', 'pipe', 'pipe'],
66
+ }).trim();
67
+
68
+ return normalizeGitUrlFn(url);
69
+ } catch {
70
+ return null;
71
+ }
72
+ }
73
+
74
+ // ============================================================================
75
+ // Verification Logic
76
+ // ============================================================================
77
+
78
+ export async function verify(
79
+ gitUrl?: string,
80
+ projectId?: string
81
+ ): Promise<VerificationResult> {
82
+ // Check environment (read at runtime for testability)
83
+ const apiKey = getApiKey();
84
+ if (!apiKey) {
85
+ return {
86
+ status: 'error',
87
+ reason: 'VIBESCOPE_API_KEY environment variable not set',
88
+ };
89
+ }
90
+
91
+ // Auto-detect git URL if not provided
92
+ if (!gitUrl && !projectId) {
93
+ gitUrl = detectGitUrl() || undefined;
94
+ }
95
+
96
+ try {
97
+ const response = await fetch(`${getApiUrl()}/api/mcp/verify`, {
98
+ method: 'POST',
99
+ headers: {
100
+ 'Content-Type': 'application/json',
101
+ },
102
+ body: JSON.stringify({
103
+ api_key: apiKey,
104
+ git_url: gitUrl,
105
+ project_id: projectId,
106
+ }),
107
+ });
108
+
109
+ const result = await response.json() as VerificationResult;
110
+ return result;
111
+ } catch (err) {
112
+ return {
113
+ status: 'error',
114
+ reason: err instanceof Error ? err.message : 'Network error',
115
+ };
116
+ }
117
+ }
118
+
119
+ // ============================================================================
120
+ // CLI Entry Point
121
+ // ============================================================================
122
+
123
+ async function main() {
124
+ const args = process.argv.slice(2);
125
+ const command = args[0];
126
+
127
+ if (command === 'setup') {
128
+ // Run interactive setup wizard
129
+ await runSetup();
130
+ process.exit(0);
131
+ } else if (command === 'verify') {
132
+ // Parse --git-url and --project-id flags
133
+ let gitUrl: string | undefined;
134
+ let projectId: string | undefined;
135
+
136
+ for (let i = 1; i < args.length; i++) {
137
+ if (args[i] === '--git-url' && args[i + 1]) {
138
+ gitUrl = args[++i];
139
+ } else if (args[i] === '--project-id' && args[i + 1]) {
140
+ projectId = args[++i];
141
+ }
142
+ }
143
+
144
+ const result = await verify(gitUrl, projectId);
145
+ console.log(JSON.stringify(result, null, 2));
146
+
147
+ // Exit codes: 0=compliant, 1=non-compliant, 2=error
148
+ if (result.status === 'compliant') {
149
+ process.exit(0);
150
+ } else if (result.status === 'error') {
151
+ process.exit(2);
152
+ } else {
153
+ process.exit(1);
154
+ }
155
+ } else if (command === 'help' || command === '--help' || command === '-h') {
156
+ console.log(`
157
+ Vibescope CLI - Setup wizard and enforcement verification tool
158
+
159
+ Usage:
160
+ vibescope-cli setup Interactive setup wizard for your IDE
161
+ vibescope-cli verify [options] Check Vibescope compliance before exit
162
+
163
+ Setup:
164
+ Configures Vibescope MCP integration for:
165
+ - Claude Code (CLI)
166
+ - Claude Desktop
167
+ - Cursor
168
+ - Gemini CLI
169
+
170
+ Verify Options:
171
+ --git-url <url> Git repository URL (auto-detected if not provided)
172
+ --project-id <id> Vibescope project UUID
173
+
174
+ Exit Codes (verify):
175
+ 0 Compliant - agent can exit
176
+ 1 Non-compliant - agent should continue work
177
+ 2 Error - allow exit with warning
178
+
179
+ Environment Variables:
180
+ VIBESCOPE_API_KEY Required for verify - Your Vibescope API key
181
+ VIBESCOPE_API_URL Optional - API URL (default: https://vibescope.dev)
182
+ `);
183
+ process.exit(0);
184
+ } else {
185
+ console.error('Usage: vibescope-cli setup');
186
+ console.error(' vibescope-cli verify [--git-url <url>] [--project-id <id>]');
187
+ console.error(' vibescope-cli --help');
188
+ process.exit(2);
189
+ }
190
+ }
191
+
192
+ // Only run main when executed directly (not when imported for testing)
193
+ const isMainModule = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, '/')}`;
194
+ if (isMainModule || process.argv[1]?.endsWith('cli.js')) {
195
+ main().catch((err) => {
196
+ console.error(
197
+ JSON.stringify({
198
+ status: 'error',
199
+ reason: err instanceof Error ? err.message : 'Unknown error',
200
+ })
201
+ );
202
+ process.exit(2);
203
+ });
204
+ }