@syke1/mcp-server 1.3.3 → 1.3.5

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 CHANGED
@@ -24,6 +24,7 @@ Works with **Claude Code**, **Cursor**, **Windsurf**, and any MCP-compatible AI
24
24
  "args": ["@syke1/mcp-server@latest"],
25
25
  "env": {
26
26
  "SYKE_LICENSE_KEY": "your-key-here",
27
+ "SYKE_WEB_PORT": "3333",
27
28
  "GEMINI_KEY": "your-gemini-key",
28
29
  "OPENAI_KEY": "your-openai-key",
29
30
  "ANTHROPIC_KEY": "your-anthropic-key"
@@ -43,6 +44,7 @@ Works with **Claude Code**, **Cursor**, **Windsurf**, and any MCP-compatible AI
43
44
  "args": ["@syke1/mcp-server@latest"],
44
45
  "env": {
45
46
  "SYKE_LICENSE_KEY": "your-key-here",
47
+ "SYKE_WEB_PORT": "3333",
46
48
  "GEMINI_KEY": "your-gemini-key"
47
49
  }
48
50
  }
@@ -60,6 +62,7 @@ Works with **Claude Code**, **Cursor**, **Windsurf**, and any MCP-compatible AI
60
62
  "args": ["@syke1/mcp-server@latest"],
61
63
  "env": {
62
64
  "SYKE_LICENSE_KEY": "your-key-here",
65
+ "SYKE_WEB_PORT": "3333",
63
66
  "GEMINI_KEY": "your-gemini-key"
64
67
  }
65
68
  }
@@ -77,7 +80,7 @@ SYKE auto-detects your project language and builds the dependency graph on start
77
80
 
78
81
  ### 3. Open the dashboard
79
82
 
80
- A web dashboard opens automatically at `http://localhost:3333` showing your live dependency graph.
83
+ A web dashboard opens automatically at `http://localhost:3333` (configurable via `SYKE_WEB_PORT`) showing your live dependency graph.
81
84
 
82
85
  ## Features
83
86
 
@@ -113,7 +116,7 @@ Auto-detected, zero-config: **Dart/Flutter**, **TypeScript/JavaScript**, **Pytho
113
116
 
114
117
  ### Web Dashboard
115
118
 
116
- Live dependency graph visualization at `localhost:3333` with:
119
+ Live dependency graph visualization at `localhost:3333` (or your custom `SYKE_WEB_PORT`) with:
117
120
  - Interactive node graph (click any file to see its connections)
118
121
  - Real-time cascade monitoring
119
122
  - Risk level indicators
package/dist/index.js CHANGED
@@ -120,7 +120,7 @@ async function main() {
120
120
  };
121
121
  process.on("SIGINT", shutdown);
122
122
  process.on("SIGTERM", shutdown);
123
- const server = new index_js_1.Server({ name: "syke", version: "1.3.3" }, { capabilities: { tools: {} } });
123
+ const server = new index_js_1.Server({ name: "syke", version: "1.3.5" }, { capabilities: { tools: {} } });
124
124
  // List tools
125
125
  server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
126
126
  tools: [
@@ -389,10 +389,11 @@ async function main() {
389
389
  };
390
390
  }
391
391
  case "ai_analyze": {
392
- // Pro-only feature
393
- if (licenseStatus.plan !== "pro") {
392
+ // BYOK: allow if user has their own AI key, even on Free plan
393
+ const hasAIKey = !!(0, provider_1.getAIProvider)();
394
+ if (licenseStatus.plan !== "pro" && !hasAIKey) {
394
395
  return {
395
- content: [{ type: "text", text: getProToolError("ai_analyze") }],
396
+ content: [{ type: "text", text: getProToolError("ai_analyze") + "\n\nOr set GEMINI_KEY / OPENAI_KEY / ANTHROPIC_KEY to use ai_analyze with your own API key." }],
396
397
  };
397
398
  }
398
399
  const file = args.file;
@@ -408,10 +409,18 @@ async function main() {
408
409
  ],
409
410
  };
410
411
  }
