@syke1/mcp-server 1.8.6 → 1.8.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.
@@ -1,5 +1,6 @@
1
1
  export interface LicenseStatus {
2
2
  plan: "free" | "pro" | "pro_trial" | "cortex";
3
+ billingPeriod?: "monthly" | "annual";
3
4
  email?: string;
4
5
  expiresAt?: string;
5
6
  source: "online" | "cache" | "default";
@@ -256,6 +256,13 @@ function mapPlan(serverPlan) {
256
256
  return "cortex";
257
257
  return "pro"; // pro_monthly, pro_annual, pro_founding, master, etc.
258
258
  }
259
+ function extractBillingPeriod(serverPlan) {
260
+ if (serverPlan.endsWith("_annual"))
261
+ return "annual";
262
+ if (serverPlan.endsWith("_monthly"))
263
+ return "monthly";
264
+ return undefined;
265
+ }
259
266
  /**
260
267
  * Main license validation — called on MCP server startup
261
268
  */
@@ -274,6 +281,7 @@ async function checkLicense() {
274
281
  const cachedPlan = mapPlan(cache.plan || "");
275
282
  return {
276
283
  plan: cachedPlan,
284
+ billingPeriod: extractBillingPeriod(cache.plan || ""),
277
285
  email: cache.email,
278
286
  expiresAt: cache.expiresAt,
279
287
  source: "cache",
@@ -299,6 +307,7 @@ async function checkLicense() {
299
307
  const foundingPlan = mapPlan(result.plan || "");
300
308
  return {
301
309
  plan: foundingPlan,
310
+ billingPeriod: extractBillingPeriod(result.plan || ""),
302
311
  email: result.email,
303
312
  expiresAt: result.expiresAt,
304
313
  source: "online",
@@ -323,6 +332,7 @@ async function checkLicense() {
323
332
  const onlinePlan = mapPlan(result.plan || "");
324
333
  return {
325
334
  plan: onlinePlan,
335
+ billingPeriod: extractBillingPeriod(result.plan || ""),
326
336
  email: result.email,
327
337
  expiresAt: result.expiresAt,
328
338
  source: "online",
@@ -344,6 +354,7 @@ async function checkLicense() {
344
354
  const gracePlan = mapPlan(cache.plan || "");
345
355
  return {
346
356
  plan: gracePlan,
357
+ billingPeriod: extractBillingPeriod(cache.plan || ""),
347
358
  email: cache.email,
348
359
  expiresAt: cache.expiresAt,
349
360
  source: "cache",
@@ -1328,7 +1328,7 @@ async function loadCodePreview(fileId) {
1328
1328
  const el = document.getElementById("code-content");
1329
1329
  el.innerHTML = '<div class="loading"><div class="spinner"></div>LOADING...</div>';
1330
1330
  try {
1331
- const res = await fetch("/api/file-content/" + fileId.split("/").map(encodeURIComponent).join("/"));
1331
+ const res = await fetch("/api/file-content?path=" + encodeURIComponent(fileId));
1332
1332
  const ct = res.headers.get("content-type") || "";
1333
1333
  if (!ct.includes("application/json")) {
1334
1334
  el.innerHTML = `<p class="placeholder">ERROR: Server returned non-JSON (${res.status}). File: ${fileId}</p>`;
@@ -2099,21 +2099,33 @@ function setupEventListeners() {
2099
2099
  const modal = document.getElementById("cortex-modal");
2100
2100
  const planInfo = document.getElementById("cortex-plan-info");
2101
2101
  const upgradeLink = document.getElementById("cortex-upgrade-link");
2102
+ const priceNote = document.querySelector(".cortex-price-note");
2102
2103
  const plan = _currentPlan.toLowerCase();
2104
+ const billing = _billingPeriod; // "monthly" | "annual" | null
2103
2105
 
2104
2106
  if (plan === "cortex" || plan === "cortex_trial") {
2105
- // Already on Cortex — trigger scan_project via MCP (show coming-soon notice for now)
2106
2107
  alert("Onboarding document generation is coming in the next update. Stay tuned!");
2107
2108
  return;
2108
2109
  }
2109
2110
 
2110
- // Show modal with plan-specific messaging
2111
+ // Show modal with plan-specific pricing
2111
2112
  if (plan === "pro" || plan === "pro_trial") {
2112
- planInfo.textContent = "You're on Pro ($9/mo). Upgrade to Cortex for just $20/mo more.";
2113
- upgradeLink.textContent = "UPGRADE TO CORTEX (+$20/mo)";
2113
+ if (billing === "annual") {
2114
+ // Pro Annual $99/yr Cortex Annual $249/yr = +$150/yr
2115
+ planInfo.textContent = "You're on Pro ($99/yr). Upgrade to Cortex for just $150/yr more.";
2116
+ upgradeLink.textContent = "UPGRADE TO CORTEX (+$150/yr)";
2117
+ if (priceNote) priceNote.textContent = "$249/yr · 14-day money-back guarantee";
2118
+ } else {
2119
+ // Pro Monthly $9/mo → Cortex Monthly $29/mo = +$20/mo
2120
+ planInfo.textContent = "You're on Pro ($9/mo). Upgrade to Cortex for just $20/mo more.";
2121
+ upgradeLink.textContent = "UPGRADE TO CORTEX (+$20/mo)";
2122
+ if (priceNote) priceNote.textContent = "$29/mo · $249/yr · 14-day money-back guarantee";
2123
+ }
2114
2124
  } else {
2125
+ // Free → Cortex (full price)
2115
2126
  planInfo.textContent = "You're on the Free plan. Upgrade to Cortex to unlock AI-powered analysis.";
2116
2127
  upgradeLink.textContent = "UPGRADE TO CORTEX";
2128
+ if (priceNote) priceNote.textContent = "$29/mo · $249/yr · 14-day money-back guarantee";
2117
2129
  }
2118
2130
  modal.classList.remove("hidden");
2119
2131
  });
@@ -3646,7 +3658,10 @@ function updateLicenseBadge(plan, expiresAt) {
3646
3658
 
3647
3659
  badge.className = "license-badge";
3648
3660
 
3649
- if (plan === "pro" || plan === "pro_trial") {
3661
+ if (plan === "cortex") {
3662
+ badge.classList.add("cortex");
3663
+ badge.textContent = "CORTEX";
3664
+ } else if (plan === "pro" || plan === "pro_trial") {
3650
3665
  if (expiresAt && new Date(expiresAt) < new Date()) {
3651
3666
  badge.classList.add("expired");
3652
3667
  badge.textContent = "EXPIRED";
@@ -3703,12 +3718,14 @@ function hideServerOffline() {
3703
3718
  }
3704
3719
 
3705
3720
  let _currentPlan = "free"; // track current plan for Cortex modal
3721
+ let _billingPeriod = null; // "monthly" | "annual" | null
3706
3722
 
3707
3723
  async function loadProjectInfo() {
3708
3724
  try {
3709
3725
  const res = await fetch("/api/project-info");
3710
3726
  const info = await res.json();
3711
3727
  _currentPlan = info.plan || "free";
3728
+ _billingPeriod = info.billingPeriod || null;
3712
3729
  const el = document.getElementById("current-project");
3713
3730
  if (el) {
3714
3731
  const short = info.projectRoot.length > 50
@@ -147,6 +147,12 @@ body {
147
147
  text-shadow: 0 0 8px rgba(255,215,0,0.3);
148
148
  }
149
149
 
150
+ .license-badge.cortex {
151
+ color: #e040fb;
152
+ border-color: rgba(224,64,251,0.4);
153
+ text-shadow: 0 0 8px rgba(224,64,251,0.3);
154
+ }
155
+
150
156
  .license-badge.trial {
151
157
  color: var(--risk-medium);
152
158
  border-color: rgba(255,159,10,0.4);
@@ -32,6 +32,7 @@ export interface WebServerHandle {
32
32
  }
33
33
  export declare function createWebServer(getGraphFn: () => DependencyGraph, initialFileCache?: FileCache, switchProjectFn?: (newRoot: string) => SwitchProjectResult, getProjectRoot?: () => string, getPackageName?: () => string, getLicenseStatus?: () => {
34
34
  plan: string;
35
+ billingPeriod?: string;
35
36
  expiresAt?: string;
36
37
  error?: string;
37
38
  source?: string;
@@ -629,10 +629,9 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
629
629
  }
630
630
  res.json({ files: results });
631
631
  });
632
- // GET /api/file-content/:file — Source code preview
633
- app.get("/api/file-content/*splat", (req, res) => {
634
- const splat = req.params.splat;
635
- const fileParam = Array.isArray(splat) ? splat.join("/") : splat;
632
+ // GET /api/file-content?path=... — Source code preview
633
+ app.get("/api/file-content", (req, res) => {
634
+ const fileParam = req.query.path;
636
635
  if (!fileParam)
637
636
  return res.status(400).json({ error: "File path required" });
638
637
  const graph = getGraphFn();
@@ -834,6 +833,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
834
833
  fileCount: graph.files.size,
835
834
  edgeCount,
836
835
  plan: license?.plan || "free",
836
+ billingPeriod: license?.billingPeriod || null,
837
837
  planSource: license?.source || "default",
838
838
  expiresAt: license?.expiresAt || null,
839
839
  licenseKey: maskedKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syke1/mcp-server",
3
- "version": "1.8.6",
3
+ "version": "1.8.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",