@syke1/mcp-server 1.3.0 ā 1.3.2
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 +18 -8
- package/dist/languages/plugin.d.ts +10 -0
- package/dist/languages/plugin.js +52 -0
- package/dist/languages/python.js +3 -7
- package/dist/languages/typescript.js +9 -8
- package/dist/web/public/app.js +27 -0
- package/dist/web/public/index.html +28 -0
- package/dist/web/public/style.css +147 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -111,7 +111,7 @@ async function main() {
|
|
|
111
111
|
};
|
|
112
112
|
process.on("SIGINT", shutdown);
|
|
113
113
|
process.on("SIGTERM", shutdown);
|
|
114
|
-
const server = new index_js_1.Server({ name: "syke", version: "1.3.
|
|
114
|
+
const server = new index_js_1.Server({ name: "syke", version: "1.3.2" }, { capabilities: { tools: {} } });
|
|
115
115
|
// List tools
|
|
116
116
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
117
117
|
tools: [
|
|
@@ -218,6 +218,16 @@ async function main() {
|
|
|
218
218
|
},
|
|
219
219
|
],
|
|
220
220
|
}));
|
|
221
|
+
// Dashboard URL footer ā shown only on the first successful tool call
|
|
222
|
+
let firstToolCall = true;
|
|
223
|
+
const DASHBOARD_FOOTER = `\n\n---\nš SYKE Dashboard: http://localhost:${WEB_PORT}`;
|
|
224
|
+
function appendDashboardFooter(text) {
|
|
225
|
+
if (firstToolCall && currentProjectRoot) {
|
|
226
|
+
firstToolCall = false;
|
|
227
|
+
return text + DASHBOARD_FOOTER;
|
|
228
|
+
}
|
|
229
|
+
return text;
|
|
230
|
+
}
|
|
221
231
|
// Handle tool calls
|
|
222
232
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
223
233
|
const { name, arguments: args } = request.params;
|
|
@@ -228,7 +238,7 @@ async function main() {
|
|
|
228
238
|
const result = (0, gate_build_1.gateCheck)(graph, files);
|
|
229
239
|
return {
|
|
230
240
|
content: [
|
|
231
|
-
{ type: "text", text: (0, gate_build_1.formatGateResult)(result) },
|
|
241
|
+
{ type: "text", text: appendDashboardFooter((0, gate_build_1.formatGateResult)(result)) },
|
|
232
242
|
],
|
|
233
243
|
isError: result.verdict === "FAIL",
|
|
234
244
|
};
|
|
@@ -270,7 +280,7 @@ async function main() {
|
|
|
270
280
|
lines.push(`- ${d}`);
|
|
271
281
|
}
|
|
272
282
|
}
|
|
273
|
-
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
283
|
+
return { content: [{ type: "text", text: appendDashboardFooter(lines.join("\n")) }] };
|
|
274
284
|
}
|
|
275
285
|
case "check_safe": {
|
|
276
286
|
const file = args.file;
|
|
@@ -295,7 +305,7 @@ async function main() {
|
|
|
295
305
|
content: [
|
|
296
306
|
{
|
|
297
307
|
type: "text",
|
|
298
|
-
text: `${result.riskLevel} ā ${rel} impacts ${result.totalImpacted} file(s)
|
|
308
|
+
text: appendDashboardFooter(`${result.riskLevel} ā ${rel} impacts ${result.totalImpacted} file(s)`),
|
|
299
309
|
},
|
|
300
310
|
],
|
|
301
311
|
};
|
|
@@ -397,7 +407,7 @@ async function main() {
|
|
|
397
407
|
const impactResult = (0, analyze_impact_1.analyzeImpact)(resolved, graph);
|
|
398
408
|
const aiResult = await (0, analyzer_1.analyzeWithAI)(resolved, impactResult, graph);
|
|
399
409
|
return {
|
|
400
|
-
content: [{ type: "text", text: aiResult }],
|
|
410
|
+
content: [{ type: "text", text: appendDashboardFooter(aiResult) }],
|
|
401
411
|
};
|
|
402
412
|
}
|
|
403
413
|
case "check_warnings": {
|
|
@@ -448,7 +458,7 @@ async function main() {
|
|
|
448
458
|
lines.push(`${count} warning(s) acknowledged.`);
|
|
449
459
|
}
|
|
450
460
|
return {
|
|
451
|
-
content: [{ type: "text", text: lines.join("\n") }],
|
|
461
|
+
content: [{ type: "text", text: appendDashboardFooter(lines.join("\n")) }],
|
|
452
462
|
};
|
|
453
463
|
}
|
|
454
464
|
default:
|
|
@@ -461,7 +471,7 @@ async function main() {
|
|
|
461
471
|
}
|
|
462
472
|
});
|
|
463
473
|
// Pre-warm the graph (skip if no project root ā e.g. Smithery scan)
|
|
464
|
-
console.error(`[syke] Starting SYKE MCP Server v1.3.
|
|
474
|
+
console.error(`[syke] Starting SYKE MCP Server v1.3.2`);
|
|
465
475
|
console.error(`[syke] License: ${licenseStatus.plan.toUpperCase()} (${licenseStatus.source})`);
|
|
466
476
|
// Log AI provider status
|
|
467
477
|
const aiProvider = (0, provider_1.getAIProvider)();
|
|
@@ -553,7 +563,7 @@ main().catch((err) => {
|
|
|
553
563
|
* See: https://smithery.ai/docs/deploy#sandbox-server
|
|
554
564
|
*/
|
|
555
565
|
function createSandboxServer() {
|
|
556
|
-
const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.3.
|
|
566
|
+
const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.3.2" }, { capabilities: { tools: {} } });
|
|
557
567
|
sandboxServer.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
558
568
|
tools: [
|
|
559
569
|
{
|
|
@@ -18,3 +18,13 @@ export declare function detectLanguages(root: string): LanguagePlugin[];
|
|
|
18
18
|
export declare function detectProjectRoot(startDir?: string): string;
|
|
19
19
|
export declare function detectPackageName(root: string, detectedPlugins: LanguagePlugin[]): string;
|
|
20
20
|
export declare function discoverAllFiles(rootDir: string, extensions: string[], extraSkipDirs?: string[]): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Check if any of the given manifest files exist at root or in first-level subdirectories.
|
|
23
|
+
* Useful for detecting projects with non-standard structures (e.g. backend/requirements.txt).
|
|
24
|
+
*/
|
|
25
|
+
export declare function hasManifestFile(root: string, manifests: string[]): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Find first-level subdirectories (and optionally root) that contain files with given extensions.
|
|
28
|
+
* Skips hidden dirs and common non-source dirs (.venv, node_modules, etc.).
|
|
29
|
+
*/
|
|
30
|
+
export declare function findSourceDirsWithFiles(root: string, extensions: string[]): string[];
|
package/dist/languages/plugin.js
CHANGED
|
@@ -41,6 +41,8 @@ exports.detectLanguages = detectLanguages;
|
|
|
41
41
|
exports.detectProjectRoot = detectProjectRoot;
|
|
42
42
|
exports.detectPackageName = detectPackageName;
|
|
43
43
|
exports.discoverAllFiles = discoverAllFiles;
|
|
44
|
+
exports.hasManifestFile = hasManifestFile;
|
|
45
|
+
exports.findSourceDirsWithFiles = findSourceDirsWithFiles;
|
|
44
46
|
const fs = __importStar(require("fs"));
|
|
45
47
|
const path = __importStar(require("path"));
|
|
46
48
|
// āā Registry āā
|
|
@@ -129,6 +131,56 @@ function discoverAllFiles(rootDir, extensions, extraSkipDirs) {
|
|
|
129
131
|
walk(rootDir);
|
|
130
132
|
return results;
|
|
131
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if any of the given manifest files exist at root or in first-level subdirectories.
|
|
136
|
+
* Useful for detecting projects with non-standard structures (e.g. backend/requirements.txt).
|
|
137
|
+
*/
|
|
138
|
+
function hasManifestFile(root, manifests) {
|
|
139
|
+
// Check root
|
|
140
|
+
if (manifests.some(f => fs.existsSync(path.join(root, f))))
|
|
141
|
+
return true;
|
|
142
|
+
// Check first-level subdirectories
|
|
143
|
+
try {
|
|
144
|
+
const entries = fs.readdirSync(root, { withFileTypes: true });
|
|
145
|
+
for (const entry of entries) {
|
|
146
|
+
if (!entry.isDirectory())
|
|
147
|
+
continue;
|
|
148
|
+
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
|
|
149
|
+
continue;
|
|
150
|
+
if (manifests.some(f => fs.existsSync(path.join(root, entry.name, f))))
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch { }
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Find first-level subdirectories (and optionally root) that contain files with given extensions.
|
|
159
|
+
* Skips hidden dirs and common non-source dirs (.venv, node_modules, etc.).
|
|
160
|
+
*/
|
|
161
|
+
function findSourceDirsWithFiles(root, extensions) {
|
|
162
|
+
const dirs = [];
|
|
163
|
+
try {
|
|
164
|
+
const entries = fs.readdirSync(root, { withFileTypes: true });
|
|
165
|
+
// Check root for direct source files
|
|
166
|
+
if (entries.some(e => e.isFile() && extensions.some(ext => e.name.endsWith(ext)))) {
|
|
167
|
+
dirs.push(root);
|
|
168
|
+
}
|
|
169
|
+
// Check first-level subdirectories
|
|
170
|
+
for (const entry of entries) {
|
|
171
|
+
if (!entry.isDirectory())
|
|
172
|
+
continue;
|
|
173
|
+
if (SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
|
|
174
|
+
continue;
|
|
175
|
+
const subdir = path.join(root, entry.name);
|
|
176
|
+
if (discoverAllFiles(subdir, extensions).length > 0) {
|
|
177
|
+
dirs.push(subdir);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch { }
|
|
182
|
+
return dirs;
|
|
183
|
+
}
|
|
132
184
|
// āā Register All Plugins āā
|
|
133
185
|
const dart_1 = require("./dart");
|
|
134
186
|
const typescript_1 = require("./typescript");
|
package/dist/languages/python.js
CHANGED
|
@@ -45,15 +45,11 @@ exports.pythonPlugin = {
|
|
|
45
45
|
extensions: [".py"],
|
|
46
46
|
codeBlockLang: "python",
|
|
47
47
|
detectProject(root) {
|
|
48
|
-
return
|
|
49
|
-
fs.existsSync(path.join(root, "requirements.txt")) ||
|
|
50
|
-
fs.existsSync(path.join(root, "setup.py"));
|
|
48
|
+
return (0, plugin_1.hasManifestFile)(root, ["pyproject.toml", "requirements.txt", "setup.py", "setup.cfg"]);
|
|
51
49
|
},
|
|
52
50
|
getSourceDirs(root) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
return [srcDir];
|
|
56
|
-
return [root];
|
|
51
|
+
const dirs = (0, plugin_1.findSourceDirsWithFiles)(root, [".py"]);
|
|
52
|
+
return dirs.length > 0 ? dirs : [root];
|
|
57
53
|
},
|
|
58
54
|
getPackageName(root) {
|
|
59
55
|
try {
|
|
@@ -39,12 +39,15 @@ const path = __importStar(require("path"));
|
|
|
39
39
|
const plugin_1 = require("./plugin");
|
|
40
40
|
const TS_IMPORT_RE = /(?:import|export)\s+.*?from\s+['"](.+?)['"]/;
|
|
41
41
|
const TS_SIDE_EFFECT_RE = /^import\s+['"](.+?)['"]/;
|
|
42
|
+
const JS_REQUIRE_RE = /(?:const|let|var)\s+\w+\s*=\s*require\s*\(\s*['"](.+?)['"]\s*\)/;
|
|
42
43
|
function resolveTsImport(fromDir, importPath) {
|
|
43
44
|
const base = path.resolve(fromDir, importPath);
|
|
44
45
|
const candidates = [
|
|
45
46
|
base,
|
|
46
47
|
base + ".ts",
|
|
48
|
+
base + ".tsx",
|
|
47
49
|
base + ".js",
|
|
50
|
+
base + ".jsx",
|
|
48
51
|
path.join(base, "index.ts"),
|
|
49
52
|
path.join(base, "index.js"),
|
|
50
53
|
];
|
|
@@ -58,16 +61,14 @@ function resolveTsImport(fromDir, importPath) {
|
|
|
58
61
|
exports.typescriptPlugin = {
|
|
59
62
|
id: "typescript",
|
|
60
63
|
name: "TypeScript",
|
|
61
|
-
extensions: [".ts", ".tsx"],
|
|
64
|
+
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
62
65
|
codeBlockLang: "typescript",
|
|
63
66
|
detectProject(root) {
|
|
64
|
-
return
|
|
65
|
-
(fs.existsSync(path.join(root, "package.json")) &&
|
|
66
|
-
fs.existsSync(path.join(root, "src")));
|
|
67
|
+
return (0, plugin_1.hasManifestFile)(root, ["tsconfig.json", "package.json"]);
|
|
67
68
|
},
|
|
68
69
|
getSourceDirs(root) {
|
|
69
|
-
const
|
|
70
|
-
return
|
|
70
|
+
const dirs = (0, plugin_1.findSourceDirsWithFiles)(root, [".ts", ".tsx", ".js", ".jsx"]);
|
|
71
|
+
return dirs.length > 0 ? dirs : [];
|
|
71
72
|
},
|
|
72
73
|
getPackageName(root) {
|
|
73
74
|
try {
|
|
@@ -79,7 +80,7 @@ exports.typescriptPlugin = {
|
|
|
79
80
|
}
|
|
80
81
|
},
|
|
81
82
|
discoverFiles(dir) {
|
|
82
|
-
return (0, plugin_1.discoverAllFiles)(dir, [".ts", ".tsx"]).filter(f => !f.endsWith(".d.ts"));
|
|
83
|
+
return (0, plugin_1.discoverAllFiles)(dir, [".ts", ".tsx", ".js", ".jsx"]).filter(f => !f.endsWith(".d.ts"));
|
|
83
84
|
},
|
|
84
85
|
parseImports(filePath, _projectRoot, _sourceDir) {
|
|
85
86
|
let content;
|
|
@@ -94,7 +95,7 @@ exports.typescriptPlugin = {
|
|
|
94
95
|
for (const line of content.split("\n")) {
|
|
95
96
|
const trimmed = line.trim();
|
|
96
97
|
let importPath = null;
|
|
97
|
-
const match = trimmed.match(TS_IMPORT_RE) || trimmed.match(TS_SIDE_EFFECT_RE);
|
|
98
|
+
const match = trimmed.match(TS_IMPORT_RE) || trimmed.match(TS_SIDE_EFFECT_RE) || trimmed.match(JS_REQUIRE_RE);
|
|
98
99
|
if (match)
|
|
99
100
|
importPath = match[1];
|
|
100
101
|
if (!importPath)
|
package/dist/web/public/app.js
CHANGED
|
@@ -51,6 +51,27 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
51
51
|
initSSE();
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
55
|
+
// WELCOME OVERLAY
|
|
56
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
57
|
+
function showWelcomeOverlay() {
|
|
58
|
+
const overlay = document.getElementById("welcome-overlay");
|
|
59
|
+
if (overlay) overlay.classList.remove("hidden");
|
|
60
|
+
|
|
61
|
+
const btn = document.getElementById("btn-welcome-open");
|
|
62
|
+
if (btn && !btn._bound) {
|
|
63
|
+
btn.addEventListener("click", () => {
|
|
64
|
+
document.getElementById("btn-change-project").click();
|
|
65
|
+
});
|
|
66
|
+
btn._bound = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function hideWelcomeOverlay() {
|
|
71
|
+
const overlay = document.getElementById("welcome-overlay");
|
|
72
|
+
if (overlay) overlay.classList.add("hidden");
|
|
73
|
+
}
|
|
74
|
+
|
|
54
75
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
55
76
|
// GRAPH LOADING
|
|
56
77
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
@@ -59,6 +80,12 @@ async function loadGraph() {
|
|
|
59
80
|
const raw = await res.json();
|
|
60
81
|
console.log("[SYKE]", raw.nodes.length, "nodes", raw.edges.length, "edges");
|
|
61
82
|
|
|
83
|
+
if (raw.nodes.length === 0) {
|
|
84
|
+
showWelcomeOverlay();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
hideWelcomeOverlay();
|
|
88
|
+
|
|
62
89
|
const nodes = raw.nodes.map(n => {
|
|
63
90
|
const layer = n.data.layer || "UTIL";
|
|
64
91
|
const c = LAYER_CENTERS[layer] || LAYER_CENTERS.UTIL;
|
|
@@ -56,6 +56,34 @@
|
|
|
56
56
|
<input type="text" id="search-input" placeholder="SEARCH TARGET...">
|
|
57
57
|
</div>
|
|
58
58
|
<div id="3d-graph"></div>
|
|
59
|
+
<!-- Welcome Overlay (shown when no project loaded) -->
|
|
60
|
+
<div id="welcome-overlay" class="welcome-overlay hidden">
|
|
61
|
+
<div class="welcome-content">
|
|
62
|
+
<div class="welcome-logo">
|
|
63
|
+
<div class="welcome-pulse-ring"><span class="welcome-pulse-dot"></span></div>
|
|
64
|
+
<span class="welcome-title">SYKE</span>
|
|
65
|
+
</div>
|
|
66
|
+
<p class="welcome-subtitle">CODE IMPACT RADAR</p>
|
|
67
|
+
<p class="welcome-msg">Open a project to get started</p>
|
|
68
|
+
<button id="btn-welcome-open" class="welcome-open-btn">OPEN PROJECT</button>
|
|
69
|
+
<div class="welcome-steps">
|
|
70
|
+
<div class="welcome-step">
|
|
71
|
+
<span class="step-num">1</span>
|
|
72
|
+
<span class="step-text">Open Project</span>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="welcome-step-arrow">→</div>
|
|
75
|
+
<div class="welcome-step">
|
|
76
|
+
<span class="step-num">2</span>
|
|
77
|
+
<span class="step-text">Explore Graph</span>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="welcome-step-arrow">→</div>
|
|
80
|
+
<div class="welcome-step">
|
|
81
|
+
<span class="step-num">3</span>
|
|
82
|
+
<span class="step-text">Monitor Changes</span>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
59
87
|
<!-- HTML overlay for node labels -->
|
|
60
88
|
<div id="node-labels"></div>
|
|
61
89
|
<!-- Layer Legend (clickable filter) -->
|
|
@@ -1825,3 +1825,150 @@ main {
|
|
|
1825
1825
|
font-size: 11px;
|
|
1826
1826
|
letter-spacing: 2px;
|
|
1827
1827
|
}
|
|
1828
|
+
|
|
1829
|
+
/* āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā */
|
|
1830
|
+
/* Welcome Overlay */
|
|
1831
|
+
/* āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā */
|
|
1832
|
+
.welcome-overlay {
|
|
1833
|
+
position: absolute;
|
|
1834
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
1835
|
+
display: flex;
|
|
1836
|
+
align-items: center;
|
|
1837
|
+
justify-content: center;
|
|
1838
|
+
z-index: 50;
|
|
1839
|
+
background: radial-gradient(ellipse at center, rgba(13,26,48,0.95) 0%, rgba(5,10,24,0.98) 70%);
|
|
1840
|
+
backdrop-filter: blur(2px);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
.welcome-overlay.hidden { display: none; }
|
|
1844
|
+
|
|
1845
|
+
.welcome-content {
|
|
1846
|
+
display: flex;
|
|
1847
|
+
flex-direction: column;
|
|
1848
|
+
align-items: center;
|
|
1849
|
+
gap: 16px;
|
|
1850
|
+
animation: welcome-fade-in 0.8s ease-out;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
@keyframes welcome-fade-in {
|
|
1854
|
+
0% { opacity: 0; transform: translateY(20px); }
|
|
1855
|
+
100% { opacity: 1; transform: translateY(0); }
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
.welcome-logo {
|
|
1859
|
+
display: flex;
|
|
1860
|
+
align-items: center;
|
|
1861
|
+
gap: 16px;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
.welcome-pulse-ring {
|
|
1865
|
+
position: relative;
|
|
1866
|
+
width: 28px;
|
|
1867
|
+
height: 28px;
|
|
1868
|
+
display: flex;
|
|
1869
|
+
align-items: center;
|
|
1870
|
+
justify-content: center;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
.welcome-pulse-ring::before {
|
|
1874
|
+
content: '';
|
|
1875
|
+
position: absolute;
|
|
1876
|
+
width: 28px; height: 28px;
|
|
1877
|
+
border-radius: 50%;
|
|
1878
|
+
border: 1px solid var(--risk-high);
|
|
1879
|
+
animation: pulse-ring 2s ease-out infinite;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
.welcome-pulse-dot {
|
|
1883
|
+
width: 10px;
|
|
1884
|
+
height: 10px;
|
|
1885
|
+
border-radius: 50%;
|
|
1886
|
+
background: var(--risk-high);
|
|
1887
|
+
box-shadow: 0 0 12px var(--risk-high);
|
|
1888
|
+
animation: pulse-glow 2s ease-in-out infinite;
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
.welcome-title {
|
|
1892
|
+
font-size: 42px;
|
|
1893
|
+
font-weight: 700;
|
|
1894
|
+
letter-spacing: 12px;
|
|
1895
|
+
color: var(--accent);
|
|
1896
|
+
text-shadow: var(--glow-cyan), 0 0 40px rgba(0,212,255,0.2);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
.welcome-subtitle {
|
|
1900
|
+
font-size: 11px;
|
|
1901
|
+
color: var(--text-secondary);
|
|
1902
|
+
letter-spacing: 6px;
|
|
1903
|
+
margin-top: -8px;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
.welcome-msg {
|
|
1907
|
+
font-size: 14px;
|
|
1908
|
+
color: var(--text-primary);
|
|
1909
|
+
letter-spacing: 1px;
|
|
1910
|
+
margin-top: 8px;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
.welcome-open-btn {
|
|
1914
|
+
padding: 12px 40px;
|
|
1915
|
+
background: rgba(0,212,255,0.1);
|
|
1916
|
+
color: var(--accent);
|
|
1917
|
+
border: 1px solid var(--accent);
|
|
1918
|
+
border-radius: 3px;
|
|
1919
|
+
cursor: pointer;
|
|
1920
|
+
font-size: 13px;
|
|
1921
|
+
font-family: inherit;
|
|
1922
|
+
font-weight: 700;
|
|
1923
|
+
letter-spacing: 4px;
|
|
1924
|
+
transition: all 0.3s;
|
|
1925
|
+
margin-top: 8px;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
.welcome-open-btn:hover {
|
|
1929
|
+
background: rgba(0,212,255,0.2);
|
|
1930
|
+
box-shadow: var(--glow-cyan), 0 0 40px rgba(0,212,255,0.15);
|
|
1931
|
+
transform: translateY(-1px);
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
.welcome-steps {
|
|
1935
|
+
display: flex;
|
|
1936
|
+
align-items: center;
|
|
1937
|
+
gap: 12px;
|
|
1938
|
+
margin-top: 24px;
|
|
1939
|
+
padding: 16px 24px;
|
|
1940
|
+
background: rgba(0,0,0,0.3);
|
|
1941
|
+
border: 1px solid var(--border);
|
|
1942
|
+
border-radius: 4px;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
.welcome-step {
|
|
1946
|
+
display: flex;
|
|
1947
|
+
align-items: center;
|
|
1948
|
+
gap: 8px;
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
.step-num {
|
|
1952
|
+
width: 22px;
|
|
1953
|
+
height: 22px;
|
|
1954
|
+
border-radius: 50%;
|
|
1955
|
+
border: 1px solid var(--accent-dim);
|
|
1956
|
+
display: flex;
|
|
1957
|
+
align-items: center;
|
|
1958
|
+
justify-content: center;
|
|
1959
|
+
font-size: 10px;
|
|
1960
|
+
font-weight: 700;
|
|
1961
|
+
color: var(--accent);
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
.step-text {
|
|
1965
|
+
font-size: 11px;
|
|
1966
|
+
color: var(--text-secondary);
|
|
1967
|
+
letter-spacing: 1px;
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
.welcome-step-arrow {
|
|
1971
|
+
color: var(--text-secondary);
|
|
1972
|
+
font-size: 14px;
|
|
1973
|
+
opacity: 0.5;
|
|
1974
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
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",
|