MCP server with local RAG database and expiring memory capabilities
MCP Synaptic demonstrates solid definition quality with well-structured tool names, comprehensive parameter schemas, and clear documentation. All 12 tools follow verb_noun naming convention (memory_add, memory_get, rag_search, etc.). Parameter schemas are complete with types, descriptions, and constraints (enums, min/max bounds). Descriptions are substantive (100-300 chars typical) and explain WHAT the tool does and WHEN to use it. However, there are gaps: output schemas are documented in docstrings but not formalized in structured response types visible in code; error handling descriptions lack actionable recovery guidance; tool annotations (readOnlyHint, destructiveHint) are declared in feature list but not visible in source code; some parameter descriptions could better explain dependencies and format expectations.
Add a new memory with optional expiration. Returns: Memory object with assigned ID and timestamps
Delete a memory by its unique key. Returns: True if memory was found and deleted, False if not found Note: This operation is idempotent - deleting a non-existent memory returns False but doesn't raise an error.
Retrieve a memory by its unique key. Args: key: Unique identifier of the memory to retrieve touch: If True, updates last_accessed_at and access_count (default: True) Set to False for read-only access that doesn't affect TTL Returns: Memory object if found and not expired, None otherwise Raises: MemoryExpiredError: If memory exists but has expired (auto-removed) MemoryError: If storage operation fails
List memories with optional filtering and pagination. Returns: List of memory objects matching the criteria Example: # Get all short-term memories memories = await memory_list(memory_types=["short_term"]) # Get specific memories by key memories = await memory_list(keys=["user_profile", "session_data"]) # Paginated results memories = await memory_list(limit=5, offset=10)
Output schemas not explicitly formalized in visible code. Docstrings describe return types (Memory, Document, CollectionStats) but no structured Pydantic models or JSON Schema definitions visible in source excerpt. LLMs cannot reliably infer output structure without explicit response schemas.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) declared in feature list but NOT visible in FastMCP tool registration. memory_delete and rag_delete_document are destructive but lack @mcp.tool(destructiveHint=true) or equivalent annotation in visible code.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | <=2025-11-25 | v2 |
| 2026-03-09 | D | 58 | - | v1 |
Get comprehensive memory usage statistics. Returns: MemoryStats object containing memory statistics: - total_memories: Total number of memories stored - memories_by_type: Count breakdown by memory type - expired_memories: Number of expired memories - total_size_bytes: Approximate total size - average_ttl_seconds: Average TTL across all memories - oldest_memory: Creation time of oldest memory - newest_memory: Creation time of newest memory - most_accessed_count: Highest access count Note: Statistics are computed in real-time and may include expired memories that haven't been cleaned up yet.
Update an existing memory's data, TTL, or metadata. Returns: Updated memory object if found, None if not found Note: Only provided parameters are updated, others remain unchanged. Updates the memory's updated_at timestamp.
Add a document to the RAG database for vector search. Returns: Document object with ID, embeddings, and timestamps Note: The document content will be embedded using the configured embedding provider for semantic search capabilities.
Get comprehensive statistics about the RAG document collection. Returns: CollectionStats object containing collection statistics: - total_documents: Total number of documents in collection - total_embeddings: Total number of embedding vectors - average_document_length: Average content length - embedding_dimensions: Dimensionality of embedding vectors - collection_size_bytes: Approximate storage size - oldest_document: Creation time of oldest document - newest_document: Creation time of newest document Note: Statistics are computed in real-time from the vector database.
Delete a document by its unique ID. Returns: True if document was found and deleted, False if not found Note: This permanently removes the document and its embeddings. This operation is idempotent.
Retrieve a document by its unique ID. Returns: Document object if found, None if not found
Search for documents using semantic similarity. Returns: List of search result objects with similarity scores, ordered by relevance (highest similarity first) Example: # Basic search results = await rag_search("machine learning algorithms") # Filtered search with threshold results = await rag_search( query="python tutorial", limit=5, similarity_threshold=0.7, metadata_filter={"category": "programming"} )
Update an existing document's content or metadata. Returns: Updated document object if found, None if not found Note: Updating content will regenerate embeddings, which may take time. Only provided parameters are updated.
Error handling descriptions lack actionable recovery guidance. memory_get docstring mentions 'Raises: MemoryExpiredError' and 'MemoryError' but does not tell the LLM what to do next (e.g., 'Call memory_add to store fresh data' or 'Check storage configuration'). Bare error types provide no guidance.
Parameter format constraints not fully documented in descriptions. memory_add 'key' param says 'must be unique' but does not specify format (alphanumeric, length limits, allowed characters). rag_search 'similarity_threshold' says '0.0-1.0, optional' but does not explain interpretation (higher = more similar) or typical ranges for good results.
Mutual exclusivity and parameter dependencies not documented. memory_list 'keys' and 'memory_types' could both filter independently, but interaction is unclear. memory_update 'data', 'extend_ttl', 'tags', 'metadata' are all optional and independent, a docstring note 'All fields are optional and independent; omitted fields are not modified' would prevent the LLM from assuming atomicity.