@syke1/mcp-server 1.4.6 → 1.4.8

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/dist/index.js CHANGED
@@ -621,11 +621,14 @@ async function main() {
621
621
  const dashUrl = `http://localhost:${WEB_PORT}`;
622
622
  console.error(`[syke] Web dashboard: ${dashUrl}`);
623
623
  // Auto-open browser (disable with SYKE_NO_BROWSER=1)
624
+ // Delay 1s to let server fully stabilize before dashboard connects
624
625
  if (process.env.SYKE_NO_BROWSER !== "1") {
625
- const cmd = process.platform === "win32" ? `start ${dashUrl}`
626
- : process.platform === "darwin" ? `open ${dashUrl}`
627
- : `xdg-open ${dashUrl}`;
628
- (0, child_process_1.exec)(cmd, () => { });
626
+ setTimeout(() => {
627
+ const cmd = process.platform === "win32" ? `start ${dashUrl}`
628
+ : process.platform === "darwin" ? `open ${dashUrl}`
629
+ : `xdg-open ${dashUrl}`;
630
+ (0, child_process_1.exec)(cmd, () => { });
631
+ }, 1000);
629
632
  }
630
633
  });
631
634
  }
@@ -2734,11 +2734,17 @@ window.syke = {
2734
2734
  let sseSource = null;
2735
2735
  let sseReconnectTimer = null;
2736
2736
  let sseBlocked = false;
2737
+ let sseEverConnected = false; // track if SSE has ever connected successfully
2737
2738
  const realtimeLog = []; // recent events for panel
2738
2739
 
2739
2740
  async function initSSE() {
2740
2741
  if (sseSource) { sseSource.close(); sseSource = null; }
2741
2742
 
2743
+ // Show appropriate status based on whether we've connected before
2744
+ if (!sseEverConnected) {
2745
+ updateSSEStatus("CONNECTING...", "warning");
2746
+ }
2747
+
2742
2748
  // Pre-check: if Free tier, SSE will 403 — don't attempt connection
2743
2749
  try {
2744
2750
  const probe = await fetch("/api/events");
@@ -2749,7 +2755,14 @@ async function initSSE() {
2749
2755
  }
2750
2756
  // Close the successful probe connection (we'll open EventSource next)
2751
2757
  if (probe.body) probe.body.cancel().catch(() => {});
2752
- } catch(e) { /* network error, try SSE anyway */ }
2758
+ } catch(e) {
2759
+ // Server not ready yet — retry after short delay on first attempt
2760
+ if (!sseEverConnected) {
2761
+ if (sseReconnectTimer) clearTimeout(sseReconnectTimer);
2762
+ sseReconnectTimer = setTimeout(() => { initSSE(); }, 2000);
2763
+ return;
2764
+ }
2765
+ }
2753
2766
 
2754
2767
  sseSource = new EventSource("/api/events");
2755
2768
 
@@ -2757,6 +2770,7 @@ async function initSSE() {
2757
2770
  const data = JSON.parse(e.data);
2758
2771
  console.log("[SYKE:SSE] Connected, cache:", data.cacheSize, "files");
2759
2772
  healthFailCount = 0; // Reset health failures on SSE connect
2773
+ sseEverConnected = true;
2760
2774
  updateSSEStatus("LIVE", "connected");
2761
2775
  });
2762
2776
 
