superlocalmemory 2.3.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/ATTRIBUTION.md +140 -0
- package/CHANGELOG.md +1749 -0
- package/LICENSE +21 -0
- package/README.md +600 -0
- package/bin/aider-smart +72 -0
- package/bin/slm +202 -0
- package/bin/slm-npm +73 -0
- package/bin/slm.bat +195 -0
- package/bin/slm.cmd +10 -0
- package/bin/superlocalmemoryv2:list +3 -0
- package/bin/superlocalmemoryv2:profile +3 -0
- package/bin/superlocalmemoryv2:recall +3 -0
- package/bin/superlocalmemoryv2:remember +3 -0
- package/bin/superlocalmemoryv2:reset +3 -0
- package/bin/superlocalmemoryv2:status +3 -0
- package/completions/slm.bash +58 -0
- package/completions/slm.zsh +76 -0
- package/configs/antigravity-mcp.json +13 -0
- package/configs/chatgpt-desktop-mcp.json +7 -0
- package/configs/claude-desktop-mcp.json +15 -0
- package/configs/codex-mcp.toml +13 -0
- package/configs/cody-commands.json +29 -0
- package/configs/continue-mcp.yaml +14 -0
- package/configs/continue-skills.yaml +26 -0
- package/configs/cursor-mcp.json +15 -0
- package/configs/gemini-cli-mcp.json +11 -0
- package/configs/jetbrains-mcp.json +11 -0
- package/configs/opencode-mcp.json +12 -0
- package/configs/perplexity-mcp.json +9 -0
- package/configs/vscode-copilot-mcp.json +12 -0
- package/configs/windsurf-mcp.json +16 -0
- package/configs/zed-mcp.json +12 -0
- package/docs/ARCHITECTURE.md +877 -0
- package/docs/CLI-COMMANDS-REFERENCE.md +425 -0
- package/docs/COMPETITIVE-ANALYSIS.md +210 -0
- package/docs/COMPRESSION-README.md +390 -0
- package/docs/GRAPH-ENGINE.md +503 -0
- package/docs/MCP-MANUAL-SETUP.md +720 -0
- package/docs/MCP-TROUBLESHOOTING.md +787 -0
- package/docs/PATTERN-LEARNING.md +363 -0
- package/docs/PROFILES-GUIDE.md +453 -0
- package/docs/RESET-GUIDE.md +353 -0
- package/docs/SEARCH-ENGINE-V2.2.0.md +748 -0
- package/docs/SEARCH-INTEGRATION-GUIDE.md +502 -0
- package/docs/UI-SERVER.md +254 -0
- package/docs/UNIVERSAL-INTEGRATION.md +432 -0
- package/docs/V2.2.0-OPTIONAL-SEARCH.md +666 -0
- package/docs/WINDOWS-INSTALL-README.txt +34 -0
- package/docs/WINDOWS-POST-INSTALL.txt +45 -0
- package/docs/example_graph_usage.py +148 -0
- package/hooks/memory-list-skill.js +130 -0
- package/hooks/memory-profile-skill.js +284 -0
- package/hooks/memory-recall-skill.js +109 -0
- package/hooks/memory-remember-skill.js +127 -0
- package/hooks/memory-reset-skill.js +274 -0
- package/install-skills.sh +436 -0
- package/install.ps1 +417 -0
- package/install.sh +755 -0
- package/mcp_server.py +585 -0
- package/package.json +94 -0
- package/requirements-core.txt +24 -0
- package/requirements.txt +10 -0
- package/scripts/postinstall.js +126 -0
- package/scripts/preuninstall.js +57 -0
- package/skills/slm-build-graph/SKILL.md +423 -0
- package/skills/slm-list-recent/SKILL.md +348 -0
- package/skills/slm-recall/SKILL.md +325 -0
- package/skills/slm-remember/SKILL.md +194 -0
- package/skills/slm-status/SKILL.md +363 -0
- package/skills/slm-switch-profile/SKILL.md +442 -0
- package/src/__pycache__/cache_manager.cpython-312.pyc +0 -0
- package/src/__pycache__/embedding_engine.cpython-312.pyc +0 -0
- package/src/__pycache__/graph_engine.cpython-312.pyc +0 -0
- package/src/__pycache__/hnsw_index.cpython-312.pyc +0 -0
- package/src/__pycache__/hybrid_search.cpython-312.pyc +0 -0
- package/src/__pycache__/memory-profiles.cpython-312.pyc +0 -0
- package/src/__pycache__/memory-reset.cpython-312.pyc +0 -0
- package/src/__pycache__/memory_compression.cpython-312.pyc +0 -0
- package/src/__pycache__/memory_store_v2.cpython-312.pyc +0 -0
- package/src/__pycache__/migrate_v1_to_v2.cpython-312.pyc +0 -0
- package/src/__pycache__/pattern_learner.cpython-312.pyc +0 -0
- package/src/__pycache__/query_optimizer.cpython-312.pyc +0 -0
- package/src/__pycache__/search_engine_v2.cpython-312.pyc +0 -0
- package/src/__pycache__/setup_validator.cpython-312.pyc +0 -0
- package/src/__pycache__/tree_manager.cpython-312.pyc +0 -0
- package/src/cache_manager.py +520 -0
- package/src/embedding_engine.py +671 -0
- package/src/graph_engine.py +970 -0
- package/src/hnsw_index.py +626 -0
- package/src/hybrid_search.py +693 -0
- package/src/memory-profiles.py +518 -0
- package/src/memory-reset.py +485 -0
- package/src/memory_compression.py +999 -0
- package/src/memory_store_v2.py +1088 -0
- package/src/migrate_v1_to_v2.py +638 -0
- package/src/pattern_learner.py +898 -0
- package/src/query_optimizer.py +513 -0
- package/src/search_engine_v2.py +403 -0
- package/src/setup_validator.py +479 -0
- package/src/tree_manager.py +720 -0
package/mcp_server.py
ADDED
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SuperLocalMemory V2 - MCP Server
|
|
4
|
+
Universal memory access for all MCP-compatible tools (Cursor, Windsurf, Claude Desktop, Continue.dev)
|
|
5
|
+
|
|
6
|
+
Copyright (c) 2026 Varun Pratap Bhardwaj
|
|
7
|
+
Licensed under MIT License
|
|
8
|
+
Repository: https://github.com/varun369/SuperLocalMemoryV2
|
|
9
|
+
|
|
10
|
+
IMPORTANT: This is an ADDITION to existing skills, not a replacement.
|
|
11
|
+
Skills in Claude Code continue to work unchanged.
|
|
12
|
+
|
|
13
|
+
Architecture:
|
|
14
|
+
MCP Server (this file)
|
|
15
|
+
↓
|
|
16
|
+
Calls existing memory_store_v2.py
|
|
17
|
+
↓
|
|
18
|
+
Same SQLite database as skills
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
# Run as stdio MCP server (for local IDEs)
|
|
22
|
+
python3 mcp_server.py
|
|
23
|
+
|
|
24
|
+
# Run as HTTP MCP server (for remote access)
|
|
25
|
+
python3 mcp_server.py --transport http --port 8001
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from mcp.server.fastmcp import FastMCP
|
|
29
|
+
from mcp.types import ToolAnnotations
|
|
30
|
+
import sys
|
|
31
|
+
import json
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
from typing import Optional
|
|
34
|
+
|
|
35
|
+
# Add src directory to path (use existing code!)
|
|
36
|
+
MEMORY_DIR = Path.home() / ".claude-memory"
|
|
37
|
+
sys.path.insert(0, str(MEMORY_DIR))
|
|
38
|
+
|
|
39
|
+
# Import existing core modules (zero duplicate logic)
|
|
40
|
+
try:
|
|
41
|
+
from memory_store_v2 import MemoryStoreV2
|
|
42
|
+
from graph_engine import GraphEngine
|
|
43
|
+
from pattern_learner import PatternLearner
|
|
44
|
+
except ImportError as e:
|
|
45
|
+
print(f"Error: Could not import SuperLocalMemory modules: {e}", file=sys.stderr)
|
|
46
|
+
print(f"Ensure SuperLocalMemory V2 is installed at {MEMORY_DIR}", file=sys.stderr)
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
|
|
49
|
+
# Initialize MCP server
|
|
50
|
+
mcp = FastMCP(
|
|
51
|
+
name="SuperLocalMemory V2"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Database path
|
|
55
|
+
DB_PATH = MEMORY_DIR / "memory.db"
|
|
56
|
+
|
|
57
|
+
# ============================================================================
|
|
58
|
+
# MCP TOOLS (Functions callable by AI)
|
|
59
|
+
# ============================================================================
|
|
60
|
+
|
|
61
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
62
|
+
readOnlyHint=False,
|
|
63
|
+
destructiveHint=False,
|
|
64
|
+
openWorldHint=False,
|
|
65
|
+
))
|
|
66
|
+
async def remember(
|
|
67
|
+
content: str,
|
|
68
|
+
tags: str = "",
|
|
69
|
+
project: str = "",
|
|
70
|
+
importance: int = 5
|
|
71
|
+
) -> dict:
|
|
72
|
+
"""
|
|
73
|
+
Save content to SuperLocalMemory with intelligent indexing.
|
|
74
|
+
|
|
75
|
+
This calls the SAME backend as /superlocalmemoryv2:remember skill.
|
|
76
|
+
All memories are stored in the same local SQLite database.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
content: The content to remember (required)
|
|
80
|
+
tags: Comma-separated tags (optional, e.g. "python,api,backend")
|
|
81
|
+
project: Project name (optional, groups related memories)
|
|
82
|
+
importance: Importance score 1-10 (default 5)
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
{
|
|
86
|
+
"success": bool,
|
|
87
|
+
"memory_id": int,
|
|
88
|
+
"message": str,
|
|
89
|
+
"content_preview": str
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Examples:
|
|
93
|
+
remember("Use FastAPI for REST APIs", tags="python,backend", project="myapp")
|
|
94
|
+
remember("JWT auth with refresh tokens", tags="security,auth", importance=8)
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
# Use existing MemoryStoreV2 class (no duplicate logic)
|
|
98
|
+
store = MemoryStoreV2(DB_PATH)
|
|
99
|
+
|
|
100
|
+
# Call existing add_memory method
|
|
101
|
+
memory_id = store.add_memory(
|
|
102
|
+
content=content,
|
|
103
|
+
tags=tags.split(",") if tags else None,
|
|
104
|
+
project_name=project or None,
|
|
105
|
+
importance=importance
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Format response
|
|
109
|
+
preview = content[:100] + "..." if len(content) > 100 else content
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
"success": True,
|
|
113
|
+
"memory_id": memory_id,
|
|
114
|
+
"message": f"Memory saved with ID {memory_id}",
|
|
115
|
+
"content_preview": preview
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
except Exception as e:
|
|
119
|
+
return {
|
|
120
|
+
"success": False,
|
|
121
|
+
"error": str(e),
|
|
122
|
+
"message": "Failed to save memory"
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
127
|
+
readOnlyHint=True,
|
|
128
|
+
destructiveHint=False,
|
|
129
|
+
openWorldHint=False,
|
|
130
|
+
))
|
|
131
|
+
async def recall(
|
|
132
|
+
query: str,
|
|
133
|
+
limit: int = 10,
|
|
134
|
+
min_score: float = 0.3
|
|
135
|
+
) -> dict:
|
|
136
|
+
"""
|
|
137
|
+
Search memories using semantic similarity and knowledge graph.
|
|
138
|
+
|
|
139
|
+
This calls the SAME backend as /superlocalmemoryv2:recall skill.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
query: Search query (required)
|
|
143
|
+
limit: Maximum results to return (default 10)
|
|
144
|
+
min_score: Minimum relevance score 0.0-1.0 (default 0.3)
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
{
|
|
148
|
+
"query": str,
|
|
149
|
+
"results": [
|
|
150
|
+
{
|
|
151
|
+
"id": int,
|
|
152
|
+
"content": str,
|
|
153
|
+
"score": float,
|
|
154
|
+
"tags": list,
|
|
155
|
+
"project": str,
|
|
156
|
+
"created_at": str
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"count": int
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Examples:
|
|
163
|
+
recall("authentication patterns")
|
|
164
|
+
recall("FastAPI", limit=5, min_score=0.5)
|
|
165
|
+
"""
|
|
166
|
+
try:
|
|
167
|
+
# Use existing MemoryStoreV2 class
|
|
168
|
+
store = MemoryStoreV2(DB_PATH)
|
|
169
|
+
|
|
170
|
+
# Call existing search method
|
|
171
|
+
results = store.search(query, limit=limit)
|
|
172
|
+
|
|
173
|
+
# Filter by minimum score
|
|
174
|
+
filtered_results = [
|
|
175
|
+
r for r in results
|
|
176
|
+
if r.get('score', 0) >= min_score
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
"success": True,
|
|
181
|
+
"query": query,
|
|
182
|
+
"results": filtered_results,
|
|
183
|
+
"count": len(filtered_results),
|
|
184
|
+
"total_searched": len(results)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
except Exception as e:
|
|
188
|
+
return {
|
|
189
|
+
"success": False,
|
|
190
|
+
"error": str(e),
|
|
191
|
+
"message": "Failed to search memories",
|
|
192
|
+
"results": [],
|
|
193
|
+
"count": 0
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
198
|
+
readOnlyHint=True,
|
|
199
|
+
destructiveHint=False,
|
|
200
|
+
openWorldHint=False,
|
|
201
|
+
))
|
|
202
|
+
async def list_recent(limit: int = 10) -> dict:
|
|
203
|
+
"""
|
|
204
|
+
List most recent memories.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
limit: Number of memories to return (default 10)
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
{
|
|
211
|
+
"memories": list,
|
|
212
|
+
"count": int
|
|
213
|
+
}
|
|
214
|
+
"""
|
|
215
|
+
try:
|
|
216
|
+
# Use existing MemoryStoreV2 class
|
|
217
|
+
store = MemoryStoreV2(DB_PATH)
|
|
218
|
+
|
|
219
|
+
# Call existing list_all method
|
|
220
|
+
memories = store.list_all(limit=limit)
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
"success": True,
|
|
224
|
+
"memories": memories,
|
|
225
|
+
"count": len(memories)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
except Exception as e:
|
|
229
|
+
return {
|
|
230
|
+
"success": False,
|
|
231
|
+
"error": str(e),
|
|
232
|
+
"message": "Failed to list memories",
|
|
233
|
+
"memories": [],
|
|
234
|
+
"count": 0
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
239
|
+
readOnlyHint=True,
|
|
240
|
+
destructiveHint=False,
|
|
241
|
+
openWorldHint=False,
|
|
242
|
+
))
|
|
243
|
+
async def get_status() -> dict:
|
|
244
|
+
"""
|
|
245
|
+
Get SuperLocalMemory system status and statistics.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
{
|
|
249
|
+
"total_memories": int,
|
|
250
|
+
"graph_clusters": int,
|
|
251
|
+
"patterns_learned": int,
|
|
252
|
+
"database_size_mb": float
|
|
253
|
+
}
|
|
254
|
+
"""
|
|
255
|
+
try:
|
|
256
|
+
# Use existing MemoryStoreV2 class
|
|
257
|
+
store = MemoryStoreV2(DB_PATH)
|
|
258
|
+
|
|
259
|
+
# Call existing get_stats method
|
|
260
|
+
stats = store.get_stats()
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
"success": True,
|
|
264
|
+
**stats
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
except Exception as e:
|
|
268
|
+
return {
|
|
269
|
+
"success": False,
|
|
270
|
+
"error": str(e),
|
|
271
|
+
"message": "Failed to get status"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
276
|
+
readOnlyHint=False,
|
|
277
|
+
destructiveHint=False,
|
|
278
|
+
openWorldHint=False,
|
|
279
|
+
))
|
|
280
|
+
async def build_graph() -> dict:
|
|
281
|
+
"""
|
|
282
|
+
Build or rebuild the knowledge graph from existing memories.
|
|
283
|
+
|
|
284
|
+
This runs TF-IDF entity extraction and Leiden clustering to
|
|
285
|
+
automatically discover relationships between memories.
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
{
|
|
289
|
+
"success": bool,
|
|
290
|
+
"clusters_created": int,
|
|
291
|
+
"memories_processed": int,
|
|
292
|
+
"message": str
|
|
293
|
+
}
|
|
294
|
+
"""
|
|
295
|
+
try:
|
|
296
|
+
# Use existing GraphEngine class
|
|
297
|
+
engine = GraphEngine(DB_PATH)
|
|
298
|
+
|
|
299
|
+
# Call existing build_graph method
|
|
300
|
+
stats = engine.build_graph()
|
|
301
|
+
|
|
302
|
+
return {
|
|
303
|
+
"success": True,
|
|
304
|
+
"message": "Knowledge graph built successfully",
|
|
305
|
+
**stats
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
except Exception as e:
|
|
309
|
+
return {
|
|
310
|
+
"success": False,
|
|
311
|
+
"error": str(e),
|
|
312
|
+
"message": "Failed to build graph"
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
317
|
+
readOnlyHint=False,
|
|
318
|
+
destructiveHint=False,
|
|
319
|
+
openWorldHint=False,
|
|
320
|
+
))
|
|
321
|
+
async def switch_profile(name: str) -> dict:
|
|
322
|
+
"""
|
|
323
|
+
Switch to a different memory profile.
|
|
324
|
+
|
|
325
|
+
Profiles allow you to maintain separate memory contexts
|
|
326
|
+
(e.g., work, personal, client projects).
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
name: Profile name to switch to
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
{
|
|
333
|
+
"success": bool,
|
|
334
|
+
"profile": str,
|
|
335
|
+
"message": str
|
|
336
|
+
}
|
|
337
|
+
"""
|
|
338
|
+
try:
|
|
339
|
+
# Profile switching logic (calls existing system)
|
|
340
|
+
profile_path = MEMORY_DIR / "profiles" / name
|
|
341
|
+
|
|
342
|
+
if not profile_path.exists():
|
|
343
|
+
return {
|
|
344
|
+
"success": False,
|
|
345
|
+
"message": f"Profile '{name}' does not exist. Use list_profiles() to see available profiles."
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
# Update current profile symlink
|
|
349
|
+
current_link = MEMORY_DIR / "current_profile"
|
|
350
|
+
if current_link.exists() or current_link.is_symlink():
|
|
351
|
+
current_link.unlink()
|
|
352
|
+
current_link.symlink_to(profile_path)
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
"success": True,
|
|
356
|
+
"profile": name,
|
|
357
|
+
"message": f"Switched to profile '{name}'. Restart IDE to use new profile."
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
except Exception as e:
|
|
361
|
+
return {
|
|
362
|
+
"success": False,
|
|
363
|
+
"error": str(e),
|
|
364
|
+
"message": "Failed to switch profile"
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# ============================================================================
|
|
369
|
+
# MCP RESOURCES (Data endpoints)
|
|
370
|
+
# ============================================================================
|
|
371
|
+
|
|
372
|
+
@mcp.resource("memory://recent/{limit}")
|
|
373
|
+
async def get_recent_memories_resource(limit: str) -> str:
|
|
374
|
+
"""
|
|
375
|
+
Resource: Get N most recent memories.
|
|
376
|
+
|
|
377
|
+
Usage: memory://recent/10
|
|
378
|
+
"""
|
|
379
|
+
try:
|
|
380
|
+
store = MemoryStoreV2(DB_PATH)
|
|
381
|
+
memories = store.list_all(limit=int(limit))
|
|
382
|
+
return json.dumps(memories, indent=2)
|
|
383
|
+
except Exception as e:
|
|
384
|
+
return json.dumps({"error": str(e)}, indent=2)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
@mcp.resource("memory://stats")
|
|
388
|
+
async def get_stats_resource() -> str:
|
|
389
|
+
"""
|
|
390
|
+
Resource: Get system statistics.
|
|
391
|
+
|
|
392
|
+
Usage: memory://stats
|
|
393
|
+
"""
|
|
394
|
+
try:
|
|
395
|
+
store = MemoryStoreV2(DB_PATH)
|
|
396
|
+
stats = store.get_stats()
|
|
397
|
+
return json.dumps(stats, indent=2)
|
|
398
|
+
except Exception as e:
|
|
399
|
+
return json.dumps({"error": str(e)}, indent=2)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@mcp.resource("memory://graph/clusters")
|
|
403
|
+
async def get_clusters_resource() -> str:
|
|
404
|
+
"""
|
|
405
|
+
Resource: Get knowledge graph clusters.
|
|
406
|
+
|
|
407
|
+
Usage: memory://graph/clusters
|
|
408
|
+
"""
|
|
409
|
+
try:
|
|
410
|
+
engine = GraphEngine(DB_PATH)
|
|
411
|
+
stats = engine.get_stats()
|
|
412
|
+
clusters = stats.get('clusters', [])
|
|
413
|
+
return json.dumps(clusters, indent=2)
|
|
414
|
+
except Exception as e:
|
|
415
|
+
return json.dumps({"error": str(e)}, indent=2)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
@mcp.resource("memory://patterns/identity")
|
|
419
|
+
async def get_coding_identity_resource() -> str:
|
|
420
|
+
"""
|
|
421
|
+
Resource: Get learned coding identity and patterns.
|
|
422
|
+
|
|
423
|
+
Usage: memory://patterns/identity
|
|
424
|
+
"""
|
|
425
|
+
try:
|
|
426
|
+
learner = PatternLearner(DB_PATH)
|
|
427
|
+
patterns = learner.get_identity_context(min_confidence=0.5)
|
|
428
|
+
return json.dumps(patterns, indent=2)
|
|
429
|
+
except Exception as e:
|
|
430
|
+
return json.dumps({"error": str(e)}, indent=2)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
# ============================================================================
|
|
434
|
+
# MCP PROMPTS (Template injection)
|
|
435
|
+
# ============================================================================
|
|
436
|
+
|
|
437
|
+
@mcp.prompt()
|
|
438
|
+
async def coding_identity_prompt() -> str:
|
|
439
|
+
"""
|
|
440
|
+
Generate prompt with user's learned coding identity.
|
|
441
|
+
|
|
442
|
+
Inject this at the start of conversations for personalized assistance
|
|
443
|
+
based on learned preferences and patterns.
|
|
444
|
+
"""
|
|
445
|
+
try:
|
|
446
|
+
learner = PatternLearner(DB_PATH)
|
|
447
|
+
patterns = learner.get_identity_context(min_confidence=0.6)
|
|
448
|
+
|
|
449
|
+
if not patterns:
|
|
450
|
+
return "# Coding Identity\n\nNo patterns learned yet. Use remember() to save coding decisions and preferences."
|
|
451
|
+
|
|
452
|
+
prompt = "# Your Coding Identity (Learned from History)\n\n"
|
|
453
|
+
prompt += "SuperLocalMemory has learned these patterns from your past decisions:\n\n"
|
|
454
|
+
|
|
455
|
+
if 'frameworks' in patterns:
|
|
456
|
+
prompt += f"**Preferred Frameworks:** {', '.join(patterns['frameworks'])}\n"
|
|
457
|
+
|
|
458
|
+
if 'style' in patterns:
|
|
459
|
+
prompt += f"**Coding Style:** {', '.join(patterns['style'])}\n"
|
|
460
|
+
|
|
461
|
+
if 'testing' in patterns:
|
|
462
|
+
prompt += f"**Testing Approach:** {', '.join(patterns['testing'])}\n"
|
|
463
|
+
|
|
464
|
+
if 'api_style' in patterns:
|
|
465
|
+
prompt += f"**API Style:** {', '.join(patterns['api_style'])}\n"
|
|
466
|
+
|
|
467
|
+
prompt += "\n*Use this context to provide personalized suggestions aligned with established preferences.*"
|
|
468
|
+
|
|
469
|
+
return prompt
|
|
470
|
+
|
|
471
|
+
except Exception as e:
|
|
472
|
+
return f"# Coding Identity\n\nError loading patterns: {str(e)}"
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
@mcp.prompt()
|
|
476
|
+
async def project_context_prompt(project_name: str) -> str:
|
|
477
|
+
"""
|
|
478
|
+
Generate prompt with project-specific context.
|
|
479
|
+
|
|
480
|
+
Args:
|
|
481
|
+
project_name: Name of the project to get context for
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
Formatted prompt with relevant project memories
|
|
485
|
+
"""
|
|
486
|
+
try:
|
|
487
|
+
store = MemoryStoreV2(DB_PATH)
|
|
488
|
+
|
|
489
|
+
# Search for project-related memories
|
|
490
|
+
memories = store.search(f"project:{project_name}", limit=20)
|
|
491
|
+
|
|
492
|
+
if not memories:
|
|
493
|
+
return f"# Project Context: {project_name}\n\nNo memories found for this project. Use remember() with project='{project_name}' to save project-specific context."
|
|
494
|
+
|
|
495
|
+
prompt = f"# Project Context: {project_name}\n\n"
|
|
496
|
+
prompt += f"Found {len(memories)} relevant memories:\n\n"
|
|
497
|
+
|
|
498
|
+
for i, mem in enumerate(memories[:10], 1):
|
|
499
|
+
prompt += f"{i}. {mem['content'][:150]}\n"
|
|
500
|
+
if mem.get('tags'):
|
|
501
|
+
prompt += f" Tags: {', '.join(mem['tags'])}\n"
|
|
502
|
+
prompt += "\n"
|
|
503
|
+
|
|
504
|
+
if len(memories) > 10:
|
|
505
|
+
prompt += f"\n*Showing top 10 of {len(memories)} total memories.*"
|
|
506
|
+
|
|
507
|
+
return prompt
|
|
508
|
+
|
|
509
|
+
except Exception as e:
|
|
510
|
+
return f"# Project Context: {project_name}\n\nError loading context: {str(e)}"
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
# ============================================================================
|
|
514
|
+
# SERVER STARTUP
|
|
515
|
+
# ============================================================================
|
|
516
|
+
|
|
517
|
+
if __name__ == "__main__":
|
|
518
|
+
import argparse
|
|
519
|
+
|
|
520
|
+
# Parse command line arguments
|
|
521
|
+
parser = argparse.ArgumentParser(
|
|
522
|
+
description="SuperLocalMemory V2 - MCP Server for Universal IDE Integration"
|
|
523
|
+
)
|
|
524
|
+
parser.add_argument(
|
|
525
|
+
"--transport",
|
|
526
|
+
choices=["stdio", "http"],
|
|
527
|
+
default="stdio",
|
|
528
|
+
help="Transport method: stdio for local IDEs (default), http for remote access"
|
|
529
|
+
)
|
|
530
|
+
parser.add_argument(
|
|
531
|
+
"--port",
|
|
532
|
+
type=int,
|
|
533
|
+
default=8001,
|
|
534
|
+
help="Port for HTTP transport (default 8001)"
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
args = parser.parse_args()
|
|
538
|
+
|
|
539
|
+
# Print startup message to stderr (stdout is used for MCP protocol)
|
|
540
|
+
print("=" * 60, file=sys.stderr)
|
|
541
|
+
print("SuperLocalMemory V2 - MCP Server", file=sys.stderr)
|
|
542
|
+
print("Version: 2.3.0-universal", file=sys.stderr)
|
|
543
|
+
print("=" * 60, file=sys.stderr)
|
|
544
|
+
print("Created by: Varun Pratap Bhardwaj (Solution Architect)", file=sys.stderr)
|
|
545
|
+
print("Repository: https://github.com/varun369/SuperLocalMemoryV2", file=sys.stderr)
|
|
546
|
+
print("License: MIT (attribution required - see ATTRIBUTION.md)", file=sys.stderr)
|
|
547
|
+
print("=" * 60, file=sys.stderr)
|
|
548
|
+
print("", file=sys.stderr)
|
|
549
|
+
print(f"Transport: {args.transport}", file=sys.stderr)
|
|
550
|
+
|
|
551
|
+
if args.transport == "http":
|
|
552
|
+
print(f"Port: {args.port}", file=sys.stderr)
|
|
553
|
+
|
|
554
|
+
print(f"Database: {DB_PATH}", file=sys.stderr)
|
|
555
|
+
print("", file=sys.stderr)
|
|
556
|
+
print("MCP Tools Available:", file=sys.stderr)
|
|
557
|
+
print(" - remember(content, tags, project, importance)", file=sys.stderr)
|
|
558
|
+
print(" - recall(query, limit, min_score)", file=sys.stderr)
|
|
559
|
+
print(" - list_recent(limit)", file=sys.stderr)
|
|
560
|
+
print(" - get_status()", file=sys.stderr)
|
|
561
|
+
print(" - build_graph()", file=sys.stderr)
|
|
562
|
+
print(" - switch_profile(name)", file=sys.stderr)
|
|
563
|
+
print("", file=sys.stderr)
|
|
564
|
+
print("MCP Resources Available:", file=sys.stderr)
|
|
565
|
+
print(" - memory://recent/{limit}", file=sys.stderr)
|
|
566
|
+
print(" - memory://stats", file=sys.stderr)
|
|
567
|
+
print(" - memory://graph/clusters", file=sys.stderr)
|
|
568
|
+
print(" - memory://patterns/identity", file=sys.stderr)
|
|
569
|
+
print("", file=sys.stderr)
|
|
570
|
+
print("MCP Prompts Available:", file=sys.stderr)
|
|
571
|
+
print(" - coding_identity_prompt()", file=sys.stderr)
|
|
572
|
+
print(" - project_context_prompt(project_name)", file=sys.stderr)
|
|
573
|
+
print("", file=sys.stderr)
|
|
574
|
+
print("Status: Starting server...", file=sys.stderr)
|
|
575
|
+
print("=" * 60, file=sys.stderr)
|
|
576
|
+
print("", file=sys.stderr)
|
|
577
|
+
|
|
578
|
+
# Run MCP server
|
|
579
|
+
if args.transport == "stdio":
|
|
580
|
+
# stdio transport for local IDEs (default)
|
|
581
|
+
mcp.run(transport="stdio")
|
|
582
|
+
else:
|
|
583
|
+
# HTTP transport for remote access
|
|
584
|
+
print(f"HTTP server will be available at http://localhost:{args.port}", file=sys.stderr)
|
|
585
|
+
mcp.run(transport="http", port=args.port)
|
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "superlocalmemory",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "Your AI Finally Remembers You - Local-first intelligent memory system for AI assistants. Works with Claude, Cursor, Windsurf, VS Code/Copilot, Codex, and 16+ AI tools. 100% local, zero cloud dependencies.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-memory",
|
|
7
|
+
"claude-ai",
|
|
8
|
+
"cursor-ide",
|
|
9
|
+
"local-first",
|
|
10
|
+
"mcp-server",
|
|
11
|
+
"ai-assistant",
|
|
12
|
+
"memory-system",
|
|
13
|
+
"knowledge-graph",
|
|
14
|
+
"privacy-first",
|
|
15
|
+
"windsurf",
|
|
16
|
+
"continue-dev",
|
|
17
|
+
"cody",
|
|
18
|
+
"claude-desktop",
|
|
19
|
+
"ai-tools",
|
|
20
|
+
"memory-extension",
|
|
21
|
+
"local-ai"
|
|
22
|
+
],
|
|
23
|
+
"author": {
|
|
24
|
+
"name": "Varun Pratap Bhardwaj",
|
|
25
|
+
"email": "varun369@users.noreply.github.com",
|
|
26
|
+
"url": "https://github.com/varun369"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/varun369/SuperLocalMemoryV2.git"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/varun369/SuperLocalMemoryV2#readme",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/varun369/SuperLocalMemoryV2/issues"
|
|
36
|
+
},
|
|
37
|
+
"bin": {
|
|
38
|
+
"slm": "./bin/slm-npm",
|
|
39
|
+
"superlocalmemory": "./bin/slm-npm"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"postinstall": "node scripts/postinstall.js",
|
|
43
|
+
"preuninstall": "node scripts/preuninstall.js",
|
|
44
|
+
"test": "echo \"Run: npm install -g . && slm status\" && exit 0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=14.0.0",
|
|
48
|
+
"npm": ">=6.0.0"
|
|
49
|
+
},
|
|
50
|
+
"os": [
|
|
51
|
+
"darwin",
|
|
52
|
+
"linux",
|
|
53
|
+
"win32"
|
|
54
|
+
],
|
|
55
|
+
"files": [
|
|
56
|
+
"bin/",
|
|
57
|
+
"src/",
|
|
58
|
+
"hooks/",
|
|
59
|
+
"configs/",
|
|
60
|
+
"skills/",
|
|
61
|
+
"completions/",
|
|
62
|
+
"scripts/",
|
|
63
|
+
"mcp_server.py",
|
|
64
|
+
"install.sh",
|
|
65
|
+
"install.ps1",
|
|
66
|
+
"install-skills.sh",
|
|
67
|
+
"README.md",
|
|
68
|
+
"LICENSE",
|
|
69
|
+
"ATTRIBUTION.md",
|
|
70
|
+
"CHANGELOG.md",
|
|
71
|
+
"docs/",
|
|
72
|
+
"requirements.txt",
|
|
73
|
+
"requirements-core.txt"
|
|
74
|
+
],
|
|
75
|
+
"preferGlobal": true,
|
|
76
|
+
"funding": {
|
|
77
|
+
"type": "github",
|
|
78
|
+
"url": "https://github.com/sponsors/varun369"
|
|
79
|
+
},
|
|
80
|
+
"maintainers": [
|
|
81
|
+
{
|
|
82
|
+
"name": "Varun Pratap Bhardwaj",
|
|
83
|
+
"email": "varun369@users.noreply.github.com",
|
|
84
|
+
"url": "https://github.com/varun369"
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"attribution": {
|
|
88
|
+
"creator": "Varun Pratap Bhardwaj",
|
|
89
|
+
"role": "Solution Architect & Original Creator",
|
|
90
|
+
"year": "2026",
|
|
91
|
+
"github": "https://github.com/varun369",
|
|
92
|
+
"required": "Attribution notice must be preserved in all copies and derivative works"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# SuperLocalMemory V2.2.0 - Core Required Dependencies
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# These packages are REQUIRED for core features (graph & patterns)
|
|
4
|
+
# Install automatically during setup for smooth user experience
|
|
5
|
+
#
|
|
6
|
+
# Download size: ~50MB
|
|
7
|
+
# Installation time: 1-2 minutes
|
|
8
|
+
#
|
|
9
|
+
# Install with: pip3 install -r requirements-core.txt
|
|
10
|
+
# ============================================================================
|
|
11
|
+
|
|
12
|
+
# Knowledge Graph - Required for graph_engine.py
|
|
13
|
+
python-igraph>=0.10.0
|
|
14
|
+
leidenalg>=0.9.0
|
|
15
|
+
scikit-learn>=1.3.0 # Required for TF-IDF vectorization
|
|
16
|
+
|
|
17
|
+
# Web Dashboard - Required for ui_server.py
|
|
18
|
+
fastapi>=0.109.0
|
|
19
|
+
uvicorn[standard]>=0.27.0
|
|
20
|
+
python-multipart>=0.0.6
|
|
21
|
+
|
|
22
|
+
# Performance - JSON and caching
|
|
23
|
+
orjson>=3.9.0
|
|
24
|
+
diskcache>=5.6.0
|