@syke1/mcp-server 1.3.2 → 1.3.4

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
@@ -86,6 +86,15 @@ function isFileInFreeSet(resolvedPath, graph) {
86
86
  return idx >= 0 && idx < FREE_MAX_FILES;
87
87
  }
88
88
  const PRO_UPGRADE_MSG = "This file exceeds the Free tier limit (50 files). Upgrade to Pro for unlimited analysis: https://syke.cloud/dashboard/";
89
+ function getProToolError(toolName) {
90
+ if (licenseStatus.error) {
91
+ return `${toolName}: ${licenseStatus.error}`;
92
+ }
93
+ if (licenseStatus.expiresAt) {
94
+ return `${toolName}: Trial expired. Upgrade at https://syke.cloud/dashboard/`;
95
+ }
96
+ return `${toolName} requires SYKE Pro. Set SYKE_LICENSE_KEY in your MCP config or sign up at https://syke.cloud`;
97
+ }
89
98
  async function main() {
90
99
  // Check license before starting (graceful fallback for hosted environments like Smithery)
91
100
  try {
@@ -111,7 +120,7 @@ async function main() {
111
120
  };
112
121
  process.on("SIGINT", shutdown);
113
122
  process.on("SIGTERM", shutdown);
114
- const server = new index_js_1.Server({ name: "syke", version: "1.3.2" }, { capabilities: { tools: {} } });
123
+ const server = new index_js_1.Server({ name: "syke", version: "1.3.4" }, { capabilities: { tools: {} } });
115
124
  // List tools
116
125
  server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
117
126
  tools: [
@@ -349,7 +358,7 @@ async function main() {
349
358
  // Pro-only feature
350
359
  if (licenseStatus.plan !== "pro") {
351
360
  return {
352
- content: [{ type: "text", text: "get_hub_files requires SYKE Pro. Upgrade at https://syke.cloud/dashboard/\n\nSet SYKE_LICENSE_KEY in your MCP config to activate Pro features." }],
361
+ content: [{ type: "text", text: getProToolError("get_hub_files") }],
353
362
  };
354
363
  }
355
364
  const requestedN = args.top_n || 10;
@@ -383,12 +392,7 @@ async function main() {
383
392
  // Pro-only feature
384
393
  if (licenseStatus.plan !== "pro") {
385
394
  return {
386
- content: [
387
- {
388
- type: "text",
389
- text: "ai_analyze requires SYKE Pro. Upgrade at https://syke.cloud/dashboard/\n\nSet SYKE_LICENSE_KEY in your MCP config to activate Pro features.",
390
- },
391
- ],
395
+ content: [{ type: "text", text: getProToolError("ai_analyze") }],
392
396
  };
393
397
  }
394
398
  const file = args.file;
@@ -414,7 +418,7 @@ async function main() {
414
418
  // Pro-only feature (real-time monitoring)
415
419
  if (licenseStatus.plan !== "pro") {
416
420
  return {
417
- content: [{ type: "text", text: "check_warnings requires SYKE Pro (real-time monitoring feature). Upgrade at https://syke.cloud/dashboard/\n\nSet SYKE_LICENSE_KEY in your MCP config to activate Pro features." }],
421
+ content: [{ type: "text", text: getProToolError("check_warnings") }],
418
422
  };
419
423
  }
420
424
  const shouldAck = args.acknowledge || false;
@@ -471,8 +475,11 @@ async function main() {
471
475
  }
472
476
  });
473
477
  // Pre-warm the graph (skip if no project root — e.g. Smithery scan)
474
- console.error(`[syke] Starting SYKE MCP Server v1.3.2`);
478
+ console.error(`[syke] Starting SYKE MCP Server v1.3.4`);
475
479
  console.error(`[syke] License: ${licenseStatus.plan.toUpperCase()} (${licenseStatus.source})`);
480
+ if (licenseStatus.expiresAt) {
481
+ console.error(`[syke] Expires: ${licenseStatus.expiresAt}`);
482
+ }
476
483
  // Log AI provider status
477
484
  const aiProvider = (0, provider_1.getAIProvider)();
478
485
  if (aiProvider) {
@@ -563,7 +570,7 @@ main().catch((err) => {
563
570
  * See: https://smithery.ai/docs/deploy#sandbox-server
564
571
  */
565
572
  function createSandboxServer() {
566
- const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.3.2" }, { capabilities: { tools: {} } });
573
+ const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.3.4" }, { capabilities: { tools: {} } });
567
574
  sandboxServer.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
568
575
  tools: [
569
576
  {
@@ -255,6 +255,10 @@ async function checkLicense() {
255
255
  }
256
256
  // Try online validation (with device binding)
257
257
  const result = await validateOnline(key);
258
+ if (!result.valid) {
259
+ const reason = result.error || "invalid key or expired";
260
+ console.error(`[syke] License validation failed: ${reason}`);
261
+ }
258
262
  if (result.valid) {
259
263
  // Update cache
260
264
  writeCache({
@@ -26,4 +26,7 @@ export interface SwitchProjectResult {
26
26
  }
27
27
  export declare function createWebServer(getGraphFn: () => DependencyGraph, fileCache?: FileCache, switchProjectFn?: (newRoot: string) => SwitchProjectResult, getProjectRoot?: () => string, getPackageName?: () => string, getLicenseStatus?: () => {
28
28
  plan: string;
29
+ expiresAt?: string;
30
+ error?: string;
31
+ source?: string;
29
32
  }): import("express-serve-static-core").Express;
@@ -245,11 +245,26 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
245
245
  }
246
246
  }
247
247
  }
248
+ /**
249
+ * Build a specific error message for Pro-only features based on license state.
250
+ */
251
+ function getProFeatureError(featureName) {
252
+ const license = getLicenseStatus?.();
253
+ const upgrade = "https://syke.cloud/dashboard/";
254
+ if (license?.error) {
255
+ return { error: `${featureName}: ${license.error}`, requiresPro: true, upgrade };
256
+ }
257
+ if (license?.source === "online" && license?.expiresAt) {
258
+ // Had a license but it's no longer valid (expired trial or subscription)
259
+ return { error: `Trial expired. Upgrade at ${upgrade}`, requiresPro: true, upgrade };
260
+ }
261
+ return { error: `${featureName} requires SYKE Pro. Set SYKE_LICENSE_KEY or sign up at https://syke.cloud`, requiresPro: true, upgrade };
262
+ }
248
263
  app.get("/api/events", (_req, res) => {
249
264
  // Pro-only: real-time monitoring via SSE
250
265
  const license = getLicenseStatus?.();
251
266
  if (!license || license.plan !== "pro") {
252
- res.status(403).json({ error: "Real-time monitoring requires SYKE Pro.", upgrade: "https://syke.cloud/dashboard/" });
267
+ res.status(403).json(getProFeatureError("Real-time monitoring"));
253
268
  return;
254
269
  }
255
270
  res.writeHead(200, {
@@ -438,10 +453,7 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
438
453
  // License check — Pro only
439
454
  const license = getLicenseStatus?.();
440
455
  if (!license || license.plan !== "pro") {
441
- return res.status(403).json({
442
- error: "AI analysis requires SYKE Pro. Upgrade at https://syke.cloud/dashboard/",
443
- requiresPro: true,
444
- });
456
+ return res.status(403).json(getProFeatureError("AI analysis"));
445
457
  }
446
458
  const { file } = req.body;
447
459
  if (!file) {
@@ -465,7 +477,7 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
465
477
  app.get("/api/hub-files", (req, res) => {
466
478
  const license = getLicenseStatus?.();
467
479
  if (!license || license.plan !== "pro") {
468
- return res.status(403).json({ error: "Hub files ranking requires SYKE Pro.", upgrade: "https://syke.cloud/dashboard/" });
480
+ return res.status(403).json(getProFeatureError("Hub files ranking"));
469
481
  }
470
482
  const requested = parseInt(req.query.top) || 10;
471
483
  const graph = getGraphFn();
@@ -540,7 +552,7 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
540
552
  app.get("/api/cycles", (_req, res) => {
541
553
  const license = getLicenseStatus?.();
542
554
  if (!license || license.plan !== "pro") {
543
- return res.status(403).json({ error: "This feature requires SYKE Pro.", upgrade: "https://syke.cloud/dashboard/" });
555
+ return res.status(403).json(getProFeatureError("Cycle detection"));
544
556
  }
545
557
  const graph = getGraphFn();
546
558
  const toRel = (f) => path.relative(graph.sourceDir, f).replace(/\\/g, "/");
@@ -628,7 +640,7 @@ function createWebServer(getGraphFn, fileCache, switchProjectFn, getProjectRoot,
628
640
  app.get("/api/simulate-delete/*splat", (req, res) => {
629
641
  const license = getLicenseStatus?.();
630
642
  if (!license || license.plan !== "pro") {
631
- return res.status(403).json({ error: "This feature requires SYKE Pro.", upgrade: "https://syke.cloud/dashboard/" });
643
+ return res.status(403).json(getProFeatureError("Delete simulation"));
632
644
  }
633
645
  const splat = req.params.splat;
634
646
  const fileParam = Array.isArray(splat) ? splat.join("/") : splat;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syke1/mcp-server",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
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' } })