@@ -2949,7 +2963,7 @@ async function initSSE() {
2949
2963
  if (sseBlocked) return;
2950
2964
 
2951
2965
  sseRetryCount++;
2952
- updateSSEStatus("RECONNECTING...", "warning");
2966
+ updateSSEStatus(sseEverConnected ? "RECONNECTING..." : "CONNECTING...", "warning");
2953
2967
 
2954
2968
  // Only show offline after 5 consecutive SSE failures
2955
2969
  if (sseRetryCount >= 5) {
@@ -230,6 +230,11 @@ function getAllWarnings() {
230
230
  function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProjectRoot, getPackageName, getLicenseStatus, hasAIKeyFn, setLicenseKeyFn, setAIKeyFn, getAIInfoFn) {
231
231
  const app = (0, express_1.default)();
232
232
  app.use(express_1.default.json());
233
+ /** Check if current license is Pro (includes pro_trial) */
234
+ function isProPlan() {
235
+ const license = getLicenseStatus?.();
236
+ return license?.plan === "pro" || license?.plan === "pro_trial";
237
+ }
233
238
  // Serve static files from public/
234
239
  const publicDir = path.join(__dirname, "public");
235
240
  app.use(express_1.default.static(publicDir));
@@ -264,8 +269,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
264
269
  }
265
270
  app.get("/api/events", (_req, res) => {
266
271
  // Pro-only: real-time monitoring via SSE
267
- const license = getLicenseStatus?.();
268
- if (!license || license.plan !== "pro") {
272
+ if (!isProPlan()) {
269
273
  res.status(403).json(getProFeatureError("Real-time monitoring"));
270
274
  return;
271
275
  }
@@ -315,8 +319,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
315
319
  timestamp: change.timestamp,
316
320
  });
317
321
  // Run Gemini real-time analysis (Pro only)
318
- const license = getLicenseStatus?.();
319
- if (license && license.plan === "pro") {
322
+ if (isProPlan()) {
320
323
  broadcastSSE("analysis-start", { file: change.relativePath });
321
324
  try {
322
325
  const analysis = await (0, realtime_analyzer_1.analyzeChangeRealtime)(change, graph, (relPath) => currentFileCache?.getFileByRelPath(relPath) ?? null);
@@ -366,8 +369,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
366
369
  // GET /api/graph — Cytoscape.js compatible JSON
367
370
  app.get("/api/graph", (_req, res) => {
368
371
  const graph = getGraphFn();
369
- const license = getLicenseStatus?.();
370
- const isPro = license?.plan === "pro";
372
+ const isPro = isProPlan();
371
373
  const FREE_GRAPH_LIMIT = 50;
372
374
  const nodes = [];
373
375
  const edges = [];
@@ -460,8 +462,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
460
462
  });
461
463
  // POST /api/ai-analyze — AI semantic analysis (Pro or BYOK)
462
464
  app.post("/api/ai-analyze", async (req, res) => {
463
- const license = getLicenseStatus?.();
464
- const isPro = license?.plan === "pro";
465
+ const isPro = isProPlan();
465
466
  const hasKey = hasAIKeyFn?.() || false;
466
467
  if (!isPro && !hasKey) {
467
468
  return res.status(403).json({
@@ -498,8 +499,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
498
499
  });
499
500
  // GET /api/hub-files — Top hub files ranking (Pro only)
500
501
  app.get("/api/hub-files", (req, res) => {
501
- const license = getLicenseStatus?.();
502
- if (!license || license.plan !== "pro") {
502
+ if (!isProPlan()) {
503
503
  return res.status(403).json(getProFeatureError("Hub files ranking"));
504
504
  }
505
505
  const requested = parseInt(req.query.top) || 10;
@@ -573,8 +573,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
573
573
  });
574
574
  // GET /api/cycles — Detect circular dependencies (Pro only)
575
575
  app.get("/api/cycles", (_req, res) => {
576
- const license = getLicenseStatus?.();
577
- if (!license || license.plan !== "pro") {
576
+ if (!isProPlan()) {
578
577
  return res.status(403).json(getProFeatureError("Cycle detection"));
579
578
  }
580
579
  const graph = getGraphFn();
@@ -661,8 +660,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
661
660
  });
662
661
  // GET /api/simulate-delete/:file — Simulate file removal (Pro only)
663
662
  app.get("/api/simulate-delete/*splat", (req, res) => {
664
- const license = getLicenseStatus?.();
665
- if (!license || license.plan !== "pro") {
663
+ if (!isProPlan()) {
666
664
  return res.status(403).json(getProFeatureError("Delete simulation"));
667
665
  }
668
666
  const splat = req.params.splat;
@@ -841,8 +839,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
841
839
  }
842
840
  const normalized = path.normalize(projectRoot);
843
841
  // Free tier: only 1 project allowed — block switch to a different project
844
- const license = getLicenseStatus?.();
845
- if (!license || license.plan !== "pro") {
842
+ if (!isProPlan()) {
846
843
  const currentRoot = getProjectRoot ? path.normalize(getProjectRoot()) : null;
847
844
  if (currentRoot && normalized !== currentRoot) {
848
845
  return res.status(403).json({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syke1/mcp-server",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "mcpName": "io.github.khalomsky/syke",
5
5
  "description": "AI code impact analysis MCP server — dependency graphs, cascade detection, and a mandatory build gate for AI coding agents",
6
6
  "main": "dist/index.js",