spatial-memory-mcp 1.9.1__py3-none-any.whl
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.
- spatial_memory/__init__.py +97 -0
- spatial_memory/__main__.py +271 -0
- spatial_memory/adapters/__init__.py +7 -0
- spatial_memory/adapters/lancedb_repository.py +880 -0
- spatial_memory/config.py +769 -0
- spatial_memory/core/__init__.py +118 -0
- spatial_memory/core/cache.py +317 -0
- spatial_memory/core/circuit_breaker.py +297 -0
- spatial_memory/core/connection_pool.py +220 -0
- spatial_memory/core/consolidation_strategies.py +401 -0
- spatial_memory/core/database.py +3072 -0
- spatial_memory/core/db_idempotency.py +242 -0
- spatial_memory/core/db_indexes.py +576 -0
- spatial_memory/core/db_migrations.py +588 -0
- spatial_memory/core/db_search.py +512 -0
- spatial_memory/core/db_versioning.py +178 -0
- spatial_memory/core/embeddings.py +558 -0
- spatial_memory/core/errors.py +317 -0
- spatial_memory/core/file_security.py +701 -0
- spatial_memory/core/filesystem.py +178 -0
- spatial_memory/core/health.py +289 -0
- spatial_memory/core/helpers.py +79 -0
- spatial_memory/core/import_security.py +433 -0
- spatial_memory/core/lifecycle_ops.py +1067 -0
- spatial_memory/core/logging.py +194 -0
- spatial_memory/core/metrics.py +192 -0
- spatial_memory/core/models.py +660 -0
- spatial_memory/core/rate_limiter.py +326 -0
- spatial_memory/core/response_types.py +500 -0
- spatial_memory/core/security.py +588 -0
- spatial_memory/core/spatial_ops.py +430 -0
- spatial_memory/core/tracing.py +300 -0
- spatial_memory/core/utils.py +110 -0
- spatial_memory/core/validation.py +406 -0
- spatial_memory/factory.py +444 -0
- spatial_memory/migrations/__init__.py +40 -0
- spatial_memory/ports/__init__.py +11 -0
- spatial_memory/ports/repositories.py +630 -0
- spatial_memory/py.typed +0 -0
- spatial_memory/server.py +1214 -0
- spatial_memory/services/__init__.py +70 -0
- spatial_memory/services/decay_manager.py +411 -0
- spatial_memory/services/export_import.py +1031 -0
- spatial_memory/services/lifecycle.py +1139 -0
- spatial_memory/services/memory.py +412 -0
- spatial_memory/services/spatial.py +1152 -0
- spatial_memory/services/utility.py +429 -0
- spatial_memory/tools/__init__.py +5 -0
- spatial_memory/tools/definitions.py +695 -0
- spatial_memory/verify.py +140 -0
- spatial_memory_mcp-1.9.1.dist-info/METADATA +509 -0
- spatial_memory_mcp-1.9.1.dist-info/RECORD +55 -0
- spatial_memory_mcp-1.9.1.dist-info/WHEEL +4 -0
- spatial_memory_mcp-1.9.1.dist-info/entry_points.txt +2 -0
- spatial_memory_mcp-1.9.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Spatial Memory MCP Server - Vector-based semantic memory for LLMs."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.9.1"
|
|
4
|
+
__author__ = "arman-tech"
|
|
5
|
+
|
|
6
|
+
# Re-export core components for convenience
|
|
7
|
+
# Adapters
|
|
8
|
+
from spatial_memory.adapters.lancedb_repository import LanceDBMemoryRepository
|
|
9
|
+
from spatial_memory.config import Settings, get_settings
|
|
10
|
+
from spatial_memory.core import (
|
|
11
|
+
ClusterInfo,
|
|
12
|
+
ClusteringError,
|
|
13
|
+
ConfigurationError,
|
|
14
|
+
# Core services
|
|
15
|
+
Database,
|
|
16
|
+
EmbeddingError,
|
|
17
|
+
EmbeddingService,
|
|
18
|
+
Filter,
|
|
19
|
+
FilterGroup,
|
|
20
|
+
FilterOperator,
|
|
21
|
+
JourneyStep,
|
|
22
|
+
# Models
|
|
23
|
+
Memory,
|
|
24
|
+
MemoryNotFoundError,
|
|
25
|
+
MemoryResult,
|
|
26
|
+
MemorySource,
|
|
27
|
+
NamespaceNotFoundError,
|
|
28
|
+
# Errors
|
|
29
|
+
SpatialMemoryError,
|
|
30
|
+
StorageError,
|
|
31
|
+
ValidationError,
|
|
32
|
+
VisualizationCluster,
|
|
33
|
+
VisualizationData,
|
|
34
|
+
VisualizationEdge,
|
|
35
|
+
VisualizationError,
|
|
36
|
+
VisualizationNode,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Server
|
|
40
|
+
from spatial_memory.server import SpatialMemoryServer, create_server
|
|
41
|
+
|
|
42
|
+
# Services
|
|
43
|
+
from spatial_memory.services.memory import (
|
|
44
|
+
ForgetResult,
|
|
45
|
+
MemoryService,
|
|
46
|
+
NearbyResult,
|
|
47
|
+
RecallResult,
|
|
48
|
+
RememberBatchResult,
|
|
49
|
+
RememberResult,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
# Version info
|
|
54
|
+
"__version__",
|
|
55
|
+
"__author__",
|
|
56
|
+
# Configuration
|
|
57
|
+
"Settings",
|
|
58
|
+
"get_settings",
|
|
59
|
+
# Errors
|
|
60
|
+
"SpatialMemoryError",
|
|
61
|
+
"MemoryNotFoundError",
|
|
62
|
+
"NamespaceNotFoundError",
|
|
63
|
+
"EmbeddingError",
|
|
64
|
+
"StorageError",
|
|
65
|
+
"ValidationError",
|
|
66
|
+
"ConfigurationError",
|
|
67
|
+
"ClusteringError",
|
|
68
|
+
"VisualizationError",
|
|
69
|
+
# Models
|
|
70
|
+
"Memory",
|
|
71
|
+
"MemorySource",
|
|
72
|
+
"MemoryResult",
|
|
73
|
+
"ClusterInfo",
|
|
74
|
+
"JourneyStep",
|
|
75
|
+
"VisualizationNode",
|
|
76
|
+
"VisualizationEdge",
|
|
77
|
+
"VisualizationCluster",
|
|
78
|
+
"VisualizationData",
|
|
79
|
+
"Filter",
|
|
80
|
+
"FilterOperator",
|
|
81
|
+
"FilterGroup",
|
|
82
|
+
# Core services
|
|
83
|
+
"Database",
|
|
84
|
+
"EmbeddingService",
|
|
85
|
+
# Services
|
|
86
|
+
"MemoryService",
|
|
87
|
+
"RememberResult",
|
|
88
|
+
"RememberBatchResult",
|
|
89
|
+
"RecallResult",
|
|
90
|
+
"NearbyResult",
|
|
91
|
+
"ForgetResult",
|
|
92
|
+
# Adapters
|
|
93
|
+
"LanceDBMemoryRepository",
|
|
94
|
+
# Server
|
|
95
|
+
"SpatialMemoryServer",
|
|
96
|
+
"create_server",
|
|
97
|
+
]
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""Entry point for running the Spatial Memory MCP Server and CLI commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import asyncio
|
|
7
|
+
import logging
|
|
8
|
+
import sys
|
|
9
|
+
from typing import NoReturn
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def run_server() -> None:
|
|
15
|
+
"""Run the Spatial Memory MCP Server."""
|
|
16
|
+
from spatial_memory.server import main as server_main
|
|
17
|
+
|
|
18
|
+
asyncio.run(server_main())
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def run_migrate(args: argparse.Namespace) -> int:
|
|
22
|
+
"""Run database migrations.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
args: Parsed command line arguments.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Exit code (0 for success, 1 for error).
|
|
29
|
+
"""
|
|
30
|
+
from spatial_memory.config import get_settings
|
|
31
|
+
from spatial_memory.core.database import Database
|
|
32
|
+
from spatial_memory.core.db_migrations import (
|
|
33
|
+
CURRENT_SCHEMA_VERSION,
|
|
34
|
+
MigrationManager,
|
|
35
|
+
)
|
|
36
|
+
from spatial_memory.core.embeddings import EmbeddingService
|
|
37
|
+
|
|
38
|
+
settings = get_settings()
|
|
39
|
+
|
|
40
|
+
# Set up logging based on verbosity
|
|
41
|
+
log_level = logging.DEBUG if args.verbose else logging.INFO
|
|
42
|
+
logging.basicConfig(
|
|
43
|
+
level=log_level,
|
|
44
|
+
format="%(levelname)s: %(message)s",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
print("Spatial Memory Migration Tool")
|
|
48
|
+
print(f"Target schema version: {CURRENT_SCHEMA_VERSION}")
|
|
49
|
+
print(f"Database path: {settings.memory_path}")
|
|
50
|
+
print()
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
# Create embedding service if needed for migrations
|
|
54
|
+
embeddings = None
|
|
55
|
+
if not args.dry_run:
|
|
56
|
+
# Only load embeddings for actual migrations (some may need re-embedding)
|
|
57
|
+
print("Loading embedding service...")
|
|
58
|
+
embeddings = EmbeddingService(
|
|
59
|
+
model_name=settings.embedding_model,
|
|
60
|
+
openai_api_key=settings.openai_api_key,
|
|
61
|
+
backend=settings.embedding_backend, # type: ignore[arg-type]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Connect to database
|
|
65
|
+
print("Connecting to database...")
|
|
66
|
+
db = Database(
|
|
67
|
+
storage_path=settings.memory_path,
|
|
68
|
+
embedding_dim=embeddings.dimensions if embeddings else 384,
|
|
69
|
+
auto_create_indexes=settings.auto_create_indexes,
|
|
70
|
+
)
|
|
71
|
+
db.connect()
|
|
72
|
+
|
|
73
|
+
# Create migration manager
|
|
74
|
+
manager = MigrationManager(db, embeddings)
|
|
75
|
+
manager.register_builtin_migrations()
|
|
76
|
+
|
|
77
|
+
current_version = manager.get_current_version()
|
|
78
|
+
print(f"Current schema version: {current_version}")
|
|
79
|
+
|
|
80
|
+
if args.status:
|
|
81
|
+
# Just show status, don't run migrations
|
|
82
|
+
pending = manager.get_pending_migrations()
|
|
83
|
+
if pending:
|
|
84
|
+
print(f"\nPending migrations ({len(pending)}):")
|
|
85
|
+
for migration in pending:
|
|
86
|
+
print(f" - {migration.version}: {migration.description}")
|
|
87
|
+
else:
|
|
88
|
+
print("\nNo pending migrations. Database is up to date.")
|
|
89
|
+
|
|
90
|
+
applied = manager.get_applied_migrations()
|
|
91
|
+
if applied:
|
|
92
|
+
print(f"\nApplied migrations ({len(applied)}):")
|
|
93
|
+
for record in applied:
|
|
94
|
+
applied_ts = record.applied_at
|
|
95
|
+
print(f" - {record.version}: {record.description} (applied: {applied_ts})")
|
|
96
|
+
|
|
97
|
+
db.close()
|
|
98
|
+
return 0
|
|
99
|
+
|
|
100
|
+
if args.rollback:
|
|
101
|
+
# Rollback to specified version
|
|
102
|
+
print(f"\nRolling back to version {args.rollback}...")
|
|
103
|
+
result = manager.rollback(args.rollback)
|
|
104
|
+
|
|
105
|
+
if result.errors:
|
|
106
|
+
print("\nRollback failed with errors:")
|
|
107
|
+
for error in result.errors:
|
|
108
|
+
print(f" - {error}")
|
|
109
|
+
db.close()
|
|
110
|
+
return 1
|
|
111
|
+
|
|
112
|
+
if result.migrations_applied:
|
|
113
|
+
print("\nRolled back migrations:")
|
|
114
|
+
for v in result.migrations_applied:
|
|
115
|
+
print(f" - {v}")
|
|
116
|
+
print(f"\nCurrent version: {result.current_version}")
|
|
117
|
+
else:
|
|
118
|
+
print("\nNo migrations to rollback.")
|
|
119
|
+
|
|
120
|
+
db.close()
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
# Run pending migrations
|
|
124
|
+
pending = manager.get_pending_migrations()
|
|
125
|
+
if not pending:
|
|
126
|
+
print("\nNo pending migrations. Database is up to date.")
|
|
127
|
+
db.close()
|
|
128
|
+
return 0
|
|
129
|
+
|
|
130
|
+
print(f"\nPending migrations ({len(pending)}):")
|
|
131
|
+
for m in pending:
|
|
132
|
+
print(f" - {m.version}: {m.description}")
|
|
133
|
+
|
|
134
|
+
if args.dry_run:
|
|
135
|
+
print("\n[DRY RUN] Would apply the above migrations.")
|
|
136
|
+
print("Run without --dry-run to apply.")
|
|
137
|
+
db.close()
|
|
138
|
+
return 0
|
|
139
|
+
|
|
140
|
+
# Confirm before applying
|
|
141
|
+
if not args.yes:
|
|
142
|
+
print()
|
|
143
|
+
response = input("Apply these migrations? [y/N] ").strip().lower()
|
|
144
|
+
if response not in ("y", "yes"):
|
|
145
|
+
print("Aborted.")
|
|
146
|
+
db.close()
|
|
147
|
+
return 0
|
|
148
|
+
|
|
149
|
+
print("\nApplying migrations...")
|
|
150
|
+
result = manager.run_pending(dry_run=False)
|
|
151
|
+
|
|
152
|
+
if result.errors:
|
|
153
|
+
print("\nMigration failed with errors:")
|
|
154
|
+
for error in result.errors:
|
|
155
|
+
print(f" - {error}")
|
|
156
|
+
print("\nSome migrations may have been applied. Check database state.")
|
|
157
|
+
db.close()
|
|
158
|
+
return 1
|
|
159
|
+
|
|
160
|
+
print(f"\nSuccessfully applied {len(result.migrations_applied)} migration(s):")
|
|
161
|
+
for v in result.migrations_applied:
|
|
162
|
+
print(f" - {v}")
|
|
163
|
+
print(f"\nCurrent version: {result.current_version}")
|
|
164
|
+
|
|
165
|
+
db.close()
|
|
166
|
+
return 0
|
|
167
|
+
|
|
168
|
+
except Exception as e:
|
|
169
|
+
logger.error(f"Migration failed: {e}", exc_info=args.verbose)
|
|
170
|
+
print(f"\nError: {e}")
|
|
171
|
+
return 1
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def run_version() -> None:
|
|
175
|
+
"""Print version information."""
|
|
176
|
+
from spatial_memory import __version__
|
|
177
|
+
|
|
178
|
+
print(f"spatial-memory {__version__}")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def run_instructions() -> None:
|
|
182
|
+
"""Print the MCP server instructions that are auto-injected into Claude's context."""
|
|
183
|
+
from spatial_memory.server import SpatialMemoryServer
|
|
184
|
+
|
|
185
|
+
instructions = SpatialMemoryServer._get_server_instructions()
|
|
186
|
+
print(instructions)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def main() -> NoReturn:
|
|
190
|
+
"""Main entry point with subcommand support."""
|
|
191
|
+
parser = argparse.ArgumentParser(
|
|
192
|
+
prog="spatial-memory",
|
|
193
|
+
description="Spatial Memory MCP Server and CLI tools",
|
|
194
|
+
)
|
|
195
|
+
parser.add_argument(
|
|
196
|
+
"--version", "-V",
|
|
197
|
+
action="store_true",
|
|
198
|
+
help="Show version and exit",
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
subparsers = parser.add_subparsers(
|
|
202
|
+
dest="command",
|
|
203
|
+
title="commands",
|
|
204
|
+
description="Available commands",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Server command (default)
|
|
208
|
+
subparsers.add_parser(
|
|
209
|
+
"serve",
|
|
210
|
+
help="Start the MCP server (default if no command given)",
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Instructions command
|
|
214
|
+
subparsers.add_parser(
|
|
215
|
+
"instructions",
|
|
216
|
+
help="Show the MCP instructions injected into Claude's context",
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
# Migrate command
|
|
220
|
+
migrate_parser = subparsers.add_parser(
|
|
221
|
+
"migrate",
|
|
222
|
+
help="Run database migrations",
|
|
223
|
+
)
|
|
224
|
+
migrate_parser.add_argument(
|
|
225
|
+
"--dry-run",
|
|
226
|
+
action="store_true",
|
|
227
|
+
help="Preview migrations without applying",
|
|
228
|
+
)
|
|
229
|
+
migrate_parser.add_argument(
|
|
230
|
+
"--status",
|
|
231
|
+
action="store_true",
|
|
232
|
+
help="Show migration status and exit",
|
|
233
|
+
)
|
|
234
|
+
migrate_parser.add_argument(
|
|
235
|
+
"--rollback",
|
|
236
|
+
metavar="VERSION",
|
|
237
|
+
help="Rollback to specified version (e.g., 1.0.0)",
|
|
238
|
+
)
|
|
239
|
+
migrate_parser.add_argument(
|
|
240
|
+
"-y", "--yes",
|
|
241
|
+
action="store_true",
|
|
242
|
+
help="Skip confirmation prompt",
|
|
243
|
+
)
|
|
244
|
+
migrate_parser.add_argument(
|
|
245
|
+
"-v", "--verbose",
|
|
246
|
+
action="store_true",
|
|
247
|
+
help="Enable verbose output",
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
args = parser.parse_args()
|
|
251
|
+
|
|
252
|
+
if args.version:
|
|
253
|
+
run_version()
|
|
254
|
+
sys.exit(0)
|
|
255
|
+
|
|
256
|
+
if args.command == "instructions":
|
|
257
|
+
run_instructions()
|
|
258
|
+
sys.exit(0)
|
|
259
|
+
elif args.command == "migrate":
|
|
260
|
+
sys.exit(run_migrate(args))
|
|
261
|
+
elif args.command == "serve" or args.command is None:
|
|
262
|
+
# Default to running the server
|
|
263
|
+
run_server()
|
|
264
|
+
sys.exit(0)
|
|
265
|
+
else:
|
|
266
|
+
parser.print_help()
|
|
267
|
+
sys.exit(1)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
if __name__ == "__main__":
|
|
271
|
+
main()
|