specmem-hardwicksoftware 3.7.46 → 3.7.47
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/HOW_TO_USE_SPECMEM_MCP.md +448 -0
- package/dist/mcp/mcpProtocolHandler.js +30 -2
- package/mcp-proxy.cjs +62 -0
- package/package.json +2 -1
- package/specmem/model-config.json +2 -2
- package/specmem/supervisord.conf +1 -1
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
# SpecMem Search Tools - HOW TO USE
|
|
2
|
+
|
|
3
|
+
This document provides a comprehensive guide to using SpecMem's semantic search tools: `find_code_pointers` and `find_memory`. These tools use embeddings to search by meaning rather than keywords.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Introduction](#introduction)
|
|
10
|
+
2. [Query Formulation (CRITICAL)](#query-formulation-critical)
|
|
11
|
+
3. [find_code_pointers - Semantic Code Search](#find_code_pointers---semantic-code-search)
|
|
12
|
+
4. [find_memory - Semantic Memory Search](#find_memory---semantic-memory-search)
|
|
13
|
+
5. [Timeout Behavior](#timeout-behavior)
|
|
14
|
+
6. [Common Mistakes](#common-mistakes)
|
|
15
|
+
7. [Best Practices](#best-practices)
|
|
16
|
+
8. [Troubleshooting](#troubleshooting)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Introduction
|
|
21
|
+
|
|
22
|
+
SpecMem provides two powerful semantic search tools:
|
|
23
|
+
|
|
24
|
+
### find_code_pointers
|
|
25
|
+
- **Purpose**: Search your codebase by meaning, not keywords
|
|
26
|
+
- **What it finds**: Functions, classes, methods, interfaces, and other code definitions
|
|
27
|
+
- **Unique feature**: Shows tracebacks (who imports/calls the code you find)
|
|
28
|
+
- **Best for**: Understanding code architecture, finding implementations, tracing dependencies
|
|
29
|
+
|
|
30
|
+
### find_memory
|
|
31
|
+
- **Purpose**: Search stored memories (past conversations, decisions, context)
|
|
32
|
+
- **What it finds**: Episodic events, semantic facts, procedural knowledge, working memories
|
|
33
|
+
- **Unique feature**: Supports time queries like "yesterday", "last week", specific dates
|
|
34
|
+
- **Best for**: Recall past discussions, find decisions, locate context from previous sessions
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Query Formulation (CRITICAL)
|
|
39
|
+
|
|
40
|
+
The most important factor for getting good results is how you write your query. The two tools have different requirements:
|
|
41
|
+
|
|
42
|
+
### find_code_pointers: Use CODE TERMS
|
|
43
|
+
|
|
44
|
+
**DO write queries using code-related terms:**
|
|
45
|
+
- `admin login auth`
|
|
46
|
+
- `database connection pool`
|
|
47
|
+
- `api handler middleware`
|
|
48
|
+
- `user authentication flow`
|
|
49
|
+
- `json response serializer`
|
|
50
|
+
|
|
51
|
+
**DO NOT write natural language questions:**
|
|
52
|
+
- `"how does admin login work"` - BAD
|
|
53
|
+
- `"where is the database connection defined"` - BAD
|
|
54
|
+
- `"what middleware handles authentication"` - BAD
|
|
55
|
+
|
|
56
|
+
**Why?** find_code_pointers searches for code definitions using embeddings trained on code. Natural language questions don't match the embedding space well.
|
|
57
|
+
|
|
58
|
+
**Query examples by use case:**
|
|
59
|
+
|
|
60
|
+
| Use Case | Good Query | Bad Query |
|
|
61
|
+
|----------|-----------|-----------|
|
|
62
|
+
| Find auth logic | `authentication token validation` | `how does token auth work` |
|
|
63
|
+
| Find DB code | `postgres connection pool` | `where do we connect to database` |
|
|
64
|
+
| Find API code | `rest endpoint handler` | `how are API routes defined` |
|
|
65
|
+
| Find utilities | `string formatting helper` | `what utility functions exist` |
|
|
66
|
+
|
|
67
|
+
### find_memory: Natural Language Works
|
|
68
|
+
|
|
69
|
+
find_memory is more flexible - natural language queries work well:
|
|
70
|
+
- `"discussion about API design"`
|
|
71
|
+
- `"database migration decisions"`
|
|
72
|
+
- `"user feedback on login flow"`
|
|
73
|
+
|
|
74
|
+
Be specific about what you're looking for. Vague queries return vague results.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## find_code_pointers - Semantic Code Search
|
|
79
|
+
|
|
80
|
+
### Basic Usage
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
find_code_pointers({ query: "admin login authentication" })
|
|
84
|
+
find_code_pointers({ query: "database connection pool" })
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Parameter Reference
|
|
88
|
+
|
|
89
|
+
| Parameter | Type | Default | Description |
|
|
90
|
+
|-----------|------|---------|-------------|
|
|
91
|
+
| `query` | string | required | What to search for - use CODE TERMS |
|
|
92
|
+
| `limit` | number | 10 | Maximum results to return |
|
|
93
|
+
| `threshold` | number | 0.25 | Minimum similarity score (0-1). Higher = more strict |
|
|
94
|
+
| `language` | string | - | Filter by language: typescript, javascript, python, go, rust, etc. |
|
|
95
|
+
| `filePattern` | string | - | Filter by file path pattern: `routes/*.ts`, `src/api/**` |
|
|
96
|
+
| `definitionTypes` | array | - | Filter by type: function, method, class, interface, type, enum, variable, constant, constructor |
|
|
97
|
+
| `includeTracebacks` | boolean | true | Show who imports/calls the found code |
|
|
98
|
+
| `galleryMode` | boolean | false | Enable Mini COT analysis for deeper understanding |
|
|
99
|
+
| `zoom` | number | 50 | Detail level: 0=signature only, 50=balanced, 100=full context |
|
|
100
|
+
| `cameraRollMode` | boolean | true | Returns drilldownIDs for drill_down exploration |
|
|
101
|
+
| `zoomLevel` | string | - | Preset zoom: ultra-wide, wide, normal, close, macro |
|
|
102
|
+
| `includeMemoryLinks` | boolean | true | Link code to related memories |
|
|
103
|
+
| `includeRecent` | number | 0 | Force-include N most recently modified files |
|
|
104
|
+
| `keywordFallback` | boolean | true | Fall back to keyword search if semantic returns nothing |
|
|
105
|
+
| `allProjects` | boolean | false | Search ALL projects instead of current |
|
|
106
|
+
|
|
107
|
+
### Zoom Level Presets
|
|
108
|
+
|
|
109
|
+
| Preset | Results | Threshold | Best For |
|
|
110
|
+
|--------|---------|-----------|----------|
|
|
111
|
+
| `ultra-wide` | 50 | 15% | Exploration, unknown codebase |
|
|
112
|
+
| `wide` | 25 | 25% | Broad overview |
|
|
113
|
+
| `normal` | 15 | 40% | Balanced (default feel) |
|
|
114
|
+
| `close` | 10 | 60% | Specific known functionality |
|
|
115
|
+
| `macro` | 5 | 80% | Exact matches only |
|
|
116
|
+
|
|
117
|
+
### Example Queries
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
// Find authentication-related code
|
|
121
|
+
find_code_pointers({ query: "jwt token validation", limit: 10 })
|
|
122
|
+
|
|
123
|
+
// Find database code, TypeScript only
|
|
124
|
+
find_code_pointers({ query: "postgres query builder", language: "typescript" })
|
|
125
|
+
|
|
126
|
+
// Find with tracebacks (who calls this)
|
|
127
|
+
find_code_pointers({ query: "api middleware handler", includeTracebacks: true })
|
|
128
|
+
|
|
129
|
+
// Gallery mode for deeper analysis
|
|
130
|
+
find_code_pointers({ query: "auth flow", galleryMode: true })
|
|
131
|
+
|
|
132
|
+
// Use zoom level preset
|
|
133
|
+
find_code_pointers({ query: "connection pool", zoomLevel: "close" })
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## find_memory - Semantic Memory Search
|
|
139
|
+
|
|
140
|
+
### Basic Usage
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
find_memory({ query: "API design decisions" })
|
|
144
|
+
find_memory({ query: "database migration" })
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Parameter Reference
|
|
148
|
+
|
|
149
|
+
| Parameter | Type | Default | Description |
|
|
150
|
+
|-----------|------|---------|-------------|
|
|
151
|
+
| `query` | string | required | What to search for - natural language works |
|
|
152
|
+
| `limit` | number | 10 | Maximum results to return |
|
|
153
|
+
| `threshold` | number | 0.25 | Minimum similarity score (0-1). Higher = more strict |
|
|
154
|
+
| `memoryTypes` | array | - | Filter: episodic, semantic, procedural, working, consolidated |
|
|
155
|
+
| `tags` | array | - | Filter by tags (OR logic) |
|
|
156
|
+
| `importance` | array | - | Filter: critical, high, medium, low, trivial |
|
|
157
|
+
| `dateRange` | object | - | Filter by date: `{ start: "2024-01-01", end: "2024-12-31" }` |
|
|
158
|
+
| `includeRecent` | number | 0 | Force-include N most recent memories regardless of relevance |
|
|
159
|
+
| `recencyBoost` | boolean | true | Boost recent memories (last hour +20%, last day +10%) |
|
|
160
|
+
| `keywordFallback` | boolean | true | Fall back to keyword search if semantic returns nothing |
|
|
161
|
+
| `role` | string | - | Filter by message role: "user" or "assistant" |
|
|
162
|
+
| `summarize` | boolean | true | Return summarized content (first 500 chars) |
|
|
163
|
+
| `maxContentLength` | number | 500 | Truncate content to this many characters |
|
|
164
|
+
| `galleryMode` | boolean | false | Enable Mini COT analysis |
|
|
165
|
+
| `cameraRollMode` | boolean | true | Returns drilldownIDs for drill_down exploration |
|
|
166
|
+
| `zoomLevel` | string | - | Preset zoom: ultra-wide, wide, normal, close, macro |
|
|
167
|
+
| `projectPath` | string | - | Search specific project path |
|
|
168
|
+
| `allProjects` | boolean | false | Search ALL projects |
|
|
169
|
+
|
|
170
|
+
### Time Queries
|
|
171
|
+
|
|
172
|
+
find_memory supports natural language time expressions:
|
|
173
|
+
- `"yesterday"`
|
|
174
|
+
- `"last week"`
|
|
175
|
+
- `"last month"`
|
|
176
|
+
- `"2024-01-15"`
|
|
177
|
+
- `"past hour"`
|
|
178
|
+
|
|
179
|
+
Use with `dateRange` parameter for precise filtering.
|
|
180
|
+
|
|
181
|
+
### Memory Types
|
|
182
|
+
|
|
183
|
+
| Type | Description |
|
|
184
|
+
|------|-------------|
|
|
185
|
+
| `episodic` | Events, things that happened |
|
|
186
|
+
| `semantic` | Facts, knowledge, learned information |
|
|
187
|
+
| `procedural` | How-to, step-by-step processes |
|
|
188
|
+
| `working` | Temporary/active memory |
|
|
189
|
+
| `consolidated` | Merged/condensed memories |
|
|
190
|
+
|
|
191
|
+
### Example Queries
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
// Basic search
|
|
195
|
+
find_memory({ query: "API design decisions" })
|
|
196
|
+
|
|
197
|
+
// Filter by memory type
|
|
198
|
+
find_memory({ query: "database", memoryTypes: ["episodic", "semantic"] })
|
|
199
|
+
|
|
200
|
+
// Time-based search
|
|
201
|
+
find_memory({ query: "auth", dateRange: { start: "2024-01-01", end: "2024-12-31" } })
|
|
202
|
+
|
|
203
|
+
// Get recent memories regardless of relevance
|
|
204
|
+
find_memory({ query: "anything", includeRecent: 5 })
|
|
205
|
+
|
|
206
|
+
// Full content, no summarization
|
|
207
|
+
find_memory({ query: "important decision", summarize: false })
|
|
208
|
+
|
|
209
|
+
// Cross-project search
|
|
210
|
+
find_memory({ query: "shared utility", allProjects: true })
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Timeout Behavior
|
|
216
|
+
|
|
217
|
+
### Understanding "processing" vs "working"
|
|
218
|
+
|
|
219
|
+
**IMPORTANT**: The embedding server may send `{"status":"processing"}` responses. This status indicates the server is **alive**, NOT that it is actively processing your query.
|
|
220
|
+
|
|
221
|
+
- **"processing" status**: Server is alive and idle - does NOT mean your query is being worked on
|
|
222
|
+
- **Actual working**: The server is generating embeddings or searching
|
|
223
|
+
|
|
224
|
+
### Timeout Configuration
|
|
225
|
+
|
|
226
|
+
Timeouts are controlled by environment variable:
|
|
227
|
+
```bash
|
|
228
|
+
export SPECMEM_EMBEDDING_TIMEOUT=60 # seconds, default
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
For code search specifically:
|
|
232
|
+
```bash
|
|
233
|
+
export SPECMEM_CODE_SEARCH_TIMEOUT=60 # seconds, default
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Timeout Values by Operation
|
|
237
|
+
|
|
238
|
+
| Operation | Default Timeout | Config Variable |
|
|
239
|
+
|-----------|-----------------|-----------------|
|
|
240
|
+
| Embedding generation | 60s | SPECMEM_EMBEDDING_TIMEOUT |
|
|
241
|
+
| DB search | 6x embedding timeout | SPECMEM_EMBEDDING_TIMEOUT |
|
|
242
|
+
| Keyword fallback | 10s | - |
|
|
243
|
+
| Recent files lookup | 5s | - |
|
|
244
|
+
| Tracebacks | 30s | - |
|
|
245
|
+
| Gallery mode | 2x normal | - |
|
|
246
|
+
|
|
247
|
+
### Retry Logic
|
|
248
|
+
|
|
249
|
+
Both tools have built-in retry logic for transient failures:
|
|
250
|
+
- **find_memory**: 2 retries by default (configurable via SPECMEM_FIND_MEMORY_RETRIES)
|
|
251
|
+
- **find_code_pointers**: 2 retries by default
|
|
252
|
+
|
|
253
|
+
Retries handle:
|
|
254
|
+
- Connection timeouts
|
|
255
|
+
- Socket reset errors
|
|
256
|
+
- Resource busy errors
|
|
257
|
+
- Temporary service unavailability
|
|
258
|
+
|
|
259
|
+
### Invalid Query Behavior
|
|
260
|
+
|
|
261
|
+
Queries with wrong input format should timeout quickly with a hint about correct format. If you see timeout errors:
|
|
262
|
+
|
|
263
|
+
1. Check that all required parameters are provided
|
|
264
|
+
2. Verify parameter types are correct
|
|
265
|
+
3. Ensure query string is not empty
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Common Mistakes
|
|
270
|
+
|
|
271
|
+
### Mistake 1: Writing Natural Language Questions for Code Search
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
// WRONG - natural language
|
|
275
|
+
find_code_pointers({ query: "how does the admin login work" })
|
|
276
|
+
|
|
277
|
+
// RIGHT - code terms
|
|
278
|
+
find_code_pointers({ query: "admin login authentication flow" })
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Mistake 2: Using Too High Threshold
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
// WRONG - too strict, returns nothing
|
|
285
|
+
find_code_pointers({ query: "auth", threshold: 0.8 })
|
|
286
|
+
|
|
287
|
+
// RIGHT - balanced threshold
|
|
288
|
+
find_code_pointers({ query: "auth", threshold: 0.25 })
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Mistake 3: Forgetting cameraRollMode Returns IDs
|
|
292
|
+
|
|
293
|
+
When `cameraRollMode: true` (default), results include `drilldownID` values. Use these with `drill_down()` to explore:
|
|
294
|
+
```javascript
|
|
295
|
+
// First search
|
|
296
|
+
const results = find_code_pointers({ query: "auth", cameraRollMode: true })
|
|
297
|
+
|
|
298
|
+
// Then drill down into a specific result
|
|
299
|
+
drill_down({ drilldownID: results[0].drilldownID })
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Mistake 4: Not Using zoomLevel Presets
|
|
303
|
+
|
|
304
|
+
Instead of guessing zoom values, use presets:
|
|
305
|
+
```javascript
|
|
306
|
+
// WRONG - guessing values
|
|
307
|
+
find_code_pointers({ query: "auth", zoom: 75 })
|
|
308
|
+
|
|
309
|
+
// RIGHT - use preset
|
|
310
|
+
find_code_pointers({ query: "auth", zoomLevel: "close" })
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Mistake 5: Not Checking includeRecent
|
|
314
|
+
|
|
315
|
+
When searching unfamiliar codebases, include recent files:
|
|
316
|
+
```javascript
|
|
317
|
+
find_code_pointers({ query: "auth", includeRecent: 10 })
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Mistake 6: Not Using keywordFallback
|
|
321
|
+
|
|
322
|
+
Keyword fallback finds code that semantic search might miss:
|
|
323
|
+
```javascript
|
|
324
|
+
// Should usually keep true (default)
|
|
325
|
+
find_code_pointers({ query: "auth", keywordFallback: true })
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Best Practices
|
|
331
|
+
|
|
332
|
+
### When to Use find_code_pointers
|
|
333
|
+
|
|
334
|
+
1. **Understanding code architecture** - Find how components connect
|
|
335
|
+
2. **Finding implementations** - Locate specific function/class definitions
|
|
336
|
+
3. **Tracing dependencies** - See who imports/calls code (tracebacks)
|
|
337
|
+
4. **Exploring unfamiliar code** - Use with `includeRecent`
|
|
338
|
+
|
|
339
|
+
### When to Use find_memory
|
|
340
|
+
|
|
341
|
+
1. **Recalling past discussions** - Find previous conversations
|
|
342
|
+
2. **Locating decisions** - Search for decisions made earlier
|
|
343
|
+
3. **Cross-session context** - Carry context across sessions
|
|
344
|
+
4. **Time-based queries** - Use "yesterday", "last week"
|
|
345
|
+
|
|
346
|
+
### Parameter Selection Guide
|
|
347
|
+
|
|
348
|
+
| Goal | Recommended Parameters |
|
|
349
|
+
|------|----------------------|
|
|
350
|
+
| Quick exploration | `zoomLevel: "ultra-wide"`, `limit: 50` |
|
|
351
|
+
| Normal search | defaults (threshold: 0.25, limit: 10) |
|
|
352
|
+
| Exact match | `zoomLevel: "macro"`, `threshold: 0.8` |
|
|
353
|
+
| Understand code | `includeTracebacks: true`, `galleryMode: true` |
|
|
354
|
+
| Cross-project | `allProjects: true` |
|
|
355
|
+
| Recent context | `includeRecent: 10`, `recencyBoost: true` |
|
|
356
|
+
|
|
357
|
+
### Combining with Drill-Down
|
|
358
|
+
|
|
359
|
+
Always use `drill_down()` to explore results:
|
|
360
|
+
```javascript
|
|
361
|
+
// 1. Search
|
|
362
|
+
const results = find_code_pointers({ query: "auth" })
|
|
363
|
+
|
|
364
|
+
// 2. Drill into best match
|
|
365
|
+
drill_down({ drilldownID: results[0].drilldownID })
|
|
366
|
+
|
|
367
|
+
// Or for memory
|
|
368
|
+
const memResults = find_memory({ query: "API decisions" })
|
|
369
|
+
drill_down({ drilldownID: memResults[0].drilldownID })
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Troubleshooting
|
|
375
|
+
|
|
376
|
+
### No Results Returned
|
|
377
|
+
|
|
378
|
+
1. **Lower the threshold**:
|
|
379
|
+
```javascript
|
|
380
|
+
find_code_pointers({ query: "auth", threshold: 0.15 })
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
2. **Enable keyword fallback**:
|
|
384
|
+
```javascript
|
|
385
|
+
find_code_pointers({ query: "auth", keywordFallback: true })
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
3. **Check query formulation** - use code terms, not questions
|
|
389
|
+
|
|
390
|
+
### Timeout Errors
|
|
391
|
+
|
|
392
|
+
1. **Increase timeout**:
|
|
393
|
+
```bash
|
|
394
|
+
export SPECMEM_EMBEDDING_TIMEOUT=120
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
2. **Check embedding server status**:
|
|
398
|
+
```javascript
|
|
399
|
+
embedding_status({})
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
3. **Restart embedding server if needed**:
|
|
403
|
+
```javascript
|
|
404
|
+
embedding_stop({})
|
|
405
|
+
embedding_start({})
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Low-Quality Results
|
|
409
|
+
|
|
410
|
+
1. **Use gallery mode for analysis**:
|
|
411
|
+
```javascript
|
|
412
|
+
find_code_pointers({ query: "auth", galleryMode: true })
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
2. **Add tracebacks to understand context**:
|
|
416
|
+
```javascript
|
|
417
|
+
find_code_pointers({ query: "auth", includeTracebacks: true })
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
3. **Include recent files for fresh context**:
|
|
421
|
+
```javascript
|
|
422
|
+
find_code_pointers({ query: "auth", includeRecent: 10 })
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Memory Search Tips
|
|
426
|
+
|
|
427
|
+
1. **Use specific queries** - more context = better results
|
|
428
|
+
2. **Filter by memory type** - narrow down what you're looking for
|
|
429
|
+
3. **Use importance filter** for critical information
|
|
430
|
+
4. **Combine with dateRange** for historical context
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## Summary
|
|
435
|
+
|
|
436
|
+
| Tool | Query Style | Best For |
|
|
437
|
+
|------|-------------|----------|
|
|
438
|
+
| find_code_pointers | CODE TERMS | Code search, architecture understanding |
|
|
439
|
+
| find_memory | Natural language | Past discussions, decisions, context |
|
|
440
|
+
|
|
441
|
+
**Key Takeaways**:
|
|
442
|
+
1. Use CODE TERMS for code search, natural language for memory search
|
|
443
|
+
2. Keep threshold at 0.25 unless you need exact matches
|
|
444
|
+
3. Use zoomLevel presets instead of guessing values
|
|
445
|
+
4. Always use drill_down() to explore results
|
|
446
|
+
5. Enable galleryMode for deeper analysis
|
|
447
|
+
6. Understand that "processing" status doesn't mean your query is being worked on
|
|
448
|
+
7. Use includeRecent when exploring unfamiliar codebases
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Now integrated with LWJEB event bus for tool:execution events
|
|
8
8
|
*/
|
|
9
|
+
import { readFileSync, existsSync } from 'fs';
|
|
10
|
+
import { join, dirname } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
9
12
|
import { logger } from '../utils/logger.js';
|
|
10
13
|
import { getCoordinator } from '../coordination/integration.js';
|
|
11
14
|
// import zod schemas for validation
|
|
@@ -411,8 +414,33 @@ export class MCPProtocolHandler {
|
|
|
411
414
|
};
|
|
412
415
|
}
|
|
413
416
|
}
|
|
414
|
-
// execute the tool
|
|
415
|
-
const
|
|
417
|
+
// execute the tool with timeout - return helpful message instead of hanging
|
|
418
|
+
const TOOL_TIMEOUT_MS = 30000; // 30 second timeout
|
|
419
|
+
|
|
420
|
+
// Load HOW_TO_USE file for timeout responses
|
|
421
|
+
let howToUseContent = null;
|
|
422
|
+
try {
|
|
423
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
424
|
+
const helpPath = join(__dirname, '..', '..', 'HOW_TO_USE_SPECMEM_MCP.md');
|
|
425
|
+
if (existsSync(helpPath)) {
|
|
426
|
+
howToUseContent = readFileSync(helpPath, 'utf-8');
|
|
427
|
+
}
|
|
428
|
+
} catch (e) {
|
|
429
|
+
logger.warn({ error: e.message }, 'Could not load HOW_TO_USE file');
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const result = await Promise.race([
|
|
433
|
+
this.toolRegistry.executeTool(toolName, validatedArgs),
|
|
434
|
+
new Promise((resolve) =>
|
|
435
|
+
setTimeout(() => {
|
|
436
|
+
if (howToUseContent) {
|
|
437
|
+
logger.warn({ toolName }, 'Tool timed out, returning HOW_TO_USE guide');
|
|
438
|
+
resolve(`[TIMEOUT] ${toolName} timed out after ${TOOL_TIMEOUT_MS}ms.\n\nThe embedding service may be slow or your query may need refinement.\n\n---\n\n## SpecMem Search Guide\n\n${howToUseContent}`);
|
|
439
|
+
} else {
|
|
440
|
+
resolve(`[TIMEOUT] ${toolName} timed out after ${TOOL_TIMEOUT_MS}ms. The embedding service may be slow or unavailable. Try: 1) Check if embedding server is running 2) Use simpler search terms 3) Try find_memory or find_code_pointers with a more specific query`);
|
|
441
|
+
}
|
|
442
|
+
}, TOOL_TIMEOUT_MS))
|
|
443
|
+
]);
|
|
416
444
|
const duration = Date.now() - startTime;
|
|
417
445
|
logger.debug({ toolName, duration, callCount: this.callCount }, 'tool call handled');
|
|
418
446
|
// Emit tool execution complete event via LWJEB
|
package/mcp-proxy.cjs
CHANGED
|
@@ -20,6 +20,19 @@ const MAX_RESTART_DELAY = 10000; // 10s max backoff
|
|
|
20
20
|
const INITIAL_RESTART_DELAY = 500; // 500ms first retry
|
|
21
21
|
const MAX_QUEUE_SIZE = 200;
|
|
22
22
|
const HEARTBEAT_INTERVAL = 30000; // 30s keepalive pings
|
|
23
|
+
const TOOL_CALL_TIMEOUT = 25000; // 25s timeout for tool calls
|
|
24
|
+
|
|
25
|
+
// Load HOW_TO_USE guide for timeout responses
|
|
26
|
+
let HOW_TO_USE_CONTENT = null;
|
|
27
|
+
try {
|
|
28
|
+
const helpPath = path.join(__dirname, 'HOW_TO_USE_SPECMEM_MCP.md');
|
|
29
|
+
if (fs.existsSync(helpPath)) {
|
|
30
|
+
HOW_TO_USE_CONTENT = fs.readFileSync(helpPath, 'utf-8');
|
|
31
|
+
log(`Loaded HOW_TO_USE guide (${HOW_TO_USE_CONTENT.length} chars)`);
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
log(`Could not load HOW_TO_USE guide: ${e.message}`);
|
|
35
|
+
}
|
|
23
36
|
|
|
24
37
|
// State
|
|
25
38
|
let child = null;
|
|
@@ -34,6 +47,7 @@ let shuttingDown = false;
|
|
|
34
47
|
let heartbeatTimer = null;
|
|
35
48
|
let childStdoutBuffer = '';
|
|
36
49
|
let stdinBuffer = '';
|
|
50
|
+
let pendingToolCalls = new Map(); // Track tool calls with timeouts
|
|
37
51
|
|
|
38
52
|
function log(msg) {
|
|
39
53
|
try {
|
|
@@ -165,6 +179,46 @@ function sendToServer(msg) {
|
|
|
165
179
|
|
|
166
180
|
try {
|
|
167
181
|
child.stdin.write(serializeMessage(msg));
|
|
182
|
+
|
|
183
|
+
// Track tool calls for timeout
|
|
184
|
+
if (msg.method === 'tools/call' && msg.id) {
|
|
185
|
+
const toolName = msg.params?.name || 'unknown';
|
|
186
|
+
log(`Tool call ${msg.id}: ${toolName} - setting ${TOOL_CALL_TIMEOUT}ms timeout`);
|
|
187
|
+
|
|
188
|
+
const timeout = setTimeout(() => {
|
|
189
|
+
if (pendingToolCalls.has(msg.id)) {
|
|
190
|
+
log(`Tool call ${msg.id} (${toolName}) timed out after ${TOOL_CALL_TIMEOUT}ms`);
|
|
191
|
+
|
|
192
|
+
// Return HOW_TO_USE guide instead of error
|
|
193
|
+
let helpText = `Tool '${toolName}' timed out after ${TOOL_CALL_TIMEOUT}ms. The embedding service may be slow or your query may need refinement.`;
|
|
194
|
+
if (HOW_TO_USE_CONTENT) {
|
|
195
|
+
helpText = `[TIMEOUT] ${toolName} timed out.\n\nThe embedding service may be slow or your query may need refinement.\n\n---\n\n## SpecMem Search Guide\n\n${HOW_TO_USE_CONTENT}`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Send response with help text (as result, not error, so Claude can read it)
|
|
199
|
+
const response = {
|
|
200
|
+
jsonrpc: '2.0',
|
|
201
|
+
id: msg.id,
|
|
202
|
+
result: {
|
|
203
|
+
content: [
|
|
204
|
+
{
|
|
205
|
+
type: 'text',
|
|
206
|
+
text: helpText
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
sendToClient(response);
|
|
212
|
+
pendingToolCalls.delete(msg.id);
|
|
213
|
+
|
|
214
|
+
// Restart the server to clear any stuck state
|
|
215
|
+
log(`Restarting server after tool timeout`);
|
|
216
|
+
scheduleRestart();
|
|
217
|
+
}
|
|
218
|
+
}, TOOL_CALL_TIMEOUT);
|
|
219
|
+
|
|
220
|
+
pendingToolCalls.set(msg.id, { toolName, timeout });
|
|
221
|
+
}
|
|
168
222
|
} catch (e) {
|
|
169
223
|
log(`child stdin write error: ${e.message}`);
|
|
170
224
|
pendingQueue.push(msg);
|
|
@@ -247,6 +301,14 @@ function spawnServer() {
|
|
|
247
301
|
|
|
248
302
|
// Forward everything else to Claude
|
|
249
303
|
sendToClient(msg);
|
|
304
|
+
|
|
305
|
+
// Check if this is a tool response - clear the timeout
|
|
306
|
+
if (msg.id && pendingToolCalls.has(msg.id)) {
|
|
307
|
+
const callInfo = pendingToolCalls.get(msg.id);
|
|
308
|
+
if (callInfo.timeout) clearTimeout(callInfo.timeout);
|
|
309
|
+
pendingToolCalls.delete(msg.id);
|
|
310
|
+
log(`Tool call ${msg.id} completed, cleared timeout`);
|
|
311
|
+
}
|
|
250
312
|
}
|
|
251
313
|
});
|
|
252
314
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specmem-hardwicksoftware",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.47",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Your Claude Code sessions don't have to start from scratch anymore — SpecMem gives your AI real memory. It won't forget your conversations, your code, or your architecture decisions between sessions. That's the whole point. Semantic code indexing that actually works: TypeScript, JavaScript, Python, Go, Rust, Java, Kotlin, C, C++, HTML and more. It doesn't just track functions — it gets classes, methods, fields, constants, enums, macros, imports, structs, the whole codebase graph. There's chat memory too, powered by pgvector embeddings. You've also got token compression, team coordination, multi-agent comms, and file watching built in. 74+ MCP tools. Runs on PostgreSQL + Docker. It's kind of a big deal. justcalljon.pro",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -171,6 +171,7 @@
|
|
|
171
171
|
"embedding-sandbox/models/minisbd/",
|
|
172
172
|
"embedding-sandbox/*.txt",
|
|
173
173
|
"legal/",
|
|
174
|
+
"HOW_TO_USE_SPECMEM_MCP.md",
|
|
174
175
|
"svg-sections/",
|
|
175
176
|
"specmem/config.json",
|
|
176
177
|
"specmem/model-config.json",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"resources": {
|
|
37
37
|
"cpuMin": 10,
|
|
38
38
|
"cpuMax": 50,
|
|
39
|
-
"cpuCoreMin":
|
|
39
|
+
"cpuCoreMin": 3,
|
|
40
40
|
"cpuCoreMax": 5,
|
|
41
41
|
"ramMinMb": 6000,
|
|
42
42
|
"ramMaxMb": 19500,
|
|
43
|
-
"updatedAt": "2026-03-
|
|
43
|
+
"updatedAt": "2026-03-10T03:31:53.267Z"
|
|
44
44
|
},
|
|
45
45
|
"resourcePool": {
|
|
46
46
|
"embedding": {
|
package/specmem/supervisord.conf
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
; ============================================
|
|
2
2
|
; SPECMEM BRAIN CONTAINER - DYNAMIC SUPERVISORD CONFIG
|
|
3
|
-
; Generated by specmem-init at 2026-03-10T03:
|
|
3
|
+
; Generated by specmem-init at 2026-03-10T03:30:28.641Z
|
|
4
4
|
; Thread counts from model-config.json resourcePool
|
|
5
5
|
; ============================================
|
|
6
6
|
|