smart-coding-mcp 1.2.0 → 1.2.3

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 CHANGED
@@ -38,7 +38,17 @@ npm install -g smart-coding-mcp
38
38
 
39
39
  ## Configuration
40
40
 
41
- Add to your MCP configuration file (e.g., `~/.config/claude/mcp.json` or similar):
41
+ Add to your MCP configuration file. The location depends on your IDE and OS:
42
+
43
+ | IDE | OS | Config Path |
44
+ | -------------------- | ------- | ----------------------------------------------------------------- |
45
+ | **Claude Desktop** | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
46
+ | **Claude Desktop** | Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
47
+ | **Cascade (Cursor)** | All | Configured via UI Settings > Features > MCP |
48
+ | **Antigravity** | macOS | `~/.gemini/antigravity/mcp_config.json` |
49
+ | **Antigravity** | Windows | `%USERPROFILE%\.gemini\antigravity\mcp_config.json` |
50
+
51
+ Add the server configuration to the `mcpServers` object in your config file:
42
52
 
43
53
  ### Option 1: Specific Project (Recommended)
44
54
 
@@ -86,14 +96,17 @@ Add to your MCP configuration file (e.g., `~/.config/claude/mcp.json` or similar
86
96
 
87
97
  Override configuration settings via environment variables in your MCP config:
88
98
 
89
- | Variable | Type | Default | Description |
90
- | ----------------------------- | ------- | --------- | ------------------------------ |
91
- | `SMART_CODING_VERBOSE` | boolean | `false` | Enable detailed logging |
92
- | `SMART_CODING_BATCH_SIZE` | number | `100` | Files to process in parallel |
93
- | `SMART_CODING_MAX_FILE_SIZE` | number | `1048576` | Max file size in bytes (1MB) |
94
- | `SMART_CODING_CHUNK_SIZE` | number | `15` | Lines of code per chunk |
95
- | `SMART_CODING_MAX_RESULTS` | number | `5` | Max search results |
96
- | `SMART_CODING_SMART_INDEXING` | boolean | `true` | Enable smart project detection |
99
+ | Variable | Type | Default | Description |
100
+ | -------------------------------- | ------- | --------- | ------------------------------------- |
101
+ | `SMART_CODING_VERBOSE` | boolean | `false` | Enable detailed logging |
102
+ | `SMART_CODING_BATCH_SIZE` | number | `100` | Files to process in parallel |
103
+ | `SMART_CODING_MAX_FILE_SIZE` | number | `1048576` | Max file size in bytes (1MB) |
104
+ | `SMART_CODING_CHUNK_SIZE` | number | `15` | Lines of code per chunk |
105
+ | `SMART_CODING_MAX_RESULTS` | number | `5` | Max search results |
106
+ | `SMART_CODING_SMART_INDEXING` | boolean | `true` | Enable smart project detection |
107
+ | `SMART_CODING_WATCH_FILES` | boolean | `false` | Enable file watching for auto-reindex |
108
+ | `SMART_CODING_SEMANTIC_WEIGHT` | number | `0.7` | Weight for semantic similarity (0-1) |
109
+ | `SMART_CODING_EXACT_MATCH_BOOST` | number | `1.5` | Boost for exact text matches |
97
110
 
98
111
  **Example with environment variables:**
99
112
 
@@ -353,11 +366,24 @@ Potential areas for improvement:
353
366
 
354
367
  ## License
355
368
 
356
- MIT - see LICENSE file
369
+ MIT License
370
+
371
+ Copyright (c) 2025 Omar Haris
372
+
373
+ Permission is hereby granted, free of charge, to any person obtaining a copy
374
+ of this software and associated documentation files (the "Software"), to deal
375
+ in the Software without restriction, including without limitation the rights
376
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
377
+ copies of the Software, and to permit persons to whom the Software is
378
+ furnished to do so, subject to the following conditions:
357
379
 
358
- ## Documentation
380
+ The above copyright notice and this permission notice shall be included in all
381
+ copies or substantial portions of the Software.
359
382
 
360
- - ARCHITECTURE.md - Implementation details and design decisions
361
- - CONTRIBUTING.md - Guidelines for contributors
362
- - EXAMPLES.md - More usage examples
363
- - QUICKSTART.md - Detailed setup guide
383
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
384
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
385
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
386
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
387
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
388
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
389
+ SOFTWARE.
package/config.json CHANGED
@@ -1,7 +1,54 @@
1
1
  {
2
2
  "searchDirectory": ".",
3
- "fileExtensions": ["js", "ts", "jsx", "tsx", "mjs", "cjs", "css", "scss", "sass", "less", "html", "htm", "xml", "svg", "py", "pyw", "java", "kt", "scala", "c", "cpp", "h", "hpp", "cs", "go", "rs", "rb", "php", "swift", "sh", "bash", "json", "yaml", "yml", "toml", "sql"],
4
- "excludePatterns": ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.git/**", "**/coverage/**", "**/.next/**", "**/target/**", "**/vendor/**", "**/.smart-coding-cache/**"],
3
+ "fileExtensions": [
4
+ "js",
5
+ "ts",
6
+ "jsx",
7
+ "tsx",
8
+ "mjs",
9
+ "cjs",
10
+ "css",
11
+ "scss",
12
+ "sass",
13
+ "less",
14
+ "html",
15
+ "htm",
16
+ "xml",
17
+ "svg",
18
+ "py",
19
+ "pyw",
20
+ "java",
21
+ "kt",
22
+ "scala",
23
+ "c",
24
+ "cpp",
25
+ "h",
26
+ "hpp",
27
+ "cs",
28
+ "go",
29
+ "rs",
30
+ "rb",
31
+ "php",
32
+ "swift",
33
+ "sh",
34
+ "bash",
35
+ "json",
36
+ "yaml",
37
+ "yml",
38
+ "toml",
39
+ "sql"
40
+ ],
41
+ "excludePatterns": [
42
+ "**/node_modules/**",
43
+ "**/dist/**",
44
+ "**/build/**",
45
+ "**/.git/**",
46
+ "**/coverage/**",
47
+ "**/.next/**",
48
+ "**/target/**",
49
+ "**/vendor/**",
50
+ "**/.smart-coding-cache/**"
51
+ ],
5
52
  "smartIndexing": true,
6
53
  "chunkSize": 15,
7
54
  "chunkOverlap": 3,
@@ -10,9 +57,9 @@
10
57
  "maxResults": 5,
11
58
  "enableCache": true,
12
59
  "cacheDirectory": "./.smart-coding-cache",
13
- "watchFiles": true,
60
+ "watchFiles": false,
14
61
  "verbose": false,
15
62
  "embeddingModel": "Xenova/all-MiniLM-L6-v2",
16
63
  "semanticWeight": 0.7,
17
64
  "exactMatchBoost": 1.5
18
- }
65
+ }
@@ -21,6 +21,13 @@ export function getToolDefinition() {
21
21
  inputSchema: {
22
22
  type: "object",
23
23
  properties: {}
24
+ },
25
+ annotations: {
26
+ title: "Clear Embeddings Cache",
27
+ readOnlyHint: false,
28
+ destructiveHint: true,
29
+ idempotentHint: true,
30
+ openWorldHint: false
24
31
  }
25
32
  };
26
33
  }
@@ -89,6 +89,13 @@ export function getToolDefinition(config) {
89
89
  }
90
90
  },
91
91
  required: ["query"]
92
+ },
93
+ annotations: {
94
+ title: "Semantic Code Search",
95
+ readOnlyHint: true,
96
+ destructiveHint: false,
97
+ idempotentHint: true,
98
+ openWorldHint: false
92
99
  }
93
100
  };
94
101
  }
@@ -161,11 +161,6 @@ export class CodebaseIndexer {
161
161
 
162
162
  console.error("[Indexer] File watcher enabled for incremental indexing");
163
163
  }
164
-
165
- async initialize() {
166
- await this.indexAll();
167
- this.setupFileWatcher();
168
- }
169
164
  }
170
165
 
171
166
  // MCP Tool definition for this feature
@@ -182,6 +177,13 @@ export function getToolDefinition() {
182
177
  default: false
183
178
  }
184
179
  }
180
+ },
181
+ annotations: {
182
+ title: "Reindex Codebase",
183
+ readOnlyHint: false,
184
+ destructiveHint: false,
185
+ idempotentHint: true,
186
+ openWorldHint: false
185
187
  }
186
188
  };
187
189
  }
package/index.js CHANGED
@@ -4,6 +4,11 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
5
5
  import { pipeline } from "@xenova/transformers";
6
6
  import fs from "fs/promises";
7
+ import { createRequire } from "module";
8
+
9
+ // Import package.json for version
10
+ const require = createRequire(import.meta.url);
11
+ const packageJson = require("./package.json");
7
12
 
8
13
  import { loadConfig } from "./lib/config.js";
9
14
  import { EmbeddingsCache } from "./lib/cache.js";
@@ -49,17 +54,17 @@ let indexer = null;
49
54
  let hybridSearch = null;
50
55
  let config = null;
51
56
 
52
- // Feature registry
57
+ // Feature registry - ordered by priority (semantic_search first as primary tool)
53
58
  const features = [
54
59
  {
55
- module: IndexCodebaseFeature,
60
+ module: HybridSearchFeature,
56
61
  instance: null,
57
- handler: IndexCodebaseFeature.handleToolCall
62
+ handler: HybridSearchFeature.handleToolCall
58
63
  },
59
64
  {
60
- module: HybridSearchFeature,
65
+ module: IndexCodebaseFeature,
61
66
  instance: null,
62
- handler: HybridSearchFeature.handleToolCall
67
+ handler: IndexCodebaseFeature.handleToolCall
63
68
  },
64
69
  {
65
70
  module: ClearCacheFeature,
@@ -94,14 +99,19 @@ async function initialize() {
94
99
  hybridSearch = new HybridSearch(embedder, cache, config);
95
100
  const cacheClearer = new ClearCacheFeature.CacheClearer(embedder, cache, config);
96
101
 
97
- // Store feature instances
98
- features[0].instance = indexer;
99
- features[1].instance = hybridSearch;
102
+ // Store feature instances (matches features array order)
103
+ features[0].instance = hybridSearch;
104
+ features[1].instance = indexer;
100
105
  features[2].instance = cacheClearer;
101
106
 
102
107
  // Start indexing in background (non-blocking)
103
108
  console.error("[Server] Starting background indexing...");
104
- indexer.initialize().catch(err => {
109
+ indexer.indexAll().then(() => {
110
+ // Only start file watcher if explicitly enabled in config
111
+ if (config.watchFiles) {
112
+ indexer.setupFileWatcher();
113
+ }
114
+ }).catch(err => {
105
115
  console.error("[Server] Background indexing error:", err.message);
106
116
  });
107
117
  }
@@ -110,7 +120,7 @@ async function initialize() {
110
120
  const server = new Server(
111
121
  {
112
122
  name: "smart-coding-mcp",
113
- version: "1.0.0"
123
+ version: packageJson.version
114
124
  },
115
125
  {
116
126
  capabilities: {
package/lib/config.js CHANGED
@@ -57,7 +57,7 @@ const DEFAULT_CONFIG = {
57
57
  maxResults: 5,
58
58
  enableCache: true,
59
59
  cacheDirectory: "./.smart-coding-cache",
60
- watchFiles: true,
60
+ watchFiles: false,
61
61
  verbose: false,
62
62
  embeddingModel: "Xenova/all-MiniLM-L6-v2",
63
63
  semanticWeight: 0.7,
@@ -136,24 +136,80 @@ export async function loadConfig(workspaceDir = null) {
136
136
  console.error(`[Config] Error: ${error.message}`);
137
137
  }
138
138
 
139
- // Apply environment variable overrides (prefix: SMART_CODING_)
139
+ // Apply environment variable overrides (prefix: SMART_CODING_) with validation
140
140
  if (process.env.SMART_CODING_VERBOSE !== undefined) {
141
- config.verbose = process.env.SMART_CODING_VERBOSE === 'true';
141
+ const value = process.env.SMART_CODING_VERBOSE;
142
+ if (value === 'true' || value === 'false') {
143
+ config.verbose = value === 'true';
144
+ }
142
145
  }
146
+
143
147
  if (process.env.SMART_CODING_BATCH_SIZE !== undefined) {
144
- config.batchSize = parseInt(process.env.SMART_CODING_BATCH_SIZE, 10);
148
+ const value = parseInt(process.env.SMART_CODING_BATCH_SIZE, 10);
149
+ if (!isNaN(value) && value > 0 && value <= 1000) {
150
+ config.batchSize = value;
151
+ } else {
152
+ console.error(`[Config] Invalid SMART_CODING_BATCH_SIZE: ${process.env.SMART_CODING_BATCH_SIZE}, using default`);
153
+ }
145
154
  }
155
+
146
156
  if (process.env.SMART_CODING_MAX_FILE_SIZE !== undefined) {
147
- config.maxFileSize = parseInt(process.env.SMART_CODING_MAX_FILE_SIZE, 10);
157
+ const value = parseInt(process.env.SMART_CODING_MAX_FILE_SIZE, 10);
158
+ if (!isNaN(value) && value > 0) {
159
+ config.maxFileSize = value;
160
+ } else {
161
+ console.error(`[Config] Invalid SMART_CODING_MAX_FILE_SIZE: ${process.env.SMART_CODING_MAX_FILE_SIZE}, using default`);
162
+ }
148
163
  }
164
+
149
165
  if (process.env.SMART_CODING_CHUNK_SIZE !== undefined) {
150
- config.chunkSize = parseInt(process.env.SMART_CODING_CHUNK_SIZE, 10);
166
+ const value = parseInt(process.env.SMART_CODING_CHUNK_SIZE, 10);
167
+ if (!isNaN(value) && value > 0 && value <= 100) {
168
+ config.chunkSize = value;
169
+ } else {
170
+ console.error(`[Config] Invalid SMART_CODING_CHUNK_SIZE: ${process.env.SMART_CODING_CHUNK_SIZE}, using default`);
171
+ }
151
172
  }
173
+
152
174
  if (process.env.SMART_CODING_MAX_RESULTS !== undefined) {
153
- config.maxResults = parseInt(process.env.SMART_CODING_MAX_RESULTS, 10);
175
+ const value = parseInt(process.env.SMART_CODING_MAX_RESULTS, 10);
176
+ if (!isNaN(value) && value > 0 && value <= 100) {
177
+ config.maxResults = value;
178
+ } else {
179
+ console.error(`[Config] Invalid SMART_CODING_MAX_RESULTS: ${process.env.SMART_CODING_MAX_RESULTS}, using default`);
180
+ }
154
181
  }
182
+
155
183
  if (process.env.SMART_CODING_SMART_INDEXING !== undefined) {
156
- config.smartIndexing = process.env.SMART_CODING_SMART_INDEXING === 'true';
184
+ const value = process.env.SMART_CODING_SMART_INDEXING;
185
+ if (value === 'true' || value === 'false') {
186
+ config.smartIndexing = value === 'true';
187
+ }
188
+ }
189
+
190
+ if (process.env.SMART_CODING_WATCH_FILES !== undefined) {
191
+ const value = process.env.SMART_CODING_WATCH_FILES;
192
+ if (value === 'true' || value === 'false') {
193
+ config.watchFiles = value === 'true';
194
+ }
195
+ }
196
+
197
+ if (process.env.SMART_CODING_SEMANTIC_WEIGHT !== undefined) {
198
+ const value = parseFloat(process.env.SMART_CODING_SEMANTIC_WEIGHT);
199
+ if (!isNaN(value) && value >= 0 && value <= 1) {
200
+ config.semanticWeight = value;
201
+ } else {
202
+ console.error(`[Config] Invalid SMART_CODING_SEMANTIC_WEIGHT: ${process.env.SMART_CODING_SEMANTIC_WEIGHT}, using default (must be 0-1)`);
203
+ }
204
+ }
205
+
206
+ if (process.env.SMART_CODING_EXACT_MATCH_BOOST !== undefined) {
207
+ const value = parseFloat(process.env.SMART_CODING_EXACT_MATCH_BOOST);
208
+ if (!isNaN(value) && value >= 0) {
209
+ config.exactMatchBoost = value;
210
+ } else {
211
+ console.error(`[Config] Invalid SMART_CODING_EXACT_MATCH_BOOST: ${process.env.SMART_CODING_EXACT_MATCH_BOOST}, using default`);
212
+ }
157
213
  }
158
214
 
159
215
  return config;
package/lib/utils.js CHANGED
@@ -31,14 +31,60 @@ export function smartChunk(content, file, config) {
31
31
 
32
32
  // Language-specific patterns for function/class detection
33
33
  const patterns = {
34
+ // JavaScript/TypeScript
34
35
  js: /^(export\s+)?(async\s+)?(function|class|const|let|var)\s+\w+/,
36
+ jsx: /^(export\s+)?(async\s+)?(function|class|const|let|var)\s+\w+/,
35
37
  ts: /^(export\s+)?(async\s+)?(function|class|const|let|var|interface|type)\s+\w+/,
36
- py: /^(class|def)\s+\w+/,
37
- java: /^(public|private|protected)?\s*(static\s+)?(class|interface|void|int|String|boolean)\s+\w+/,
38
- go: /^func\s+\w+/,
39
- rs: /^(pub\s+)?(fn|struct|enum|trait|impl)\s+\w+/,
38
+ tsx: /^(export\s+)?(async\s+)?(function|class|const|let|var|interface|type)\s+\w+/,
39
+ mjs: /^(export\s+)?(async\s+)?(function|class|const|let|var)\s+\w+/,
40
+ cjs: /^(export\s+)?(async\s+)?(function|class|const|let|var)\s+\w+/,
41
+
42
+ // Python
43
+ py: /^(class|def|async\s+def)\s+\w+/,
44
+ pyw: /^(class|def|async\s+def)\s+\w+/,
45
+
46
+ // Java/Kotlin/Scala
47
+ java: /^(public|private|protected)?\s*(static\s+)?(class|interface|enum|void|int|String|boolean)\s+\w+/,
48
+ kt: /^(class|interface|object|fun|val|var)\s+\w+/,
49
+ kts: /^(class|interface|object|fun|val|var)\s+\w+/,
50
+ scala: /^(class|object|trait|def|val|var)\s+\w+/,
51
+
52
+ // C/C++
53
+ c: /^(struct|enum|union|void|int|char|float|double)\s+\w+/,
54
+ cpp: /^(class|struct|namespace|template|void|int|bool)\s+\w+/,
55
+ cc: /^(class|struct|namespace|template|void|int|bool)\s+\w+/,
56
+ cxx: /^(class|struct|namespace|template|void|int|bool)\s+\w+/,
57
+ h: /^(class|struct|namespace|template|void|int|bool)\s+\w+/,
58
+ hpp: /^(class|struct|namespace|template|void|int|bool)\s+\w+/,
59
+
60
+ // C#
61
+ cs: /^(public|private|protected)?\s*(static\s+)?(class|interface|struct|enum|void|int|string|bool)\s+\w+/,
62
+
63
+ // Go
64
+ go: /^(func|type|const|var)\s+\w+/,
65
+
66
+ // Rust
67
+ rs: /^(pub\s+)?(fn|struct|enum|trait|impl|const|static)\s+\w+/,
68
+
69
+ // PHP
70
+ php: /^(class|interface|trait|function|const)\s+\w+/,
71
+
72
+ // Ruby
73
+ rb: /^(class|module|def)\s+\w+/,
74
+ rake: /^(class|module|def|task)\s+\w+/,
75
+
76
+ // Swift
77
+ swift: /^(class|struct|enum|protocol|func|var|let)\s+\w+/,
78
+
79
+ // R
80
+ r: /^(\w+)\s*<-\s*function/,
81
+ R: /^(\w+)\s*<-\s*function/,
82
+
83
+ // Lua
84
+ lua: /^(function|local\s+function)\s+\w+/,
40
85
  };
41
86
 
87
+
42
88
  const langPattern = patterns[ext.slice(1)] || patterns.js;
43
89
  let currentChunk = [];
44
90
  let chunkStartLine = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-coding-mcp",
3
- "version": "1.2.0",
3
+ "version": "1.2.3",
4
4
  "description": "An extensible MCP server that enhances coding productivity with AI-powered features including semantic code search, intelligent indexing, and more, using local LLMs",
5
5
  "type": "module",
6
6
  "main": "index.js",