agent-memory-mcp-server 0.1.0__tar.gz

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.
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .env
8
+ keys.env
9
+ .mcp.json
10
+ memory.db
@@ -0,0 +1,83 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-memory-mcp-server
3
+ Version: 0.1.0
4
+ Summary: Persistent memory for AI agents — store, retrieve and search knowledge across sessions
5
+ Project-URL: Homepage, https://github.com/AiAgentKarl/agent-memory-mcp-server
6
+ Project-URL: Repository, https://github.com/AiAgentKarl/agent-memory-mcp-server
7
+ Author: AiAgentKarl
8
+ License: MIT
9
+ Keywords: ai-agents,knowledge-base,mcp,memory,persistence,rag
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: mcp>=1.0.0
17
+ Requires-Dist: pydantic>=2.0.0
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Agent Memory MCP Server 🧠
21
+
22
+ Persistent memory for AI agents — store, retrieve and search knowledge across sessions. No more forgetting between conversations.
23
+
24
+ ## The Problem
25
+
26
+ AI agents lose all context when a session ends. This MCP server gives agents a **persistent knowledge store** that survives across sessions, tools, and even different agent frameworks.
27
+
28
+ ## Features
29
+
30
+ - **Store & Retrieve** — Key-value storage with full persistence
31
+ - **Namespaces** — Separate memories by project, user, or context
32
+ - **Tags** — Categorize memories for easy filtering
33
+ - **Full-Text Search** — Search across all stored knowledge
34
+ - **Access Tracking** — See which memories are accessed most
35
+ - **Statistics** — Dashboard showing memory usage
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install agent-memory-mcp-server
41
+ ```
42
+
43
+ ## Usage with Claude Code
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "memory": {
49
+ "command": "uvx",
50
+ "args": ["agent-memory-mcp-server"]
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## Tools
57
+
58
+ | Tool | Description |
59
+ |------|-------------|
60
+ | `memory_store` | Store a key-value pair persistently |
61
+ | `memory_retrieve` | Retrieve stored knowledge by key |
62
+ | `memory_search` | Full-text search across all memories |
63
+ | `memory_list` | List all memories in a namespace |
64
+ | `memory_delete` | Remove a memory |
65
+ | `memory_namespaces` | List all namespaces |
66
+ | `memory_stats` | Usage statistics |
67
+
68
+ ## Examples
69
+
70
+ ```
71
+ "Remember that the user prefers dark mode"
72
+ "What do you know about Project Alpha?"
73
+ "Store this API response for later"
74
+ "What were the key decisions from last session?"
75
+ ```
76
+
77
+ ## How It Works
78
+
79
+ Uses SQLite for zero-configuration persistent storage. Data is stored locally — no cloud, no API keys, no costs. The database file (`memory.db`) is created automatically in the server directory.
80
+
81
+ ## License
82
+
83
+ MIT
@@ -0,0 +1,64 @@
1
+ # Agent Memory MCP Server 🧠
2
+
3
+ Persistent memory for AI agents — store, retrieve and search knowledge across sessions. No more forgetting between conversations.
4
+
5
+ ## The Problem
6
+
7
+ AI agents lose all context when a session ends. This MCP server gives agents a **persistent knowledge store** that survives across sessions, tools, and even different agent frameworks.
8
+
9
+ ## Features
10
+
11
+ - **Store & Retrieve** — Key-value storage with full persistence
12
+ - **Namespaces** — Separate memories by project, user, or context
13
+ - **Tags** — Categorize memories for easy filtering
14
+ - **Full-Text Search** — Search across all stored knowledge
15
+ - **Access Tracking** — See which memories are accessed most
16
+ - **Statistics** — Dashboard showing memory usage
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install agent-memory-mcp-server
22
+ ```
23
+
24
+ ## Usage with Claude Code
25
+
26
+ ```json
27
+ {
28
+ "mcpServers": {
29
+ "memory": {
30
+ "command": "uvx",
31
+ "args": ["agent-memory-mcp-server"]
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ## Tools
38
+
39
+ | Tool | Description |
40
+ |------|-------------|
41
+ | `memory_store` | Store a key-value pair persistently |
42
+ | `memory_retrieve` | Retrieve stored knowledge by key |
43
+ | `memory_search` | Full-text search across all memories |
44
+ | `memory_list` | List all memories in a namespace |
45
+ | `memory_delete` | Remove a memory |
46
+ | `memory_namespaces` | List all namespaces |
47
+ | `memory_stats` | Usage statistics |
48
+
49
+ ## Examples
50
+
51
+ ```
52
+ "Remember that the user prefers dark mode"
53
+ "What do you know about Project Alpha?"
54
+ "Store this API response for later"
55
+ "What were the key decisions from last session?"
56
+ ```
57
+
58
+ ## How It Works
59
+
60
+ Uses SQLite for zero-configuration persistent storage. Data is stored locally — no cloud, no API keys, no costs. The database file (`memory.db`) is created automatically in the server directory.
61
+
62
+ ## License
63
+
64
+ MIT
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agent-memory-mcp-server"
7
+ version = "0.1.0"
8
+ description = "Persistent memory for AI agents — store, retrieve and search knowledge across sessions"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ authors = [{name = "AiAgentKarl"}]
13
+ keywords = ["mcp", "memory", "ai-agents", "persistence", "knowledge-base", "rag"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
20
+ ]
21
+ dependencies = [
22
+ "mcp>=1.0.0",
23
+ "pydantic>=2.0.0",
24
+ ]
25
+
26
+ [project.urls]
27
+ Homepage = "https://github.com/AiAgentKarl/agent-memory-mcp-server"
28
+ Repository = "https://github.com/AiAgentKarl/agent-memory-mcp-server"
29
+
30
+ [tool.hatch.build.targets.wheel]
31
+ packages = ["src"]
File without changes
@@ -0,0 +1,176 @@
1
+ """Datenbank — SQLite-basierter persistenter Speicher für Agent-Memories."""
2
+
3
+ import sqlite3
4
+ import json
5
+ import os
6
+ from datetime import datetime, timezone
7
+ from pathlib import Path
8
+
9
+
10
+ _DB_PATH = os.getenv("MEMORY_DB_PATH", str(Path(__file__).resolve().parent.parent / "memory.db"))
11
+
12
+
13
+ def _connect() -> sqlite3.Connection:
14
+ """DB-Verbindung herstellen und Schema anlegen."""
15
+ conn = sqlite3.connect(_DB_PATH)
16
+ conn.row_factory = sqlite3.Row
17
+ conn.execute("PRAGMA journal_mode=WAL") # Bessere Performance
18
+ conn.execute("""
19
+ CREATE TABLE IF NOT EXISTS memories (
20
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
21
+ namespace TEXT NOT NULL DEFAULT 'default',
22
+ key TEXT NOT NULL,
23
+ value TEXT NOT NULL,
24
+ tags TEXT,
25
+ created_at TEXT NOT NULL,
26
+ updated_at TEXT NOT NULL,
27
+ access_count INTEGER DEFAULT 0,
28
+ UNIQUE(namespace, key)
29
+ )
30
+ """)
31
+ conn.execute("""
32
+ CREATE INDEX IF NOT EXISTS idx_namespace ON memories(namespace)
33
+ """)
34
+ conn.execute("""
35
+ CREATE INDEX IF NOT EXISTS idx_tags ON memories(tags)
36
+ """)
37
+ conn.commit()
38
+ return conn
39
+
40
+
41
+ def store(namespace: str, key: str, value: str, tags: list[str] = None) -> dict:
42
+ """Memory speichern oder aktualisieren."""
43
+ conn = _connect()
44
+ now = datetime.now(timezone.utc).isoformat()
45
+ tags_str = json.dumps(tags) if tags else None
46
+
47
+ conn.execute(
48
+ """INSERT INTO memories (namespace, key, value, tags, created_at, updated_at)
49
+ VALUES (?, ?, ?, ?, ?, ?)
50
+ ON CONFLICT(namespace, key) DO UPDATE SET
51
+ value=excluded.value,
52
+ tags=excluded.tags,
53
+ updated_at=excluded.updated_at""",
54
+ (namespace, key, value, tags_str, now, now),
55
+ )
56
+ conn.commit()
57
+ conn.close()
58
+ return {"namespace": namespace, "key": key, "stored": True, "updated_at": now}
59
+
60
+
61
+ def retrieve(namespace: str, key: str) -> dict | None:
62
+ """Memory abrufen und Zugriffszähler erhöhen."""
63
+ conn = _connect()
64
+ row = conn.execute(
65
+ "SELECT * FROM memories WHERE namespace=? AND key=?",
66
+ (namespace, key),
67
+ ).fetchone()
68
+
69
+ if row:
70
+ conn.execute(
71
+ "UPDATE memories SET access_count = access_count + 1 WHERE id=?",
72
+ (row["id"],),
73
+ )
74
+ conn.commit()
75
+ result = dict(row)
76
+ result["tags"] = json.loads(result["tags"]) if result["tags"] else []
77
+ conn.close()
78
+ return result
79
+
80
+ conn.close()
81
+ return None
82
+
83
+
84
+ def search(query: str, namespace: str = None, tags: list[str] = None, limit: int = 20) -> list:
85
+ """Memories durchsuchen (Key und Value)."""
86
+ conn = _connect()
87
+ sql = "SELECT * FROM memories WHERE (key LIKE ? OR value LIKE ?)"
88
+ params = [f"%{query}%", f"%{query}%"]
89
+
90
+ if namespace:
91
+ sql += " AND namespace=?"
92
+ params.append(namespace)
93
+
94
+ if tags:
95
+ for tag in tags:
96
+ sql += " AND tags LIKE ?"
97
+ params.append(f"%{tag}%")
98
+
99
+ sql += " ORDER BY updated_at DESC LIMIT ?"
100
+ params.append(limit)
101
+
102
+ rows = conn.execute(sql, params).fetchall()
103
+ conn.close()
104
+
105
+ results = []
106
+ for r in rows:
107
+ d = dict(r)
108
+ d["tags"] = json.loads(d["tags"]) if d["tags"] else []
109
+ results.append(d)
110
+ return results
111
+
112
+
113
+ def list_memories(namespace: str = None, limit: int = 50) -> list:
114
+ """Alle Memories auflisten."""
115
+ conn = _connect()
116
+ if namespace:
117
+ rows = conn.execute(
118
+ "SELECT * FROM memories WHERE namespace=? ORDER BY updated_at DESC LIMIT ?",
119
+ (namespace, limit),
120
+ ).fetchall()
121
+ else:
122
+ rows = conn.execute(
123
+ "SELECT * FROM memories ORDER BY updated_at DESC LIMIT ?",
124
+ (limit,),
125
+ ).fetchall()
126
+ conn.close()
127
+
128
+ results = []
129
+ for r in rows:
130
+ d = dict(r)
131
+ d["tags"] = json.loads(d["tags"]) if d["tags"] else []
132
+ results.append(d)
133
+ return results
134
+
135
+
136
+ def delete(namespace: str, key: str) -> dict:
137
+ """Memory löschen."""
138
+ conn = _connect()
139
+ cursor = conn.execute(
140
+ "DELETE FROM memories WHERE namespace=? AND key=?",
141
+ (namespace, key),
142
+ )
143
+ conn.commit()
144
+ conn.close()
145
+ return {"deleted": cursor.rowcount > 0, "namespace": namespace, "key": key}
146
+
147
+
148
+ def list_namespaces() -> list:
149
+ """Alle Namespaces auflisten mit Anzahl Memories."""
150
+ conn = _connect()
151
+ rows = conn.execute(
152
+ "SELECT namespace, COUNT(*) as count FROM memories GROUP BY namespace ORDER BY count DESC"
153
+ ).fetchall()
154
+ conn.close()
155
+ return [dict(r) for r in rows]
156
+
157
+
158
+ def get_stats() -> dict:
159
+ """Statistiken über den Speicher."""
160
+ conn = _connect()
161
+ total = conn.execute("SELECT COUNT(*) as c FROM memories").fetchone()["c"]
162
+ namespaces = conn.execute("SELECT COUNT(DISTINCT namespace) as c FROM memories").fetchone()["c"]
163
+ most_accessed = conn.execute(
164
+ "SELECT namespace, key, access_count FROM memories ORDER BY access_count DESC LIMIT 5"
165
+ ).fetchall()
166
+ recent = conn.execute(
167
+ "SELECT namespace, key, updated_at FROM memories ORDER BY updated_at DESC LIMIT 5"
168
+ ).fetchall()
169
+ conn.close()
170
+
171
+ return {
172
+ "total_memories": total,
173
+ "total_namespaces": namespaces,
174
+ "most_accessed": [dict(r) for r in most_accessed],
175
+ "recently_updated": [dict(r) for r in recent],
176
+ }
@@ -0,0 +1,25 @@
1
+ """Agent Memory MCP Server — Persistenter Speicher für AI-Agents."""
2
+
3
+ from mcp.server.fastmcp import FastMCP
4
+
5
+ from src.tools.memory import register_memory_tools
6
+
7
+ mcp = FastMCP(
8
+ "Agent Memory Server",
9
+ instructions=(
10
+ "Provides persistent memory for AI agents across sessions. "
11
+ "Store facts, preferences, context and knowledge that survives "
12
+ "session boundaries. Supports namespaces, tags and full-text search."
13
+ ),
14
+ )
15
+
16
+ register_memory_tools(mcp)
17
+
18
+
19
+ def main():
20
+ """Server starten."""
21
+ mcp.run(transport="stdio")
22
+
23
+
24
+ if __name__ == "__main__":
25
+ main()
File without changes
@@ -0,0 +1,112 @@
1
+ """Memory-Tools — Persistenter Speicher für AI-Agents."""
2
+
3
+ from mcp.server.fastmcp import FastMCP
4
+
5
+ from src import db
6
+
7
+
8
+ def register_memory_tools(mcp: FastMCP):
9
+ """Memory-bezogene MCP-Tools registrieren."""
10
+
11
+ @mcp.tool()
12
+ async def memory_store(
13
+ key: str,
14
+ value: str,
15
+ namespace: str = "default",
16
+ tags: list[str] = None,
17
+ ) -> dict:
18
+ """Wissen persistent speichern.
19
+
20
+ Speichert einen Key-Value-Eintrag der über Sessions hinweg
21
+ erhalten bleibt. Ideal für Fakten, Präferenzen, Kontext.
22
+
23
+ Args:
24
+ key: Eindeutiger Schlüssel (z.B. "user_preference_language")
25
+ value: Der zu speichernde Inhalt (Text, JSON, etc.)
26
+ namespace: Namespace zur Trennung (z.B. "project_x", "user_123")
27
+ tags: Optionale Tags zum Kategorisieren (z.B. ["preference", "important"])
28
+ """
29
+ return db.store(namespace, key, value, tags)
30
+
31
+ @mcp.tool()
32
+ async def memory_retrieve(key: str, namespace: str = "default") -> dict:
33
+ """Gespeichertes Wissen abrufen.
34
+
35
+ Args:
36
+ key: Schlüssel des gesuchten Eintrags
37
+ namespace: Namespace (Standard: "default")
38
+ """
39
+ result = db.retrieve(namespace, key)
40
+ if result:
41
+ return result
42
+ return {"found": False, "key": key, "namespace": namespace}
43
+
44
+ @mcp.tool()
45
+ async def memory_search(
46
+ query: str,
47
+ namespace: str = None,
48
+ tags: list[str] = None,
49
+ limit: int = 10,
50
+ ) -> dict:
51
+ """Memories durchsuchen.
52
+
53
+ Sucht in Keys und Values nach dem Suchbegriff.
54
+ Optional filterbar nach Namespace und Tags.
55
+
56
+ Args:
57
+ query: Suchbegriff
58
+ namespace: Optional — nur in diesem Namespace suchen
59
+ tags: Optional — nur Memories mit diesen Tags
60
+ limit: Maximale Ergebnisse (Standard: 10)
61
+ """
62
+ results = db.search(query, namespace, tags, limit)
63
+ return {
64
+ "query": query,
65
+ "results_count": len(results),
66
+ "results": results,
67
+ }
68
+
69
+ @mcp.tool()
70
+ async def memory_list(namespace: str = None, limit: int = 20) -> dict:
71
+ """Alle Memories auflisten.
72
+
73
+ Args:
74
+ namespace: Optional — nur diesen Namespace zeigen
75
+ limit: Maximale Anzahl (Standard: 20)
76
+ """
77
+ results = db.list_memories(namespace, limit)
78
+ return {
79
+ "total": len(results),
80
+ "memories": results,
81
+ }
82
+
83
+ @mcp.tool()
84
+ async def memory_delete(key: str, namespace: str = "default") -> dict:
85
+ """Ein Memory löschen.
86
+
87
+ Args:
88
+ key: Schlüssel des zu löschenden Eintrags
89
+ namespace: Namespace (Standard: "default")
90
+ """
91
+ return db.delete(namespace, key)
92
+
93
+ @mcp.tool()
94
+ async def memory_namespaces() -> dict:
95
+ """Alle Namespaces mit Anzahl Memories auflisten.
96
+
97
+ Zeigt eine Übersicht aller verwendeten Namespaces.
98
+ """
99
+ namespaces = db.list_namespaces()
100
+ return {
101
+ "total_namespaces": len(namespaces),
102
+ "namespaces": namespaces,
103
+ }
104
+
105
+ @mcp.tool()
106
+ async def memory_stats() -> dict:
107
+ """Speicher-Statistiken abrufen.
108
+
109
+ Zeigt: Gesamtzahl Memories, Namespaces, meistgenutzte
110
+ und zuletzt aktualisierte Einträge.
111
+ """
112
+ return db.get_stats()