refactor: rename search-server to mcp-server throughout codebase

- Updated all documentation references from search-server to mcp-server
- Removed legacy search-server.cjs file
- Updated debug log messages to use [mcp-server] prefix
- Updated build output references in docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-12-09 01:06:43 -05:00
parent 105b4ca70d
commit 4321add69c
9 changed files with 92 additions and 750 deletions
@@ -397,7 +397,7 @@ Claude translates to appropriate API call.
### For Developers
**Deprecated**: MCP search server (`src/servers/search-server.ts`)
**Renamed**: MCP server (formerly `search-server.ts`, now `src/servers/mcp-server.ts`)
- Source file kept for reference
- No longer built or registered
- MCP configuration removed from `plugin/.mcp.json`
+1 -1
View File
@@ -82,7 +82,7 @@ ${CLAUDE_PLUGIN_ROOT}/
│ ├── summary-hook.js # Summary generation hook
│ ├── cleanup-hook.js # Session cleanup hook
│ ├── worker-service.cjs # Worker service (CJS)
│ └── search-server.cjs # MCP search server (CJS)
│ └── mcp-server.cjs # MCP search server (CJS)
└── ui/
└── viewer.html # Web viewer UI bundle
```
+3 -3
View File
@@ -33,7 +33,7 @@ The build process uses esbuild to compile TypeScript:
1. Compiles TypeScript to JavaScript
2. Creates standalone executables for each hook in `plugin/scripts/`
3. Bundles MCP search server to `plugin/scripts/search-server.cjs`
3. Bundles MCP search server to `plugin/scripts/mcp-server.cjs`
4. Bundles worker service to `plugin/scripts/worker-service.cjs`
5. Bundles web viewer UI to `plugin/ui/viewer.html`
@@ -41,7 +41,7 @@ The build process uses esbuild to compile TypeScript:
- Hook executables: `*-hook.js` (ESM format)
- Smart installer: `smart-install.js` (ESM format)
- Worker service: `worker-service.cjs` (CJS format)
- Search server: `search-server.cjs` (CJS format)
- MCP server: `mcp-server.cjs` (CJS format)
- Viewer UI: `viewer.html` (self-contained HTML bundle)
### Build Scripts
@@ -342,7 +342,7 @@ npm test
### Adding MCP Search Tools
1. Add tool definition in `src/servers/search-server.ts`:
1. Add tool definition in `src/servers/mcp-server.ts`:
```typescript
server.setRequestHandler(CallToolRequestSchema, async (request) => {
+1 -1
View File
@@ -542,7 +542,7 @@ The skill includes comprehensive diagnostics, automated repair sequences, and de
2. Verify search server is built:
```bash
ls -l plugin/scripts/search-server.js
ls -l plugin/scripts/mcp-server.cjs
```
3. Rebuild if needed:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10 -10
View File
@@ -49,7 +49,7 @@ async function callWorkerAPI(
endpoint: string,
params: Record<string, any>
): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {
silentDebug('[search-server] → Worker API', { endpoint, params });
silentDebug('[mcp-server] → Worker API', { endpoint, params });
try {
const searchParams = new URLSearchParams();
@@ -71,12 +71,12 @@ async function callWorkerAPI(
const data = await response.json() as { content: Array<{ type: 'text'; text: string }>; isError?: boolean };
silentDebug('[search-server] ← Worker API success', { endpoint });
silentDebug('[mcp-server] ← Worker API success', { endpoint });
// Worker returns { content: [...] } format directly
return data;
} catch (error: any) {
silentDebug('[search-server] ← Worker API error', { endpoint, error: error.message });
silentDebug('[mcp-server] ← Worker API error', { endpoint, error: error.message });
return {
content: [{
type: 'text' as const,
@@ -411,7 +411,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
// Cleanup function
async function cleanup() {
silentDebug('[search-server] Shutting down...');
silentDebug('[mcp-server] Shutting down...');
process.exit(0);
}
@@ -424,22 +424,22 @@ async function main() {
// Start the MCP server
const transport = new StdioServerTransport();
await server.connect(transport);
silentDebug('[search-server] Claude-mem search server started');
silentDebug('[mcp-server] Claude-mem search server started');
// Check Worker availability in background
setTimeout(async () => {
const workerAvailable = await verifyWorkerConnection();
if (!workerAvailable) {
silentDebug('[search-server] WARNING: Worker not available at', WORKER_BASE_URL);
silentDebug('[search-server] Tools will fail until Worker is started');
silentDebug('[search-server] Start Worker with: npm run worker:restart');
silentDebug('[mcp-server] WARNING: Worker not available at', WORKER_BASE_URL);
silentDebug('[mcp-server] Tools will fail until Worker is started');
silentDebug('[mcp-server] Start Worker with: npm run worker:restart');
} else {
silentDebug('[search-server] Worker available at', WORKER_BASE_URL);
silentDebug('[mcp-server] Worker available at', WORKER_BASE_URL);
}
}, 0);
}
main().catch((error) => {
silentDebug('[search-server] Fatal error:', error);
silentDebug('[mcp-server] Fatal error:', error);
process.exit(1);
});
+58 -58
View File
@@ -97,7 +97,7 @@ export class SearchManager {
// PATH 1: FILTER-ONLY (no query text) - Skip Chroma/FTS5, use direct SQLite filtering
// This path enables date filtering which Chroma cannot do (requires direct SQLite access)
if (!query) {
silentDebug(`[search-server] Filter-only query (no query text), using direct SQLite filtering (enables date filters)`);
silentDebug(`[mcp-server] Filter-only query (no query text), using direct SQLite filtering (enables date filters)`);
const obsOptions = { ...options, type: obs_type, concepts, files };
if (searchObservations) {
observations = this.sessionSearch.searchObservations(undefined, obsOptions);
@@ -113,7 +113,7 @@ export class SearchManager {
else if (this.chromaSync) {
let chromaSucceeded = false;
try {
silentDebug(`[search-server] Using ChromaDB semantic search (type filter: ${type || 'all'})`);
silentDebug(`[mcp-server] Using ChromaDB semantic search (type filter: ${type || 'all'})`);
// Build Chroma where filter for doc_type
let whereFilter: Record<string, any> | undefined;
@@ -128,7 +128,7 @@ export class SearchManager {
// Step 1: Chroma semantic search with optional type filter
const chromaResults = await this.queryChroma(query, 100, whereFilter);
chromaSucceeded = true; // Chroma didn't throw error
silentDebug(`[search-server] ChromaDB returned ${chromaResults.ids.length} semantic matches`);
silentDebug(`[mcp-server] ChromaDB returned ${chromaResults.ids.length} semantic matches`);
if (chromaResults.ids.length > 0) {
// Step 2: Filter by recency (90 days)
@@ -139,7 +139,7 @@ export class SearchManager {
isRecent: meta && meta.created_at_epoch > ninetyDaysAgo
})).filter(item => item.isRecent);
silentDebug(`[search-server] ${recentMetadata.length} results within 90-day window`);
silentDebug(`[mcp-server] ${recentMetadata.length} results within 90-day window`);
// Step 3: Categorize IDs by document type
const obsIds: number[] = [];
@@ -157,7 +157,7 @@ export class SearchManager {
}
}
silentDebug(`[search-server] Categorized: ${obsIds.length} obs, ${sessionIds.length} sessions, ${promptIds.length} prompts`);
silentDebug(`[mcp-server] Categorized: ${obsIds.length} obs, ${sessionIds.length} sessions, ${promptIds.length} prompts`);
// Step 4: Hydrate from SQLite with additional filters
if (obsIds.length > 0) {
@@ -172,14 +172,14 @@ export class SearchManager {
prompts = this.sessionStore.getUserPromptsByIds(promptIds, { orderBy: 'date_desc', limit: options.limit });
}
silentDebug(`[search-server] Hydrated ${observations.length} obs, ${sessions.length} sessions, ${prompts.length} prompts from SQLite`);
silentDebug(`[mcp-server] Hydrated ${observations.length} obs, ${sessions.length} sessions, ${prompts.length} prompts from SQLite`);
} else {
// Chroma returned 0 results - this is the correct answer, don't fall back to FTS5
silentDebug(`[search-server] ChromaDB found no matches (this is final - NOT falling back to FTS5)`);
silentDebug(`[mcp-server] ChromaDB found no matches (this is final - NOT falling back to FTS5)`);
}
} catch (chromaError: any) {
silentDebug('[search-server] ChromaDB failed - returning empty results (FTS5 fallback removed):', chromaError.message);
silentDebug('[search-server] Install UVX/Python to enable vector search: https://docs.astral.sh/uv/getting-started/installation/');
silentDebug('[mcp-server] ChromaDB failed - returning empty results (FTS5 fallback removed):', chromaError.message);
silentDebug('[mcp-server] Install UVX/Python to enable vector search: https://docs.astral.sh/uv/getting-started/installation/');
// Return empty results - no fallback
observations = [];
sessions = [];
@@ -188,8 +188,8 @@ export class SearchManager {
}
// ChromaDB not initialized - return empty results (no fallback)
else {
silentDebug(`[search-server] ChromaDB not initialized - returning empty results (FTS5 fallback removed)`);
silentDebug(`[search-server] Install UVX/Python to enable vector search: https://docs.astral.sh/uv/getting-started/installation/`);
silentDebug(`[mcp-server] ChromaDB not initialized - returning empty results (FTS5 fallback removed)`);
silentDebug(`[mcp-server] Install UVX/Python to enable vector search: https://docs.astral.sh/uv/getting-started/installation/`);
observations = [];
sessions = [];
prompts = [];
@@ -312,9 +312,9 @@ export class SearchManager {
if (this.chromaSync) {
try {
silentDebug('[search-server] Using hybrid semantic search for timeline query');
silentDebug('[mcp-server] Using hybrid semantic search for timeline query');
const chromaResults = await this.queryChroma(query, 100);
silentDebug(`[search-server] Chroma returned ${chromaResults?.ids?.length ?? 0} semantic matches`);
silentDebug(`[mcp-server] Chroma returned ${chromaResults?.ids?.length ?? 0} semantic matches`);
if (chromaResults?.ids && chromaResults.ids.length > 0) {
const ninetyDaysAgo = Date.now() - (90 * 24 * 60 * 60 * 1000);
@@ -328,7 +328,7 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
silentDebug('[mcp-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
}
}
@@ -345,7 +345,7 @@ export class SearchManager {
const topResult = results[0];
anchorId = topResult.id;
anchorEpoch = topResult.created_at_epoch;
silentDebug(`[search-server] Query mode: Using observation #${topResult.id} as timeline anchor`);
silentDebug(`[mcp-server] Query mode: Using observation #${topResult.id} as timeline anchor`);
timelineData = this.sessionStore.getTimelineAroundObservation(topResult.id, topResult.created_at_epoch, depth_before, depth_after, project);
}
// MODE 2: Anchor-based timeline
@@ -621,7 +621,7 @@ export class SearchManager {
try {
if (query) {
// Semantic search filtered to decision type
silentDebug('[search-server] Using Chroma semantic search with type=decision filter');
silentDebug('[mcp-server] Using Chroma semantic search with type=decision filter');
const chromaResults = await this.queryChroma(query, Math.min((filters.limit || 20) * 2, 100), { type: 'decision' });
const obsIds = chromaResults.ids;
@@ -632,7 +632,7 @@ export class SearchManager {
}
} else {
// No query: get all decisions, rank by "decision" keyword
silentDebug('[search-server] Using metadata-first + semantic ranking for decisions');
silentDebug('[mcp-server] Using metadata-first + semantic ranking for decisions');
const metadataResults = this.sessionSearch.findByType('decision', filters);
if (metadataResults.length > 0) {
@@ -653,7 +653,7 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma search failed, using SQLite fallback:', chromaError.message);
silentDebug('[mcp-server] Chroma search failed, using SQLite fallback:', chromaError.message);
}
}
@@ -709,7 +709,7 @@ export class SearchManager {
// Search for change-type observations and change-related concepts
if (this.chromaSync) {
try {
silentDebug('[search-server] Using hybrid search for change-related observations');
silentDebug('[mcp-server] Using hybrid search for change-related observations');
// Get all observations with type="change" or concepts containing change
const typeResults = this.sessionSearch.findByType('change', filters);
@@ -737,7 +737,7 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma ranking failed, using SQLite order:', chromaError.message);
silentDebug('[mcp-server] Chroma ranking failed, using SQLite order:', chromaError.message);
}
}
@@ -807,7 +807,7 @@ export class SearchManager {
// Search for how-it-works concept observations
if (this.chromaSync) {
try {
silentDebug('[search-server] Using metadata-first + semantic ranking for how-it-works');
silentDebug('[mcp-server] Using metadata-first + semantic ranking for how-it-works');
const metadataResults = this.sessionSearch.findByConcept('how-it-works', filters);
if (metadataResults.length > 0) {
@@ -827,7 +827,7 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma ranking failed, using SQLite order:', chromaError.message);
silentDebug('[mcp-server] Chroma ranking failed, using SQLite order:', chromaError.message);
}
}
@@ -883,11 +883,11 @@ export class SearchManager {
// Vector-first search via ChromaDB
if (this.chromaSync) {
try {
silentDebug('[search-server] Using hybrid semantic search (Chroma + SQLite)');
silentDebug('[mcp-server] Using hybrid semantic search (Chroma + SQLite)');
// Step 1: Chroma semantic search (top 100)
const chromaResults = await this.queryChroma(query, 100);
silentDebug(`[search-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
silentDebug(`[mcp-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
if (chromaResults.ids.length > 0) {
// Step 2: Filter by recency (90 days)
@@ -897,17 +897,17 @@ export class SearchManager {
return meta && meta.created_at_epoch > ninetyDaysAgo;
});
silentDebug(`[search-server] ${recentIds.length} results within 90-day window`);
silentDebug(`[mcp-server] ${recentIds.length} results within 90-day window`);
// Step 3: Hydrate from SQLite in temporal order
if (recentIds.length > 0) {
const limit = options.limit || 20;
results = this.sessionStore.getObservationsByIds(recentIds, { orderBy: 'date_desc', limit });
silentDebug(`[search-server] Hydrated ${results.length} observations from SQLite`);
silentDebug(`[mcp-server] Hydrated ${results.length} observations from SQLite`);
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
silentDebug('[mcp-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
}
}
@@ -960,11 +960,11 @@ export class SearchManager {
// Vector-first search via ChromaDB
if (this.chromaSync) {
try {
silentDebug('[search-server] Using hybrid semantic search for sessions');
silentDebug('[mcp-server] Using hybrid semantic search for sessions');
// Step 1: Chroma semantic search (top 100)
const chromaResults = await this.queryChroma(query, 100, { doc_type: 'session_summary' });
silentDebug(`[search-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
silentDebug(`[mcp-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
if (chromaResults.ids.length > 0) {
// Step 2: Filter by recency (90 days)
@@ -974,17 +974,17 @@ export class SearchManager {
return meta && meta.created_at_epoch > ninetyDaysAgo;
});
silentDebug(`[search-server] ${recentIds.length} results within 90-day window`);
silentDebug(`[mcp-server] ${recentIds.length} results within 90-day window`);
// Step 3: Hydrate from SQLite in temporal order
if (recentIds.length > 0) {
const limit = options.limit || 20;
results = this.sessionStore.getSessionSummariesByIds(recentIds, { orderBy: 'date_desc', limit });
silentDebug(`[search-server] Hydrated ${results.length} sessions from SQLite`);
silentDebug(`[mcp-server] Hydrated ${results.length} sessions from SQLite`);
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
silentDebug('[mcp-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
}
}
@@ -1037,11 +1037,11 @@ export class SearchManager {
// Vector-first search via ChromaDB
if (this.chromaSync) {
try {
silentDebug('[search-server] Using hybrid semantic search for user prompts');
silentDebug('[mcp-server] Using hybrid semantic search for user prompts');
// Step 1: Chroma semantic search (top 100)
const chromaResults = await this.queryChroma(query, 100, { doc_type: 'user_prompt' });
silentDebug(`[search-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
silentDebug(`[mcp-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
if (chromaResults.ids.length > 0) {
// Step 2: Filter by recency (90 days)
@@ -1051,17 +1051,17 @@ export class SearchManager {
return meta && meta.created_at_epoch > ninetyDaysAgo;
});
silentDebug(`[search-server] ${recentIds.length} results within 90-day window`);
silentDebug(`[mcp-server] ${recentIds.length} results within 90-day window`);
// Step 3: Hydrate from SQLite in temporal order
if (recentIds.length > 0) {
const limit = options.limit || 20;
results = this.sessionStore.getUserPromptsByIds(recentIds, { orderBy: 'date_desc', limit });
silentDebug(`[search-server] Hydrated ${results.length} user prompts from SQLite`);
silentDebug(`[mcp-server] Hydrated ${results.length} user prompts from SQLite`);
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
silentDebug('[mcp-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
}
}
@@ -1114,11 +1114,11 @@ export class SearchManager {
// Metadata-first, semantic-enhanced search
if (this.chromaSync) {
try {
silentDebug('[search-server] Using metadata-first + semantic ranking for concept search');
silentDebug('[mcp-server] Using metadata-first + semantic ranking for concept search');
// Step 1: SQLite metadata filter (get all IDs with this concept)
const metadataResults = this.sessionSearch.findByConcept(concept, filters);
silentDebug(`[search-server] Found ${metadataResults.length} observations with concept "${concept}"`);
silentDebug(`[mcp-server] Found ${metadataResults.length} observations with concept "${concept}"`);
if (metadataResults.length > 0) {
// Step 2: Chroma semantic ranking (rank by relevance to concept)
@@ -1133,7 +1133,7 @@ export class SearchManager {
}
}
silentDebug(`[search-server] Chroma ranked ${rankedIds.length} results by semantic relevance`);
silentDebug(`[mcp-server] Chroma ranked ${rankedIds.length} results by semantic relevance`);
// Step 3: Hydrate in semantic rank order
if (rankedIds.length > 0) {
@@ -1143,14 +1143,14 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma ranking failed, using SQLite order:', chromaError.message);
silentDebug('[mcp-server] Chroma ranking failed, using SQLite order:', chromaError.message);
// Fall through to SQLite fallback
}
}
// Fall back to SQLite-only if Chroma unavailable or failed
if (results.length === 0) {
silentDebug('[search-server] Using SQLite-only concept search');
silentDebug('[mcp-server] Using SQLite-only concept search');
results = this.sessionSearch.findByConcept(concept, filters);
}
@@ -1204,11 +1204,11 @@ export class SearchManager {
// Metadata-first, semantic-enhanced search for observations
if (this.chromaSync) {
try {
silentDebug('[search-server] Using metadata-first + semantic ranking for file search');
silentDebug('[mcp-server] Using metadata-first + semantic ranking for file search');
// Step 1: SQLite metadata filter (get all results with this file)
const metadataResults = this.sessionSearch.findByFile(filePath, filters);
silentDebug(`[search-server] Found ${metadataResults.observations.length} observations, ${metadataResults.sessions.length} sessions for file "${filePath}"`);
silentDebug(`[mcp-server] Found ${metadataResults.observations.length} observations, ${metadataResults.sessions.length} sessions for file "${filePath}"`);
// Sessions: Keep as-is (already summarized, no semantic ranking needed)
sessions = metadataResults.sessions;
@@ -1227,7 +1227,7 @@ export class SearchManager {
}
}
silentDebug(`[search-server] Chroma ranked ${rankedIds.length} observations by semantic relevance`);
silentDebug(`[mcp-server] Chroma ranked ${rankedIds.length} observations by semantic relevance`);
// Step 3: Hydrate in semantic rank order
if (rankedIds.length > 0) {
@@ -1237,14 +1237,14 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma ranking failed, using SQLite order:', chromaError.message);
silentDebug('[mcp-server] Chroma ranking failed, using SQLite order:', chromaError.message);
// Fall through to SQLite fallback
}
}
// Fall back to SQLite-only if Chroma unavailable or failed
if (observations.length === 0 && sessions.length === 0) {
silentDebug('[search-server] Using SQLite-only file search');
silentDebug('[mcp-server] Using SQLite-only file search');
const results = this.sessionSearch.findByFile(filePath, filters);
observations = results.observations;
sessions = results.sessions;
@@ -1323,11 +1323,11 @@ export class SearchManager {
// Metadata-first, semantic-enhanced search
if (this.chromaSync) {
try {
silentDebug('[search-server] Using metadata-first + semantic ranking for type search');
silentDebug('[mcp-server] Using metadata-first + semantic ranking for type search');
// Step 1: SQLite metadata filter (get all IDs with this type)
const metadataResults = this.sessionSearch.findByType(type, filters);
silentDebug(`[search-server] Found ${metadataResults.length} observations with type "${typeStr}"`);
silentDebug(`[mcp-server] Found ${metadataResults.length} observations with type "${typeStr}"`);
if (metadataResults.length > 0) {
// Step 2: Chroma semantic ranking (rank by relevance to type)
@@ -1342,7 +1342,7 @@ export class SearchManager {
}
}
silentDebug(`[search-server] Chroma ranked ${rankedIds.length} results by semantic relevance`);
silentDebug(`[mcp-server] Chroma ranked ${rankedIds.length} results by semantic relevance`);
// Step 3: Hydrate in semantic rank order
if (rankedIds.length > 0) {
@@ -1352,14 +1352,14 @@ export class SearchManager {
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma ranking failed, using SQLite order:', chromaError.message);
silentDebug('[mcp-server] Chroma ranking failed, using SQLite order:', chromaError.message);
// Fall through to SQLite fallback
}
}
// Fall back to SQLite-only if Chroma unavailable or failed
if (results.length === 0) {
silentDebug('[search-server] Using SQLite-only type search');
silentDebug('[mcp-server] Using SQLite-only type search');
results = this.sessionSearch.findByType(type, filters);
}
@@ -1815,9 +1815,9 @@ export class SearchManager {
// Use hybrid search if available
if (this.chromaSync) {
try {
silentDebug('[search-server] Using hybrid semantic search for timeline query');
silentDebug('[mcp-server] Using hybrid semantic search for timeline query');
const chromaResults = await this.queryChroma(query, 100);
silentDebug(`[search-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
silentDebug(`[mcp-server] Chroma returned ${chromaResults.ids.length} semantic matches`);
if (chromaResults.ids.length > 0) {
// Filter by recency (90 days)
@@ -1827,15 +1827,15 @@ export class SearchManager {
return meta && meta.created_at_epoch > ninetyDaysAgo;
});
silentDebug(`[search-server] ${recentIds.length} results within 90-day window`);
silentDebug(`[mcp-server] ${recentIds.length} results within 90-day window`);
if (recentIds.length > 0) {
results = this.sessionStore.getObservationsByIds(recentIds, { orderBy: 'date_desc', limit: mode === 'auto' ? 1 : limit });
silentDebug(`[search-server] Hydrated ${results.length} observations from SQLite`);
silentDebug(`[mcp-server] Hydrated ${results.length} observations from SQLite`);
}
}
} catch (chromaError: any) {
silentDebug('[search-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
silentDebug('[mcp-server] Chroma query failed - no results (FTS5 fallback removed):', chromaError.message);
}
}
@@ -1886,7 +1886,7 @@ export class SearchManager {
} else {
// Auto mode: Use top result as timeline anchor
const topResult = results[0];
silentDebug(`[search-server] Auto mode: Using observation #${topResult.id} as timeline anchor`);
silentDebug(`[mcp-server] Auto mode: Using observation #${topResult.id} as timeline anchor`);
// Get timeline around this observation
const timelineData = this.sessionStore.getTimelineAroundObservation(