mem-brain-mcp 1.0.2__py3-none-any.whl → 1.0.4__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.
- mem_brain_mcp/__init__.py +1 -1
- mem_brain_mcp/server.py +70 -17
- {mem_brain_mcp-1.0.2.dist-info → mem_brain_mcp-1.0.4.dist-info}/METADATA +1 -1
- mem_brain_mcp-1.0.4.dist-info/RECORD +9 -0
- mem_brain_mcp-1.0.2.dist-info/RECORD +0 -9
- {mem_brain_mcp-1.0.2.dist-info → mem_brain_mcp-1.0.4.dist-info}/WHEEL +0 -0
- {mem_brain_mcp-1.0.2.dist-info → mem_brain_mcp-1.0.4.dist-info}/entry_points.txt +0 -0
mem_brain_mcp/__init__.py
CHANGED
mem_brain_mcp/server.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""MCP Server for Mem-Brain API using FastMCP."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
4
5
|
from typing import Any, Dict, List, Optional, Union
|
|
5
6
|
import httpx
|
|
@@ -407,11 +408,13 @@ async def add_memory(
|
|
|
407
408
|
- Example: "User prefers Python over JavaScript"
|
|
408
409
|
- Example: "User prefers dark mode interfaces"
|
|
409
410
|
|
|
410
|
-
tags (list[str], optional):
|
|
411
|
-
- Can be None (default)
|
|
411
|
+
tags (list[str] or str, optional): Tags to categorize the memory.
|
|
412
|
+
- Can be None (default), a list of strings, a comma-separated string, or a JSON array string
|
|
413
|
+
- If omitted, the system will auto-generate tags based on content
|
|
412
414
|
- Example: ["coding", "preferences"]
|
|
413
|
-
- Example:
|
|
414
|
-
-
|
|
415
|
+
- Example: "coding,preferences" (comma-separated)
|
|
416
|
+
- Example: '["coding", "preferences"]' (JSON string)
|
|
417
|
+
- Note: The system auto-generates relevant tags, so providing tags is optional
|
|
415
418
|
|
|
416
419
|
category (str, optional): Category name for the memory.
|
|
417
420
|
- Can be None (default) or a non-empty string
|
|
@@ -480,7 +483,7 @@ async def add_memory(
|
|
|
480
483
|
logger.info(f"add_memory called - content length: {len(content_str)}, tags: {tags}, category: {category}")
|
|
481
484
|
logger.debug(f"add_memory full content: {content_str[:100]}...")
|
|
482
485
|
|
|
483
|
-
# Normalize tags:
|
|
486
|
+
# Normalize tags: handle various input formats and convert to list of strings
|
|
484
487
|
normalized_tags = None
|
|
485
488
|
if tags is not None:
|
|
486
489
|
if isinstance(tags, list):
|
|
@@ -495,13 +498,31 @@ async def add_memory(
|
|
|
495
498
|
)
|
|
496
499
|
normalized_tags = tags if tags else None # Empty list becomes None
|
|
497
500
|
elif isinstance(tags, str):
|
|
498
|
-
|
|
499
|
-
|
|
501
|
+
tags_str = tags.strip()
|
|
502
|
+
if not tags_str:
|
|
503
|
+
normalized_tags = None
|
|
504
|
+
else:
|
|
505
|
+
# Try to parse as JSON array first (e.g., '["tag1", "tag2"]')
|
|
506
|
+
try:
|
|
507
|
+
parsed = json.loads(tags_str)
|
|
508
|
+
if isinstance(parsed, list):
|
|
509
|
+
normalized_tags = [str(item).strip() for item in parsed if str(item).strip()]
|
|
510
|
+
else:
|
|
511
|
+
# If JSON but not a list, treat as single tag
|
|
512
|
+
normalized_tags = [tags_str]
|
|
513
|
+
except (json.JSONDecodeError, ValueError):
|
|
514
|
+
# Not JSON, try comma-separated string
|
|
515
|
+
if ',' in tags_str:
|
|
516
|
+
normalized_tags = [tag.strip() for tag in tags_str.split(',') if tag.strip()]
|
|
517
|
+
else:
|
|
518
|
+
# Single tag string
|
|
519
|
+
normalized_tags = [tags_str]
|
|
500
520
|
else:
|
|
501
521
|
raise ToolError(
|
|
502
|
-
f"The 'tags' parameter must be a list of strings or None, but got {type(tags).__name__}.\n"
|
|
522
|
+
f"The 'tags' parameter must be a list of strings, a comma-separated string, or None, but got {type(tags).__name__}.\n"
|
|
503
523
|
f"Received: {repr(tags)}\n"
|
|
504
524
|
"Example: add_memory(content=\"...\", tags=[\"coding\", \"preferences\"])\n"
|
|
525
|
+
"Example: add_memory(content=\"...\", tags=\"coding,preferences\")\n"
|
|
505
526
|
"Example: add_memory(content=\"...\", tags=None) # or omit tags parameter"
|
|
506
527
|
)
|
|
507
528
|
|
|
@@ -738,10 +759,13 @@ async def update_memory(
|
|
|
738
759
|
- If provided, must not be empty or whitespace-only
|
|
739
760
|
- Example: "User no longer likes TypeScript, prefers Python"
|
|
740
761
|
|
|
741
|
-
tags (list[str], optional): New tags for the memory.
|
|
742
|
-
- Can be None (to keep existing tags)
|
|
762
|
+
tags (list[str] or str, optional): New tags for the memory.
|
|
763
|
+
- Can be None (to keep existing tags), a list of strings, a comma-separated string, or a JSON array string
|
|
764
|
+
- If provided, replaces existing tags
|
|
743
765
|
- Example: ["coding", "python"]
|
|
744
|
-
- Example:
|
|
766
|
+
- Example: "coding,python" (comma-separated)
|
|
767
|
+
- Example: '["coding", "python"]' (JSON string)
|
|
768
|
+
- Note: The system can auto-generate tags if you omit this parameter
|
|
745
769
|
|
|
746
770
|
Returns:
|
|
747
771
|
str: A formatted string with the updated memory details.
|
|
@@ -819,7 +843,7 @@ async def update_memory(
|
|
|
819
843
|
else:
|
|
820
844
|
content_str = None
|
|
821
845
|
|
|
822
|
-
# Validate tags if provided
|
|
846
|
+
# Validate tags if provided - handle various input formats
|
|
823
847
|
normalized_tags = None
|
|
824
848
|
if tags is not None:
|
|
825
849
|
if isinstance(tags, list):
|
|
@@ -834,13 +858,31 @@ async def update_memory(
|
|
|
834
858
|
)
|
|
835
859
|
normalized_tags = tags if tags else None # Empty list becomes None
|
|
836
860
|
elif isinstance(tags, str):
|
|
837
|
-
|
|
838
|
-
|
|
861
|
+
tags_str = tags.strip()
|
|
862
|
+
if not tags_str:
|
|
863
|
+
normalized_tags = None
|
|
864
|
+
else:
|
|
865
|
+
# Try to parse as JSON array first (e.g., '["tag1", "tag2"]')
|
|
866
|
+
try:
|
|
867
|
+
parsed = json.loads(tags_str)
|
|
868
|
+
if isinstance(parsed, list):
|
|
869
|
+
normalized_tags = [str(item).strip() for item in parsed if str(item).strip()]
|
|
870
|
+
else:
|
|
871
|
+
# If JSON but not a list, treat as single tag
|
|
872
|
+
normalized_tags = [tags_str]
|
|
873
|
+
except (json.JSONDecodeError, ValueError):
|
|
874
|
+
# Not JSON, try comma-separated string
|
|
875
|
+
if ',' in tags_str:
|
|
876
|
+
normalized_tags = [tag.strip() for tag in tags_str.split(',') if tag.strip()]
|
|
877
|
+
else:
|
|
878
|
+
# Single tag string
|
|
879
|
+
normalized_tags = [tags_str]
|
|
839
880
|
else:
|
|
840
881
|
raise ToolError(
|
|
841
|
-
f"The 'tags' parameter must be a list of strings or None, but got {type(tags).__name__}.\n"
|
|
882
|
+
f"The 'tags' parameter must be a list of strings, a comma-separated string, or None, but got {type(tags).__name__}.\n"
|
|
842
883
|
f"Received: {repr(tags)}\n"
|
|
843
884
|
"Example: update_memory(memory_id=\"...\", tags=[\"coding\", \"preferences\"])\n"
|
|
885
|
+
"Example: update_memory(memory_id=\"...\", tags=\"coding,preferences\")\n"
|
|
844
886
|
"Example: update_memory(memory_id=\"...\", tags=None) # or omit tags parameter"
|
|
845
887
|
)
|
|
846
888
|
|
|
@@ -1101,16 +1143,27 @@ async def unlink_memories(memory_id_1: str, memory_id_2: str) -> str:
|
|
|
1101
1143
|
|
|
1102
1144
|
|
|
1103
1145
|
@mcp.tool()
|
|
1104
|
-
async def get_stats() -> str:
|
|
1146
|
+
async def get_stats(_placeholder: Optional[bool] = None) -> str:
|
|
1105
1147
|
"""Get memory system statistics including total memories, links, and top tags. Use this when user asks 'how much do you remember?' or wants an overview of their memory system.
|
|
1106
1148
|
|
|
1149
|
+
Parameters:
|
|
1150
|
+
_placeholder (bool, optional): Placeholder parameter for OpenCode compatibility. This parameter is ignored and can be omitted or set to any value. The function takes no actual parameters.
|
|
1151
|
+
- This is a workaround for MCP clients that incorrectly require a parameter for parameterless tools
|
|
1152
|
+
- Can be safely omitted or set to None/True/False
|
|
1153
|
+
- Example: get_stats() or get_stats(_placeholder=True)
|
|
1154
|
+
|
|
1107
1155
|
Returns:
|
|
1108
1156
|
str: Formatted statistics including total memories, links, and top tags.
|
|
1109
1157
|
|
|
1110
1158
|
Examples:
|
|
1111
|
-
# Get statistics
|
|
1159
|
+
# Get statistics (preferred - no parameters needed)
|
|
1112
1160
|
get_stats()
|
|
1161
|
+
|
|
1162
|
+
# Get statistics (OpenCode workaround - parameter is ignored)
|
|
1163
|
+
get_stats(_placeholder=True)
|
|
1113
1164
|
"""
|
|
1165
|
+
# _placeholder parameter is ignored - this is a workaround for OpenCode compatibility
|
|
1166
|
+
# The function actually takes no parameters, but some MCP clients incorrectly require one
|
|
1114
1167
|
try:
|
|
1115
1168
|
logger.info("get_stats called")
|
|
1116
1169
|
client = await _get_api_client()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mem-brain-mcp
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: MCP Server for Mem-Brain API - Exposes memory operations as MCP tools
|
|
5
5
|
Keywords: ai,claude,cursor,llm,mcp,memory,model-context-protocol
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
mem_brain_mcp/__init__.py,sha256=IxDcMoheWmVbcdZEJSXj5fAx0WlYMjVonvvG0boqsec,89
|
|
2
|
+
mem_brain_mcp/__main__.py,sha256=H_mwoKm1FBmu4KzAcQcq-TXZqeNvlrAekAxB1s4F4hA,712
|
|
3
|
+
mem_brain_mcp/client.py,sha256=7KFGcLoPDaOOLiuG2lygQK7xH5Kio-YifDjuSpDoDJ8,6993
|
|
4
|
+
mem_brain_mcp/config.py,sha256=xx2lBkCIeT85t0HxtORwZHSU3hZT_EdsThpfjwPJhbQ,1261
|
|
5
|
+
mem_brain_mcp/server.py,sha256=Yw92d-Qy5kRDAaIC8VjEKBOYKCy2p6neZ9OSfxsThdY,69640
|
|
6
|
+
mem_brain_mcp-1.0.4.dist-info/METADATA,sha256=7N3lTIQRHbFLfYdZyf2GZIowXEbmofVxO8QOrPFUCkE,5228
|
|
7
|
+
mem_brain_mcp-1.0.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
8
|
+
mem_brain_mcp-1.0.4.dist-info/entry_points.txt,sha256=NH6QYQ-Sd8eJn5crpe_DL1PvGeUlL3y65968xPhmwG8,62
|
|
9
|
+
mem_brain_mcp-1.0.4.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
mem_brain_mcp/__init__.py,sha256=NMoDpXlRhGO858M6lrLqPN0fz7hKpqler4e96WniWxg,89
|
|
2
|
-
mem_brain_mcp/__main__.py,sha256=H_mwoKm1FBmu4KzAcQcq-TXZqeNvlrAekAxB1s4F4hA,712
|
|
3
|
-
mem_brain_mcp/client.py,sha256=7KFGcLoPDaOOLiuG2lygQK7xH5Kio-YifDjuSpDoDJ8,6993
|
|
4
|
-
mem_brain_mcp/config.py,sha256=xx2lBkCIeT85t0HxtORwZHSU3hZT_EdsThpfjwPJhbQ,1261
|
|
5
|
-
mem_brain_mcp/server.py,sha256=qnevDzJkt1rH-slV2r0pP_SeFkknZVqWRnZEKH_IeVo,66308
|
|
6
|
-
mem_brain_mcp-1.0.2.dist-info/METADATA,sha256=zLQMVD-sIRSH03dYAP6RovZH_49XqREG061Yf87ROW4,5228
|
|
7
|
-
mem_brain_mcp-1.0.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
8
|
-
mem_brain_mcp-1.0.2.dist-info/entry_points.txt,sha256=NH6QYQ-Sd8eJn5crpe_DL1PvGeUlL3y65968xPhmwG8,62
|
|
9
|
-
mem_brain_mcp-1.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|