ai-mind-map 1.6.1 → 1.7.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/dist/change-tracker/change-log.js +123 -123
- package/dist/change-tracker/watcher.d.ts.map +1 -1
- package/dist/change-tracker/watcher.js +1 -0
- package/dist/change-tracker/watcher.js.map +1 -1
- package/dist/cli.js +83 -83
- package/dist/cli.js.map +1 -1
- package/dist/context/compressor.js +3 -3
- package/dist/context/compressor.js.map +1 -1
- package/dist/context/progressive-disclosure.js +4 -4
- package/dist/context/progressive-disclosure.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +168 -143
- package/dist/index.js.map +1 -1
- package/dist/install.js +114 -114
- package/dist/install.js.map +1 -1
- package/dist/knowledge-graph/changelog.js +62 -62
- package/dist/knowledge-graph/dead-code.js +31 -31
- package/dist/knowledge-graph/graph.d.ts +5 -0
- package/dist/knowledge-graph/graph.d.ts.map +1 -1
- package/dist/knowledge-graph/graph.js +214 -202
- package/dist/knowledge-graph/graph.js.map +1 -1
- package/dist/knowledge-graph/indexer.d.ts +9 -0
- package/dist/knowledge-graph/indexer.d.ts.map +1 -1
- package/dist/knowledge-graph/indexer.js +339 -289
- package/dist/knowledge-graph/indexer.js.map +1 -1
- package/dist/knowledge-graph/semantic-search.js +50 -50
- package/dist/memory/decision-log.d.ts.map +1 -1
- package/dist/memory/decision-log.js +72 -61
- package/dist/memory/decision-log.js.map +1 -1
- package/dist/memory/persistent-memory.d.ts.map +1 -1
- package/dist/memory/persistent-memory.js +77 -70
- package/dist/memory/persistent-memory.js.map +1 -1
- package/dist/memory/session-memory.js +54 -54
- package/dist/memory/shared-sync.d.ts.map +1 -1
- package/dist/memory/shared-sync.js +6 -2
- package/dist/memory/shared-sync.js.map +1 -1
- package/dist/tools/context-tools.js +2 -2
- package/dist/tools/context-tools.js.map +1 -1
- package/dist/tools/debug-tools.js +9 -9
- package/dist/tools/debug-tools.js.map +1 -1
- package/dist/tools/evolving-tools.js +3 -3
- package/dist/tools/evolving-tools.js.map +1 -1
- package/dist/tools/flow-tools.js +29 -29
- package/dist/tools/flow-tools.js.map +1 -1
- package/dist/tools/session-tools.js +2 -2
- package/dist/tools/session-tools.js.map +1 -1
- package/dist/tools/snapshot-tools.js +24 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* AI Mind Map
|
|
3
|
+
* AI Mind Map — MCP Server Entry Point
|
|
4
4
|
*
|
|
5
5
|
* Creates the MCP server with stdio transport, registers all tools,
|
|
6
6
|
* initialises ALL real subsystems (knowledge graph, change tracker,
|
|
@@ -16,27 +16,27 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
16
16
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
17
17
|
import Database from 'better-sqlite3';
|
|
18
18
|
import { loadConfig, parseCliArgs } from './config.js';
|
|
19
|
-
//
|
|
19
|
+
// ── Knowledge Graph ───────────────────────────────────────────
|
|
20
20
|
import { KnowledgeGraph } from './knowledge-graph/graph.js';
|
|
21
21
|
// Note: parser.ts exports functions (parseFile, parseFiles, etc.), not a class
|
|
22
22
|
import { Indexer } from './knowledge-graph/indexer.js';
|
|
23
23
|
import { PageRankEngine } from './knowledge-graph/pagerank.js';
|
|
24
|
-
//
|
|
24
|
+
// ── Change Tracker ────────────────────────────────────────────
|
|
25
25
|
import { FileWatcher } from './change-tracker/watcher.js';
|
|
26
26
|
import { DiffEngine } from './change-tracker/diff-engine.js';
|
|
27
27
|
import { ChangeLog } from './change-tracker/change-log.js';
|
|
28
|
-
//
|
|
28
|
+
// ── Memory ────────────────────────────────────────────────────
|
|
29
29
|
import { SessionMemory } from './memory/session-memory.js';
|
|
30
30
|
import { PersistentMemory } from './memory/persistent-memory.js';
|
|
31
31
|
import { DecisionLog } from './memory/decision-log.js';
|
|
32
32
|
import { syncSharedContext } from './memory/shared-sync.js';
|
|
33
|
-
//
|
|
33
|
+
// ── Context Engine ────────────────────────────────────────────
|
|
34
34
|
// compressor.ts exports functions: compress, detectContentType
|
|
35
35
|
import { compress as compressContent } from './context/compressor.js';
|
|
36
36
|
// progressive-disclosure.ts exports function: buildContextPackage
|
|
37
37
|
import { buildContextPackage } from './context/progressive-disclosure.js';
|
|
38
38
|
import { estimateTokens } from './utils/token-counter.js';
|
|
39
|
-
//
|
|
39
|
+
// ── Tools ─────────────────────────────────────────────────────
|
|
40
40
|
import { registerGraphTools } from './tools/graph-tools.js';
|
|
41
41
|
import { registerChangeTools } from './tools/change-tools.js';
|
|
42
42
|
import { registerMemoryTools } from './tools/memory-tools.js';
|
|
@@ -53,7 +53,7 @@ import { ChangelogEngine } from './knowledge-graph/changelog.js';
|
|
|
53
53
|
import { registerSessionTools } from './tools/session-tools.js';
|
|
54
54
|
import { registerDigestTools } from './tools/digest-tools.js';
|
|
55
55
|
// ============================================================
|
|
56
|
-
// Logger
|
|
56
|
+
// Logger — writes to stderr so MCP stdio is uncontaminated
|
|
57
57
|
// ============================================================
|
|
58
58
|
const LOG_LEVELS = {
|
|
59
59
|
debug: 0,
|
|
@@ -78,18 +78,18 @@ function log(level, message, ...extra) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
// ============================================================
|
|
81
|
-
// Adapters
|
|
81
|
+
// Adapters — Bridge real implementations to tool interfaces
|
|
82
82
|
// ============================================================
|
|
83
83
|
/**
|
|
84
84
|
* Creates an adapter that satisfies IKnowledgeGraph from the real
|
|
85
85
|
* KnowledgeGraph and PageRankEngine classes.
|
|
86
86
|
*
|
|
87
87
|
* Key API mappings:
|
|
88
|
-
* - graph.search(query, limit)
|
|
89
|
-
* - graph.getProjectOverview()
|
|
90
|
-
* - graph.findCallers(nodeId) / graph.findCallees(nodeId)
|
|
91
|
-
* - graph.getNodesByName(name)
|
|
92
|
-
* - graph.getFileStructure(filePath)
|
|
88
|
+
* - graph.search(query, limit) — FTS5 search, no type filter param
|
|
89
|
+
* - graph.getProjectOverview() — returns Map<string, GraphNode[]>, no args
|
|
90
|
+
* - graph.findCallers(nodeId) / graph.findCallees(nodeId) — single nodeId arg
|
|
91
|
+
* - graph.getNodesByName(name) — returns GraphNode[]
|
|
92
|
+
* - graph.getFileStructure(filePath) — returns GraphNode[]
|
|
93
93
|
*/
|
|
94
94
|
function createGraphAdapter(graph, pagerank) {
|
|
95
95
|
return {
|
|
@@ -248,10 +248,10 @@ function createGraphAdapter(graph, pagerank) {
|
|
|
248
248
|
* DiffEngine and ChangeLog classes.
|
|
249
249
|
*
|
|
250
250
|
* Key API mappings:
|
|
251
|
-
* - changeLog.getLatestSession()
|
|
252
|
-
* - changeLog.queryChanges(options)
|
|
253
|
-
* - changeLog.generateSessionSummary(sessionId)
|
|
254
|
-
* - changeLog.recordChange(change)
|
|
251
|
+
* - changeLog.getLatestSession() — returns ChangeSession | null
|
|
252
|
+
* - changeLog.queryChanges(options) — options has `since` (timestamp), not `afterTimestamp`
|
|
253
|
+
* - changeLog.generateSessionSummary(sessionId) — returns string
|
|
254
|
+
* - changeLog.recordChange(change) — records a FileChange
|
|
255
255
|
*/
|
|
256
256
|
function createChangeAdapter(diffEngine, changeLog, graph) {
|
|
257
257
|
return {
|
|
@@ -383,13 +383,13 @@ function createChangeAdapter(diffEngine, changeLog, graph) {
|
|
|
383
383
|
* DecisionLog, and SessionMemory.
|
|
384
384
|
*
|
|
385
385
|
* Key API mappings:
|
|
386
|
-
* - persistentMemory.queryMemories(query)
|
|
387
|
-
* - persistentMemory.createMemory(input)
|
|
388
|
-
* - persistentMemory.getStats()
|
|
389
|
-
* - decisionLog.queryDecisions(query)
|
|
390
|
-
* - decisionLog.createDecision(input)
|
|
391
|
-
* - decisionLog.getActiveDecisions()
|
|
392
|
-
* - sessionMemory.listRecentSessions(limit)
|
|
386
|
+
* - persistentMemory.queryMemories(query) — query uses MemoryQuery shape
|
|
387
|
+
* - persistentMemory.createMemory(input) — input is CreateMemoryInput
|
|
388
|
+
* - persistentMemory.getStats() — returns MemoryStats
|
|
389
|
+
* - decisionLog.queryDecisions(query) — query uses DecisionQuery
|
|
390
|
+
* - decisionLog.createDecision(input) — returns { decision, conflicts }
|
|
391
|
+
* - decisionLog.getActiveDecisions() — returns Decision[]
|
|
392
|
+
* - sessionMemory.listRecentSessions(limit) — returns SessionListItem[]
|
|
393
393
|
*/
|
|
394
394
|
function createMemoryAdapter(persistentMemory, decisionLog, sessionMemory) {
|
|
395
395
|
return {
|
|
@@ -423,7 +423,7 @@ function createMemoryAdapter(persistentMemory, decisionLog, sessionMemory) {
|
|
|
423
423
|
if (!params.status || params.status === 'active') {
|
|
424
424
|
return decisionLog.getActiveDecisions();
|
|
425
425
|
}
|
|
426
|
-
// 'all'
|
|
426
|
+
// 'all' — query with no filters
|
|
427
427
|
return decisionLog.queryDecisions({});
|
|
428
428
|
},
|
|
429
429
|
decide: (params) => {
|
|
@@ -492,8 +492,8 @@ function createSessionAdapter(sessionMemory) {
|
|
|
492
492
|
* Creates an adapter that satisfies IContextEngine.
|
|
493
493
|
*
|
|
494
494
|
* Key API mappings:
|
|
495
|
-
* - compress(text, level, contentType)
|
|
496
|
-
* - buildContextPackage(...)
|
|
495
|
+
* - compress(text, level, contentType) — module-level function from compressor.ts
|
|
496
|
+
* - buildContextPackage(...) — module-level function from progressive-disclosure.ts
|
|
497
497
|
*/
|
|
498
498
|
function createContextAdapter(graph, persistentMemory, decisionLog, changeLog, config) {
|
|
499
499
|
return {
|
|
@@ -534,7 +534,7 @@ function createContextAdapter(graph, persistentMemory, decisionLog, changeLog, c
|
|
|
534
534
|
tier2Data.graphNodes = graphNodes;
|
|
535
535
|
}
|
|
536
536
|
// Build context package
|
|
537
|
-
const pkg = buildContextPackage(projectInfo, tier2Data, {}, // Tier 3 data
|
|
537
|
+
const pkg = buildContextPackage(projectInfo, tier2Data, {}, // Tier 3 data — empty for initial load
|
|
538
538
|
config.tokenBudgets, params.taskDescription);
|
|
539
539
|
return pkg;
|
|
540
540
|
}
|
|
@@ -568,12 +568,12 @@ function createContextAdapter(graph, persistentMemory, decisionLog, changeLog, c
|
|
|
568
568
|
* Creates an adapter that satisfies IIndexer.
|
|
569
569
|
*
|
|
570
570
|
* Key API mappings:
|
|
571
|
-
* - indexer.fullIndex(onProgress?)
|
|
571
|
+
* - indexer.fullIndex(onProgress?) — returns Promise<IndexStats>
|
|
572
572
|
* IndexStats has: filesScanned, filesParsed, filesSkipped, filesDeleted,
|
|
573
573
|
* nodesCreated, edgesCreated, parseErrors, durationMs, languages
|
|
574
|
-
* - graph.getStats()
|
|
575
|
-
* - persistentMemory.getStats()
|
|
576
|
-
* - changeLog.getStats(topN?)
|
|
574
|
+
* - graph.getStats() — returns { totalNodes, totalEdges, totalFiles, nodesByType, edgesByType, languageBreakdown }
|
|
575
|
+
* - persistentMemory.getStats() — returns MemoryStats
|
|
576
|
+
* - changeLog.getStats(topN?) — returns ChangeLogStats
|
|
577
577
|
*/
|
|
578
578
|
function createIndexerAdapter(indexer, graph, persistentMemory, decisionLog, changeLog, config, watcher) {
|
|
579
579
|
return {
|
|
@@ -609,13 +609,13 @@ function createIndexerAdapter(indexer, graph, persistentMemory, decisionLog, cha
|
|
|
609
609
|
try {
|
|
610
610
|
// Re-target the indexer to the new project
|
|
611
611
|
indexer.setProjectRoot(resolvedPath);
|
|
612
|
-
log('info',
|
|
612
|
+
log('info', `📠Re-targeted to project: ${resolvedPath}`);
|
|
613
613
|
// Also watch the new project directory for changes
|
|
614
614
|
if (watcher) {
|
|
615
615
|
watcher.addRoot(resolvedPath);
|
|
616
|
-
log('info',
|
|
616
|
+
log('info', `ðŸ‘ï¸ File watcher now also watching: ${resolvedPath}`);
|
|
617
617
|
}
|
|
618
|
-
// Run full index on the new project (don't clear
|
|
618
|
+
// Run full index on the new project (don't clear — multi-project)
|
|
619
619
|
const result = await indexer.fullIndex();
|
|
620
620
|
return {
|
|
621
621
|
filesScanned: result.filesScanned,
|
|
@@ -715,6 +715,20 @@ class SessionTokenTracker {
|
|
|
715
715
|
};
|
|
716
716
|
}
|
|
717
717
|
}
|
|
718
|
+
/**
|
|
719
|
+
* Directories that should NEVER be indexed — IDE install dirs, tool dirs, etc.
|
|
720
|
+
*/
|
|
721
|
+
const BLOCKED_DIRECTORY_PATTERNS = [
|
|
722
|
+
'antigravity', '.gemini', '.cursor', '.vscode-server',
|
|
723
|
+
'program files', 'programdata', 'appdata',
|
|
724
|
+
'node_modules', '.npm', '.yarn',
|
|
725
|
+
'system32', 'windows',
|
|
726
|
+
];
|
|
727
|
+
/** Check if a path is a known IDE/tool directory that should never be indexed */
|
|
728
|
+
function isBlockedDirectory(dirPath) {
|
|
729
|
+
const lower = dirPath.toLowerCase().replace(/\\/g, '/');
|
|
730
|
+
return BLOCKED_DIRECTORY_PATTERNS.some(pattern => lower.includes(pattern));
|
|
731
|
+
}
|
|
718
732
|
/**
|
|
719
733
|
* Intercept an MCP tool response to inject session token metadata.
|
|
720
734
|
*
|
|
@@ -732,23 +746,20 @@ function enrichToolResponse(response, tracker, estimator, graphNodeCount, getPro
|
|
|
732
746
|
const tokensSaved = result.tokensSaved ?? 0;
|
|
733
747
|
// Record in tracker
|
|
734
748
|
tracker.record(0, outputTokens, tokensSaved);
|
|
735
|
-
// Always add session token metadata
|
|
736
|
-
result._sessionTokens = tracker.getSummary();
|
|
737
749
|
// Always add project metadata
|
|
738
|
-
|
|
739
|
-
|
|
750
|
+
const projectInfo = getProjectInfo();
|
|
751
|
+
result._project = projectInfo;
|
|
752
|
+
// ALWAYS tell the agent to provide project path if no real project is indexed
|
|
740
753
|
const nodeCount = graphNodeCount();
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
result._hint = '⚠️ No codebase index found. Call mindmap_reindex with the projectPath parameter ' +
|
|
748
|
-
'set to the root directory of the user\'s project (e.g. "E:\\\\myproject"). ' +
|
|
749
|
-
'This is a one-time operation that takes ~10-30 seconds.';
|
|
750
|
-
}
|
|
754
|
+
const rootIsBlocked = isBlockedDirectory(projectInfo.root);
|
|
755
|
+
if (nodeCount === 0 || rootIsBlocked) {
|
|
756
|
+
result._indexRequired = true;
|
|
757
|
+
result._action = 'REQUIRED: Call mindmap_reindex({ projectPath: "<USER_WORKSPACE_PATH>" }). ' +
|
|
758
|
+
'The current root "' + projectInfo.root + '" is NOT a user project. ' +
|
|
759
|
+
'Use the workspace/project directory that the user has open in their editor.';
|
|
751
760
|
}
|
|
761
|
+
// Always add session token metadata
|
|
762
|
+
result._sessionTokens = tracker.getSummary();
|
|
752
763
|
response.content[0].text = JSON.stringify(result);
|
|
753
764
|
}
|
|
754
765
|
catch {
|
|
@@ -760,7 +771,7 @@ function enrichToolResponse(response, tracker, estimator, graphNodeCount, getPro
|
|
|
760
771
|
// Main entry point
|
|
761
772
|
// ============================================================
|
|
762
773
|
async function main() {
|
|
763
|
-
//
|
|
774
|
+
// ── 1. Parse CLI & load config ──────────────────────────────
|
|
764
775
|
let cliArgs;
|
|
765
776
|
try {
|
|
766
777
|
cliArgs = parseCliArgs();
|
|
@@ -771,7 +782,7 @@ async function main() {
|
|
|
771
782
|
process.exit(1);
|
|
772
783
|
}
|
|
773
784
|
setLogLevel(cliArgs.logLevel);
|
|
774
|
-
log('info', '
|
|
785
|
+
log('info', '🧠AI Mind Map MCP Server starting…');
|
|
775
786
|
let config;
|
|
776
787
|
try {
|
|
777
788
|
config = await loadConfig(cliArgs);
|
|
@@ -784,7 +795,7 @@ async function main() {
|
|
|
784
795
|
log('error', `Failed to load configuration: ${msg}`);
|
|
785
796
|
process.exit(1);
|
|
786
797
|
}
|
|
787
|
-
//
|
|
798
|
+
// ── 2. Initialise database directory ────────────────────────
|
|
788
799
|
try {
|
|
789
800
|
ensureDbDirectory(config.dbPath);
|
|
790
801
|
}
|
|
@@ -793,11 +804,11 @@ async function main() {
|
|
|
793
804
|
log('error', `Failed to create DB directory: ${msg}`);
|
|
794
805
|
process.exit(1);
|
|
795
806
|
}
|
|
796
|
-
//
|
|
807
|
+
// ── 3. Initialise SQLite database ──────────────────────────
|
|
797
808
|
// KnowledgeGraph manages its own db connection, but ChangeLog,
|
|
798
809
|
// SessionMemory, PersistentMemory, and DecisionLog each need
|
|
799
810
|
// a shared Database instance for their tables.
|
|
800
|
-
log('info', 'Initialising database
|
|
811
|
+
log('info', 'Initialising database…');
|
|
801
812
|
let sharedDb;
|
|
802
813
|
try {
|
|
803
814
|
sharedDb = new Database(config.dbPath);
|
|
@@ -811,24 +822,24 @@ async function main() {
|
|
|
811
822
|
log('error', `Failed to initialize database: ${msg}`);
|
|
812
823
|
process.exit(1);
|
|
813
824
|
}
|
|
814
|
-
//
|
|
815
|
-
log('info', 'Initialising subsystems
|
|
816
|
-
// Knowledge Graph
|
|
825
|
+
// ── 4. Initialise real subsystems ──────────────────────────
|
|
826
|
+
log('info', 'Initialising subsystems…');
|
|
827
|
+
// Knowledge Graph — constructor takes dbPath string
|
|
817
828
|
const graph = new KnowledgeGraph(config.dbPath);
|
|
818
|
-
// Indexer
|
|
829
|
+
// Indexer — constructor is Indexer(graph, config)
|
|
819
830
|
const indexer = new Indexer(graph, config);
|
|
820
|
-
// PageRankEngine
|
|
831
|
+
// PageRankEngine — constructor is PageRankEngine(graph, config?)
|
|
821
832
|
const pagerank = new PageRankEngine(graph);
|
|
822
|
-
// Changelog Engine
|
|
833
|
+
// Changelog Engine — node-level change tracking (v1.4.0)
|
|
823
834
|
const changelogEngine = new ChangelogEngine(graph.getDb());
|
|
824
835
|
indexer.setChangelog(changelogEngine);
|
|
825
|
-
log('info', '
|
|
836
|
+
log('info', '✅ Knowledge Graph initialized (with changelog engine)');
|
|
826
837
|
// Change Tracker
|
|
827
838
|
// ChangeLog constructor takes ChangeLogConfig: { dbPath, retentionDays?, defaultSearchLimit? }
|
|
828
839
|
const changeLog = new ChangeLog({ dbPath: config.dbPath });
|
|
829
840
|
const diffEngine = new DiffEngine(config.projectRoot);
|
|
830
841
|
let watcher = null;
|
|
831
|
-
// SessionMemory
|
|
842
|
+
// SessionMemory — must be created before watcher so it's available in the handler
|
|
832
843
|
// SessionMemory constructor takes Database.Database instance
|
|
833
844
|
const sessionMemory = new SessionMemory(sharedDb);
|
|
834
845
|
const sessionId = sessionMemory.startSession();
|
|
@@ -841,6 +852,8 @@ async function main() {
|
|
|
841
852
|
watchDebounceMs: config.watchDebounceMs,
|
|
842
853
|
maxFileSize: config.maxFileSize,
|
|
843
854
|
});
|
|
855
|
+
// Wire watcher to indexer so fullIndex() can pause/resume it
|
|
856
|
+
indexer.setWatcher(watcher);
|
|
844
857
|
// FileWatcher emits 'changes' with WatcherEvent[]
|
|
845
858
|
watcher.on('changes', async (events) => {
|
|
846
859
|
log('debug', `File watcher detected ${events.length} changes`);
|
|
@@ -872,7 +885,7 @@ async function main() {
|
|
|
872
885
|
pagerank.invalidateCache();
|
|
873
886
|
});
|
|
874
887
|
}
|
|
875
|
-
log('info',
|
|
888
|
+
log('info', `✅ Change Tracker initialized (watcher: ${config.watchEnabled ? 'enabled' : 'disabled'})`);
|
|
876
889
|
// Memory
|
|
877
890
|
// PersistentMemory constructor: (db, config?) where config is Pick<MindMapConfig['memory'], 'decayRate' | 'maxMemories' | 'importanceThreshold'>
|
|
878
891
|
const persistentMemory = new PersistentMemory(sharedDb, {
|
|
@@ -884,7 +897,7 @@ async function main() {
|
|
|
884
897
|
const decisionLog = new DecisionLog(sharedDb, {
|
|
885
898
|
maxDecisions: config.memory.maxDecisions,
|
|
886
899
|
});
|
|
887
|
-
log('info',
|
|
900
|
+
log('info', `✅ Memory initialized (session: ${sessionMemory.getCurrentSessionId()})`);
|
|
888
901
|
// Apply memory decay on startup
|
|
889
902
|
try {
|
|
890
903
|
const decayed = persistentMemory.applyDecay();
|
|
@@ -893,9 +906,9 @@ async function main() {
|
|
|
893
906
|
catch (err) {
|
|
894
907
|
log('warn', 'Failed to apply memory decay at startup', err);
|
|
895
908
|
}
|
|
896
|
-
// Context Engine
|
|
897
|
-
log('info', '
|
|
898
|
-
//
|
|
909
|
+
// Context Engine — no class instances needed; uses module-level functions
|
|
910
|
+
log('info', '✅ Context Engine initialized');
|
|
911
|
+
// ── 5. Build adapters ──────────────────────────────────────
|
|
899
912
|
const graphAdapter = createGraphAdapter(graph, pagerank);
|
|
900
913
|
const changeAdapter = createChangeAdapter(diffEngine, changeLog, graph);
|
|
901
914
|
const memoryAdapter = createMemoryAdapter(persistentMemory, decisionLog, sessionMemory);
|
|
@@ -906,25 +919,38 @@ async function main() {
|
|
|
906
919
|
const tokenEstimator = {
|
|
907
920
|
estimate: (text) => estimateTokens(text),
|
|
908
921
|
};
|
|
909
|
-
//
|
|
922
|
+
// ── 6. Create MCP server ──────────────────────────────────
|
|
910
923
|
const server = new McpServer({
|
|
911
924
|
name: 'ai-mind-map',
|
|
912
|
-
version: '1.
|
|
925
|
+
version: '1.7.0',
|
|
913
926
|
}, {
|
|
914
927
|
instructions: [
|
|
915
928
|
'# AI Mind Map — Code Memory Engine',
|
|
916
929
|
'',
|
|
917
|
-
'
|
|
930
|
+
'## ⚠ CRITICAL: FIRST STEP IN EVERY CONVERSATION',
|
|
931
|
+
'Before calling ANY other tool, you MUST ensure a project is indexed:',
|
|
932
|
+
'1. Check if `_indexRequired: true` appears in any response — if so, the index is empty or pointing at an IDE directory.',
|
|
933
|
+
'2. Call `mindmap_reindex({ projectPath: "<WORKSPACE>" })` where <WORKSPACE> is the user project directory from their open editor.',
|
|
934
|
+
'3. NEVER use paths containing: .gemini, antigravity, .cursor, .vscode, AppData, Program Files — these are IDE directories, NOT projects.',
|
|
935
|
+
'4. Example: `mindmap_reindex({ projectPath: "E:\\myproject" })`',
|
|
918
936
|
'',
|
|
919
|
-
'##
|
|
920
|
-
'Call `mindmap_session_resume
|
|
937
|
+
'## After Indexing - Resume Session:',
|
|
938
|
+
'Call `mindmap_session_resume`. It returns:',
|
|
921
939
|
'- What the previous AI worked on',
|
|
922
940
|
'- What code changed since then (function-level diffs)',
|
|
923
941
|
'- Project structure + tech stack',
|
|
924
942
|
'- Hot files (most frequently changed)',
|
|
925
|
-
'This ONE call replaces reading 10+ files.',
|
|
926
943
|
'',
|
|
927
|
-
'##
|
|
944
|
+
'## Project Indexing:',
|
|
945
|
+
'Every response includes `_project.root` and `_project.totalNodes`.',
|
|
946
|
+
'If `_indexRequired: true` appears, you MUST call `mindmap_reindex` with the correct project path.',
|
|
947
|
+
'NEVER index directories containing: antigravity, .gemini, .cursor, .vscode, AppData, Program Files.',
|
|
948
|
+
'The graph supports multiple projects — call `mindmap_reindex` with different paths to switch.',
|
|
949
|
+
'',
|
|
950
|
+
'## Token Tracking:',
|
|
951
|
+
'Every response includes `_sessionTokens` with cumulative usage.',
|
|
952
|
+
'',
|
|
953
|
+
'## Tool Selection Guide:',
|
|
928
954
|
'',
|
|
929
955
|
'### When you need to UNDERSTAND the project:',
|
|
930
956
|
'- `mindmap_digest` → Full project summary in <2000 tokens',
|
|
@@ -938,48 +964,47 @@ async function main() {
|
|
|
938
964
|
'- `mindmap_trace_dependencies` → Who calls X? What does X call?',
|
|
939
965
|
'',
|
|
940
966
|
'### When you need to READ code:',
|
|
941
|
-
'- `
|
|
942
|
-
'- `
|
|
943
|
-
'- `mindmap_get_file_map` → All symbols in a file with signatures + line ranges',
|
|
967
|
+
'- `mindmap_get_code_snippet` → Read actual source code for a function/class',
|
|
968
|
+
'- `mindmap_get_file_map` → All symbols in a file with signatures + line ranges',
|
|
944
969
|
'',
|
|
945
970
|
'### When you need to know WHAT CHANGED:',
|
|
946
|
-
'- `mindmap_changelog`
|
|
947
|
-
'- `mindmap_git_changes`
|
|
948
|
-
'- `mindmap_verify`
|
|
949
|
-
'- `mindmap_hotspots`
|
|
971
|
+
'- `mindmap_changelog` → Symbol-level diffs (added/modified/deleted functions)',
|
|
972
|
+
'- `mindmap_git_changes` → Git-aware changes with symbol mapping',
|
|
973
|
+
'- `mindmap_verify` → Check if your cached knowledge is still valid',
|
|
974
|
+
'- `mindmap_hotspots` → Most frequently changed files + symbols',
|
|
950
975
|
'',
|
|
951
976
|
'### When you need to REMEMBER:',
|
|
952
|
-
'- `mindmap_remember`
|
|
953
|
-
'- `mindmap_recall`
|
|
954
|
-
'- `mindmap_decide`
|
|
977
|
+
'- `mindmap_remember` → Save a fact/convention for future sessions',
|
|
978
|
+
'- `mindmap_recall` → Retrieve relevant memories for current task',
|
|
979
|
+
'- `mindmap_decide` → Record architectural decisions with rationale',
|
|
955
980
|
'',
|
|
956
981
|
'### When you finish work:',
|
|
957
|
-
'- `mindmap_session_end`
|
|
982
|
+
'- `mindmap_session_end` → Save summary so next AI can resume instantly',
|
|
958
983
|
'',
|
|
959
984
|
'### After editing code:',
|
|
960
|
-
'- `mindmap_verify_changes`
|
|
985
|
+
'- `mindmap_verify_changes` → Verify your edits at the symbol level WITHOUT re-reading files',
|
|
961
986
|
'',
|
|
962
|
-
'##
|
|
963
|
-
'1. ALWAYS call `mindmap_session_resume` first
|
|
964
|
-
'2. Use `mindmap_file_digest` BEFORE reading a full file
|
|
965
|
-
'3. Use `mindmap_verify_changes` after editing to verify changes
|
|
987
|
+
'## âš¡ Token-Saving Rules:',
|
|
988
|
+
'1. ALWAYS call `mindmap_session_resume` first — never start blind',
|
|
989
|
+
'2. Use `mindmap_file_digest` BEFORE reading a full file — you may not need the full file',
|
|
990
|
+
'3. Use `mindmap_verify_changes` after editing to verify changes — do NOT re-read whole files',
|
|
966
991
|
'4. Use `mindmap_changelog` instead of re-reading files to see what changed',
|
|
967
|
-
'5. Call `mindmap_session_end` when done
|
|
992
|
+
'5. Call `mindmap_session_end` when done — save context for next session',
|
|
968
993
|
'',
|
|
969
|
-
'##
|
|
994
|
+
'## 🔄 Project Indexing:',
|
|
970
995
|
'Every response includes `_project.root` showing which directory is currently indexed.',
|
|
971
996
|
'If `_project.totalNodes` is 0, you MUST call `mindmap_reindex` with `projectPath` set to',
|
|
972
997
|
'the user\'s project directory (e.g. their workspace root). This creates the knowledge graph.',
|
|
973
998
|
'Example: `mindmap_reindex({ projectPath: "/home/user/my-project" })`',
|
|
974
|
-
'You can also reindex to switch between projects
|
|
999
|
+
'You can also reindex to switch between projects — the graph supports multiple projects.',
|
|
975
1000
|
'',
|
|
976
|
-
'##
|
|
1001
|
+
'## 📊 Token Tracking:',
|
|
977
1002
|
'Every response includes `_sessionTokens` with cumulative usage.',
|
|
978
1003
|
].join('\n'),
|
|
979
1004
|
});
|
|
980
|
-
//
|
|
981
|
-
log('info', 'Registering MCP tools
|
|
982
|
-
//
|
|
1005
|
+
// ── 7. Register all tools ─────────────────────────────────
|
|
1006
|
+
log('info', 'Registering MCP tools…');
|
|
1007
|
+
// ── 7.0 Token tracking middleware ──────────────────────────
|
|
983
1008
|
// Wrap every tool handler to inject session token metadata
|
|
984
1009
|
const tokenTracker = new SessionTokenTracker();
|
|
985
1010
|
const originalToolFn = server.tool.bind(server);
|
|
@@ -1036,7 +1061,7 @@ async function main() {
|
|
|
1036
1061
|
log('debug', 'Registered session tools (5)');
|
|
1037
1062
|
registerDigestTools(server, graph, changelogEngine, config, tokenEstimator);
|
|
1038
1063
|
log('debug', 'Registered digest tools (3)');
|
|
1039
|
-
//
|
|
1064
|
+
// ── mindmap_sync_shared_context ─────────────────────────────
|
|
1040
1065
|
server.tool('mindmap_sync_shared_context', 'Synchronise local memories, decisions, and learned rules with the team-shared `.mindmap-shared.json` file. ' +
|
|
1041
1066
|
'Performs a bidirectional sync to import new conventions/decisions and export local updates.', {}, async () => {
|
|
1042
1067
|
try {
|
|
@@ -1070,21 +1095,21 @@ async function main() {
|
|
|
1070
1095
|
}
|
|
1071
1096
|
});
|
|
1072
1097
|
log('debug', 'Registered shared context sync tool');
|
|
1073
|
-
log('info', '
|
|
1098
|
+
log('info', '🔧 All MCP tools registered:');
|
|
1074
1099
|
log('info', ' Graph: mindmap_search, mindmap_get_structure, mindmap_trace_dependencies, mindmap_get_signature, mindmap_find_references, mindmap_get_file_map');
|
|
1075
1100
|
log('info', ' Changes: mindmap_what_changed, mindmap_session_diff, mindmap_impact_analysis');
|
|
1076
1101
|
log('info', ' Memory: mindmap_recall, mindmap_remember, mindmap_get_decisions, mindmap_decide, mindmap_session_summary, mindmap_sync_shared_context');
|
|
1077
1102
|
log('info', ' Context: mindmap_get_context, mindmap_compress, mindmap_reindex, mindmap_status');
|
|
1078
1103
|
log('info', ' Debug: mindmap_debug_changes, mindmap_file_before, mindmap_file_history');
|
|
1079
1104
|
log('info', ' Flow: mindmap_trace_flow, mindmap_interaction_map, mindmap_classify_file, mindmap_layer_overview');
|
|
1080
|
-
log('info', ' Snapshot: mindmap_project_map, mindmap_change_delta, mindmap_session_kickoff
|
|
1105
|
+
log('info', ' Snapshot: mindmap_project_map, mindmap_change_delta, mindmap_session_kickoff â');
|
|
1081
1106
|
log('info', ' Advanced: mindmap_query_graph, mindmap_dead_code, mindmap_architecture, mindmap_get_code_snippet, mindmap_search_code, mindmap_list_projects, mindmap_health');
|
|
1082
|
-
log('info', ' Smart: mindmap_explain
|
|
1083
|
-
log('info', ' Evolving: mindmap_teach
|
|
1084
|
-
log('info', ' Semantic: mindmap_semantic_search
|
|
1085
|
-
log('info', ' Session: mindmap_session_start
|
|
1086
|
-
log('info', ' Digest: mindmap_digest
|
|
1087
|
-
//
|
|
1107
|
+
log('info', ' Smart: mindmap_explain â, mindmap_git_changes â, mindmap_smart_search â');
|
|
1108
|
+
log('info', ' Evolving: mindmap_teach â, mindmap_get_learned, mindmap_forget');
|
|
1109
|
+
log('info', ' Semantic: mindmap_semantic_search â, mindmap_semantic_stats, mindmap_synonyms');
|
|
1110
|
+
log('info', ' Session: mindmap_session_start 🆕, mindmap_session_resume 🔥🆕, mindmap_session_end, mindmap_changelog 🆕, mindmap_hotspots, mindmap_verify_changes 🆕');
|
|
1111
|
+
log('info', ' Digest: mindmap_digest â, mindmap_file_digest â, mindmap_verify');
|
|
1112
|
+
// ── 7.3 Register MCP Prompts ──────────────────────────────
|
|
1088
1113
|
// These are interactive workflow templates that AI agents can request
|
|
1089
1114
|
server.prompt('start_session', 'Recommended first prompt for any AI coding session. Calls mindmap_session_resume and returns a complete project briefing.', async () => {
|
|
1090
1115
|
// Auto-start session
|
|
@@ -1127,32 +1152,32 @@ async function main() {
|
|
|
1127
1152
|
}],
|
|
1128
1153
|
};
|
|
1129
1154
|
});
|
|
1130
|
-
server.prompt('tool_guide', 'Complete guide to all AI Mind Map tools
|
|
1155
|
+
server.prompt('tool_guide', 'Complete guide to all AI Mind Map tools — when to use each one, organized by task.', async () => ({
|
|
1131
1156
|
messages: [{
|
|
1132
1157
|
role: 'user',
|
|
1133
1158
|
content: {
|
|
1134
1159
|
type: 'text',
|
|
1135
1160
|
text: [
|
|
1136
|
-
'# AI Mind Map
|
|
1161
|
+
'# AI Mind Map — Complete Tool Guide',
|
|
1137
1162
|
'',
|
|
1138
|
-
'##
|
|
1163
|
+
'## 🚀 Session Lifecycle (use these to avoid re-reading code)',
|
|
1139
1164
|
'| Tool | When to Use |',
|
|
1140
1165
|
'|------|------------|',
|
|
1141
|
-
'| `mindmap_session_resume` | **FIRST call every conversation**
|
|
1166
|
+
'| `mindmap_session_resume` | **FIRST call every conversation** — returns project context + changes |',
|
|
1142
1167
|
'| `mindmap_session_kickoff` | Full preamble: project map + change delta + memories in ONE call |',
|
|
1143
1168
|
'| `mindmap_session_start` | Start tracking a new task (records agent name + task) |',
|
|
1144
1169
|
'| `mindmap_session_end` | Save summary for next AI session |',
|
|
1145
1170
|
'',
|
|
1146
|
-
'##
|
|
1171
|
+
'## 🔠Finding Code (instead of grep/reading files)',
|
|
1147
1172
|
'| Tool | When to Use |',
|
|
1148
1173
|
'|------|------------|',
|
|
1149
|
-
'| `mindmap_smart_search` | Search by function/class name
|
|
1174
|
+
'| `mindmap_smart_search` | Search by function/class name — returns full context |',
|
|
1150
1175
|
'| `mindmap_semantic_search` | Search by concept ("error handling", "auth") |',
|
|
1151
1176
|
'| `mindmap_search_code` | Grep-like text search in code bodies |',
|
|
1152
1177
|
'| `mindmap_find_references` | Find all usages of a symbol |',
|
|
1153
1178
|
'| `mindmap_trace_dependencies` | Who calls X? What does X call? |',
|
|
1154
1179
|
'',
|
|
1155
|
-
'##
|
|
1180
|
+
'## 📖 Reading Code (without reading full files)',
|
|
1156
1181
|
'| Tool | When to Use |',
|
|
1157
1182
|
'|------|------------|',
|
|
1158
1183
|
'| `mindmap_explain` | Get EVERYTHING about a symbol in one call |',
|
|
@@ -1161,14 +1186,14 @@ async function main() {
|
|
|
1161
1186
|
'| `mindmap_get_file_map` | All symbols in a file with signatures |',
|
|
1162
1187
|
'| `mindmap_get_signature` | Just the signature (cheapest read) |',
|
|
1163
1188
|
'',
|
|
1164
|
-
'##
|
|
1189
|
+
'## 📊 Understanding the Project',
|
|
1165
1190
|
'| Tool | When to Use |',
|
|
1166
1191
|
'|------|------------|',
|
|
1167
1192
|
'| `mindmap_digest` | Full project summary in <2000 tokens |',
|
|
1168
1193
|
'| `mindmap_architecture` | Architecture layers + patterns |',
|
|
1169
1194
|
'| `mindmap_project_map` | Complete project map |',
|
|
1170
1195
|
'',
|
|
1171
|
-
'##
|
|
1196
|
+
'## 🔄 Change Tracking',
|
|
1172
1197
|
'| Tool | When to Use |',
|
|
1173
1198
|
'|------|------------|',
|
|
1174
1199
|
'| `mindmap_changelog` | Symbol-level diffs since a time |',
|
|
@@ -1176,7 +1201,7 @@ async function main() {
|
|
|
1176
1201
|
'| `mindmap_verify` | Check if cached code is still valid |',
|
|
1177
1202
|
'| `mindmap_hotspots` | Most frequently changed files |',
|
|
1178
1203
|
'',
|
|
1179
|
-
'##
|
|
1204
|
+
'## 🧠Memory & Decisions',
|
|
1180
1205
|
'| Tool | When to Use |',
|
|
1181
1206
|
'|------|------------|',
|
|
1182
1207
|
'| `mindmap_remember` | Save important facts for future |',
|
|
@@ -1188,22 +1213,22 @@ async function main() {
|
|
|
1188
1213
|
}],
|
|
1189
1214
|
}));
|
|
1190
1215
|
log('debug', 'Registered 2 MCP prompts (start_session, tool_guide)');
|
|
1191
|
-
//
|
|
1216
|
+
// ── 7.5 Auto-sync shared context on startup ────────────────
|
|
1192
1217
|
if (config.autoSyncSharedContext) {
|
|
1193
|
-
log('info', '
|
|
1218
|
+
log('info', '🔄 Auto-syncing shared context…');
|
|
1194
1219
|
try {
|
|
1195
1220
|
const syncStats = await syncSharedContext(config, graph, persistentMemory, decisionLog);
|
|
1196
|
-
log('info',
|
|
1221
|
+
log('info', `✅ Shared context sync complete: ` +
|
|
1197
1222
|
`Imported: ${syncStats.memoriesImported} memories, ${syncStats.decisionsImported} decisions, ${syncStats.rulesImported} rules. ` +
|
|
1198
1223
|
`Exported: ${syncStats.memoriesExported} memories, ${syncStats.decisionsExported} decisions, ${syncStats.rulesExported} rules.`);
|
|
1199
1224
|
}
|
|
1200
1225
|
catch (err) {
|
|
1201
|
-
log('warn',
|
|
1226
|
+
log('warn', `âš ï¸ Auto-sync of shared context failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1202
1227
|
}
|
|
1203
1228
|
}
|
|
1204
|
-
//
|
|
1229
|
+
// ── 8. Smart auto-index (only if projectRoot looks like a real project) ──
|
|
1205
1230
|
if (config.memoryOnly) {
|
|
1206
|
-
log('info', '
|
|
1231
|
+
log('info', '🧠Running in memoryOnly mode. Bypassing codebase parsing and indexing.');
|
|
1207
1232
|
}
|
|
1208
1233
|
else {
|
|
1209
1234
|
// Check if projectRoot is a real project (not an IDE install directory)
|
|
@@ -1214,33 +1239,33 @@ async function main() {
|
|
|
1214
1239
|
'pubspec.yaml', 'Gemfile', '*.sln', '*.csproj',
|
|
1215
1240
|
];
|
|
1216
1241
|
const isRealProject = projectMarkers.some(marker => existsSync(path.join(config.projectRoot, marker)));
|
|
1217
|
-
if (!isRealProject) {
|
|
1218
|
-
log('info',
|
|
1242
|
+
if (!isRealProject || isBlockedDirectory(config.projectRoot)) {
|
|
1243
|
+
log('info', `âš ï¸ Project root "${config.projectRoot}" does not look like a code project (no .git, package.json, etc.).`);
|
|
1219
1244
|
log('info', ' Skipping auto-index. The AI agent will be prompted to call mindmap_reindex with the correct project path.');
|
|
1220
1245
|
}
|
|
1221
1246
|
else {
|
|
1222
1247
|
const stats = graph.getStats();
|
|
1223
1248
|
if (stats.totalNodes === 0) {
|
|
1224
|
-
log('info',
|
|
1249
|
+
log('info', `📋 Real project detected at: ${config.projectRoot}. Running initial indexing…`);
|
|
1225
1250
|
try {
|
|
1226
1251
|
const result = await indexer.fullIndex();
|
|
1227
|
-
log('info',
|
|
1252
|
+
log('info', `✅ Initial index complete: ${result.filesParsed} files, ${result.nodesCreated} nodes, ${result.edgesCreated} edges`);
|
|
1228
1253
|
if (result.parseErrors > 0) {
|
|
1229
|
-
log('warn',
|
|
1254
|
+
log('warn', `âš ï¸ ${result.parseErrors} parse errors (non-fatal)`);
|
|
1230
1255
|
}
|
|
1231
1256
|
}
|
|
1232
1257
|
catch (err) {
|
|
1233
|
-
log('warn',
|
|
1258
|
+
log('warn', `âš ï¸ Initial indexing failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
|
|
1234
1259
|
}
|
|
1235
1260
|
}
|
|
1236
1261
|
else {
|
|
1237
|
-
log('info',
|
|
1262
|
+
log('info', `📋 Existing index found: ${stats.totalNodes} nodes. Running incremental update…`);
|
|
1238
1263
|
try {
|
|
1239
1264
|
const result = await indexer.incrementalIndex();
|
|
1240
|
-
log('info',
|
|
1265
|
+
log('info', `✅ Incremental update: ${result.filesParsed} files reindexed`);
|
|
1241
1266
|
}
|
|
1242
1267
|
catch (err) {
|
|
1243
|
-
log('warn',
|
|
1268
|
+
log('warn', `âš ï¸ Incremental update failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
|
|
1244
1269
|
}
|
|
1245
1270
|
}
|
|
1246
1271
|
}
|
|
@@ -1258,30 +1283,30 @@ async function main() {
|
|
|
1258
1283
|
filePath: n.filePath,
|
|
1259
1284
|
})));
|
|
1260
1285
|
semanticEngine.rebuildIDF();
|
|
1261
|
-
log('info',
|
|
1286
|
+
log('info', `🧠Semantic index built: ${nonFileNodes.length} symbols indexed`);
|
|
1262
1287
|
}
|
|
1263
1288
|
}
|
|
1264
1289
|
catch (err) {
|
|
1265
|
-
log('warn',
|
|
1290
|
+
log('warn', `âš ï¸ Semantic index build failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
|
|
1266
1291
|
}
|
|
1267
1292
|
}
|
|
1268
|
-
//
|
|
1293
|
+
// ── 9. Start file watcher ──────────────────────────────────
|
|
1269
1294
|
if (watcher && !config.memoryOnly) {
|
|
1270
1295
|
try {
|
|
1271
1296
|
await watcher.start();
|
|
1272
|
-
log('info', '
|
|
1297
|
+
log('info', 'ðŸ‘ï¸ File watcher started');
|
|
1273
1298
|
}
|
|
1274
1299
|
catch (err) {
|
|
1275
|
-
log('warn',
|
|
1300
|
+
log('warn', `âš ï¸ File watcher failed to start: ${err instanceof Error ? err.message : String(err)}`);
|
|
1276
1301
|
}
|
|
1277
1302
|
}
|
|
1278
|
-
//
|
|
1303
|
+
// ── 10. Graceful shutdown ──────────────────────────────────
|
|
1279
1304
|
let shuttingDown = false;
|
|
1280
1305
|
async function shutdown(signal) {
|
|
1281
1306
|
if (shuttingDown)
|
|
1282
1307
|
return;
|
|
1283
1308
|
shuttingDown = true;
|
|
1284
|
-
log('info', `Received ${signal}, shutting down gracefully
|
|
1309
|
+
log('info', `Received ${signal}, shutting down gracefully…`);
|
|
1285
1310
|
try {
|
|
1286
1311
|
// Stop file watcher
|
|
1287
1312
|
if (watcher) {
|
|
@@ -1328,7 +1353,7 @@ async function main() {
|
|
|
1328
1353
|
catch {
|
|
1329
1354
|
// Ignore close errors
|
|
1330
1355
|
}
|
|
1331
|
-
log('info', '
|
|
1356
|
+
log('info', '✅ Cleanup complete. Goodbye!');
|
|
1332
1357
|
}
|
|
1333
1358
|
catch (err) {
|
|
1334
1359
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1347,12 +1372,12 @@ async function main() {
|
|
|
1347
1372
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
1348
1373
|
log('error', `Unhandled rejection: ${msg}`);
|
|
1349
1374
|
});
|
|
1350
|
-
//
|
|
1351
|
-
log('info', 'Connecting stdio transport
|
|
1375
|
+
// ── 11. Connect transport and start serving ────────────────
|
|
1376
|
+
log('info', 'Connecting stdio transport…');
|
|
1352
1377
|
try {
|
|
1353
1378
|
const transport = new StdioServerTransport();
|
|
1354
1379
|
await server.connect(transport);
|
|
1355
|
-
log('info', '
|
|
1380
|
+
log('info', '🧠AI Mind Map MCP Server is LIVE. Waiting for requests…');
|
|
1356
1381
|
log('info', ` Project: ${config.projectRoot}`);
|
|
1357
1382
|
log('info', ` Database: ${config.dbPath}`);
|
|
1358
1383
|
log('info', ` Session: ${sessionMemory.getCurrentSessionId()}`);
|
|
@@ -1363,7 +1388,7 @@ async function main() {
|
|
|
1363
1388
|
process.exit(1);
|
|
1364
1389
|
}
|
|
1365
1390
|
}
|
|
1366
|
-
//
|
|
1391
|
+
// ── Kick off ────────────────────────────────────────────────
|
|
1367
1392
|
main().catch((err) => {
|
|
1368
1393
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1369
1394
|
process.stderr.write(`Fatal: ${msg}\n`);
|