smart-coding-mcp 1.4.0 → 2.0.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 CHANGED
@@ -5,16 +5,18 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
6
  [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-green.svg)](https://nodejs.org/)
7
7
 
8
- An extensible Model Context Protocol (MCP) server that provides intelligent semantic code search for AI assistants. Built with local AI models (RAG), inspired by Cursor's semantic search research.
8
+ An extensible Model Context Protocol (MCP) server that provides intelligent semantic code search for AI assistants. Built with local AI models using Matryoshka Representation Learning (MRL) for flexible embedding dimensions (64-768d), with runtime workspace switching and comprehensive status reporting.
9
9
 
10
10
  ### Available Tools
11
11
 
12
- | Tool | Description | Example |
13
- | ---------------------- | ------------------------------------------------- | ---------------------------------------------- |
14
- | `semantic_search` | Find code by meaning, not just keywords | `"Where do we validate user input?"` |
15
- | `index_codebase` | Manually trigger reindexing | Use after major refactoring or branch switches |
16
- | `clear_cache` | Reset the embeddings cache | Useful when cache becomes corrupted |
17
- | `d_check_last_version` | Get latest version of any package (20 ecosystems) | `"express"`, `"npm:react"`, `"pip:requests"` |
12
+ | Tool | Description | Example |
13
+ | ---------------------- | ------------------------------------------------- | ----------------------------------------------- |
14
+ | `semantic_search` | Find code by meaning, not just keywords | `"Where do we validate user input?"` |
15
+ | `index_codebase` | Manually trigger reindexing | Use after major refactoring or branch switches |
16
+ | `clear_cache` | Reset the embeddings cache | Useful when cache becomes corrupted |
17
+ | `d_check_last_version` | Get latest version of any package (20 ecosystems) | `"express"`, `"npm:react"`, `"pip:requests"` |
18
+ | `e_set_workspace` | Change project path at runtime | Switch to different project without restart |
19
+ | `f_get_status` | Get server info: version, index status, config | Check indexing progress, model info, cache size |
18
20
 
19
21
  ## What This Does
20
22
 
@@ -72,92 +74,80 @@ Add to your MCP configuration file. The location depends on your IDE and OS:
72
74
 
73
75
  Add the server configuration to the `mcpServers` object in your config file:
74
76
 
75
- ### Option 1: Auto-Detection (Recommended)
76
-
77
- By default, the server indexes the directory it is started in. Most clients start MCP servers in the workspace root automatically:
77
+ ### Option 1: Absolute Path (Recommended)
78
78
 
79
79
  ```json
80
80
  {
81
81
  "mcpServers": {
82
82
  "smart-coding-mcp": {
83
83
  "command": "smart-coding-mcp",
84
- "args": []
84
+ "args": ["--workspace", "/absolute/path/to/your/project"]
85
85
  }
86
86
  }
87
87
  }
88
88
  ```
89
89
 
90
- For explicit workspace control, use the `${workspaceFolder}` variable:
90
+ ### Option 2: Multi-Project Support
91
91
 
92
92
  ```json
93
93
  {
94
94
  "mcpServers": {
95
- "smart-coding-mcp": {
95
+ "smart-coding-mcp-frontend": {
96
96
  "command": "smart-coding-mcp",
97
- "args": ["--workspace", "${workspaceFolder}"]
97
+ "args": ["--workspace", "/path/to/frontend"]
98
+ },
99
+ "smart-coding-mcp-backend": {
100
+ "command": "smart-coding-mcp",
101
+ "args": ["--workspace", "/path/to/backend"]
98
102
  }
99
103
  }
100
104
  }
101
105
  ```
102
106
 
103
- **Client Compatibility:**
107
+ ### Option 3: Auto-Detection (May Not Work)
104
108
 
105
- | Client | Supports `${workspaceFolder}` |
106
- | ---------------- | ----------------------------- |
107
- | VS Code | Yes |
108
- | Cursor (Cascade) | Yes |
109
- | Antigravity | Yes |
110
- | Claude Desktop | No (use Option 2) |
111
-
112
- ### Option 2: Absolute Path (Claude Desktop)
109
+ > ⚠️ **Warning:** Most MCP clients (including Antigravity and Claude Desktop) do NOT support `${workspaceFolder}` variable expansion. The server will exit with an error if the variable is not expanded.
113
110
 
114
- For clients that don't support dynamic variables:
111
+ For clients that support dynamic variables (VS Code, Cursor):
115
112
 
116
113
  ```json
117
114
  {
118
115
  "mcpServers": {
119
116
  "smart-coding-mcp": {
120
117
  "command": "smart-coding-mcp",
121
- "args": ["--workspace", "/absolute/path/to/your/project"]
118
+ "args": ["--workspace", "${workspaceFolder}"]
122
119
  }
123
120
  }
124
121
  }
125
122
  ```
126
123
 
127
- ### Option 3: Multi-Project Support
128
-
129
- ```json
130
- {
131
- "mcpServers": {
132
- "smart-coding-mcp-frontend": {
133
- "command": "smart-coding-mcp",
134
- "args": ["--workspace", "/path/to/frontend"]
135
- },
136
- "smart-coding-mcp-backend": {
137
- "command": "smart-coding-mcp",
138
- "args": ["--workspace", "/path/to/backend"]
139
- }
140
- }
141
- }
142
- ```
124
+ | Client | Supports `${workspaceFolder}` |
125
+ | ---------------- | ----------------------------- |
126
+ | VS Code | Yes |
127
+ | Cursor (Cascade) | Yes |
128
+ | Antigravity | No ❌ |
129
+ | Claude Desktop | No ❌ |
143
130
 
144
131
  ## Environment Variables
145
132
 
146
133
  Override configuration settings via environment variables in your MCP config:
147
134
 
148
- | Variable | Type | Default | Description |
149
- | -------------------------------- | ------- | ------------------------- | ------------------------------------- |
150
- | `SMART_CODING_VERBOSE` | boolean | `false` | Enable detailed logging |
151
- | `SMART_CODING_BATCH_SIZE` | number | `100` | Files to process in parallel |
152
- | `SMART_CODING_MAX_FILE_SIZE` | number | `1048576` | Max file size in bytes (1MB) |
153
- | `SMART_CODING_CHUNK_SIZE` | number | `25` | Lines of code per chunk |
154
- | `SMART_CODING_MAX_RESULTS` | number | `5` | Max search results |
155
- | `SMART_CODING_SMART_INDEXING` | boolean | `true` | Enable smart project detection |
156
- | `SMART_CODING_WATCH_FILES` | boolean | `false` | Enable file watching for auto-reindex |
157
- | `SMART_CODING_SEMANTIC_WEIGHT` | number | `0.7` | Weight for semantic similarity (0-1) |
158
- | `SMART_CODING_EXACT_MATCH_BOOST` | number | `1.5` | Boost for exact text matches |
159
- | `SMART_CODING_EMBEDDING_MODEL` | string | `Xenova/all-MiniLM-L6-v2` | AI embedding model to use |
160
- | `SMART_CODING_WORKER_THREADS` | string | `auto` | Worker threads (`auto` or 1-32) |
135
+ | Variable | Type | Default | Description |
136
+ | ---------------------------------- | ------- | -------------------------------- | ------------------------------------------ |
137
+ | `SMART_CODING_VERBOSE` | boolean | `false` | Enable detailed logging |
138
+ | `SMART_CODING_BATCH_SIZE` | number | `100` | Files to process in parallel |
139
+ | `SMART_CODING_MAX_FILE_SIZE` | number | `1048576` | Max file size in bytes (1MB) |
140
+ | `SMART_CODING_CHUNK_SIZE` | number | `25` | Lines of code per chunk |
141
+ | `SMART_CODING_MAX_RESULTS` | number | `5` | Max search results |
142
+ | `SMART_CODING_SMART_INDEXING` | boolean | `true` | Enable smart project detection |
143
+ | `SMART_CODING_WATCH_FILES` | boolean | `false` | Enable file watching for auto-reindex |
144
+ | `SMART_CODING_SEMANTIC_WEIGHT` | number | `0.7` | Weight for semantic similarity (0-1) |
145
+ | `SMART_CODING_EXACT_MATCH_BOOST` | number | `1.5` | Boost for exact text matches |
146
+ | `SMART_CODING_EMBEDDING_MODEL` | string | `nomic-ai/nomic-embed-text-v1.5` | AI embedding model to use |
147
+ | `SMART_CODING_EMBEDDING_DIMENSION` | number | `256` | MRL dimension (64, 128, 256, 512, 768) |
148
+ | `SMART_CODING_DEVICE` | string | `cpu` | Inference device (`cpu`, `webgpu`, `auto`) |
149
+ | `SMART_CODING_CHUNKING_MODE` | string | `smart` | Code chunking (`smart`, `ast`, `line`) |
150
+ | `SMART_CODING_WORKER_THREADS` | string | `auto` | Worker threads (`auto` or 1-32) |
161
151
 
162
152
  **Example with environment variables:**
163
153
 
@@ -181,16 +171,72 @@ Override configuration settings via environment variables in your MCP config:
181
171
 
182
172
  ## How It Works
183
173
 
184
- The server indexes your code in four steps:
174
+ ```mermaid
175
+ flowchart TB
176
+ subgraph IDE["IDE / AI Assistant"]
177
+ Agent["AI Agent<br/>(Claude, GPT, Gemini)"]
178
+ end
179
+
180
+ subgraph MCP["Smart Coding MCP Server"]
181
+ direction TB
182
+ Protocol["Model Context Protocol<br/>JSON-RPC over stdio"]
183
+ Tools["MCP Tools<br/>semantic_search | index_codebase | set_workspace | get_status"]
184
+
185
+ subgraph Indexing["Indexing Pipeline"]
186
+ Discovery["File Discovery<br/>glob patterns + smart ignore"]
187
+ Chunking["Code Chunking<br/>Smart (regex) / AST (Tree-sitter)"]
188
+ Embedding["AI Embedding<br/>transformers.js + ONNX Runtime"]
189
+ end
190
+
191
+ subgraph AI["AI Model"]
192
+ Model["nomic-embed-text-v1.5<br/>Matryoshka Representation Learning"]
193
+ Dimensions["Flexible Dimensions<br/>64 | 128 | 256 | 512 | 768"]
194
+ Normalize["Layer Norm → Slice → L2 Normalize"]
195
+ end
196
+
197
+ subgraph Search["Search"]
198
+ QueryEmbed["Query → Vector"]
199
+ Cosine["Cosine Similarity"]
200
+ Hybrid["Hybrid Search<br/>Semantic + Exact Match Boost"]
201
+ end
202
+ end
203
+
204
+ subgraph Storage["Cache"]
205
+ Vectors["Vector Store<br/>embeddings.json"]
206
+ Hashes["File Hashes<br/>Incremental updates"]
207
+ end
208
+
209
+ Agent <-->|"MCP Protocol"| Protocol
210
+ Protocol --> Tools
211
+
212
+ Tools --> Discovery
213
+ Discovery --> Chunking
214
+ Chunking --> Embedding
215
+ Embedding --> Model
216
+ Model --> Dimensions
217
+ Dimensions --> Normalize
218
+ Normalize --> Vectors
219
+
220
+ Tools --> QueryEmbed
221
+ QueryEmbed --> Model
222
+ Cosine --> Hybrid
223
+ Vectors --> Cosine
224
+ Hybrid --> Agent
225
+ ```
226
+
227
+ ### Tech Stack
185
228
 
186
- 1. **Discovery**: Scans your project for source files
187
- 2. **Chunking**: Breaks code into meaningful pieces (respecting function boundaries)
188
- 3. **Embedding**: Converts each chunk to a vector using a local AI model
189
- 4. **Storage**: Saves embeddings to `.smart-coding-cache/` for fast startup
229
+ | Component | Technology |
230
+ | ------------- | ------------------------------------- |
231
+ | **Protocol** | Model Context Protocol (JSON-RPC) |
232
+ | **AI Model** | nomic-embed-text-v1.5 (MRL) |
233
+ | **Inference** | transformers.js + ONNX Runtime |
234
+ | **Chunking** | Smart regex / Tree-sitter AST |
235
+ | **Search** | Cosine similarity + exact match boost |
190
236
 
191
- When you search, your query is converted to the same vector format and compared against all code chunks using cosine similarity. The most relevant matches are returned.
237
+ ### Search Flow
192
238
 
193
- ![How It Works](how-its-works.png)
239
+ Query Vector embedding → Cosine similarity → Ranked results
194
240
 
195
241
  ## Examples
196
242
 
@@ -229,11 +275,18 @@ Finds all try/catch blocks and error handling patterns.
229
275
 
230
276
  ## Technical Details
231
277
 
232
- **Embedding Model**: all-MiniLM-L6-v2 via transformers.js
278
+ **Embedding Model**: nomic-embed-text-v1.5 via transformers.js v3
279
+
280
+ - Matryoshka Representation Learning (MRL) for flexible dimensions
281
+ - Configurable output: 64, 128, 256, 512, or 768 dimensions
282
+ - Longer context (8192 tokens vs 256 for MiniLM)
283
+ - Better code understanding through specialized training
284
+ - WebGPU support for up to 100x faster inference (when available)
285
+
286
+ **Legacy Model**: all-MiniLM-L6-v2 (fallback)
233
287
 
234
- - Fast inference (CPU-friendly)
235
- - Small model size (~100MB)
236
- - Good accuracy for code search
288
+ - Fast inference, small footprint (~100MB)
289
+ - Fixed 384-dimensional output
237
290
 
238
291
  **Vector Similarity**: Cosine similarity
239
292
 
package/config.json CHANGED
@@ -60,7 +60,10 @@
60
60
  "cacheDirectory": "./.smart-coding-cache",
61
61
  "watchFiles": false,
62
62
  "verbose": false,
63
- "embeddingModel": "Xenova/all-MiniLM-L6-v2",
63
+ "embeddingModel": "nomic-ai/nomic-embed-text-v1.5",
64
+ "embeddingDimension": 256,
65
+ "device": "auto",
66
+ "chunkingMode": "smart",
64
67
  "semanticWeight": 0.7,
65
68
  "exactMatchBoost": 1.5,
66
69
  "workerThreads": "auto"
@@ -8,14 +8,14 @@ export class VersionChecker {
8
8
  /**
9
9
  * Creates a new VersionChecker instance.
10
10
  * @param {Object} config - Configuration object
11
- * @param {number} [config.versionCheckTimeout=5000] - Timeout for API requests in ms
11
+ * @param {number} [config.versionCheckTimeout=10000] - Timeout for API requests in ms
12
12
  * @param {number} [config.versionCacheTTL=300000] - Cache TTL in ms (default: 5 minutes)
13
13
  * @param {number} [config.retryAttempts=1] - Number of retry attempts for failed requests
14
14
  * @param {number} [config.retryDelay=500] - Delay between retries in ms
15
15
  */
16
16
  constructor(config) {
17
17
  this.config = config;
18
- this.timeout = config.versionCheckTimeout || 5000;
18
+ this.timeout = config.versionCheckTimeout || 10000; // 10 seconds for slow APIs
19
19
  this.cacheTTL = config.versionCacheTTL || 300000; // 5 minutes
20
20
  this.retryAttempts = config.retryAttempts ?? 1;
21
21
  this.retryDelay = config.retryDelay || 500;
@@ -154,7 +154,8 @@ export class VersionChecker {
154
154
  // Check for Maven patterns last (generic colon for group:artifact or explicit mvn:)
155
155
  if (packageName.startsWith("mvn:") || packageName.includes(":")) return "maven";
156
156
 
157
- return null;
157
+ // Default to npm for unprefixed package names (most common use case)
158
+ return "npm";
158
159
  }
159
160
 
160
161
  /**
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Get Status Feature
3
+ *
4
+ * MCP tool to return comprehensive status information about the server.
5
+ * Useful for agents to understand current state and configuration.
6
+ */
7
+
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+ import { createRequire } from 'module';
11
+
12
+ const require = createRequire(import.meta.url);
13
+ const packageJson = require('../package.json');
14
+
15
+ /**
16
+ * Get tool definition for MCP registration
17
+ */
18
+ export function getToolDefinition(config) {
19
+ return {
20
+ name: "f_get_status",
21
+ description: "Get comprehensive status information about the Smart Coding MCP server. Returns version, workspace path, model configuration, indexing status, and cache information. Useful for understanding the current state of the semantic search system.",
22
+ inputSchema: {
23
+ type: "object",
24
+ properties: {},
25
+ required: []
26
+ }
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Status Reporter class
32
+ */
33
+ export class StatusReporter {
34
+ constructor(config, cache, indexer, embedder) {
35
+ this.config = config;
36
+ this.cache = cache;
37
+ this.indexer = indexer;
38
+ this.embedder = embedder;
39
+ this.startTime = Date.now();
40
+ }
41
+
42
+ /**
43
+ * Get comprehensive status
44
+ */
45
+ async getStatus() {
46
+ const vectorStore = this.cache?.getVectorStore() || [];
47
+
48
+ // Get unique files from vector store
49
+ const uniqueFiles = new Set(vectorStore.map(v => v.file));
50
+
51
+ // Get cache size
52
+ let cacheSizeBytes = 0;
53
+ try {
54
+ const cachePath = path.join(this.config.cacheDirectory, 'embeddings.json');
55
+ const stats = await fs.stat(cachePath);
56
+ cacheSizeBytes = stats.size;
57
+ } catch {
58
+ // Cache file doesn't exist yet
59
+ }
60
+
61
+ // Determine index status
62
+ let indexStatus = 'empty';
63
+ if (this.indexer?.isIndexing) {
64
+ indexStatus = 'indexing';
65
+ } else if (vectorStore.length > 0) {
66
+ indexStatus = 'ready';
67
+ }
68
+
69
+ return {
70
+ version: packageJson.version,
71
+ uptime: Math.floor((Date.now() - this.startTime) / 1000),
72
+
73
+ workspace: {
74
+ path: this.config.searchDirectory,
75
+ cacheDirectory: this.config.cacheDirectory
76
+ },
77
+
78
+ model: {
79
+ name: this.embedder?.modelName || this.config.embeddingModel,
80
+ dimension: this.embedder?.dimension || this.config.embeddingDimension,
81
+ device: this.embedder?.device || this.config.device
82
+ },
83
+
84
+ index: {
85
+ status: indexStatus,
86
+ filesIndexed: uniqueFiles.size,
87
+ chunksCount: vectorStore.length,
88
+ chunkingMode: this.config.chunkingMode
89
+ },
90
+
91
+ cache: {
92
+ enabled: this.config.enableCache,
93
+ path: this.config.cacheDirectory,
94
+ sizeBytes: cacheSizeBytes,
95
+ sizeFormatted: formatBytes(cacheSizeBytes)
96
+ },
97
+
98
+ config: {
99
+ maxResults: this.config.maxResults,
100
+ chunkSize: this.config.chunkSize,
101
+ semanticWeight: this.config.semanticWeight,
102
+ exactMatchBoost: this.config.exactMatchBoost,
103
+ workerThreads: this.config.workerThreads
104
+ }
105
+ };
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Format bytes to human readable
111
+ */
112
+ function formatBytes(bytes) {
113
+ if (bytes === 0) return '0 B';
114
+ const k = 1024;
115
+ const sizes = ['B', 'KB', 'MB', 'GB'];
116
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
117
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
118
+ }
119
+
120
+ /**
121
+ * Handle MCP tool call
122
+ */
123
+ export async function handleToolCall(request, instance) {
124
+ const status = await instance.getStatus();
125
+
126
+ return {
127
+ content: [{
128
+ type: "text",
129
+ text: JSON.stringify(status, null, 2)
130
+ }]
131
+ };
132
+ }
@@ -25,6 +25,13 @@ export class CodebaseIndexer {
25
25
  * Initialize worker thread pool for parallel embedding
26
26
  */
27
27
  async initializeWorkers() {
28
+ // Force single-threaded mode for nomic models (transformers.js v3 worker thread issue)
29
+ const isNomicModel = this.config.embeddingModel?.includes('nomic');
30
+ if (isNomicModel) {
31
+ console.error("[Indexer] Single-threaded mode (nomic model - workers disabled for stability)");
32
+ return;
33
+ }
34
+
28
35
  const numWorkers = this.config.workerThreads === "auto"
29
36
  ? Math.max(1, os.cpus().length - 1)
30
37
  : (this.config.workerThreads || 1);
@@ -48,6 +55,7 @@ export class CodebaseIndexer {
48
55
  const worker = new Worker(workerPath, {
49
56
  workerData: {
50
57
  embeddingModel: this.config.embeddingModel,
58
+ embeddingDimension: this.config.embeddingDimension,
51
59
  verbose: this.config.verbose
52
60
  }
53
61
  });
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Set Workspace Feature
3
+ *
4
+ * MCP tool to change the project workspace path at runtime.
5
+ * Useful when agent detects it's in a different directory.
6
+ */
7
+
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+
11
+ /**
12
+ * Get tool definition for MCP registration
13
+ */
14
+ export function getToolDefinition(config) {
15
+ return {
16
+ name: "e_set_workspace",
17
+ description: "Change the project workspace path at runtime. Use this when you detect the current workspace is incorrect or you need to switch to a different project directory. Creates cache folder automatically and optionally re-indexes the new workspace.",
18
+ inputSchema: {
19
+ type: "object",
20
+ properties: {
21
+ path: {
22
+ type: "string",
23
+ description: "Absolute path to the new workspace directory"
24
+ },
25
+ clearCache: {
26
+ type: "boolean",
27
+ description: "Whether to clear existing cache before switching (default: false)"
28
+ },
29
+ reindex: {
30
+ type: "boolean",
31
+ description: "Whether to trigger re-indexing after switching (default: true)"
32
+ }
33
+ },
34
+ required: ["path"]
35
+ }
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Workspace Manager class
41
+ */
42
+ export class WorkspaceManager {
43
+ constructor(config, cache, indexer) {
44
+ this.config = config;
45
+ this.cache = cache;
46
+ this.indexer = indexer;
47
+ }
48
+
49
+ /**
50
+ * Set new workspace path
51
+ */
52
+ async setWorkspace(newPath, options = {}) {
53
+ const { clearCache = false, reindex = true } = options;
54
+
55
+ // Validate path
56
+ try {
57
+ const stats = await fs.stat(newPath);
58
+ if (!stats.isDirectory()) {
59
+ return {
60
+ success: false,
61
+ error: `Path is not a directory: ${newPath}`
62
+ };
63
+ }
64
+ } catch (err) {
65
+ return {
66
+ success: false,
67
+ error: `Path does not exist: ${newPath}`
68
+ };
69
+ }
70
+
71
+ const oldPath = this.config.searchDirectory;
72
+
73
+ // Update config
74
+ this.config.searchDirectory = newPath;
75
+
76
+ // Update cache directory
77
+ const newCacheDir = path.join(newPath, '.smart-coding-cache');
78
+ this.config.cacheDirectory = newCacheDir;
79
+
80
+ // Ensure cache directory exists
81
+ try {
82
+ await fs.mkdir(newCacheDir, { recursive: true });
83
+ } catch (err) {
84
+ // Ignore if already exists
85
+ }
86
+
87
+ // Clear cache if requested
88
+ if (clearCache && this.cache) {
89
+ this.cache.setVectorStore([]);
90
+ this.cache.fileHashes = new Map();
91
+ console.error(`[Workspace] Cache cleared for new workspace`);
92
+ }
93
+
94
+ // Update cache path and reload
95
+ if (this.cache) {
96
+ this.cache.config = this.config;
97
+ await this.cache.load();
98
+ }
99
+
100
+ // Update indexer config
101
+ if (this.indexer) {
102
+ this.indexer.config = this.config;
103
+ }
104
+
105
+ console.error(`[Workspace] Changed from ${oldPath} to ${newPath}`);
106
+
107
+ // Trigger re-indexing if requested
108
+ let indexResult = null;
109
+ if (reindex && this.indexer) {
110
+ console.error(`[Workspace] Starting re-indexing...`);
111
+ try {
112
+ indexResult = await this.indexer.indexAll(clearCache);
113
+ } catch (err) {
114
+ console.error(`[Workspace] Re-indexing error: ${err.message}`);
115
+ }
116
+ }
117
+
118
+ return {
119
+ success: true,
120
+ oldPath,
121
+ newPath,
122
+ cacheDirectory: newCacheDir,
123
+ reindexed: reindex,
124
+ indexResult
125
+ };
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Handle MCP tool call
131
+ */
132
+ export async function handleToolCall(request, instance) {
133
+ const { path: newPath, clearCache, reindex } = request.params.arguments || {};
134
+
135
+ if (!newPath) {
136
+ return {
137
+ content: [{
138
+ type: "text",
139
+ text: JSON.stringify({
140
+ success: false,
141
+ error: "Missing required parameter: path"
142
+ }, null, 2)
143
+ }]
144
+ };
145
+ }
146
+
147
+ const result = await instance.setWorkspace(newPath, { clearCache, reindex });
148
+
149
+ return {
150
+ content: [{
151
+ type: "text",
152
+ text: JSON.stringify(result, null, 2)
153
+ }]
154
+ };
155
+ }
package/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
5
- import { pipeline } from "@xenova/transformers";
6
5
  import fs from "fs/promises";
7
6
  import { createRequire } from "module";
8
7
 
@@ -12,6 +11,7 @@ const packageJson = require("./package.json");
12
11
 
13
12
  import { loadConfig } from "./lib/config.js";
14
13
  import { EmbeddingsCache } from "./lib/cache.js";
14
+ import { createEmbedder } from "./lib/mrl-embedder.js";
15
15
  import { CodebaseIndexer } from "./features/index-codebase.js";
16
16
  import { HybridSearch } from "./features/hybrid-search.js";
17
17
 
@@ -19,6 +19,8 @@ import * as IndexCodebaseFeature from "./features/index-codebase.js";
19
19
  import * as HybridSearchFeature from "./features/hybrid-search.js";
20
20
  import * as ClearCacheFeature from "./features/clear-cache.js";
21
21
  import * as CheckLastVersionFeature from "./features/check-last-version.js";
22
+ import * as SetWorkspaceFeature from "./features/set-workspace.js";
23
+ import * as GetStatusFeature from "./features/get-status.js";
22
24
 
23
25
  // Parse workspace from command line arguments
24
26
  const args = process.argv.slice(2);
@@ -78,6 +80,16 @@ const features = [
78
80
  module: CheckLastVersionFeature,
79
81
  instance: null,
80
82
  handler: CheckLastVersionFeature.handleToolCall
83
+ },
84
+ {
85
+ module: SetWorkspaceFeature,
86
+ instance: null,
87
+ handler: SetWorkspaceFeature.handleToolCall
88
+ },
89
+ {
90
+ module: GetStatusFeature,
91
+ instance: null,
92
+ handler: GetStatusFeature.handleToolCall
81
93
  }
82
94
  ];
83
95
 
@@ -94,9 +106,10 @@ async function initialize() {
94
106
  process.exit(1);
95
107
  }
96
108
 
97
- // Load AI model
109
+ // Load AI model using MRL embedder factory
98
110
  console.error("[Server] Loading AI embedding model (this may take time on first run)...");
99
- embedder = await pipeline("feature-extraction", config.embeddingModel);
111
+ embedder = await createEmbedder(config);
112
+ console.error(`[Server] Model: ${embedder.modelName} (${embedder.dimension}d, device: ${embedder.device})`);
100
113
 
101
114
  // Initialize cache
102
115
  cache = new EmbeddingsCache(config);
@@ -113,6 +126,12 @@ async function initialize() {
113
126
  features[1].instance = indexer;
114
127
  features[2].instance = cacheClearer;
115
128
  features[3].instance = versionChecker;
129
+
130
+ // Initialize new tools
131
+ const workspaceManager = new SetWorkspaceFeature.WorkspaceManager(config, cache, indexer);
132
+ const statusReporter = new GetStatusFeature.StatusReporter(config, cache, indexer, embedder);
133
+ features[4].instance = workspaceManager;
134
+ features[5].instance = statusReporter;
116
135
 
117
136
  // Start indexing in background (non-blocking)
118
137
  console.error("[Server] Starting background indexing...");