@syke1/mcp-server 1.4.22 → 1.5.0
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 +15 -16
- package/dist/graph.d.ts +3 -3
- package/dist/graph.js +18 -6
- package/dist/index.js +25 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,16 +89,16 @@ SYKE auto-detects your project language and builds the dependency graph on start
|
|
|
89
89
|
|
|
90
90
|
### 8 MCP Tools
|
|
91
91
|
|
|
92
|
-
| Tool | Description |
|
|
93
|
-
|
|
94
|
-
| `gate_build` | **Mandatory pre-build check.** Returns PASS/WARN/FAIL verdict before any build or deploy. |
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `get_hub_files` | Ranks files by
|
|
99
|
-
| `refresh_graph` | Re-scans all source files and rebuilds the dependency graph. |
|
|
100
|
-
| `ai_analyze` | **Pro**
|
|
101
|
-
| `check_warnings` | Real-time monitoring alerts for file changes that may break dependents. |
|
|
92
|
+
| Tool | Tier | Description |
|
|
93
|
+
|------|------|-------------|
|
|
94
|
+
| `gate_build` | Free | **Mandatory pre-build check.** Returns PASS/WARN/FAIL verdict before any build or deploy. |
|
|
95
|
+
| `check_safe` | Free | Quick one-line safety verdict: HIGH/MEDIUM/LOW/NONE risk. |
|
|
96
|
+
| `get_dependencies` | Free | Lists internal imports (forward dependencies) of a file. |
|
|
97
|
+
| `analyze_impact` | **Pro** | Full impact analysis with SCC, risk scoring, and git coupling. |
|
|
98
|
+
| `get_hub_files` | **Pro** | Ranks files by PageRank importance score. |
|
|
99
|
+
| `refresh_graph` | **Pro** | Re-scans all source files and rebuilds the dependency graph. |
|
|
100
|
+
| `ai_analyze` | **Pro** | AI semantic analysis (Gemini/OpenAI/Claude) of a file and its dependents. |
|
|
101
|
+
| `check_warnings` | **Pro** | Real-time monitoring alerts for file changes that may break dependents. |
|
|
102
102
|
|
|
103
103
|
### Multi-AI Provider Support
|
|
104
104
|
|
|
@@ -254,15 +254,14 @@ You (developer) AI Agent SYKE
|
|
|
254
254
|
## Pricing
|
|
255
255
|
|
|
256
256
|
### Free — $0 forever
|
|
257
|
-
-
|
|
258
|
-
-
|
|
257
|
+
- 3 tools: `gate_build`, `check_safe`, `get_dependencies`
|
|
258
|
+
- 50 files per project, single project
|
|
259
259
|
- 8 language support
|
|
260
260
|
|
|
261
261
|
### Pro — $12/mo (or $99/yr, save 31%)
|
|
262
|
-
-
|
|
263
|
-
-
|
|
264
|
-
- Real-time cascade monitoring
|
|
265
|
-
- Cycle detection & simulation
|
|
262
|
+
- All 8 tools with advanced algorithms (SCC, PageRank, Risk Scoring, Git Coupling)
|
|
263
|
+
- Unlimited files, multi-project support
|
|
264
|
+
- Real-time cascade monitoring + web dashboard
|
|
266
265
|
- AI semantic analysis (BYOK — Gemini, OpenAI, or Claude)
|
|
267
266
|
- Priority support
|
|
268
267
|
|
package/dist/graph.d.ts
CHANGED
|
@@ -14,6 +14,6 @@ export interface DependencyGraph {
|
|
|
14
14
|
/** PageRank importance scores — computed after graph build */
|
|
15
15
|
pageRank?: PageRankResult;
|
|
16
16
|
}
|
|
17
|
-
export declare function buildGraph(projectRoot: string, packageName?: string): DependencyGraph;
|
|
18
|
-
export declare function getGraph(projectRoot: string, packageName?: string): DependencyGraph;
|
|
19
|
-
export declare function
|
|
17
|
+
export declare function buildGraph(projectRoot: string, packageName?: string, maxFiles?: number): DependencyGraph;
|
|
18
|
+
export declare function getGraph(projectRoot: string, packageName?: string, maxFiles?: number): DependencyGraph;
|
|
19
|
+
export declare function rebuildGraph(projectRoot: string, packageName?: string, maxFiles?: number): DependencyGraph;
|
package/dist/graph.js
CHANGED
|
@@ -35,7 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.buildGraph = buildGraph;
|
|
37
37
|
exports.getGraph = getGraph;
|
|
38
|
-
exports.
|
|
38
|
+
exports.rebuildGraph = rebuildGraph;
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
40
|
const plugin_1 = require("./languages/plugin");
|
|
41
41
|
const typescript_1 = require("./languages/typescript");
|
|
@@ -44,13 +44,15 @@ const risk_scorer_1 = require("./scoring/risk-scorer");
|
|
|
44
44
|
const pagerank_1 = require("./scoring/pagerank");
|
|
45
45
|
const memo_cache_1 = require("./graph/memo-cache");
|
|
46
46
|
let cachedGraph = null;
|
|
47
|
-
function buildGraph(projectRoot, packageName) {
|
|
47
|
+
function buildGraph(projectRoot, packageName, maxFiles) {
|
|
48
48
|
const detectedPlugins = (0, plugin_1.detectLanguages)(projectRoot);
|
|
49
49
|
const languages = detectedPlugins.map(p => p.id);
|
|
50
50
|
const forward = new Map();
|
|
51
51
|
const reverse = new Map();
|
|
52
52
|
const files = new Set();
|
|
53
53
|
const allSourceDirs = [];
|
|
54
|
+
let totalDiscovered = 0;
|
|
55
|
+
let fileLimitHit = false;
|
|
54
56
|
for (const plugin of detectedPlugins) {
|
|
55
57
|
const dirs = plugin.getSourceDirs(projectRoot);
|
|
56
58
|
console.error(`[syke:debug] ${plugin.id} getSourceDirs(${projectRoot}) => ${dirs.length} dirs: ${dirs.join(", ")}`);
|
|
@@ -59,12 +61,19 @@ function buildGraph(projectRoot, packageName) {
|
|
|
59
61
|
allSourceDirs.push(dir);
|
|
60
62
|
const sourceFiles = plugin.discoverFiles(dir);
|
|
61
63
|
console.error(`[syke:debug] ${plugin.id} discoverFiles(${dir}) => ${sourceFiles.length} files`);
|
|
64
|
+
totalDiscovered += sourceFiles.length;
|
|
62
65
|
for (const f of sourceFiles) {
|
|
66
|
+
if (maxFiles && files.size >= maxFiles) {
|
|
67
|
+
fileLimitHit = true;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
63
70
|
files.add(f);
|
|
64
71
|
if (!forward.has(f))
|
|
65
72
|
forward.set(f, []);
|
|
66
73
|
}
|
|
67
74
|
for (const f of sourceFiles) {
|
|
75
|
+
if (!files.has(f))
|
|
76
|
+
continue;
|
|
68
77
|
const imports = plugin.parseImports(f, projectRoot, dir);
|
|
69
78
|
const validImports = [];
|
|
70
79
|
for (const imp of imports) {
|
|
@@ -79,6 +88,9 @@ function buildGraph(projectRoot, packageName) {
|
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
}
|
|
91
|
+
if (fileLimitHit) {
|
|
92
|
+
console.error(`[syke] Free tier: loaded ${files.size}/${totalDiscovered} files (limit: ${maxFiles}). Upgrade to Pro for unlimited.`);
|
|
93
|
+
}
|
|
82
94
|
const sourceDir = allSourceDirs[0] || path.join(projectRoot, "src");
|
|
83
95
|
const graph = {
|
|
84
96
|
forward,
|
|
@@ -109,17 +121,17 @@ function countEdges(forward) {
|
|
|
109
121
|
}
|
|
110
122
|
return count;
|
|
111
123
|
}
|
|
112
|
-
function getGraph(projectRoot, packageName) {
|
|
124
|
+
function getGraph(projectRoot, packageName, maxFiles) {
|
|
113
125
|
if (cachedGraph && cachedGraph.projectRoot === projectRoot) {
|
|
114
126
|
return cachedGraph;
|
|
115
127
|
}
|
|
116
|
-
return buildGraph(projectRoot, packageName);
|
|
128
|
+
return buildGraph(projectRoot, packageName, maxFiles);
|
|
117
129
|
}
|
|
118
|
-
function
|
|
130
|
+
function rebuildGraph(projectRoot, packageName, maxFiles) {
|
|
119
131
|
cachedGraph = null;
|
|
120
132
|
(0, typescript_1.clearAliasCache)();
|
|
121
133
|
(0, risk_scorer_1.invalidateProjectMetrics)();
|
|
122
134
|
(0, pagerank_1.invalidatePageRank)();
|
|
123
135
|
(0, memo_cache_1.resetMemoCache)();
|
|
124
|
-
return buildGraph(projectRoot, packageName);
|
|
136
|
+
return buildGraph(projectRoot, packageName, maxFiles);
|
|
125
137
|
}
|
package/dist/index.js
CHANGED
|
@@ -81,6 +81,9 @@ const FREE_MAX_FILES = 50;
|
|
|
81
81
|
function isPro() {
|
|
82
82
|
return licenseStatus.plan === "pro" || licenseStatus.plan === "pro_trial";
|
|
83
83
|
}
|
|
84
|
+
function getMaxFiles() {
|
|
85
|
+
return isPro() ? undefined : FREE_MAX_FILES;
|
|
86
|
+
}
|
|
84
87
|
/**
|
|
85
88
|
* Check if a resolved file path is within the free tier limit.
|
|
86
89
|
* Free set = first 50 files sorted alphabetically by relative path.
|
|
@@ -150,7 +153,7 @@ async function main() {
|
|
|
150
153
|
},
|
|
151
154
|
{
|
|
152
155
|
name: "analyze_impact",
|
|
153
|
-
description: "Analyze which files are impacted when a given file is modified. Returns direct and transitive dependents with risk level.",
|
|
156
|
+
description: "[PRO] Analyze which files are impacted when a given file is modified. Returns direct and transitive dependents with risk level.",
|
|
154
157
|
inputSchema: {
|
|
155
158
|
type: "object",
|
|
156
159
|
properties: {
|
|
@@ -186,7 +189,7 @@ async function main() {
|
|
|
186
189
|
},
|
|
187
190
|
{
|
|
188
191
|
name: "get_hub_files",
|
|
189
|
-
description: "Rank files by how many other files depend on them. High-hub files are risky to modify.",
|
|
192
|
+
description: "[PRO] Rank files by how many other files depend on them (PageRank). High-hub files are risky to modify.",
|
|
190
193
|
inputSchema: {
|
|
191
194
|
type: "object",
|
|
192
195
|
properties: {
|
|
@@ -199,7 +202,7 @@ async function main() {
|
|
|
199
202
|
},
|
|
200
203
|
{
|
|
201
204
|
name: "refresh_graph",
|
|
202
|
-
description: "Re-scan all source files and rebuild the dependency graph. Use after adding/removing files.",
|
|
205
|
+
description: "[PRO] Re-scan all source files and rebuild the dependency graph. Use after adding/removing files.",
|
|
203
206
|
inputSchema: {
|
|
204
207
|
type: "object",
|
|
205
208
|
properties: {},
|
|
@@ -207,7 +210,7 @@ async function main() {
|
|
|
207
210
|
},
|
|
208
211
|
{
|
|
209
212
|
name: "ai_analyze",
|
|
210
|
-
description: "Use AI (Gemini/OpenAI/Claude) to perform semantic analysis on a file. Reads the file's source code and its dependents to explain what might break when modified and how to safely make changes.",
|
|
213
|
+
description: "[PRO] Use AI (Gemini/OpenAI/Claude) to perform semantic analysis on a file. Reads the file's source code and its dependents to explain what might break when modified and how to safely make changes.",
|
|
211
214
|
inputSchema: {
|
|
212
215
|
type: "object",
|
|
213
216
|
properties: {
|
|
@@ -221,7 +224,7 @@ async function main() {
|
|
|
221
224
|
},
|
|
222
225
|
{
|
|
223
226
|
name: "check_warnings",
|
|
224
|
-
description: "Check for unresolved warnings from SYKE's real-time monitoring. Returns warnings about file changes that may have broken dependents. Use this AFTER modifying files to see if SYKE caught any issues you may have missed. Pass acknowledge=true to clear warnings after reading them.",
|
|
227
|
+
description: "[PRO] Check for unresolved warnings from SYKE's real-time monitoring. Returns warnings about file changes that may have broken dependents. Use this AFTER modifying files to see if SYKE caught any issues you may have missed. Pass acknowledge=true to clear warnings after reading them.",
|
|
225
228
|
inputSchema: {
|
|
226
229
|
type: "object",
|
|
227
230
|
properties: {
|
|
@@ -249,7 +252,7 @@ async function main() {
|
|
|
249
252
|
const { name, arguments: args } = request.params;
|
|
250
253
|
switch (name) {
|
|
251
254
|
case "gate_build": {
|
|
252
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
255
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
253
256
|
const files = args.files?.map((f) => resolveFilePath(f, currentProjectRoot, graph.sourceDir));
|
|
254
257
|
const result = await (0, gate_build_1.gateCheck)(graph, files);
|
|
255
258
|
return {
|
|
@@ -260,8 +263,11 @@ async function main() {
|
|
|
260
263
|
};
|
|
261
264
|
}
|
|
262
265
|
case "analyze_impact": {
|
|
266
|
+
if (!isPro()) {
|
|
267
|
+
return { content: [{ type: "text", text: getProToolError("analyze_impact") }] };
|
|
268
|
+
}
|
|
263
269
|
const file = args.file;
|
|
264
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
270
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
265
271
|
const resolved = resolveFilePath(file, currentProjectRoot, graph.sourceDir);
|
|
266
272
|
if (!graph.files.has(resolved)) {
|
|
267
273
|
return {
|
|
@@ -273,9 +279,6 @@ async function main() {
|
|
|
273
279
|
],
|
|
274
280
|
};
|
|
275
281
|
}
|
|
276
|
-
if (!isFileInFreeSet(resolved, graph)) {
|
|
277
|
-
return { content: [{ type: "text", text: PRO_UPGRADE_MSG }] };
|
|
278
|
-
}
|
|
279
282
|
const result = await (0, analyze_impact_1.analyzeImpact)(resolved, graph, { includeRiskScore: true, includeCoupling: true });
|
|
280
283
|
const cachedTag = result.fromCache ? " (cached)" : "";
|
|
281
284
|
const lines = [
|
|
@@ -360,7 +363,7 @@ async function main() {
|
|
|
360
363
|
}
|
|
361
364
|
case "check_safe": {
|
|
362
365
|
const file = args.file;
|
|
363
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
366
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
364
367
|
const resolved = resolveFilePath(file, currentProjectRoot, graph.sourceDir);
|
|
365
368
|
if (!graph.files.has(resolved)) {
|
|
366
369
|
return {
|
|
@@ -412,7 +415,7 @@ async function main() {
|
|
|
412
415
|
}
|
|
413
416
|
case "get_dependencies": {
|
|
414
417
|
const file = args.file;
|
|
415
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
418
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
416
419
|
const resolved = resolveFilePath(file, currentProjectRoot, graph.sourceDir);
|
|
417
420
|
if (!graph.files.has(resolved)) {
|
|
418
421
|
return {
|
|
@@ -453,7 +456,7 @@ async function main() {
|
|
|
453
456
|
};
|
|
454
457
|
}
|
|
455
458
|
const requestedN = args.top_n || 10;
|
|
456
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
459
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
457
460
|
const hubs = (0, analyze_impact_1.getHubFiles)(graph, requestedN);
|
|
458
461
|
// If PageRank is available, build enriched entries sorted by PageRank
|
|
459
462
|
const pageRankAvailable = !!graph.pageRank;
|
|
@@ -517,7 +520,10 @@ async function main() {
|
|
|
517
520
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
518
521
|
}
|
|
519
522
|
case "refresh_graph": {
|
|
520
|
-
|
|
523
|
+
if (!isPro()) {
|
|
524
|
+
return { content: [{ type: "text", text: getProToolError("refresh_graph") }] };
|
|
525
|
+
}
|
|
526
|
+
const graph = (0, graph_1.rebuildGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
521
527
|
(0, change_coupling_1.invalidateCouplingCache)();
|
|
522
528
|
const cacheStats = (0, analyze_impact_1.getImpactMemoCache)().stats();
|
|
523
529
|
return {
|
|
@@ -538,7 +544,7 @@ async function main() {
|
|
|
538
544
|
};
|
|
539
545
|
}
|
|
540
546
|
const file = args.file;
|
|
541
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
547
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
542
548
|
const resolved = resolveFilePath(file, currentProjectRoot, graph.sourceDir);
|
|
543
549
|
if (!graph.files.has(resolved)) {
|
|
544
550
|
return {
|
|
@@ -642,7 +648,7 @@ async function main() {
|
|
|
642
648
|
console.error(`[syke] Pro activated for: ${licenseStatus.email || "unknown"}`);
|
|
643
649
|
}
|
|
644
650
|
else {
|
|
645
|
-
console.error(`[syke] Free tier: ${FREE_MAX_FILES} file limit,
|
|
651
|
+
console.error(`[syke] Free tier: ${FREE_MAX_FILES} file limit, 3 tools (gate_build, check_safe, get_dependencies)`);
|
|
646
652
|
console.error(`[syke] Upgrade at https://syke.cloud/dashboard/`);
|
|
647
653
|
}
|
|
648
654
|
let fileCache = null;
|
|
@@ -651,12 +657,7 @@ async function main() {
|
|
|
651
657
|
console.error(`[syke] Project root: ${currentProjectRoot}`);
|
|
652
658
|
console.error(`[syke] Detected languages: ${detectedLangs}`);
|
|
653
659
|
console.error(`[syke] Package name: ${currentPackageName}`);
|
|
654
|
-
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName);
|
|
655
|
-
// Free tier: warn if over file limit
|
|
656
|
-
if (licenseStatus.plan === "free" && graph.files.size > FREE_MAX_FILES) {
|
|
657
|
-
console.error(`[syke] WARNING: Free tier limited to ${FREE_MAX_FILES} files. Your project has ${graph.files.size} files.`);
|
|
658
|
-
console.error(`[syke] Only the first ${FREE_MAX_FILES} files will be analyzed. Upgrade to Pro for unlimited files.`);
|
|
659
|
-
}
|
|
660
|
+
const graph = (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles());
|
|
660
661
|
// Initialize file cache (load ALL source files into memory)
|
|
661
662
|
fileCache = new file_cache_1.FileCache(currentProjectRoot);
|
|
662
663
|
fileCache.initialize();
|
|
@@ -676,7 +677,7 @@ async function main() {
|
|
|
676
677
|
fileCache = new file_cache_1.FileCache(newRoot);
|
|
677
678
|
fileCache.initialize();
|
|
678
679
|
// Rebuild graph
|
|
679
|
-
const graph = (0, graph_1.
|
|
680
|
+
const graph = (0, graph_1.rebuildGraph)(newRoot, currentPackageName, getMaxFiles());
|
|
680
681
|
// Enable incremental updates on the new cache
|
|
681
682
|
fileCache.setGraph(graph);
|
|
682
683
|
fileCache.startWatching();
|
|
@@ -701,7 +702,7 @@ async function main() {
|
|
|
701
702
|
}
|
|
702
703
|
// Start Express web server with file cache for SSE (only if project detected)
|
|
703
704
|
if (currentProjectRoot) {
|
|
704
|
-
const { app: webApp, setFileCache: setWebFileCache } = (0, server_1.createWebServer)(() => (0, graph_1.getGraph)(currentProjectRoot, currentPackageName), fileCache, switchProject, () => currentProjectRoot, () => currentPackageName, () => licenseStatus, () => !!(0, provider_1.getAIProvider)(), async (key) => {
|
|
705
|
+
const { app: webApp, setFileCache: setWebFileCache } = (0, server_1.createWebServer)(() => (0, graph_1.getGraph)(currentProjectRoot, currentPackageName, getMaxFiles()), fileCache, switchProject, () => currentProjectRoot, () => currentPackageName, () => licenseStatus, () => !!(0, provider_1.getAIProvider)(), async (key) => {
|
|
705
706
|
// Stop existing heartbeat/session
|
|
706
707
|
await (0, validator_1.stopAndDeactivate)();
|
|
707
708
|
if (key && (key.startsWith("SYKE-") || key.startsWith("FOUNDING-"))) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
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",
|