memgraph-sdk 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,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .eggs/
7
+ *.egg
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+ .coverage
14
+ htmlcov/
15
+ .env
16
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Memgraph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,183 @@
1
+ Metadata-Version: 2.4
2
+ Name: memgraph-sdk
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for Memgraph - the memory graph for AI agents
5
+ Project-URL: Homepage, https://memgraph.ai
6
+ Project-URL: Documentation, https://memgraph.ai/docs
7
+ Project-URL: Repository, https://github.com/memgraph-ai/memgraph-sdk
8
+ Project-URL: Bug Tracker, https://github.com/memgraph-ai/memgraph-sdk/issues
9
+ Project-URL: Changelog, https://github.com/memgraph-ai/memgraph-sdk/blob/main/CHANGELOG.md
10
+ Author-email: Memgraph Team <sdk@memgraph.ai>
11
+ License: MIT License
12
+
13
+ Copyright (c) 2026 Memgraph
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: agents,ai,context,llm,memgraph,memory,rag
34
+ Classifier: Development Status :: 4 - Beta
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Programming Language :: Python :: 3.13
45
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
46
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
47
+ Requires-Python: >=3.8
48
+ Requires-Dist: pydantic>=2.0.0
49
+ Requires-Dist: requests>=2.25.0
50
+ Requires-Dist: typing-extensions>=4.0.0
51
+ Provides-Extra: all
52
+ Requires-Dist: httpx>=0.24.0; extra == 'all'
53
+ Requires-Dist: rich>=13.0.0; extra == 'all'
54
+ Provides-Extra: async
55
+ Requires-Dist: httpx>=0.24.0; extra == 'async'
56
+ Provides-Extra: cli
57
+ Requires-Dist: rich>=13.0.0; extra == 'cli'
58
+ Provides-Extra: dev
59
+ Requires-Dist: httpx>=0.24.0; extra == 'dev'
60
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
61
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
62
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
63
+ Description-Content-Type: text/markdown
64
+
65
+ # Memgraph SDK
66
+
67
+ The official Python SDK for **[Memgraph](https://memgraph.ai)** -- the memory graph for AI agents.
68
+
69
+ [![PyPI version](https://badge.fury.io/py/memgraph-sdk.svg)](https://pypi.org/project/memgraph-sdk/)
70
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
71
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
72
+
73
+ ## Installation
74
+
75
+ ```bash
76
+ pip install memgraph-sdk
77
+ ```
78
+
79
+ For async support:
80
+
81
+ ```bash
82
+ pip install "memgraph-sdk[async]"
83
+ ```
84
+
85
+ ## Quick Start
86
+
87
+ ```python
88
+ from memgraph_sdk import MemgraphClient
89
+
90
+ client = MemgraphClient(
91
+ api_key="mg_your_api_key",
92
+ tenant_id="your-tenant-id",
93
+ )
94
+
95
+ # Store a memory
96
+ client.add(
97
+ text="User prefers dark mode and uses PyTorch.",
98
+ user_id="user_123",
99
+ )
100
+
101
+ # Search for relevant context
102
+ result = client.search(
103
+ query="What does this user prefer?",
104
+ user_id="user_123",
105
+ )
106
+ print(result)
107
+ ```
108
+
109
+ ## Async Client
110
+
111
+ ```python
112
+ from memgraph_sdk import AsyncMemgraphClient
113
+
114
+ async with AsyncMemgraphClient(
115
+ api_key="mg_your_api_key",
116
+ tenant_id="your-tenant-id",
117
+ ) as client:
118
+ await client.add("User prefers dark mode", user_id="user_123")
119
+ result = await client.search("user preferences", user_id="user_123")
120
+ ```
121
+
122
+ ## Memory Intelligence API
123
+
124
+ ```python
125
+ # Memory health metrics
126
+ health = client.health(user_id="user_123")
127
+
128
+ # Detect contradictions
129
+ contradictions = client.contradictions(user_id="user_123")
130
+
131
+ # Evaluate retrieval quality
132
+ evaluation = client.evaluate(query="test query", user_id="user_123")
133
+
134
+ # Cognitive Integrity Score (0-100)
135
+ score = client.mcis(user_id="user_123")
136
+
137
+ # Run benchmarks
138
+ result = client.benchmark(scenario="contradiction_storm")
139
+ scenarios = client.benchmark_scenarios()
140
+ ```
141
+
142
+ ## CLI
143
+
144
+ ```bash
145
+ # Initialize Memgraph in your project
146
+ memgraph init
147
+
148
+ # Store a memory
149
+ memgraph remember "We decided to use PostgreSQL" -c decision
150
+
151
+ # Search memories
152
+ memgraph recall "database choice"
153
+
154
+ # Check connection
155
+ memgraph status
156
+ ```
157
+
158
+ ## Configuration
159
+
160
+ The client reads the API URL from the `MEMGRAPH_API_URL` environment variable, defaulting to `http://localhost:8001/v1`. You can also pass it explicitly:
161
+
162
+ ```python
163
+ client = MemgraphClient(
164
+ api_key="mg_your_key",
165
+ tenant_id="your-tenant-id",
166
+ base_url="https://api.memgraph.ai/v1",
167
+ )
168
+ ```
169
+
170
+ ## Examples
171
+
172
+ See the [examples/](examples/) directory for complete integration examples:
173
+
174
+ - [Quick Start](examples/quick_start.py) -- Basic add and search
175
+ - [Agent Integration](examples/agent_integration.py) -- OpenAI-powered agent with memory
176
+ - [MCP Server](examples/integrations/mcp_server.py) -- Model Context Protocol server for Claude/Cursor
177
+ - [LangChain](examples/integrations/langchain_integration.py) -- LangChain integration
178
+ - [OpenAI](examples/integrations/openai_integration.py) -- OpenAI integration
179
+ - [Benchmarks](examples/integrations/benchmark.py) -- Performance benchmarking
180
+
181
+ ## License
182
+
183
+ MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,119 @@
1
+ # Memgraph SDK
2
+
3
+ The official Python SDK for **[Memgraph](https://memgraph.ai)** -- the memory graph for AI agents.
4
+
5
+ [![PyPI version](https://badge.fury.io/py/memgraph-sdk.svg)](https://pypi.org/project/memgraph-sdk/)
6
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install memgraph-sdk
13
+ ```
14
+
15
+ For async support:
16
+
17
+ ```bash
18
+ pip install "memgraph-sdk[async]"
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```python
24
+ from memgraph_sdk import MemgraphClient
25
+
26
+ client = MemgraphClient(
27
+ api_key="mg_your_api_key",
28
+ tenant_id="your-tenant-id",
29
+ )
30
+
31
+ # Store a memory
32
+ client.add(
33
+ text="User prefers dark mode and uses PyTorch.",
34
+ user_id="user_123",
35
+ )
36
+
37
+ # Search for relevant context
38
+ result = client.search(
39
+ query="What does this user prefer?",
40
+ user_id="user_123",
41
+ )
42
+ print(result)
43
+ ```
44
+
45
+ ## Async Client
46
+
47
+ ```python
48
+ from memgraph_sdk import AsyncMemgraphClient
49
+
50
+ async with AsyncMemgraphClient(
51
+ api_key="mg_your_api_key",
52
+ tenant_id="your-tenant-id",
53
+ ) as client:
54
+ await client.add("User prefers dark mode", user_id="user_123")
55
+ result = await client.search("user preferences", user_id="user_123")
56
+ ```
57
+
58
+ ## Memory Intelligence API
59
+
60
+ ```python
61
+ # Memory health metrics
62
+ health = client.health(user_id="user_123")
63
+
64
+ # Detect contradictions
65
+ contradictions = client.contradictions(user_id="user_123")
66
+
67
+ # Evaluate retrieval quality
68
+ evaluation = client.evaluate(query="test query", user_id="user_123")
69
+
70
+ # Cognitive Integrity Score (0-100)
71
+ score = client.mcis(user_id="user_123")
72
+
73
+ # Run benchmarks
74
+ result = client.benchmark(scenario="contradiction_storm")
75
+ scenarios = client.benchmark_scenarios()
76
+ ```
77
+
78
+ ## CLI
79
+
80
+ ```bash
81
+ # Initialize Memgraph in your project
82
+ memgraph init
83
+
84
+ # Store a memory
85
+ memgraph remember "We decided to use PostgreSQL" -c decision
86
+
87
+ # Search memories
88
+ memgraph recall "database choice"
89
+
90
+ # Check connection
91
+ memgraph status
92
+ ```
93
+
94
+ ## Configuration
95
+
96
+ The client reads the API URL from the `MEMGRAPH_API_URL` environment variable, defaulting to `http://localhost:8001/v1`. You can also pass it explicitly:
97
+
98
+ ```python
99
+ client = MemgraphClient(
100
+ api_key="mg_your_key",
101
+ tenant_id="your-tenant-id",
102
+ base_url="https://api.memgraph.ai/v1",
103
+ )
104
+ ```
105
+
106
+ ## Examples
107
+
108
+ See the [examples/](examples/) directory for complete integration examples:
109
+
110
+ - [Quick Start](examples/quick_start.py) -- Basic add and search
111
+ - [Agent Integration](examples/agent_integration.py) -- OpenAI-powered agent with memory
112
+ - [MCP Server](examples/integrations/mcp_server.py) -- Model Context Protocol server for Claude/Cursor
113
+ - [LangChain](examples/integrations/langchain_integration.py) -- LangChain integration
114
+ - [OpenAI](examples/integrations/openai_integration.py) -- OpenAI integration
115
+ - [Benchmarks](examples/integrations/benchmark.py) -- Performance benchmarking
116
+
117
+ ## License
118
+
119
+ MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,12 @@
1
+ """Memgraph SDK - The official Python SDK for Memgraph, the memory graph for AI agents."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ from .client import MemgraphClient
6
+
7
+ try:
8
+ from .async_client import AsyncMemgraphClient
9
+ except ImportError:
10
+ AsyncMemgraphClient = None # httpx not installed
11
+
12
+ __all__ = ["MemgraphClient", "AsyncMemgraphClient", "__version__"]
@@ -0,0 +1,163 @@
1
+ """
2
+ Async SDK client for Memgraph.
3
+
4
+ Uses httpx for non-blocking HTTP calls, suitable for async frameworks
5
+ (FastAPI, aiohttp, etc.) and high-throughput pipelines.
6
+
7
+ Usage:
8
+ from memgraph_sdk import AsyncMemgraphClient
9
+
10
+ async with AsyncMemgraphClient(api_key="...", tenant_id="...") as client:
11
+ await client.add("User prefers dark mode", user_id="u1")
12
+ ctx = await client.search("What theme does the user prefer?", user_id="u1")
13
+ """
14
+
15
+ import os
16
+ from typing import Dict, Any, Optional
17
+
18
+ try:
19
+ import httpx
20
+ except ImportError:
21
+ raise ImportError(
22
+ "httpx is required for AsyncMemgraphClient. Install it with: pip install httpx"
23
+ )
24
+
25
+
26
+ class AsyncMemgraphClient:
27
+ def __init__(self, api_key: str, tenant_id: str, base_url: str = None, timeout: float = 30.0):
28
+ self.api_key = api_key
29
+ self.tenant_id = tenant_id
30
+ self.base_url = base_url or os.getenv("MEMGRAPH_API_URL", "http://localhost:8001/v1")
31
+ self._client = httpx.AsyncClient(
32
+ base_url=self.base_url,
33
+ headers={"X-API-KEY": api_key},
34
+ timeout=timeout,
35
+ )
36
+
37
+ async def __aenter__(self):
38
+ return self
39
+
40
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
41
+ await self.close()
42
+
43
+ async def close(self):
44
+ await self._client.aclose()
45
+
46
+ async def add(self, text: str, user_id: str, metadata: Optional[Dict] = None) -> Dict:
47
+ """Add a memory via the /ingest endpoint."""
48
+ data = {
49
+ "tenant_id": self.tenant_id,
50
+ "user_id": user_id,
51
+ "text": text,
52
+ }
53
+ resp = await self._client.post("/ingest", data=data)
54
+ resp.raise_for_status()
55
+ return resp.json()
56
+
57
+ async def search(self, query: str, user_id: str, agent_id: str = "sdk_client") -> Dict[str, Any]:
58
+ """Retrieve relevant context for a query via /context endpoint."""
59
+ payload = {
60
+ "task": query,
61
+ "user_id": user_id,
62
+ "tenant_id": self.tenant_id,
63
+ "agent_id": agent_id,
64
+ }
65
+ resp = await self._client.post("/context", json=payload)
66
+ resp.raise_for_status()
67
+ return resp.json()
68
+
69
+ async def get_context(self, query: str, user_id: str) -> Dict[str, Any]:
70
+ """Alias for search()."""
71
+ return await self.search(query, user_id)
72
+
73
+ async def log_event(
74
+ self,
75
+ event_type: str,
76
+ content: Dict[str, Any],
77
+ user_id: str = "default_user",
78
+ agent_id: str = "sdk_client",
79
+ thread_id: Optional[str] = None,
80
+ ) -> Dict:
81
+ """Log a raw event to the /events endpoint."""
82
+ payload = {
83
+ "tenant_id": self.tenant_id,
84
+ "user_id": user_id,
85
+ "agent_id": agent_id,
86
+ "event_type": event_type,
87
+ "content": content,
88
+ }
89
+ if thread_id:
90
+ payload["thread_id"] = thread_id
91
+
92
+ resp = await self._client.post("/events", json=payload)
93
+ resp.raise_for_status()
94
+ return resp.json()
95
+
96
+ async def get_beliefs(self, user_id: str, limit: int = 50) -> list:
97
+ """Fetch beliefs for a user via /beliefs endpoint."""
98
+ resp = await self._client.get(
99
+ "/beliefs",
100
+ params={"tenant_id": self.tenant_id, "subject_id": user_id, "limit": limit},
101
+ )
102
+ resp.raise_for_status()
103
+ return resp.json()
104
+
105
+ # ------------------------------------------------------------------
106
+ # Memory Intelligence API
107
+ # ------------------------------------------------------------------
108
+
109
+ async def health(self, user_id: Optional[str] = None) -> Dict[str, Any]:
110
+ """Get memory health metrics for the tenant (optionally scoped to a user)."""
111
+ params = {}
112
+ if user_id:
113
+ params["user_id"] = user_id
114
+ resp = await self._client.get("/intelligence/health", params=params)
115
+ resp.raise_for_status()
116
+ return resp.json()
117
+
118
+ async def contradictions(self, user_id: Optional[str] = None) -> Dict[str, Any]:
119
+ """Get contradiction report — all detected contradictions with resolution history."""
120
+ params = {}
121
+ if user_id:
122
+ params["user_id"] = user_id
123
+ resp = await self._client.get("/intelligence/contradictions", params=params)
124
+ resp.raise_for_status()
125
+ return resp.json()
126
+
127
+ async def evaluate(self, query: str, user_id: str) -> Dict[str, Any]:
128
+ """Run a retrieval query and get detailed scoring breakdown."""
129
+ payload = {"query": query, "user_id": user_id}
130
+ resp = await self._client.post("/intelligence/evaluate", json=payload)
131
+ resp.raise_for_status()
132
+ return resp.json()
133
+
134
+ async def mcis(self, user_id: Optional[str] = None, save: bool = False) -> Dict[str, Any]:
135
+ """Compute the Memgraph Cognitive Integrity Score (0-100)."""
136
+ params = {"save": str(save).lower()}
137
+ if user_id:
138
+ params["user_id"] = user_id
139
+ resp = await self._client.get("/intelligence/mcis", params=params)
140
+ resp.raise_for_status()
141
+ return resp.json()
142
+
143
+ async def mcis_history(self, user_id: Optional[str] = None, limit: int = 30) -> Dict[str, Any]:
144
+ """Get historical MCIS snapshots for trend visualization."""
145
+ params = {"limit": limit}
146
+ if user_id:
147
+ params["user_id"] = user_id
148
+ resp = await self._client.get("/intelligence/mcis/history", params=params)
149
+ resp.raise_for_status()
150
+ return resp.json()
151
+
152
+ async def benchmark(self, scenario: str) -> Dict[str, Any]:
153
+ """Run a memory benchmark scenario (e.g. 'contradiction_storm', 'retrieval_accuracy')."""
154
+ payload = {"scenario": scenario}
155
+ resp = await self._client.post("/benchmark/run", json=payload)
156
+ resp.raise_for_status()
157
+ return resp.json()
158
+
159
+ async def benchmark_scenarios(self) -> list:
160
+ """List available benchmark scenarios."""
161
+ resp = await self._client.get("/benchmark/scenarios")
162
+ resp.raise_for_status()
163
+ return resp.json().get("scenarios", [])
@@ -0,0 +1,308 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Memgraph CLI - One-command setup for AI agent memory integration.
4
+
5
+ Usage:
6
+ memgraph init # Set up Memgraph in current project
7
+ memgraph remember # Store a memory
8
+ memgraph recall # Search memories
9
+ memgraph status # Check connection
10
+ """
11
+ import os
12
+ import sys
13
+ import shutil
14
+ import argparse
15
+ from pathlib import Path
16
+
17
+ try:
18
+ import requests
19
+ except ImportError:
20
+ requests = None
21
+
22
+ # --- Constants ---
23
+ CLOUD_URL = "https://api.memgraph.ai/v1"
24
+ LOCAL_URL = os.getenv("MEMGRAPH_API_URL", "http://localhost:8001/v1")
25
+ CONFIG_FILE = ".memgraph.env"
26
+ SKILL_DIR = ".agent/skills/memgraph"
27
+
28
+ # Template for skill file
29
+ SKILL_TEMPLATE = '''---
30
+ name: Memgraph Memory
31
+ description: Seamless long-term memory for AI agents via Memgraph. Auto-learn, inject context, and suggest based on project history.
32
+ ---
33
+
34
+ # Memgraph Memory Skill
35
+
36
+ This skill gives you persistent memory across sessions.
37
+
38
+ ## MCP Tools Available
39
+
40
+ | Tool | Use For |
41
+ |------|---------|
42
+ | `memgraph_search` | Find past decisions, architecture, context |
43
+ | `memgraph_remember` | Store new facts and learnings |
44
+
45
+ ## When to SEARCH
46
+ Call `memgraph_search` BEFORE answering questions about:
47
+ - Architecture or design patterns
48
+ - Previous decisions or bugs
49
+ - "How does X work?" / "Why did we choose Y?"
50
+
51
+ ## When to REMEMBER
52
+ Call `memgraph_remember` AFTER:
53
+ - Completing a significant feature or fix
54
+ - User makes an architectural decision
55
+ - Resolving a tricky bug
56
+
57
+ Categories: `decision`, `architecture`, `bug_fix`, `preference`, `general`
58
+ '''
59
+
60
+ MCP_CONFIG_TEMPLATE = '''{
61
+ "mcpServers": {
62
+ "memgraph": {
63
+ "command": "python3",
64
+ "args": ["${MCP_SERVER_PATH}"],
65
+ "env": {
66
+ "MEMGRAPH_API_URL": "${API_URL}",
67
+ "MEMGRAPH_TENANT_ID": "${TENANT_ID}",
68
+ "MEMGRAPH_API_KEY": "${API_KEY}"
69
+ }
70
+ }
71
+ }
72
+ }
73
+ '''
74
+
75
+
76
+ def get_package_dir():
77
+ """Get the memgraph-sdk package installation directory."""
78
+ return Path(__file__).parent.parent
79
+
80
+
81
+ def init_project():
82
+ """Initialize Memgraph in the current project."""
83
+ print("🚀 Memgraph Agent Memory Setup\n")
84
+
85
+ # 1. Choose deployment mode
86
+ print("Where is your Memgraph server running?")
87
+ print(" 1) Cloud (api.memgraph.ai)")
88
+ print(" 2) On-prem / Local (localhost:8001)")
89
+ print(" 3) Custom URL")
90
+
91
+ choice = input("\nChoose [1/2/3]: ").strip()
92
+
93
+ if choice == "1":
94
+ api_url = CLOUD_URL
95
+ elif choice == "2":
96
+ api_url = LOCAL_URL
97
+ elif choice == "3":
98
+ api_url = input("Enter API URL: ").strip()
99
+ else:
100
+ print("Invalid choice")
101
+ return
102
+
103
+ # 2. Get credentials
104
+ tenant_id = input("\nTenant ID: ").strip()
105
+ api_key = input("API Key (optional, press Enter to skip): ").strip()
106
+
107
+ # 3. Create .memgraph.env
108
+ config_path = Path(CONFIG_FILE)
109
+ with open(config_path, "w") as f:
110
+ f.write(f"MEMGRAPH_API_URL={api_url}\n")
111
+ f.write(f"MEMGRAPH_TENANT_ID={tenant_id}\n")
112
+ if api_key:
113
+ f.write(f"MEMGRAPH_API_KEY={api_key}\n")
114
+ print(f"\n✅ Created {CONFIG_FILE}")
115
+
116
+ # 4. Create skill directory
117
+ skill_path = Path(SKILL_DIR)
118
+ skill_path.mkdir(parents=True, exist_ok=True)
119
+
120
+ skill_file = skill_path / "SKILL.md"
121
+ with open(skill_file, "w") as f:
122
+ f.write(SKILL_TEMPLATE)
123
+ print(f"✅ Created {skill_file}")
124
+
125
+ # 5. Copy or reference MCP server
126
+ mcp_server_path = get_package_dir() / "examples" / "integrations" / "mcp_server.py"
127
+ if mcp_server_path.exists():
128
+ mcp_dest = skill_path / "mcp_server.py"
129
+ shutil.copy(mcp_server_path, mcp_dest)
130
+ print(f"✅ Copied MCP server to {mcp_dest}")
131
+
132
+ # 6. Create MCP config hints
133
+ print("\n📋 To enable MCP in your editor:")
134
+ print("\n For Cursor, add to .cursor/mcp.json:")
135
+ mcp_config = MCP_CONFIG_TEMPLATE.replace("${API_URL}", api_url)
136
+ mcp_config = mcp_config.replace("${TENANT_ID}", tenant_id)
137
+ mcp_config = mcp_config.replace("${API_KEY}", api_key or "")
138
+ mcp_config = mcp_config.replace("${MCP_SERVER_PATH}", str(skill_path / "mcp_server.py"))
139
+ print(mcp_config)
140
+
141
+ print("\n🎉 Memgraph agent memory is ready!")
142
+ print(" Your AI agent can now use memgraph_search and memgraph_remember tools.")
143
+
144
+
145
+ def remember_cmd(text: str, category: str = "general"):
146
+ """Store a memory via CLI."""
147
+ if not requests:
148
+ print("Error: 'requests' package not installed. Run: pip install requests")
149
+ return
150
+
151
+ config = load_config()
152
+ if not config:
153
+ print("Error: Not initialized. Run 'memgraph init' first.")
154
+ return
155
+
156
+ try:
157
+ resp = requests.post(
158
+ f"{config['api_url']}/ingest",
159
+ data={
160
+ "tenant_id": config["tenant_id"],
161
+ "user_id": "cli_user",
162
+ "text": f"[{category}] {text}",
163
+ },
164
+ headers={"X-API-KEY": config.get("api_key", "")},
165
+ timeout=10
166
+ )
167
+ if resp.status_code == 200:
168
+ print(f"✅ Remembered: {text[:80]}...")
169
+ else:
170
+ print(f"❌ Error: {resp.text}")
171
+ except requests.ConnectionError:
172
+ print("❌ Cannot connect to Memgraph server")
173
+
174
+
175
+ def recall_cmd(query: str):
176
+ """Search memories via CLI."""
177
+ if not requests:
178
+ print("Error: 'requests' package not installed. Run: pip install requests")
179
+ return
180
+
181
+ config = load_config()
182
+ if not config:
183
+ print("Error: Not initialized. Run 'memgraph init' first.")
184
+ return
185
+
186
+ try:
187
+ resp = requests.post(
188
+ f"{config['api_url']}/context",
189
+ json={
190
+ "tenant_id": config["tenant_id"],
191
+ "user_id": "cli_user",
192
+ "task": query,
193
+ "agent_id": "cli"
194
+ },
195
+ headers={"X-API-KEY": config.get("api_key", "")},
196
+ timeout=10
197
+ )
198
+ if resp.status_code == 200:
199
+ data = resp.json()
200
+ results = data.get("results", [])
201
+ if results:
202
+ print(f"\n🔍 Found {len(results)} results for '{query}':\n")
203
+ for r in results:
204
+ if isinstance(r, dict):
205
+ print(f" • {r.get('text', r)}")
206
+ else:
207
+ print(f" • {r}")
208
+ else:
209
+ print("No memories found for this query.")
210
+ else:
211
+ print(f"❌ Error: {resp.text}")
212
+ except requests.ConnectionError:
213
+ print("❌ Cannot connect to Memgraph server")
214
+
215
+
216
+ def status_cmd():
217
+ """Check Memgraph connection status."""
218
+ config = load_config()
219
+ if not config:
220
+ print("❌ Not initialized. Run 'memgraph init' first.")
221
+ return
222
+
223
+ print(f"📡 API URL: {config['api_url']}")
224
+ print(f"🏢 Tenant: {config['tenant_id']}")
225
+ print(f"🔑 API Key: {'***' + config['api_key'][-4:] if config.get('api_key') else '(not set)'}")
226
+
227
+ if requests:
228
+ try:
229
+ resp = requests.get(f"{config['api_url']}/health", timeout=5)
230
+ if resp.status_code == 200:
231
+ print("\n✅ Server is reachable")
232
+ else:
233
+ print(f"\n⚠️ Server returned: {resp.status_code}")
234
+ except requests.ConnectionError:
235
+ print("\n❌ Cannot connect to server")
236
+ else:
237
+ print("\n⚠️ Cannot check connection (requests not installed)")
238
+
239
+
240
+ def load_config():
241
+ """Load config from .memgraph.env file."""
242
+ config_path = Path(CONFIG_FILE)
243
+ if not config_path.exists():
244
+ return None
245
+
246
+ config = {}
247
+ with open(config_path) as f:
248
+ for line in f:
249
+ line = line.strip()
250
+ if "=" in line and not line.startswith("#"):
251
+ key, value = line.split("=", 1)
252
+ key = key.strip().lower().replace("memgraph_", "")
253
+ config[key] = value.strip()
254
+
255
+ return {
256
+ "api_url": config.get("api_url", LOCAL_URL),
257
+ "tenant_id": config.get("tenant_id"),
258
+ "api_key": config.get("api_key")
259
+ }
260
+
261
+
262
+ def main():
263
+ parser = argparse.ArgumentParser(
264
+ description="Memgraph - AI Agent Memory Graph",
265
+ formatter_class=argparse.RawDescriptionHelpFormatter,
266
+ epilog="""
267
+ Examples:
268
+ memgraph init # Set up Memgraph in current project
269
+ memgraph remember "Used JWT" # Store a memory
270
+ memgraph recall "authentication" # Search memories
271
+ memgraph status # Check connection
272
+ """
273
+ )
274
+
275
+ subparsers = parser.add_subparsers(dest="command")
276
+
277
+ # init
278
+ subparsers.add_parser("init", help="Initialize Memgraph in current project")
279
+
280
+ # remember
281
+ rem_parser = subparsers.add_parser("remember", help="Store a memory")
282
+ rem_parser.add_argument("text", help="Text to remember")
283
+ rem_parser.add_argument("-c", "--category", default="general",
284
+ choices=["decision", "architecture", "bug_fix", "preference", "general"])
285
+
286
+ # recall
287
+ rec_parser = subparsers.add_parser("recall", help="Search memories")
288
+ rec_parser.add_argument("query", help="Search query")
289
+
290
+ # status
291
+ subparsers.add_parser("status", help="Check connection status")
292
+
293
+ args = parser.parse_args()
294
+
295
+ if args.command == "init":
296
+ init_project()
297
+ elif args.command == "remember":
298
+ remember_cmd(args.text, args.category)
299
+ elif args.command == "recall":
300
+ recall_cmd(args.query)
301
+ elif args.command == "status":
302
+ status_cmd()
303
+ else:
304
+ parser.print_help()
305
+
306
+
307
+ if __name__ == "__main__":
308
+ main()
@@ -0,0 +1,115 @@
1
+ import os
2
+ import requests
3
+ from typing import List, Dict, Any, Optional
4
+
5
+ class MemgraphClient:
6
+ def __init__(self, api_key: str, tenant_id: str, base_url: str = None):
7
+ self.api_key = api_key
8
+ self.tenant_id = tenant_id
9
+ self.base_url = base_url or os.getenv("MEMGRAPH_API_URL", "http://localhost:8001/v1")
10
+ self.headers = {
11
+ "X-API-KEY": api_key,
12
+ # "Content-Type" is handled automatically by requests for Form data or JSON
13
+ }
14
+
15
+ def add(self, text: str, user_id: str, metadata: Optional[Dict] = None) -> Dict:
16
+ """
17
+ Add a memory via the /ingest endpoint.
18
+ Uses multipart/form-data as required by the backend.
19
+ """
20
+ data = {
21
+ "tenant_id": self.tenant_id,
22
+ "user_id": user_id,
23
+ "text": text,
24
+ }
25
+ # If we had metadata/files, we would add them here.
26
+ # Verify if metadata is supported by ingest_omni (it currently isn't in the Form params shown in ingest.py,
27
+ # but the logic creates an event with content_payload which we might want to extend later).
28
+
29
+ resp = requests.post(f"{self.base_url}/ingest", data=data, headers=self.headers)
30
+ resp.raise_for_status()
31
+ return resp.json()
32
+
33
+ def search(self, query: str, user_id: str, agent_id: str = "sdk_client") -> Dict[str, Any]:
34
+ """
35
+ Retrieve relevant context for a query via /context endpoint.
36
+ """
37
+ payload = {
38
+ "task": query, # Server expects 'task', not 'query' based on E2E
39
+ "user_id": user_id,
40
+ "tenant_id": self.tenant_id,
41
+ "agent_id": agent_id
42
+ }
43
+ resp = requests.post(f"{self.base_url}/context", json=payload, headers=self.headers)
44
+ resp.raise_for_status()
45
+ return resp.json()
46
+
47
+ # Deprecated/Legacy methods mapped to new ones for compatibility
48
+ def log_event(self, event_type: str, content: Dict[str, Any], metadata: Optional[Dict] = None) -> Dict:
49
+ # Fallback to ingest if content has text
50
+ if "text" in content:
51
+ return self.add(content["text"], "legacy_user")
52
+ raise NotImplementedError("Generic log_event not fully supported yet.")
53
+
54
+ def get_context(self, query: str, user_id: str) -> Dict[str, Any]:
55
+ return self.search(query, user_id)
56
+
57
+ # ------------------------------------------------------------------
58
+ # Memory Intelligence API
59
+ # ------------------------------------------------------------------
60
+
61
+ def health(self, user_id: Optional[str] = None) -> Dict[str, Any]:
62
+ """Get memory health metrics for the tenant (optionally scoped to a user)."""
63
+ params = {}
64
+ if user_id:
65
+ params["user_id"] = user_id
66
+ resp = requests.get(f"{self.base_url}/intelligence/health", params=params, headers=self.headers)
67
+ resp.raise_for_status()
68
+ return resp.json()
69
+
70
+ def contradictions(self, user_id: Optional[str] = None) -> Dict[str, Any]:
71
+ """Get contradiction report — all detected contradictions with resolution history."""
72
+ params = {}
73
+ if user_id:
74
+ params["user_id"] = user_id
75
+ resp = requests.get(f"{self.base_url}/intelligence/contradictions", params=params, headers=self.headers)
76
+ resp.raise_for_status()
77
+ return resp.json()
78
+
79
+ def evaluate(self, query: str, user_id: str) -> Dict[str, Any]:
80
+ """Run a retrieval query and get detailed scoring breakdown."""
81
+ payload = {"query": query, "user_id": user_id}
82
+ resp = requests.post(f"{self.base_url}/intelligence/evaluate", json=payload, headers=self.headers)
83
+ resp.raise_for_status()
84
+ return resp.json()
85
+
86
+ def mcis(self, user_id: Optional[str] = None, save: bool = False) -> Dict[str, Any]:
87
+ """Compute the Memgraph Cognitive Integrity Score (0-100)."""
88
+ params = {"save": str(save).lower()}
89
+ if user_id:
90
+ params["user_id"] = user_id
91
+ resp = requests.get(f"{self.base_url}/intelligence/mcis", params=params, headers=self.headers)
92
+ resp.raise_for_status()
93
+ return resp.json()
94
+
95
+ def mcis_history(self, user_id: Optional[str] = None, limit: int = 30) -> Dict[str, Any]:
96
+ """Get historical MCIS snapshots for trend visualization."""
97
+ params = {"limit": limit}
98
+ if user_id:
99
+ params["user_id"] = user_id
100
+ resp = requests.get(f"{self.base_url}/intelligence/mcis/history", params=params, headers=self.headers)
101
+ resp.raise_for_status()
102
+ return resp.json()
103
+
104
+ def benchmark(self, scenario: str) -> Dict[str, Any]:
105
+ """Run a memory benchmark scenario (e.g. 'contradiction_storm', 'retrieval_accuracy')."""
106
+ payload = {"scenario": scenario}
107
+ resp = requests.post(f"{self.base_url}/benchmark/run", json=payload, headers=self.headers)
108
+ resp.raise_for_status()
109
+ return resp.json()
110
+
111
+ def benchmark_scenarios(self) -> List[Dict]:
112
+ """List available benchmark scenarios."""
113
+ resp = requests.get(f"{self.base_url}/benchmark/scenarios", headers=self.headers)
114
+ resp.raise_for_status()
115
+ return resp.json().get("scenarios", [])
File without changes
@@ -0,0 +1,80 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "memgraph-sdk"
7
+ dynamic = ["version"]
8
+ description = "Official Python SDK for Memgraph - the memory graph for AI agents"
9
+ readme = "README.md"
10
+ license = { file = "LICENSE" }
11
+ authors = [
12
+ { name = "Memgraph Team", email = "sdk@memgraph.ai" },
13
+ ]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
28
+ ]
29
+ keywords = ["memgraph", "ai", "memory", "agents", "llm", "rag", "context"]
30
+ dependencies = [
31
+ "requests>=2.25.0",
32
+ "pydantic>=2.0.0",
33
+ "typing-extensions>=4.0.0",
34
+ ]
35
+ requires-python = ">=3.8"
36
+
37
+ [project.scripts]
38
+ memgraph = "memgraph_sdk.cli:main"
39
+
40
+ [project.optional-dependencies]
41
+ async = ["httpx>=0.24.0"]
42
+ cli = ["rich>=13.0.0"]
43
+ all = ["httpx>=0.24.0", "rich>=13.0.0"]
44
+ dev = [
45
+ "pytest>=7.0.0",
46
+ "pytest-asyncio>=0.21.0",
47
+ "httpx>=0.24.0",
48
+ "ruff>=0.1.0",
49
+ ]
50
+
51
+ [project.urls]
52
+ Homepage = "https://memgraph.ai"
53
+ Documentation = "https://memgraph.ai/docs"
54
+ Repository = "https://github.com/memgraph-ai/memgraph-sdk"
55
+ "Bug Tracker" = "https://github.com/memgraph-ai/memgraph-sdk/issues"
56
+ Changelog = "https://github.com/memgraph-ai/memgraph-sdk/blob/main/CHANGELOG.md"
57
+
58
+ [tool.hatch.version]
59
+ path = "memgraph_sdk/__init__.py"
60
+
61
+ [tool.hatch.build.targets.sdist]
62
+ include = [
63
+ "memgraph_sdk/",
64
+ "LICENSE",
65
+ "README.md",
66
+ ]
67
+
68
+ [tool.hatch.build.targets.wheel]
69
+ packages = ["memgraph_sdk"]
70
+
71
+ [tool.ruff]
72
+ line-length = 100
73
+ target-version = "py38"
74
+
75
+ [tool.ruff.lint]
76
+ select = ["E", "F", "W", "I"]
77
+ ignore = ["E501"]
78
+
79
+ [tool.pytest.ini_options]
80
+ testpaths = ["tests"]