412
+ if (!isFileInFreeSet(resolved, graph)) {
413
+ return { content: [{ type: "text", text: PRO_UPGRADE_MSG }] };
414
+ }
411
415
  const impactResult = (0, analyze_impact_1.analyzeImpact)(resolved, graph);
412
416
  const aiResult = await (0, analyzer_1.analyzeWithAI)(resolved, impactResult, graph);
417
+ // Free tier: append partial analysis warning
418
+ let resultText = aiResult;
419
+ if (licenseStatus.plan !== "pro" && graph.files.size > FREE_MAX_FILES) {
420
+ resultText += `\n\n---\n⚠️ Free tier: analyzing ${FREE_MAX_FILES}/${graph.files.size} files. Some dependencies may be missing. Upgrade to Pro for full analysis: https://syke.cloud/dashboard/`;
421
+ }
413
422
  return {
414
- content: [{ type: "text", text: appendDashboardFooter(aiResult) }],
423
+ content: [{ type: "text", text: appendDashboardFooter(resultText) }],
415
424
  };
416
425
  }
417
426
  case "check_warnings": {
@@ -475,7 +484,7 @@ async function main() {
475
484
  }
476
485
  });
477
486
  // Pre-warm the graph (skip if no project root — e.g. Smithery scan)
478
- console.error(`[syke] Starting SYKE MCP Server v1.3.3`);
487
+ console.error(`[syke] Starting SYKE MCP Server v1.3.5`);
479
488
  console.error(`[syke] License: ${licenseStatus.plan.toUpperCase()} (${licenseStatus.source})`);
