@syke1/mcp-server 1.4.2 → 1.4.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/dist/index.js +10 -7
- package/dist/license/validator.d.ts +1 -1
- package/dist/license/validator.js +7 -3
- package/dist/web/public/app.js +26 -7
- package/dist/web/server.js +7 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -75,12 +75,15 @@ function resolveFilePath(fileArg, projectRoot, sourceDir) {
|
|
|
75
75
|
let licenseStatus = { plan: "free", source: "default" };
|
|
76
76
|
// Free tier limits
|
|
77
77
|
const FREE_MAX_FILES = 50;
|
|
78
|
+
function isPro() {
|
|
79
|
+
return isPro() || licenseStatus.plan === "pro_trial";
|
|
80
|
+
}
|
|
78
81
|
/**
|
|
79
82
|
* Check if a resolved file path is within the free tier limit.
|
|
80
83
|
* Free set = first 50 files sorted alphabetically by relative path.
|
|
81
84
|
*/
|
|
82
85
|
function isFileInFreeSet(resolvedPath, graph) {
|
|
83
|
-
if (
|
|
86
|
+
if (isPro())
|
|
84
87
|
return true;
|
|
85
88
|
const allFiles = [...graph.files].sort();
|
|
86
89
|
const idx = allFiles.indexOf(resolvedPath);
|
|
@@ -357,7 +360,7 @@ async function main() {
|
|
|
357
360
|
}
|
|
358
361
|
case "get_hub_files": {
|
|
359
362
|
// Pro-only feature
|
|
360
|
-
if (
|
|
363
|
+
if (!isPro()) {
|
|
361
364
|
return {
|
|
362
365
|
content: [{ type: "text", text: getProToolError("get_hub_files") }],
|
|
363
366
|
};
|
|
@@ -392,7 +395,7 @@ async function main() {
|
|
|
392
395
|
case "ai_analyze": {
|
|
393
396
|
// BYOK: allow if user has their own AI key, even on Free plan
|
|
394
397
|
const hasAIKey = !!(0, provider_1.getAIProvider)();
|
|
395
|
-
if (
|
|
398
|
+
if (!isPro() && !hasAIKey) {
|
|
396
399
|
return {
|
|
397
400
|
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." }],
|
|
398
401
|
};
|
|
@@ -417,7 +420,7 @@ async function main() {
|
|
|
417
420
|
const aiResult = await (0, analyzer_1.analyzeWithAI)(resolved, impactResult, graph);
|
|
418
421
|
// Free tier: append partial analysis warning
|
|
419
422
|
let resultText = aiResult;
|
|
420
|
-
if (
|
|
423
|
+
if (!isPro() && graph.files.size > FREE_MAX_FILES) {
|
|
421
424
|
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/`;
|
|
422
425
|
}
|
|
423
426
|
return {
|
|
@@ -426,7 +429,7 @@ async function main() {
|
|
|
426
429
|
}
|
|
427
430
|
case "check_warnings": {
|
|
428
431
|
// Pro-only feature (real-time monitoring)
|
|
429
|
-
if (
|
|
432
|
+
if (!isPro()) {
|
|
430
433
|
return {
|
|
431
434
|
content: [{ type: "text", text: getProToolError("check_warnings") }],
|
|
432
435
|
};
|
|
@@ -498,7 +501,7 @@ async function main() {
|
|
|
498
501
|
else {
|
|
499
502
|
console.error(`[syke] AI: disabled (set GEMINI_KEY, OPENAI_KEY, or ANTHROPIC_KEY)`);
|
|
500
503
|
}
|
|
501
|
-
if (
|
|
504
|
+
if (isPro()) {
|
|
502
505
|
console.error(`[syke] Pro activated for: ${licenseStatus.email || "unknown"}`);
|
|
503
506
|
}
|
|
504
507
|
else {
|
|
@@ -570,7 +573,7 @@ async function main() {
|
|
|
570
573
|
catch {
|
|
571
574
|
licenseStatus = { plan: "free", source: "default" };
|
|
572
575
|
}
|
|
573
|
-
if (
|
|
576
|
+
if (isPro()) {
|
|
574
577
|
return { success: true, plan: licenseStatus.plan, expiresAt: licenseStatus.expiresAt };
|
|
575
578
|
}
|
|
576
579
|
else {
|
|
@@ -170,6 +170,7 @@ async function sendHeartbeat() {
|
|
|
170
170
|
await postJSON(HEARTBEAT_URL, {
|
|
171
171
|
key: currentLicenseKey,
|
|
172
172
|
deviceId: currentDeviceId,
|
|
173
|
+
deviceName: getDeviceName(),
|
|
173
174
|
});
|
|
174
175
|
}
|
|
175
176
|
catch {
|
|
@@ -248,8 +249,9 @@ async function checkLicense() {
|
|
|
248
249
|
if (cache && cache.valid && (now - cache.cachedAt) < CACHE_MAX_AGE) {
|
|
249
250
|
// Cache is fresh — still start heartbeat with cached session
|
|
250
251
|
startHeartbeat(key, getDeviceFingerprint());
|
|
252
|
+
const cachedPlan = cache.plan === "pro_trial" ? "pro_trial" : "pro";
|
|
251
253
|
return {
|
|
252
|
-
plan:
|
|
254
|
+
plan: cachedPlan,
|
|
253
255
|
email: cache.email,
|
|
254
256
|
expiresAt: cache.expiresAt,
|
|
255
257
|
source: "cache",
|
|
@@ -272,8 +274,9 @@ async function checkLicense() {
|
|
|
272
274
|
});
|
|
273
275
|
// Start heartbeat
|
|
274
276
|
startHeartbeat(key, getDeviceFingerprint());
|
|
277
|
+
const onlinePlan = result.plan === "pro_trial" ? "pro_trial" : "pro";
|
|
275
278
|
return {
|
|
276
|
-
plan:
|
|
279
|
+
plan: onlinePlan,
|
|
277
280
|
email: result.email,
|
|
278
281
|
expiresAt: result.expiresAt,
|
|
279
282
|
source: "online",
|
|
@@ -290,8 +293,9 @@ async function checkLicense() {
|
|
|
290
293
|
// Online validation failed — check if we have a grace-period cache
|
|
291
294
|
if (cache && cache.valid && (now - cache.cachedAt) < CACHE_GRACE_PERIOD) {
|
|
292
295
|
startHeartbeat(key, getDeviceFingerprint());
|
|
296
|
+
const gracePlan = cache.plan === "pro_trial" ? "pro_trial" : "pro";
|
|
293
297
|
return {
|
|
294
|
-
plan:
|
|
298
|
+
plan: gracePlan,
|
|
295
299
|
email: cache.email,
|
|
296
300
|
expiresAt: cache.expiresAt,
|
|
297
301
|
source: "cache",
|
package/dist/web/public/app.js
CHANGED
|
@@ -3595,10 +3595,13 @@ function updateLicenseBadge(plan, expiresAt) {
|
|
|
3595
3595
|
|
|
3596
3596
|
badge.className = "license-badge";
|
|
3597
3597
|
|
|
3598
|
-
if (plan === "pro") {
|
|
3598
|
+
if (plan === "pro" || plan === "pro_trial") {
|
|
3599
3599
|
if (expiresAt && new Date(expiresAt) < new Date()) {
|
|
3600
3600
|
badge.classList.add("expired");
|
|
3601
3601
|
badge.textContent = "EXPIRED";
|
|
3602
|
+
} else if (plan === "pro_trial") {
|
|
3603
|
+
badge.classList.add("pro");
|
|
3604
|
+
badge.textContent = "TRIAL-PRO";
|
|
3602
3605
|
} else {
|
|
3603
3606
|
badge.classList.add("pro");
|
|
3604
3607
|
badge.textContent = "PRO";
|
|
@@ -3817,11 +3820,27 @@ function setupLicenseModal() {
|
|
|
3817
3820
|
const statusEl = document.getElementById("license-modal-status");
|
|
3818
3821
|
if (!btn || !modal) return;
|
|
3819
3822
|
|
|
3820
|
-
function openModal() {
|
|
3823
|
+
async function openModal() {
|
|
3821
3824
|
modal.classList.remove("hidden");
|
|
3822
3825
|
input.value = "";
|
|
3823
3826
|
statusEl.textContent = "";
|
|
3824
3827
|
statusEl.className = "";
|
|
3828
|
+
// Fetch current key status
|
|
3829
|
+
try {
|
|
3830
|
+
const res = await fetch("/api/project-info");
|
|
3831
|
+
const info = await res.json();
|
|
3832
|
+
if (info.licenseKey) {
|
|
3833
|
+
input.placeholder = info.licenseKey;
|
|
3834
|
+
statusEl.className = "success";
|
|
3835
|
+
statusEl.textContent = "ACTIVE — " + (info.plan || "free").toUpperCase();
|
|
3836
|
+
deactivateBtn.style.display = "";
|
|
3837
|
+
} else {
|
|
3838
|
+
input.placeholder = "SYKE-XXXX-XXXX-XXXX-XXXX";
|
|
3839
|
+
deactivateBtn.style.display = "none";
|
|
3840
|
+
}
|
|
3841
|
+
} catch {
|
|
3842
|
+
input.placeholder = "SYKE-XXXX-XXXX-XXXX-XXXX";
|
|
3843
|
+
}
|
|
3825
3844
|
input.focus();
|
|
3826
3845
|
}
|
|
3827
3846
|
function closeModal() {
|
|
@@ -3850,11 +3869,11 @@ function setupLicenseModal() {
|
|
|
3850
3869
|
body: JSON.stringify({ key }),
|
|
3851
3870
|
});
|
|
3852
3871
|
const data = await res.json();
|
|
3853
|
-
if (data.success && data.plan === "pro") {
|
|
3872
|
+
if (data.success && (data.plan === "pro" || data.plan === "pro_trial")) {
|
|
3854
3873
|
statusEl.className = "success";
|
|
3855
|
-
statusEl.textContent = "PRO ACTIVATED";
|
|
3856
|
-
updateLicenseBadge(
|
|
3857
|
-
updateLicenseButton(
|
|
3874
|
+
statusEl.textContent = data.plan === "pro_trial" ? "TRIAL-PRO ACTIVATED" : "PRO ACTIVATED";
|
|
3875
|
+
updateLicenseBadge(data.plan, data.expiresAt);
|
|
3876
|
+
updateLicenseButton(data.plan);
|
|
3858
3877
|
setTimeout(closeModal, 1200);
|
|
3859
3878
|
} else {
|
|
3860
3879
|
statusEl.className = "error";
|
|
@@ -3901,7 +3920,7 @@ function setupLicenseModal() {
|
|
|
3901
3920
|
function updateLicenseButton(plan) {
|
|
3902
3921
|
const btn = document.getElementById("btn-license");
|
|
3903
3922
|
if (!btn) return;
|
|
3904
|
-
btn.textContent = plan === "pro" ? "LICENSED" : "LICENSE";
|
|
3923
|
+
btn.textContent = (plan === "pro" || plan === "pro_trial") ? "LICENSED" : "LICENSE";
|
|
3905
3924
|
}
|
|
3906
3925
|
|
|
3907
3926
|
function setupProjectModal() {
|
package/dist/web/server.js
CHANGED
|
@@ -48,6 +48,7 @@ const plugin_1 = require("../languages/plugin");
|
|
|
48
48
|
const analyze_impact_1 = require("../tools/analyze-impact");
|
|
49
49
|
const analyzer_1 = require("../ai/analyzer");
|
|
50
50
|
const realtime_analyzer_1 = require("../ai/realtime-analyzer");
|
|
51
|
+
const config_1 = require("../config");
|
|
51
52
|
function resolveFilePath(fileArg, projectRoot, sourceDir) {
|
|
52
53
|
const srcDir = sourceDir || path.join(projectRoot, "lib");
|
|
53
54
|
const srcDirName = path.basename(srcDir); // "lib" or "src"
|
|
@@ -739,6 +740,11 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
739
740
|
sykeVersion = pkg.version || "unknown";
|
|
740
741
|
}
|
|
741
742
|
catch { }
|
|
743
|
+
// Read current license key (masked for display)
|
|
744
|
+
const rawKey = (0, config_1.getConfig)("licenseKey", "SYKE_LICENSE_KEY") || "";
|
|
745
|
+
const maskedKey = rawKey.length > 10
|
|
746
|
+
? rawKey.substring(0, 9) + "····" + rawKey.substring(rawKey.length - 4)
|
|
747
|
+
: "";
|
|
742
748
|
res.json({
|
|
743
749
|
projectRoot: getProjectRoot ? getProjectRoot() : graph.projectRoot,
|
|
744
750
|
packageName: getPackageName ? getPackageName() : "",
|
|
@@ -748,6 +754,7 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
748
754
|
plan: license?.plan || "free",
|
|
749
755
|
planSource: license?.source || "default",
|
|
750
756
|
expiresAt: license?.expiresAt || null,
|
|
757
|
+
licenseKey: maskedKey,
|
|
751
758
|
freeFileLimit: 50,
|
|
752
759
|
sykeVersion,
|
|
753
760
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.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",
|