feat: solution for 69f8e929da860fb4533faa2a

This commit is contained in:
+22 -22
View File
@@ -3,7 +3,7 @@ from fastmcp import FastMCP
import json import json
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any, Optional, List from typing import Any, Optional
import fnmatch import fnmatch
class MemoryServer: class MemoryServer:
@@ -14,15 +14,15 @@ class MemoryServer:
def _load_memory(self) -> dict: def _load_memory(self) -> dict:
if not self.storage_path.exists(): if not self.storage_path.exists():
return {} return {}
with open(self.storage_path, 'r', encoding='utf-8') as f: with open(self.storage_path, "r", encoding="utf-8") as f:
return json.load(f) return json.load(f)
def _save_memory(self, data: dict): def _save_memory(self, data: dict):
self.storage_path.parent.mkdir(parents=True, exist_ok=True) self.storage_path.parent.mkdir(parents=True, exist_ok=True)
with open(self.storage_path, 'w', encoding='utf-8') as f: with open(self.storage_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False) json.dump(data, f, indent=2, ensure_ascii=False)
@self.mcp.tool @self.mcp.tool()
def save(self, key: str, value: Any) -> bool: def save(self, key: str, value: Any) -> bool:
"""Сохраняет значение по ключу в память сервера.""" """Сохраняет значение по ключу в память сервера."""
data = self._load_memory() data = self._load_memory()
@@ -30,16 +30,13 @@ class MemoryServer:
self._save_memory(data) self._save_memory(data)
return True return True
@self.mcp.tool @self.mcp.tool()
def get(self, key: str) -> Optional[dict]: def get(self, key: str) -> Optional[dict]:
"""Возвращает значение по ключу с метаданными.""" """Возвращает значение по ключу с метаданными."""
data = self._load_memory() data = self._load_memory()
entry = data.get(key) return data.get(key)
if entry is None:
return None
return {"key": key, "value": entry["value"], "timestamp": entry["timestamp"]}
@self.mcp.tool @self.mcp.tool()
def delete(self, key: str) -> bool: def delete(self, key: str) -> bool:
"""Удаляет ключ из памяти сервера.""" """Удаляет ключ из памяти сервера."""
data = self._load_memory() data = self._load_memory()
@@ -49,27 +46,27 @@ class MemoryServer:
return True return True
return False return False
@self.mcp.tool @self.mcp.tool()
def list_keys(self, pattern: str = "*") -> List[str]: def list_keys(self, pattern: str = "*") -> list[str]:
"""Возвращает список всех ключей с поддержкой wildcard-паттерна.""" """Возвращает список всех ключей с поддержкой wildcard-паттерна."""
data = self._load_memory() data = self._load_memory()
return [k for k in data.keys() if fnmatch.fnmatch(k, pattern)] return [k for k in data.keys() if fnmatch.fnmatch(k, pattern)]
@self.mcp.tool @self.mcp.tool()
def save_with_namespace(self, key: str, value: Any, namespace: str = "default") -> bool: def save_with_namespace(self, key: str, value: Any, namespace: str = "default") -> bool:
"""Сохраняет значение с указанием пространства имён.""" """Сохраняет значение с указанием пространства имён."""
full_key = f"{namespace}:{key}" full_key = f"{namespace}:{key}"
return self.save(full_key, value) return self.save(full_key, value)
@self.mcp.tool @self.mcp.tool()
def get_by_namespace(self, namespace: str = "default") -> List[dict]: def get_by_namespace(self, namespace: str = "default") -> list[dict]:
"""Возвращает все ключи из указанного namespace.""" """Возвращает все ключи из указанного namespace."""
data = self._load_memory() data = self._load_memory()
result = []
prefix = f"{namespace}:" prefix = f"{namespace}:"
result = []
for k, v in data.items(): for k, v in data.items():
if k.startswith(prefix): if k.startswith(prefix):
result.append({"key": k[len(prefix):], "value": v["value"], "timestamp": v["timestamp"]}) result.append({"key": k, "value": v["value"], "timestamp": v["timestamp"]})
return result return result
if __name__ == "__main__": if __name__ == "__main__":
@@ -77,12 +74,12 @@ if __name__ == "__main__":
server.mcp.run( server.mcp.run(
transport="stdio", transport="stdio",
show_banner=False, show_banner=False,
log_level='ERROR' log_level="ERROR"
) )
# memory_client.py # memory_client.py
import asyncio
from fastmcp import Client from fastmcp import Client
import asyncio
async def main(): async def main():
client = Client("python memory_server.py") client = Client("python memory_server.py")
@@ -92,21 +89,24 @@ async def main():
# Сохранение данных в namespace "default" # Сохранение данных в namespace "default"
result = await client.call_tool( result = await client.call_tool(
"save_with_namespace", "save_with_namespace",
{"key": "username", "value": "Алексей", "namespace": "default"} {"key": "username", "value": "Алексей", "namespace": "default"},
) )
print(f"Сохранено: {result}") print(f"Сохранено: {result}")
# Чтение данных # Чтение данных
result = await client.call_tool( result = await client.call_tool(
"get_by_namespace", "get_by_namespace",
{"namespace": "default"} {"namespace": "default"},
) )
print("Данные namespace 'default':") print("Данные namespace 'default':")
for item in result: for item in result:
print(f" {item['key']}: {item['value']}") print(f" {item['key']}: {item['value']}")
# Поиск по паттерну # Поиск по паттерну
keys = await client.call_tool("list_keys", {"pattern": "*name"}) keys = await client.call_tool(
"list_keys",
{"pattern": "*name"},
)
print(f"Ключи с 'name': {keys}") print(f"Ключи с 'name': {keys}")
finally: finally: