From 368c17197c2f825c624647f70a8d33ebb6bf39c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=B8=D1=8F=20=D0=91=D0=B5=D1=80=D0=B4?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Wed, 27 May 2026 08:16:32 +0000 Subject: [PATCH] =?UTF-8?q?MCP-=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D0=BC=D1=8F=D1=82=D1=8C=D1=8E?= =?UTF-8?q?=20=D0=B0=D0=B3=D0=B5=D0=BD=D1=82=D0=B0:=20memory=5Fserver.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../memory_server.py | 165 +++++++++--------- 1 file changed, 85 insertions(+), 80 deletions(-) diff --git a/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/memory_server.py b/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/memory_server.py index f575405..c59689a 100644 --- a/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/memory_server.py +++ b/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/memory_server.py @@ -1,104 +1,109 @@ import json -from typing import Dict, List, Optional +from typing import Any, Dict, List -from fastmcp import FastMCP -from fastmcp.exceptions import RPCError -from pydantic import BaseModel +from fastmcp import FastMCP, tool -class SaveRequest(BaseModel): - key: str - value: str +class MemoryStore: + """ + Простое хранилище в памяти с поддержкой пространств имён. + """ + + def __init__(self) -> None: + # основной словарь: ключ → значение + self._store: Dict[str, Any] = {} + # словари по namespace: namespace → {key: value} + self._namespaces: Dict[str, Dict[str, Any]] = {} + + # ---------- Основные операции ---------- + def save(self, key: str, value: Any) -> None: + """Сохраняет значение под ключом.""" + self._store[key] = value + + def get(self, key: str) -> Any | None: + """Возвращает значение по ключу или None, если его нет.""" + return self._store.get(key) + + def delete(self, key: str) -> bool: + """Удаляет ключ. Возвращает True, если удалено.""" + if key in self._store: + del self._store[key] + return True + return False + + def list_keys(self) -> List[str]: + """Возвращает список всех ключей.""" + return list(self._store.keys()) + + # ---------- Операции с namespace ---------- + def save_with_namespace(self, namespace: str, key: str, value: Any) -> None: + """Сохраняет значение в указанном пространстве имён.""" + ns = self._namespaces.setdefault(namespace, {}) + ns[key] = value + + def get_by_namespace(self, namespace: str, key: str) -> Any | None: + """Получает значение из пространства имён.""" + return self._namespaces.get(namespace, {}).get(key) -class GetRequest(BaseModel): - key: str +# Создаём экземпляр хранилища +memory_store = MemoryStore() -class DeleteRequest(BaseModel): - key: str +@tool(name="save", description="Сохраняет значение по ключу") +def tool_save(key: str, value: Any) -> None: + memory_store.save(key, value) + return f"Ключ '{key}' сохранён." -class ListKeysResponse(BaseModel): - keys: List[str] +@tool(name="get", description="Получает значение по ключу") +def tool_get(key: str) -> Any | None: + result = memory_store.get(key) + if result is None: + return f"Ключ '{key}' не найден." + return result -class NamespaceSaveRequest(BaseModel): - namespace: str - key: str - value: str +@tool(name="delete", description="Удаляет ключ из памяти") +def tool_delete(key: str) -> bool: + deleted = memory_store.delete(key) + return deleted -class NamespaceGetRequest(BaseModel): - namespace: str - key: str +@tool(name="list_keys", description="Возвращает список всех ключей в памяти") +def tool_list_keys() -> List[str]: + return memory_store.list_keys() -# In‑memory store. Keys are strings, values are arbitrary JSON serialisable objects. -_memory_store: Dict[str, any] = {} -# Namespaces are dictionaries inside the main store. -_namespaces: Dict[str, Dict[str, any]] = {} +@tool(name="save_with_namespace", description="Сохраняет значение под ключом внутри namespace") +def tool_save_with_namespace(namespace: str, key: str, value: Any) -> None: + memory_store.save_with_namespace(namespace, key, value) + return f"Ключ '{key}' в namespace '{namespace}' сохранён." -def _ensure_namespace(namespace: str): - if namespace not in _namespaces: - _namespaces[namespace] = {} +@tool(name="get_by_namespace", description="Получает значение по ключу из namespace") +def tool_get_by_namespace(namespace: str, key: str) -> Any | None: + result = memory_store.get_by_namespace(namespace, key) + if result is None: + return f"Ключ '{key}' в namespace '{namespace}' не найден." + return result -app = FastMCP() +# Создаём FastMCP приложение +app = FastMCP( + name="MemoryServer", + description="FastMCP сервер для управления памятью агента", +) - -@app.rpc("save") -async def save(request: SaveRequest) -> None: - """Сохраняет значение по ключу.""" - _memory_store[request.key] = request.value - - -@app.rpc("get") -async def get(request: GetRequest): - """Возвращает сохранённое значение. Если ключа нет – ошибка.""" - if request.key not in _memory_store: - raise RPCError(f"Key '{request.key}' not found") - return _memory_store[request.key] - - -@app.rpc("delete") -async def delete(request: DeleteRequest) -> None: - """Удаляет ключ из памяти.""" - if request.key in _memory_store: - del _memory_store[request.key] - else: - raise RPCError(f"Key '{request.key}' not found") - - -@app.rpc("list_keys") -async def list_keys() -> ListKeysResponse: - """Возвращает список всех ключей.""" - return ListKeysResponse(keys=list(_memory_store.keys())) - - -@app.rpc("save_with_namespace") -async def save_with_namespace(request: NamespaceSaveRequest) -> None: - """Сохраняет значение в указанном пространстве имён.""" - _ensure_namespace(request.namespace) - _namespaces[request.namespace][request.key] = request.value - - -@app.rpc("get_by_namespace") -async def get_by_namespace(request: NamespaceGetRequest): - """Получает значение из пространства имён. Ошибка, если не найдено.""" - if request.namespace not in _namespaces: - raise RPCError(f"Namespace '{request.namespace}' does not exist") - ns = _namespaces[request.namespace] - if request.key not in ns: - raise RPCError( - f"Key '{request.key}' not found in namespace '{request.namespace}'" - ) - return ns[request.key] +# Регистрируем все инструменты +app.register_tool(tool_save) +app.register_tool(tool_get) +app.register_tool(tool_delete) +app.register_tool(tool_list_keys) +app.register_tool(tool_save_with_namespace) +app.register_tool(tool_get_by_namespace) if __name__ == "__main__": - # Запускаем сервер FastMCP - import uvicorn - - uvicorn.run(app, host="0.0.0.0", port=8000) \ No newline at end of file + # Запускаем сервер на порту 8000 + app.run(host="0.0.0.0", port=8000) \ No newline at end of file