Memory MCP Server
by evangstav
# Memory MCP Server
A Model Context Protocol (MCP) server that provides knowledge graph functionality for managing entities, relations, and observations in memory, with strict validation rules to maintain data consistency.
## Installation
Install the server in Claude Desktop:
```bash
mcp install main.py -v MEMORY_FILE_PATH=/path/to/memory.jsonl
```
## Data Validation Rules
### Entity Names
- Must start with a lowercase letter
- Can contain lowercase letters, numbers, and hyphens
- Maximum length of 100 characters
- Must be unique within the graph
- Example valid names: `python-project`, `meeting-notes-2024`, `user-john`
### Entity Types
The following entity types are supported:
- `person`: Human entities
- `concept`: Abstract ideas or principles
- `project`: Work initiatives or tasks
- `document`: Any form of documentation
- `tool`: Software tools or utilities
- `organization`: Companies or groups
- `location`: Physical or virtual places
- `event`: Time-bound occurrences
### Observations
- Non-empty strings
- Maximum length of 500 characters
- Must be unique per entity
- Should be factual and objective statements
- Include timestamp when relevant
### Relations
The following relation types are supported:
- `knows`: Person to person connection
- `contains`: Parent/child relationship
- `uses`: Entity utilizing another entity
- `created`: Authorship/creation relationship
- `belongs-to`: Membership/ownership
- `depends-on`: Dependency relationship
- `related-to`: Generic relationship
Additional relation rules:
- Both source and target entities must exist
- Self-referential relations not allowed
- No circular dependencies allowed
- Must use predefined relation types
## Usage
The server provides tools for managing a knowledge graph:
### Get Entity
```python
result = await session.call_tool("get_entity", {
"entity_name": "example"
})
if not result.success:
if result.error_type == "NOT_FOUND":
print(f"Entity not found: {result.error}")
elif result.error_type == "VALIDATION_ERROR":
print(f"Invalid input: {result.error}")
else:
print(f"Error: {result.error}")
else:
entity = result.data
print(f"Found entity: {entity}")
```
### Get Graph
```python
result = await session.call_tool("get_graph", {})
if result.success:
graph = result.data
print(f"Graph data: {graph}")
else:
print(f"Error retrieving graph: {result.error}")
```
### Create Entities
```python
# Valid entity creation
entities = [
Entity(
name="python-project", # Lowercase with hyphens
entityType="project", # Must be a valid type
observations=["Started development on 2024-01-29"]
),
Entity(
name="john-doe",
entityType="person",
observations=["Software engineer", "Joined team in 2024"]
)
]
result = await session.call_tool("create_entities", {
"entities": entities
})
if not result.success:
if result.error_type == "VALIDATION_ERROR":
print(f"Invalid entity data: {result.error}")
else:
print(f"Error creating entities: {result.error}")
```
### Add Observation
```python
# Valid observation
result = await session.call_tool("add_observation", {
"entity": "python-project",
"observation": "Completed initial prototype" # Must be unique for entity
})
if not result.success:
if result.error_type == "NOT_FOUND":
print(f"Entity not found: {result.error}")
elif result.error_type == "VALIDATION_ERROR":
print(f"Invalid observation: {result.error}")
else:
print(f"Error adding observation: {result.error}")
```
### Create Relation
```python
# Valid relation
result = await session.call_tool("create_relation", {
"from_entity": "john-doe",
"to_entity": "python-project",
"relation_type": "created" # Must be a valid type
})
if not result.success:
if result.error_type == "NOT_FOUND":
print(f"Entity not found: {result.error}")
elif result.error_type == "VALIDATION_ERROR":
print(f"Invalid relation data: {result.error}")
else:
print(f"Error creating relation: {result.error}")
```
### Search Memory
```python
result = await session.call_tool("search_memory", {
"query": "most recent workout" # Supports natural language queries
})
if result.success:
if result.error_type == "NO_RESULTS":
print(f"No results found: {result.error}")
else:
results = result.data
print(f"Search results: {results}")
else:
print(f"Error searching memory: {result.error}")
```
The search functionality supports:
- Temporal queries (e.g., "most recent", "last", "latest")
- Activity queries (e.g., "workout", "exercise")
- General entity searches
- Fuzzy matching with 80% similarity threshold
- Weighted search across:
- Entity names (weight: 1.0)
- Entity types (weight: 0.8)
- Observations (weight: 0.6)
### Delete Entities
```python
result = await session.call_tool("delete_entities", {
"names": ["python-project", "john-doe"]
})
if not result.success:
if result.error_type == "NOT_FOUND":
print(f"Entity not found: {result.error}")
else:
print(f"Error deleting entities: {result.error}")
```
### Delete Relation
```python
result = await session.call_tool("delete_relation", {
"from_entity": "john-doe",
"to_entity": "python-project"
})
if not result.success:
if result.error_type == "NOT_FOUND":
print(f"Entity not found: {result.error}")
else:
print(f"Error deleting relation: {result.error}")
```
### Flush Memory
```python
result = await session.call_tool("flush_memory", {})
if not result.success:
print(f"Error flushing memory: {result.error}")
```
## Error Types
The server uses the following error types:
- `NOT_FOUND`: Entity or resource not found
- `VALIDATION_ERROR`: Invalid input data
- `INTERNAL_ERROR`: Server-side error
- `ALREADY_EXISTS`: Resource already exists
- `INVALID_RELATION`: Invalid relation between entities
## Response Models
All tools return typed responses using these models:
### EntityResponse
```python
class EntityResponse(BaseModel):
success: bool
data: Optional[Dict[str, Any]] = None
error: Optional[str] = None
error_type: Optional[str] = None
```
### GraphResponse
```python
class GraphResponse(BaseModel):
success: bool
data: Optional[Dict[str, Any]] = None
error: Optional[str] = None
error_type: Optional[str] = None
```
### OperationResponse
```python
class OperationResponse(BaseModel):
success: bool
error: Optional[str] = None
error_type: Optional[str] = None
```
## Development
### Running Tests
```bash
pytest tests/
```
### Adding New Features
1. Update validation rules in `validation.py`
2. Add tests in `tests/test_validation.py`
3. Implement changes in `knowledge_graph_manager.py`