@vibescope/mcp-server 0.2.8 → 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 (97) hide show
  1. package/CHANGELOG.md +84 -84
  2. package/README.md +194 -194
  3. package/dist/api-client.d.ts +41 -5
  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/roles.js +1 -8
  9. package/dist/handlers/session.d.ts +11 -0
  10. package/dist/handlers/session.js +124 -32
  11. package/dist/handlers/tasks.d.ts +8 -0
  12. package/dist/handlers/tasks.js +163 -3
  13. package/dist/handlers/tool-docs.js +840 -828
  14. package/dist/handlers/validation.js +71 -15
  15. package/dist/index.js +73 -73
  16. package/dist/setup.js +6 -6
  17. package/dist/templates/agent-guidelines.js +185 -185
  18. package/dist/templates/help-content.d.ts +24 -0
  19. package/dist/templates/help-content.js +1728 -0
  20. package/dist/tools.js +132 -87
  21. package/dist/utils.d.ts +15 -11
  22. package/dist/utils.js +53 -28
  23. package/docs/TOOLS.md +2406 -2053
  24. package/package.json +1 -1
  25. package/scripts/generate-docs.ts +212 -212
  26. package/scripts/version-bump.ts +203 -203
  27. package/src/api-client.test.ts +723 -723
  28. package/src/api-client.ts +2561 -2499
  29. package/src/cli.test.ts +24 -8
  30. package/src/cli.ts +204 -212
  31. package/src/handlers/__test-setup__.ts +236 -236
  32. package/src/handlers/__test-utils__.ts +87 -87
  33. package/src/handlers/blockers.test.ts +468 -468
  34. package/src/handlers/blockers.ts +163 -163
  35. package/src/handlers/bodies-of-work.test.ts +704 -704
  36. package/src/handlers/bodies-of-work.ts +526 -526
  37. package/src/handlers/connectors.test.ts +834 -834
  38. package/src/handlers/connectors.ts +229 -229
  39. package/src/handlers/cost.test.ts +462 -462
  40. package/src/handlers/cost.ts +285 -285
  41. package/src/handlers/decisions.test.ts +382 -382
  42. package/src/handlers/decisions.ts +153 -153
  43. package/src/handlers/deployment.test.ts +551 -551
  44. package/src/handlers/deployment.ts +541 -541
  45. package/src/handlers/discovery.test.ts +206 -206
  46. package/src/handlers/discovery.ts +392 -390
  47. package/src/handlers/fallback.test.ts +537 -537
  48. package/src/handlers/fallback.ts +194 -194
  49. package/src/handlers/file-checkouts.test.ts +750 -750
  50. package/src/handlers/file-checkouts.ts +185 -185
  51. package/src/handlers/findings.test.ts +633 -633
  52. package/src/handlers/findings.ts +239 -239
  53. package/src/handlers/git-issues.test.ts +631 -631
  54. package/src/handlers/git-issues.ts +136 -136
  55. package/src/handlers/ideas.test.ts +644 -644
  56. package/src/handlers/ideas.ts +207 -207
  57. package/src/handlers/index.ts +84 -84
  58. package/src/handlers/milestones.test.ts +475 -475
  59. package/src/handlers/milestones.ts +180 -180
  60. package/src/handlers/organizations.test.ts +826 -826
  61. package/src/handlers/organizations.ts +315 -315
  62. package/src/handlers/progress.test.ts +269 -269
  63. package/src/handlers/progress.ts +77 -77
  64. package/src/handlers/project.test.ts +546 -546
  65. package/src/handlers/project.ts +239 -239
  66. package/src/handlers/requests.test.ts +303 -303
  67. package/src/handlers/requests.ts +99 -99
  68. package/src/handlers/roles.test.ts +305 -303
  69. package/src/handlers/roles.ts +219 -226
  70. package/src/handlers/session.test.ts +998 -875
  71. package/src/handlers/session.ts +839 -738
  72. package/src/handlers/sprints.test.ts +732 -732
  73. package/src/handlers/sprints.ts +537 -537
  74. package/src/handlers/tasks.test.ts +931 -907
  75. package/src/handlers/tasks.ts +1121 -945
  76. package/src/handlers/tool-categories.test.ts +66 -66
  77. package/src/handlers/tool-docs.ts +1109 -1096
  78. package/src/handlers/types.test.ts +259 -259
  79. package/src/handlers/types.ts +175 -175
  80. package/src/handlers/validation.test.ts +582 -582
  81. package/src/handlers/validation.ts +159 -97
  82. package/src/index.test.ts +674 -0
  83. package/src/index.ts +792 -792
  84. package/src/setup.test.ts +233 -233
  85. package/src/setup.ts +404 -403
  86. package/src/templates/agent-guidelines.ts +210 -210
  87. package/src/templates/help-content.ts +1751 -0
  88. package/src/token-tracking.test.ts +463 -463
  89. package/src/token-tracking.ts +166 -166
  90. package/src/tools.test.ts +416 -0
  91. package/src/tools.ts +3607 -3562
  92. package/src/utils.test.ts +785 -683
  93. package/src/utils.ts +469 -436
  94. package/src/validators.test.ts +223 -223
  95. package/src/validators.ts +249 -249
  96. package/tsconfig.json +16 -16
  97. 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
+ }