@syke1/mcp-server 1.3.0 → 1.3.1

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.
@@ -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[];
@@ -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");
@@ -45,15 +45,11 @@ exports.pythonPlugin = {
45
45
  extensions: [".py"],
46
46
  codeBlockLang: "python",
47
47
  detectProject(root) {
48
- return fs.existsSync(path.join(root, "pyproject.toml")) ||
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 srcDir = path.join(root, "src");
54
- if (fs.existsSync(srcDir))
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 fs.existsSync(path.join(root, "tsconfig.json")) ||
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 srcDir = path.join(root, "src");
70
- return fs.existsSync(srcDir) ? [srcDir] : [];
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syke1/mcp-server",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
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",