480
489
  if (licenseStatus.expiresAt) {
481
490
  console.error(`[syke] Expires: ${licenseStatus.expiresAt}`);
@@ -542,7 +551,7 @@ async function main() {
542
551
  }
543
552
  // Start Express web server with file cache for SSE (only if project detected)
544
553
  if (currentProjectRoot) {
545
- const webApp = (0, server_1.createWebServer)(() => (0, graph_1.getGraph)(currentProjectRoot, currentPackageName), fileCache, switchProject, () => currentProjectRoot, () => currentPackageName, () => licenseStatus);
554
+ const webApp = (0, server_1.createWebServer)(() => (0, graph_1.getGraph)(currentProjectRoot, currentPackageName), fileCache, switchProject, () => currentProjectRoot, () => currentPackageName, () => licenseStatus, () => !!(0, provider_1.getAIProvider)());
546
555
  webApp.listen(WEB_PORT, () => {
547
556
  const dashUrl = `http://localhost:${WEB_PORT}`;
548
557
  console.error(`[syke] Web dashboard: ${dashUrl}`);
@@ -570,7 +579,7 @@ main().catch((err) => {
570
579
  * See: https://smithery.ai/docs/deploy#sandbox-server
571
580
  */
572
581
  function createSandboxServer() {
573
- const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.3.3" }, { capabilities: { tools: {} } });
582
+ const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.3.5" }, { capabilities: { tools: {} } });
574
583
  sandboxServer.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
575
584
  tools: [
576
585
  {
@@ -29,4 +29,4 @@ export declare function createWebServer(getGraphFn: () => DependencyGraph, fileC
29
29
  expiresAt?: string;
30
30
  error?: string;
31
31
  source?: string;
32
- }): import("express-serve-static-core").Express;
32
+ }, hasAIKeyFn?: () => boolean): import("express-serve-static-core").Express;
@@ -226,7 +226,7 @@ function acknowledgeWarnings() {
226
226
  function getAllWarnings() {
227
227
  return [...warningStore];
228
228
  }
229
- function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot, getPackageName, getLicenseStatus) {
229
+ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot, getPackageName, getLicenseStatus, hasAIKeyFn) {
230
230
  const app = (0, express_1.default)();
231
231
  app.use(express_1.default.json());
232
232
  // Serve static files from public/
@@ -448,12 +448,16 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
448
448
  const result = (0, analyze_impact_1.analyzeImpact)(resolved, graph);
449
449
  res.json(result);
450
450
  });
451
- // POST /api/ai-analyze — Gemini AI semantic analysis (Pro only)
451
+ // POST /api/ai-analyze — AI semantic analysis (Pro or BYOK)
452
452
  app.post("/api/ai-analyze", async (req, res) => {
453
- // License check — Pro only
454
453
  const license = getLicenseStatus?.();
455
- if (!license || license.plan !== "pro") {
456
- return res.status(403).json(getProFeatureError("AI analysis"));
454
+ const isPro = license?.plan === "pro";
455
+ const hasKey = hasAIKeyFn?.() || false;
456
+ if (!isPro && !hasKey) {
457
+ return res.status(403).json({
458
+ ...getProFeatureError("AI analysis"),
459
+ hint: "Or set GEMINI_KEY / OPENAI_KEY / ANTHROPIC_KEY to use ai_analyze with your own API key.",
460
+ });
457
461
  }
458
462
  const { file } = req.body;
459
463
  if (!file) {
@@ -464,10 +468,19 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
464
468
  if (!graph.files.has(resolved)) {
465
469
  return res.status(404).json({ error: `File not found in graph: ${file}` });
466
470
  }
471
+ // Free tier: check file limit
472
+ if (!isPro) {
473
+ const allFiles = [...graph.files].sort();
474
+ const idx = allFiles.indexOf(resolved);
475
+ if (idx < 0 || idx >= 50) {
476
+ return res.status(403).json({ error: "This file exceeds the Free tier limit (50 files). Upgrade to Pro for unlimited analysis.", upgrade: "https://syke.cloud/dashboard/" });
477
+ }
478
+ }
467
479
  const impactResult = (0, analyze_impact_1.analyzeImpact)(resolved, graph);
468
480
  try {
469
481
  const aiResult = await (0, analyzer_1.analyzeWithAI)(resolved, impactResult, graph);
470
- res.json({ file: impactResult.relativePath, analysis: aiResult });
482
+ const partial = !isPro && graph.files.size > 50;
483
+ res.json({ file: impactResult.relativePath, analysis: aiResult, partial });
471
484
  }
472
485
  catch (err) {
473
486
  res.status(500).json({ error: err.message || "AI analysis failed" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syke1/mcp-server",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
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",
package/smithery.yaml CHANGED
@@ -25,6 +25,10 @@ startCommand:
25
25
  type: string
26
26
  default: ""
27
27
  description: Force a specific AI provider (gemini, openai, or anthropic). Auto-selects if empty.
28
+ webPort:
29
+ type: string
30
+ default: "3333"
31
+ description: Dashboard port (default 3333). Change if port is already in use.
28
32
  commandFunction:
29
33
  |-
30
- config => ({ command: 'npx', args: ['-y', '@syke1/mcp-server@latest'], env: { SYKE_LICENSE_KEY: config.licenseKey || '', GEMINI_KEY: config.geminiKey || '', OPENAI_KEY: config.openaiKey || '', ANTHROPIC_KEY: config.anthropicKey || '', SYKE_AI_PROVIDER: config.aiProvider || '', SYKE_NO_BROWSER: '1' } })
34
+ config => ({ command: 'npx', args: ['-y', '@syke1/mcp-server@latest'], env: { SYKE_LICENSE_KEY: config.licenseKey || '', SYKE_WEB_PORT: config.webPort || '3333', GEMINI_KEY: config.geminiKey || '', OPENAI_KEY: config.openaiKey || '', ANTHROPIC_KEY: config.anthropicKey || '', SYKE_AI_PROVIDER: config.aiProvider || '', SYKE_NO_BROWSER: '1' } })