MCP-сервер для управления памятью агента: добавлен solution.py

This commit is contained in:
2026-05-25 12:40:39 +00:00
parent a4bdbf76e0
commit 12d3c164f3
@@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
# MCP-сервер для управления памятью агента
# Используем FastMCP, pydantic и python-dotenv
import json
import os
from pathlib import Path
from typing import Any, Dict, List, Optional
from dotenv import load_dotenv
from fastmcp import MCPServer, MCPRequest, MCPResponse
from pydantic import BaseModel, Field
# Загружаем переменные окружения из .env
load_dotenv()
# Путь к файлу хранения данных
DATA_FILE = Path(os.getenv("MEMORY_DATA_FILE", "memory_data.json"))
# ---------------------
# Модели данных
# ---------------------
class MemoryItem(BaseModel):
key: str = Field(..., description="Ключ памяти")
value: Any = Field(..., description="Значение памяти")
namespace: Optional[str] = Field(None, description="Опциональное пространство имён")
# ---------------------
# Хранилище памяти
# ---------------------
class MemoryStore:
def __init__(self, file_path: Path):
self.file_path = file_path
self._data: Dict[str, Any] = {}
self._load()
def _load(self) -> None:
if self.file_path.exists():
try:
with self.file_path.open("r", encoding="utf-8") as f:
self._data = json.load(f)
except Exception:
self._data = {}
else:
self._data = {}
def _save(self) -> None:
with self.file_path.open("w", encoding="utf-8") as f:
json.dump(self._data, f, ensure_ascii=False, indent=2)
def save(self, key: str, value: Any) -> None:
self._data[key] = value
self._save()
def get(self, key: str) -> Any:
return self._data.get(key)
def delete(self, key: str) -> bool:
if key in self._data:
del self._data[key]
self._save()
return True
return False
def list_keys(self) -> List[str]:
return list(self._data.keys())
def save_with_namespace(self, key: str, value: Any, namespace: str) -> None:
ns_key = f"{namespace}:{key}"
self.save(ns_key, value)
def get_by_namespace(self, key: str, namespace: str) -> Any:
ns_key = f"{namespace}:{key}"
return self.get(ns_key)
# ---------------------
# MCP-обработчики
# ---------------------
class MemoryMCPHandler:
def __init__(self, store: MemoryStore):
self.store = store
async def handle(self, request: MCPRequest) -> MCPResponse:
# Ожидаем, что payload содержит "action" и параметры
payload = request.payload
action = payload.get("action")
if not action:
return MCPResponse(error="Missing action")
try:
if action == "save":
key = payload["key"]
value = payload["value"]
self.store.save(key, value)
return MCPResponse(result="ok")
elif action == "get":
key = payload["key"]
value = self.store.get(key)
return MCPResponse(result=value)
elif action == "delete":
key = payload["key"]
success = self.store.delete(key)
return MCPResponse(result=success)
elif action == "list_keys":
keys = self.store.list_keys()
return MCPResponse(result=keys)
elif action == "save_with_namespace":
key = payload["key"]
value = payload["value"]
namespace = payload["namespace"]
self.store.save_with_namespace(key, value, namespace)
return MCPResponse(result="ok")
elif action == "get_by_namespace":
key = payload["key"]
namespace = payload["namespace"]
value = self.store.get_by_namespace(key, namespace)
return MCPResponse(result=value)
else:
return MCPResponse(error="Unknown action")
except KeyError as e:
return MCPResponse(error=f"Missing parameter: {e}")
except Exception as e:
return MCPResponse(error=str(e))
# ---------------------
# Запуск сервера
# ---------------------
async def main():
store = MemoryStore(DATA_FILE)
handler = MemoryMCPHandler(store)
server = MCPServer(handler=handler, host=os.getenv("HOST", "0.0.0.0"), port=int(os.getenv("PORT", 8000)))
await server.serve()
if __name__ == "__main__":
import asyncio
asyncio.run(main())