@tostudy-ai/mcp-setup 1.0.2 → 1.1.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 (47) hide show
  1. package/README.md +1 -1
  2. package/dist/__tests__/e2e-wizard-flow.test.d.ts.map +1 -1
  3. package/dist/__tests__/e2e-wizard-flow.test.js +128 -117
  4. package/dist/__tests__/e2e-wizard-flow.test.js.map +1 -1
  5. package/dist/__tests__/ide-handlers.test.js +15 -11
  6. package/dist/__tests__/ide-handlers.test.js.map +1 -1
  7. package/dist/__tests__/install-command.test.js +106 -95
  8. package/dist/__tests__/install-command.test.js.map +1 -1
  9. package/dist/config.d.ts +15 -4
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +79 -29
  12. package/dist/config.js.map +1 -1
  13. package/dist/diagnose.d.ts +1 -1
  14. package/dist/diagnose.d.ts.map +1 -1
  15. package/dist/diagnose.js +154 -164
  16. package/dist/diagnose.js.map +1 -1
  17. package/dist/ide-handlers/antigravity.js +1 -1
  18. package/dist/ide-handlers/antigravity.js.map +1 -1
  19. package/dist/ide-handlers/base.d.ts +8 -8
  20. package/dist/ide-handlers/base.d.ts.map +1 -1
  21. package/dist/ide-handlers/base.js +29 -4
  22. package/dist/ide-handlers/base.js.map +1 -1
  23. package/dist/ide-handlers/claude-code.js +1 -1
  24. package/dist/ide-handlers/claude-code.js.map +1 -1
  25. package/dist/ide-handlers/codex.js +1 -1
  26. package/dist/ide-handlers/codex.js.map +1 -1
  27. package/dist/ide-handlers/cursor.js +1 -1
  28. package/dist/ide-handlers/cursor.js.map +1 -1
  29. package/dist/ide-handlers/desktop.d.ts +3 -3
  30. package/dist/ide-handlers/desktop.d.ts.map +1 -1
  31. package/dist/ide-handlers/desktop.js +32 -8
  32. package/dist/ide-handlers/desktop.js.map +1 -1
  33. package/dist/ide-handlers/manual.js +1 -1
  34. package/dist/ide-handlers/manual.js.map +1 -1
  35. package/dist/ide-handlers/opencode.js +1 -1
  36. package/dist/ide-handlers/opencode.js.map +1 -1
  37. package/dist/ide-handlers/vscode.js +1 -1
  38. package/dist/ide-handlers/vscode.js.map +1 -1
  39. package/dist/ide-handlers/windsurf.js +1 -1
  40. package/dist/ide-handlers/windsurf.js.map +1 -1
  41. package/dist/index.js +198 -156
  42. package/dist/index.js.map +1 -1
  43. package/dist/repair.d.ts +1 -1
  44. package/dist/repair.d.ts.map +1 -1
  45. package/dist/repair.js +213 -168
  46. package/dist/repair.js.map +1 -1
  47. package/package.json +5 -5
package/dist/repair.js CHANGED
@@ -5,13 +5,13 @@
5
5
  * Provides automatic repair functions for common MCP configuration issues.
6
6
  * Works in conjunction with diagnose.ts to fix detected problems.
7
7
  */
8
- import { existsSync, mkdirSync, writeFileSync, copyFileSync } from 'node:fs';
9
- import { dirname } from 'node:path';
10
- import chalk from 'chalk';
11
- import { getClaudeConfigPath, readClaudeConfig, writeClaudeConfig, addTostudyMcpServer, } from './config.js';
12
- import { runDiagnostics } from './diagnose.js';
13
- const DEFAULT_PLATFORM_URL = 'https://tostudy.com';
14
- function println(message = '') {
8
+ import { existsSync, mkdirSync, writeFileSync, copyFileSync } from "node:fs";
9
+ import { dirname } from "node:path";
10
+ import chalk from "chalk";
11
+ import { getClaudeConfigPath, readClaudeConfig, writeClaudeConfig, addTostudyMcpServer, extractApiKey, extractMcpUrl, } from "./config.js";
12
+ import { runDiagnostics } from "./diagnose.js";
13
+ const DEFAULT_PLATFORM_URL = "https://tostudy.com";
14
+ function println(message = "") {
15
15
  process.stdout.write(`${message}\n`);
16
16
  }
17
17
  /**
@@ -29,17 +29,17 @@ function repairMissingConfig() {
29
29
  const initialConfig = {
30
30
  mcpServers: {},
31
31
  };
32
- writeFileSync(configPath, JSON.stringify(initialConfig, null, 2), 'utf-8');
32
+ writeFileSync(configPath, JSON.stringify(initialConfig, null, 2), "utf-8");
33
33
  return {
34
- issueId: 'config-missing',
34
+ issueId: "config-missing",
35
35
  success: true,
36
- message: 'Arquivo de configuracao criado com sucesso.',
36
+ message: "Arquivo de configuracao criado com sucesso.",
37
37
  action: `Criado: ${configPath}`,
38
38
  };
39
39
  }
40
40
  catch (error) {
41
41
  return {
42
- issueId: 'config-missing',
42
+ issueId: "config-missing",
43
43
  success: false,
44
44
  message: `Falha ao criar arquivo de configuracao: ${error instanceof Error ? error.message : String(error)}`,
45
45
  };
@@ -59,23 +59,23 @@ function repairInvalidJson() {
59
59
  const freshConfig = {
60
60
  mcpServers: {},
61
61
  };
62
- writeFileSync(configPath, JSON.stringify(freshConfig, null, 2), 'utf-8');
62
+ writeFileSync(configPath, JSON.stringify(freshConfig, null, 2), "utf-8");
63
63
  return {
64
- issueId: 'config-invalid-json',
64
+ issueId: "config-invalid-json",
65
65
  success: true,
66
- message: 'Arquivo de configuracao recriado. Backup salvo.',
66
+ message: "Arquivo de configuracao recriado. Backup salvo.",
67
67
  action: `Backup: ${backupPath}`,
68
68
  };
69
69
  }
70
70
  return {
71
- issueId: 'config-invalid-json',
71
+ issueId: "config-invalid-json",
72
72
  success: false,
73
- message: 'Arquivo de configuracao nao existe.',
73
+ message: "Arquivo de configuracao nao existe.",
74
74
  };
75
75
  }
76
76
  catch (error) {
77
77
  return {
78
- issueId: 'config-invalid-json',
78
+ issueId: "config-invalid-json",
79
79
  success: false,
80
80
  message: `Falha ao reparar JSON: ${error instanceof Error ? error.message : String(error)}`,
81
81
  };
@@ -88,15 +88,15 @@ function repairMcpNotConfigured(apiKey, platformUrl = DEFAULT_PLATFORM_URL) {
88
88
  try {
89
89
  addTostudyMcpServer(apiKey, platformUrl);
90
90
  return {
91
- issueId: 'mcp-not-configured',
91
+ issueId: "mcp-not-configured",
92
92
  success: true,
93
- message: 'Servidor MCP da Catalyst configurado com sucesso.',
94
- action: 'Servidor tostudy adicionado',
93
+ message: "Servidor MCP da Catalyst configurado com sucesso.",
94
+ action: "Servidor tostudy adicionado",
95
95
  };
96
96
  }
97
97
  catch (error) {
98
98
  return {
99
- issueId: 'mcp-not-configured',
99
+ issueId: "mcp-not-configured",
100
100
  success: false,
101
101
  message: `Falha ao configurar MCP: ${error instanceof Error ? error.message : String(error)}`,
102
102
  };
@@ -110,92 +110,116 @@ function repairApiKeyMissing(apiKey, platformUrl = DEFAULT_PLATFORM_URL) {
110
110
  // Re-add the server with the correct API key
111
111
  addTostudyMcpServer(apiKey, platformUrl);
112
112
  return {
113
- issueId: 'api-key-missing',
113
+ issueId: "api-key-missing",
114
114
  success: true,
115
- message: 'API key configurada com sucesso.',
116
- action: 'Header Authorization adicionado',
115
+ message: "API key configurada com sucesso.",
116
+ action: "Header Authorization adicionado",
117
117
  };
118
118
  }
119
119
  catch (error) {
120
120
  return {
121
- issueId: 'api-key-missing',
121
+ issueId: "api-key-missing",
122
122
  success: false,
123
123
  message: `Falha ao configurar API key: ${error instanceof Error ? error.message : String(error)}`,
124
124
  };
125
125
  }
126
126
  }
127
127
  /**
128
- * Fix invalid API key format (missing Bearer prefix)
128
+ * Fix invalid API key format (supports both SSE and stdio formats)
129
129
  */
130
130
  function repairApiKeyFormat() {
131
131
  const config = readClaudeConfig();
132
- const mcpConfig = config.mcpServers?.['tostudy'];
132
+ const mcpConfig = config.mcpServers?.["tostudy"];
133
133
  if (!mcpConfig) {
134
134
  return {
135
- issueId: 'api-key-invalid-format',
135
+ issueId: "api-key-invalid-format",
136
136
  success: false,
137
- message: 'Servidor MCP nao esta configurado.',
137
+ message: "Servidor MCP nao esta configurado.",
138
138
  };
139
139
  }
140
140
  try {
141
- const authHeader = mcpConfig.headers?.['Authorization'] || '';
142
- // If it's just the key without Bearer prefix, add it
143
- if (authHeader && !authHeader.startsWith('Bearer ')) {
144
- if (!mcpConfig.headers) {
145
- mcpConfig.headers = {};
141
+ // SSE format: fix headers
142
+ if (mcpConfig.headers) {
143
+ const authHeader = mcpConfig.headers["Authorization"] || "";
144
+ if (authHeader && !authHeader.startsWith("Bearer ")) {
145
+ mcpConfig.headers["Authorization"] = `Bearer ${authHeader}`;
146
+ writeClaudeConfig(config);
147
+ return {
148
+ issueId: "api-key-invalid-format",
149
+ success: true,
150
+ message: "Formato de API key corrigido.",
151
+ action: 'Prefixo "Bearer " adicionado',
152
+ };
153
+ }
154
+ }
155
+ // Stdio format: fix args
156
+ if (mcpConfig.args) {
157
+ for (let i = 0; i < mcpConfig.args.length; i++) {
158
+ if (mcpConfig.args[i] === "--header" &&
159
+ mcpConfig.args[i + 1]?.startsWith("Authorization:")) {
160
+ const value = mcpConfig.args[i + 1].replace("Authorization:", "");
161
+ if (value && !value.startsWith("Bearer ")) {
162
+ mcpConfig.args[i + 1] = `Authorization:Bearer ${value}`;
163
+ writeClaudeConfig(config);
164
+ return {
165
+ issueId: "api-key-invalid-format",
166
+ success: true,
167
+ message: "Formato de API key corrigido.",
168
+ action: 'Prefixo "Bearer " adicionado',
169
+ };
170
+ }
171
+ }
146
172
  }
147
- mcpConfig.headers['Authorization'] = `Bearer ${authHeader}`;
148
- writeClaudeConfig(config);
149
- return {
150
- issueId: 'api-key-invalid-format',
151
- success: true,
152
- message: 'Formato de API key corrigido.',
153
- action: 'Prefixo "Bearer " adicionado',
154
- };
155
173
  }
156
174
  return {
157
- issueId: 'api-key-invalid-format',
175
+ issueId: "api-key-invalid-format",
158
176
  success: false,
159
- message: 'API key nao encontrada para corrigir.',
177
+ message: "API key nao encontrada para corrigir.",
160
178
  };
161
179
  }
162
180
  catch (error) {
163
181
  return {
164
- issueId: 'api-key-invalid-format',
182
+ issueId: "api-key-invalid-format",
165
183
  success: false,
166
184
  message: `Falha ao corrigir formato: ${error instanceof Error ? error.message : String(error)}`,
167
185
  };
168
186
  }
169
187
  }
170
188
  /**
171
- * Fix missing or invalid server URL
189
+ * Fix missing or invalid server URL by re-adding with correct config
172
190
  */
173
191
  function repairServerUrl(platformUrl = DEFAULT_PLATFORM_URL) {
174
192
  const config = readClaudeConfig();
175
- const mcpConfig = config.mcpServers?.['tostudy'];
193
+ const mcpConfig = config.mcpServers?.["tostudy"];
176
194
  if (!mcpConfig) {
177
195
  return {
178
- issueId: 'server-url-missing',
196
+ issueId: "server-url-missing",
179
197
  success: false,
180
- message: 'Servidor MCP nao esta configurado.',
198
+ message: "Servidor MCP nao esta configurado.",
181
199
  };
182
200
  }
183
201
  try {
184
- // Construct the correct MCP SSE URL
185
- const mcpServerUrl = platformUrl.replace(':3700', ':3701');
186
- mcpConfig.url = `${mcpServerUrl}/mcp/sse`;
187
- mcpConfig.type = 'sse';
188
- writeClaudeConfig(config);
202
+ // Extract existing API key to preserve it
203
+ const apiKey = extractApiKey(mcpConfig);
204
+ if (!apiKey) {
205
+ return {
206
+ issueId: "server-url-missing",
207
+ success: false,
208
+ message: "API key nao encontrada para reconstruir configuracao.",
209
+ };
210
+ }
211
+ // Re-add with correct URL using stdio format
212
+ addTostudyMcpServer(apiKey, platformUrl);
189
213
  return {
190
- issueId: 'server-url-missing',
214
+ issueId: "server-url-missing",
191
215
  success: true,
192
- message: 'URL do servidor configurada.',
193
- action: `URL: ${mcpConfig.url}`,
216
+ message: "URL do servidor configurada.",
217
+ action: `URL: ${platformUrl}/mcp`,
194
218
  };
195
219
  }
196
220
  catch (error) {
197
221
  return {
198
- issueId: 'server-url-missing',
222
+ issueId: "server-url-missing",
199
223
  success: false,
200
224
  message: `Falha ao configurar URL: ${error instanceof Error ? error.message : String(error)}`,
201
225
  };
@@ -206,76 +230,96 @@ function repairServerUrl(platformUrl = DEFAULT_PLATFORM_URL) {
206
230
  */
207
231
  function repairServerUrlProtocol(platformUrl = DEFAULT_PLATFORM_URL) {
208
232
  const config = readClaudeConfig();
209
- const mcpConfig = config.mcpServers?.['tostudy'];
210
- if (!mcpConfig?.url) {
233
+ const mcpConfig = config.mcpServers?.["tostudy"];
234
+ if (!mcpConfig) {
211
235
  return {
212
- issueId: 'server-url-invalid-protocol',
236
+ issueId: "server-url-invalid-protocol",
213
237
  success: false,
214
- message: 'URL do servidor nao configurada.',
238
+ message: "Servidor MCP nao esta configurado.",
239
+ };
240
+ }
241
+ const url = extractMcpUrl(mcpConfig);
242
+ if (!url) {
243
+ return {
244
+ issueId: "server-url-invalid-protocol",
245
+ success: false,
246
+ message: "URL do servidor nao configurada.",
215
247
  };
216
248
  }
217
249
  try {
218
- // Parse the existing URL and fix the protocol
219
- const existingUrl = mcpConfig.url;
220
- // Replace invalid protocol with https
221
- const fixedUrl = existingUrl.replace(/^[a-z]+:/, 'https:');
222
- mcpConfig.url = fixedUrl;
223
- writeClaudeConfig(config);
250
+ // Fix the protocol to https and re-add
251
+ const fixedUrl = url.replace(/^[a-z]+:/, "https:");
252
+ // Extract base platform URL from the fixed URL
253
+ const basePlatformUrl = fixedUrl.replace(/\/mcp(\/sse)?$/, "");
254
+ const apiKey = extractApiKey(mcpConfig);
255
+ if (!apiKey) {
256
+ return {
257
+ issueId: "server-url-invalid-protocol",
258
+ success: false,
259
+ message: "API key nao encontrada para reconstruir configuracao.",
260
+ };
261
+ }
262
+ addTostudyMcpServer(apiKey, basePlatformUrl);
224
263
  return {
225
- issueId: 'server-url-invalid-protocol',
264
+ issueId: "server-url-invalid-protocol",
226
265
  success: true,
227
- message: 'Protocolo da URL corrigido para HTTPS.',
228
- action: `URL: ${fixedUrl}`,
266
+ message: "Protocolo da URL corrigido para HTTPS.",
267
+ action: `URL: ${basePlatformUrl}/mcp`,
229
268
  };
230
269
  }
231
270
  catch (error) {
232
271
  return {
233
- issueId: 'server-url-invalid-protocol',
272
+ issueId: "server-url-invalid-protocol",
234
273
  success: false,
235
274
  message: `Falha ao corrigir protocolo: ${error instanceof Error ? error.message : String(error)}`,
236
275
  };
237
276
  }
238
277
  }
239
278
  /**
240
- * Fix URL missing /mcp/sse path
279
+ * Fix URL missing /mcp path
241
280
  */
242
281
  function repairServerUrlPath() {
243
282
  const config = readClaudeConfig();
244
- const mcpConfig = config.mcpServers?.['tostudy'];
245
- if (!mcpConfig?.url) {
283
+ const mcpConfig = config.mcpServers?.["tostudy"];
284
+ if (!mcpConfig) {
285
+ return {
286
+ issueId: "server-url-missing-sse-path",
287
+ success: false,
288
+ message: "Servidor MCP nao esta configurado.",
289
+ };
290
+ }
291
+ const url = extractMcpUrl(mcpConfig);
292
+ if (!url) {
246
293
  return {
247
- issueId: 'server-url-missing-sse-path',
294
+ issueId: "server-url-missing-sse-path",
248
295
  success: false,
249
- message: 'URL do servidor nao configurada.',
296
+ message: "URL do servidor nao configurada.",
250
297
  };
251
298
  }
252
299
  try {
253
- let url = mcpConfig.url;
254
- // Parse URL and fix path
255
300
  const parsedUrl = new URL(url);
256
- // Remove trailing slash and add /mcp/sse
257
- parsedUrl.pathname = parsedUrl.pathname.replace(/\/$/, '');
258
- if (!parsedUrl.pathname.endsWith('/mcp/sse')) {
259
- // If it ends with /mcp, just add /sse
260
- if (parsedUrl.pathname.endsWith('/mcp')) {
261
- parsedUrl.pathname += '/sse';
262
- }
263
- else {
264
- parsedUrl.pathname += '/mcp/sse';
265
- }
301
+ // Extract base URL (strip /mcp or /mcp/sse if present, then re-add /mcp)
302
+ parsedUrl.pathname = parsedUrl.pathname.replace(/\/(mcp(\/sse)?)?$/, "");
303
+ const basePlatformUrl = parsedUrl.toString().replace(/\/$/, "");
304
+ const apiKey = extractApiKey(mcpConfig);
305
+ if (!apiKey) {
306
+ return {
307
+ issueId: "server-url-missing-sse-path",
308
+ success: false,
309
+ message: "API key nao encontrada para reconstruir configuracao.",
310
+ };
266
311
  }
267
- mcpConfig.url = parsedUrl.toString();
268
- writeClaudeConfig(config);
312
+ addTostudyMcpServer(apiKey, basePlatformUrl);
269
313
  return {
270
- issueId: 'server-url-missing-sse-path',
314
+ issueId: "server-url-missing-sse-path",
271
315
  success: true,
272
- message: 'Path /mcp/sse adicionado a URL.',
273
- action: `URL: ${mcpConfig.url}`,
316
+ message: "Path /mcp corrigido na URL.",
317
+ action: `URL: ${basePlatformUrl}/mcp`,
274
318
  };
275
319
  }
276
320
  catch (error) {
277
321
  return {
278
- issueId: 'server-url-missing-sse-path',
322
+ issueId: "server-url-missing-sse-path",
279
323
  success: false,
280
324
  message: `Falha ao corrigir path: ${error instanceof Error ? error.message : String(error)}`,
281
325
  };
@@ -288,25 +332,25 @@ function repairDuplicateServers() {
288
332
  const config = readClaudeConfig();
289
333
  if (!config.mcpServers) {
290
334
  return {
291
- issueId: 'duplicate-servers',
335
+ issueId: "duplicate-servers",
292
336
  success: false,
293
- message: 'Nenhum servidor MCP configurado.',
337
+ message: "Nenhum servidor MCP configurado.",
294
338
  };
295
339
  }
296
340
  try {
297
341
  const servers = Object.entries(config.mcpServers);
298
- const anaServers = servers.filter(([key, server]) => key.toLowerCase().includes('ana') ||
299
- key.toLowerCase().includes('catalyst') ||
300
- (server.url && server.url.includes('tostudy.com')));
342
+ const anaServers = servers.filter(([key, server]) => key.toLowerCase().includes("ana") ||
343
+ key.toLowerCase().includes("catalyst") ||
344
+ (server.url && server.url.includes("tostudy.com")));
301
345
  if (anaServers.length <= 1) {
302
346
  return {
303
- issueId: 'duplicate-servers',
347
+ issueId: "duplicate-servers",
304
348
  success: true,
305
- message: 'Nenhuma duplicata encontrada.',
349
+ message: "Nenhuma duplicata encontrada.",
306
350
  };
307
351
  }
308
352
  // Keep the tostudy entry if it exists, otherwise keep the first one
309
- const primaryKey = anaServers.find(([key]) => key === 'tostudy')?.[0] || anaServers[0][0];
353
+ const primaryKey = anaServers.find(([key]) => key === "tostudy")?.[0] || anaServers[0][0];
310
354
  const removedKeys = [];
311
355
  for (const [key] of anaServers) {
312
356
  if (key !== primaryKey) {
@@ -316,78 +360,78 @@ function repairDuplicateServers() {
316
360
  }
317
361
  writeClaudeConfig(config);
318
362
  return {
319
- issueId: 'duplicate-servers',
363
+ issueId: "duplicate-servers",
320
364
  success: true,
321
365
  message: `${removedKeys.length} servidor(es) duplicado(s) removido(s).`,
322
- action: `Removidos: ${removedKeys.join(', ')}`,
366
+ action: `Removidos: ${removedKeys.join(", ")}`,
323
367
  };
324
368
  }
325
369
  catch (error) {
326
370
  return {
327
- issueId: 'duplicate-servers',
371
+ issueId: "duplicate-servers",
328
372
  success: false,
329
373
  message: `Falha ao remover duplicatas: ${error instanceof Error ? error.message : String(error)}`,
330
374
  };
331
375
  }
332
376
  }
333
377
  const REPAIR_FUNCTIONS = {
334
- 'config-missing': () => repairMissingConfig(),
335
- 'config-invalid-json': () => repairInvalidJson(),
336
- 'mcp-not-configured': (apiKey, platformUrl) => {
378
+ "config-missing": () => repairMissingConfig(),
379
+ "config-invalid-json": () => repairInvalidJson(),
380
+ "mcp-not-configured": (apiKey, platformUrl) => {
337
381
  if (!apiKey) {
338
382
  return {
339
- issueId: 'mcp-not-configured',
383
+ issueId: "mcp-not-configured",
340
384
  success: false,
341
- message: 'API key necessaria para configurar o MCP.',
385
+ message: "API key necessaria para configurar o MCP.",
342
386
  };
343
387
  }
344
388
  return repairMcpNotConfigured(apiKey, platformUrl);
345
389
  },
346
- 'api-key-missing': (apiKey, platformUrl) => {
390
+ "api-key-missing": (apiKey, platformUrl) => {
347
391
  if (!apiKey) {
348
392
  return {
349
- issueId: 'api-key-missing',
393
+ issueId: "api-key-missing",
350
394
  success: false,
351
- message: 'Nova API key necessaria.',
395
+ message: "Nova API key necessaria.",
352
396
  };
353
397
  }
354
398
  return repairApiKeyMissing(apiKey, platformUrl);
355
399
  },
356
- 'api-key-invalid-format': () => repairApiKeyFormat(),
357
- 'api-key-too-short': (apiKey, platformUrl) => {
400
+ "api-key-invalid-format": () => repairApiKeyFormat(),
401
+ "api-key-too-short": (apiKey, platformUrl) => {
358
402
  if (!apiKey) {
359
403
  return {
360
- issueId: 'api-key-too-short',
404
+ issueId: "api-key-too-short",
361
405
  success: false,
362
- message: 'Nova API key necessaria.',
406
+ message: "Nova API key necessaria.",
363
407
  };
364
408
  }
365
409
  return repairApiKeyMissing(apiKey, platformUrl);
366
410
  },
367
- 'server-url-missing': (_, platformUrl) => repairServerUrl(platformUrl),
368
- 'server-url-invalid': (_, platformUrl) => repairServerUrl(platformUrl),
369
- 'server-url-invalid-protocol': () => repairServerUrlProtocol(),
370
- 'server-url-missing-sse-path': () => repairServerUrlPath(),
371
- 'auth-failed': (apiKey, platformUrl) => {
411
+ "server-url-missing": (_, platformUrl) => repairServerUrl(platformUrl),
412
+ "server-url-invalid": (_, platformUrl) => repairServerUrl(platformUrl),
413
+ "server-url-invalid-protocol": () => repairServerUrlProtocol(),
414
+ "server-url-missing-sse-path": () => repairServerUrlPath(),
415
+ "auth-failed": (apiKey, platformUrl) => {
372
416
  if (!apiKey) {
373
417
  return {
374
- issueId: 'auth-failed',
418
+ issueId: "auth-failed",
375
419
  success: false,
376
- message: 'Nova API key necessaria. Gere em /student/settings/mcp.',
420
+ message: "Nova API key necessaria. Gere em /student/settings/mcp.",
377
421
  };
378
422
  }
379
423
  return repairMcpNotConfigured(apiKey, platformUrl);
380
424
  },
381
- 'duplicate-servers': () => repairDuplicateServers(),
425
+ "duplicate-servers": () => repairDuplicateServers(),
382
426
  };
383
427
  /**
384
428
  * Issues that require user input (API key)
385
429
  */
386
430
  const ISSUES_REQUIRING_API_KEY = [
387
- 'mcp-not-configured',
388
- 'api-key-missing',
389
- 'api-key-too-short',
390
- 'auth-failed',
431
+ "mcp-not-configured",
432
+ "api-key-missing",
433
+ "api-key-too-short",
434
+ "auth-failed",
391
435
  ];
392
436
  /**
393
437
  * Check if an issue requires user input to repair
@@ -426,7 +470,7 @@ export function repairAllIssues(report, apiKey, platformUrl = DEFAULT_PLATFORM_U
426
470
  results.push({
427
471
  issueId: issue.id,
428
472
  success: false,
429
- message: 'Requer API key para reparar.',
473
+ message: "Requer API key para reparar.",
430
474
  });
431
475
  failed++;
432
476
  continue;
@@ -462,63 +506,63 @@ export async function diagnoseAndRepair(apiKey, platformUrl = DEFAULT_PLATFORM_U
462
506
  */
463
507
  export function printRepairReport(report) {
464
508
  println();
465
- println(chalk.cyan(' ╔═══════════════════════════════════════╗'));
466
- println(chalk.cyan('') + chalk.white.bold(' Catalyst MCP Auto-Repair ') + chalk.cyan(''));
467
- println(chalk.cyan(' ╚═══════════════════════════════════════╝'));
509
+ println(chalk.cyan(" ╔═══════════════════════════════════════╗"));
510
+ println(chalk.cyan("") + chalk.white.bold(" Catalyst MCP Auto-Repair ") + chalk.cyan(""));
511
+ println(chalk.cyan(" ╚═══════════════════════════════════════╝"));
468
512
  println();
469
513
  if (report.repairsAttempted === 0) {
470
- println(chalk.green.bold('✓ Nenhum reparo necessario!'));
514
+ println(chalk.green.bold("✓ Nenhum reparo necessario!"));
471
515
  println();
472
- println(chalk.gray('Nenhum problema corrigivel automaticamente foi encontrado.'));
516
+ println(chalk.gray("Nenhum problema corrigivel automaticamente foi encontrado."));
473
517
  println();
474
518
  return;
475
519
  }
476
520
  // Summary
477
- println(chalk.white.bold('Resumo:'));
521
+ println(chalk.white.bold("Resumo:"));
478
522
  println(` Reparos tentados: ${report.repairsAttempted}`);
479
- println(` ${chalk.green('✓ Sucesso:')} ${report.repairsSucceeded}`);
523
+ println(` ${chalk.green("✓ Sucesso:")} ${report.repairsSucceeded}`);
480
524
  if (report.repairsFailed > 0) {
481
- println(` ${chalk.red('✗ Falha:')} ${report.repairsFailed}`);
525
+ println(` ${chalk.red("✗ Falha:")} ${report.repairsFailed}`);
482
526
  }
483
527
  println();
484
528
  // Results
485
- println(chalk.white.bold('Detalhes:'));
529
+ println(chalk.white.bold("Detalhes:"));
486
530
  println();
487
531
  for (const result of report.results) {
488
532
  if (result.success) {
489
- println(` ${chalk.green('')} ${result.message}`);
533
+ println(` ${chalk.green("")} ${result.message}`);
490
534
  if (result.action) {
491
535
  println(chalk.gray(` ${result.action}`));
492
536
  }
493
537
  }
494
538
  else {
495
- println(` ${chalk.red('')} ${result.message}`);
539
+ println(` ${chalk.red("")} ${result.message}`);
496
540
  }
497
541
  }
498
542
  println();
499
543
  // User input required
500
544
  if (report.requiresUserInput.length > 0) {
501
- println(chalk.yellow('⚠ Alguns reparos requerem interacao:'));
545
+ println(chalk.yellow("⚠ Alguns reparos requerem interacao:"));
502
546
  println();
503
- println(' Para reparar problemas de API key, execute:');
504
- println(chalk.cyan(' npx @tostudy-ai/mcp-setup repair --api-key <sua-api-key>'));
547
+ println(" Para reparar problemas de API key, execute:");
548
+ println(chalk.cyan(" npx @tostudy-ai/mcp-setup repair --api-key <sua-api-key>"));
505
549
  println();
506
- println(' Para gerar uma nova API key:');
507
- println(chalk.cyan(' https://tostudy.com/student/settings/mcp'));
550
+ println(" Para gerar uma nova API key:");
551
+ println(chalk.cyan(" https://tostudy.com/student/settings/mcp"));
508
552
  println();
509
553
  }
510
554
  // Final status
511
555
  if (report.repairsFailed === 0 && report.requiresUserInput.length === 0) {
512
- println(chalk.green.bold('✓ Todos os reparos concluidos com sucesso!'));
513
- println(chalk.gray(' Reinicie o Claude Code para aplicar as mudancas.'));
556
+ println(chalk.green.bold("✓ Todos os reparos concluidos com sucesso!"));
557
+ println(chalk.gray(" Reinicie o Claude Code para aplicar as mudancas."));
514
558
  }
515
559
  else if (report.repairsSucceeded > 0) {
516
- println(chalk.yellow('⚠ Alguns reparos foram concluidos, mas outros falharam.'));
517
- println(chalk.gray(' Execute o diagnostico novamente para verificar o status.'));
560
+ println(chalk.yellow("⚠ Alguns reparos foram concluidos, mas outros falharam."));
561
+ println(chalk.gray(" Execute o diagnostico novamente para verificar o status."));
518
562
  }
519
563
  else {
520
- println(chalk.red('✗ Nenhum reparo foi concluido com sucesso.'));
521
- println(chalk.gray(' Verifique os erros acima e tente novamente.'));
564
+ println(chalk.red("✗ Nenhum reparo foi concluido com sucesso."));
565
+ println(chalk.gray(" Verifique os erros acima e tente novamente."));
522
566
  }
523
567
  println();
524
568
  }
@@ -529,7 +573,7 @@ export function exportRepairReportJson(report) {
529
573
  return JSON.stringify(report, null, 2);
530
574
  }
531
575
  // CLI entry point
532
- if (process.argv[1]?.endsWith('repair.js')) {
576
+ if (process.argv[1]?.endsWith("repair.js")) {
533
577
  (async () => {
534
578
  try {
535
579
  // Parse command line arguments
@@ -538,25 +582,25 @@ if (process.argv[1]?.endsWith('repair.js')) {
538
582
  let jsonOutput = false;
539
583
  for (let i = 2; i < process.argv.length; i++) {
540
584
  const arg = process.argv[i];
541
- if (arg === '--api-key' && process.argv[i + 1]) {
585
+ if (arg === "--api-key" && process.argv[i + 1]) {
542
586
  apiKey = process.argv[++i];
543
587
  }
544
- else if (arg === '--url' && process.argv[i + 1]) {
588
+ else if (arg === "--url" && process.argv[i + 1]) {
545
589
  platformUrl = process.argv[++i];
546
590
  }
547
- else if (arg === '--json') {
591
+ else if (arg === "--json") {
548
592
  jsonOutput = true;
549
593
  }
550
- else if (arg === '--help' || arg === '-h') {
551
- println('Catalyst MCP Auto-Repair');
594
+ else if (arg === "--help" || arg === "-h") {
595
+ println("Catalyst MCP Auto-Repair");
552
596
  println();
553
- println('Usage: node repair.js [options]');
597
+ println("Usage: node repair.js [options]");
554
598
  println();
555
- println('Options:');
556
- println(' --api-key <key> API key para reparos que necessitam autenticacao');
557
- println(' --url <url> URL da plataforma (default: https://tostudy.com)');
558
- println(' --json Saida em formato JSON');
559
- println(' --help, -h Mostra esta ajuda');
599
+ println("Options:");
600
+ println(" --api-key <key> API key para reparos que necessitam autenticacao");
601
+ println(" --url <url> URL da plataforma (default: https://tostudy.com)");
602
+ println(" --json Saida em formato JSON");
603
+ println(" --help, -h Mostra esta ajuda");
560
604
  println();
561
605
  process.exit(0);
562
606
  }
@@ -575,12 +619,13 @@ if (process.argv[1]?.endsWith('repair.js')) {
575
619
  printRepairReport(repair);
576
620
  }
577
621
  // Exit code based on repair results
578
- const hasUnfixedCritical = diagnostic.issues.some((issue) => issue.severity === 'critical' && !repair.results.find((r) => r.issueId === issue.id && r.success));
622
+ const hasUnfixedCritical = diagnostic.issues.some((issue) => issue.severity === "critical" &&
623
+ !repair.results.find((r) => r.issueId === issue.id && r.success));
579
624
  process.exit(hasUnfixedCritical ? 1 : 0);
580
625
  }
581
626
  catch (error) {
582
- process.stderr.write(chalk.red('Erro ao executar reparo:\n'));
583
- process.stderr.write((error instanceof Error ? error.message : String(error)) + '\n');
627
+ process.stderr.write(chalk.red("Erro ao executar reparo:\n"));
628
+ process.stderr.write((error instanceof Error ? error.message : String(error)) + "\n");
584
629
  process.exit(1);
585
630
  }
586
631
  })();