diff --git a/opax-mcp/server.py b/opax-mcp/server.py index 3435e34..50c7a9e 100644 --- a/opax-mcp/server.py +++ b/opax-mcp/server.py @@ -383,6 +383,61 @@ async def push_file(p): if "sha" in body: return await _gitea_put(f"/repos/{repo}/contents/{path}", body) return await _gitea_post(f"/repos/{repo}/contents/{path}", body) +# --------------------------------------------------------------------------- +# Memory Bank Tools +# --------------------------------------------------------------------------- +PROJECT_DIR = os.path.abspath("project") + +def _resolve_memory_path(file_name: str) -> str: + """Resolves a file path and ensures it is within the project/ directory.""" + if not file_name or '..' in file_name or file_name.startswith('/'): + raise ValueError("Invalid file name.") + + abs_path = os.path.abspath(os.path.join(PROJECT_DIR, file_name)) + + if not abs_path.startswith(PROJECT_DIR): + raise ValueError("Security violation: Path is outside the allowed memory bank directory.") + + return abs_path + +async def read_memory_bank(p: dict) -> dict: + """Reads content from a file in the memory bank (project/ directory).""" + file_name = p.get("file_name") + if not file_name: + raise ValueError("Missing required parameter: 'file_name'") + + file_path = _resolve_memory_path(file_name) + + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + return {"file_path": file_name, "content": content} + except FileNotFoundError: + raise ValueError(f"File not found: {file_name}") + except Exception as e: + logger.error(f"Error reading memory bank file {file_name}: {e}", exc_info=True) + raise + +async def write_memory_bank(p: dict) -> dict: + """Writes or overwrites content to a file in the memory bank (project/ directory).""" + file_name = p.get("file_name") + content = p.get("content") + + if not file_name or content is None: + raise ValueError("Missing required parameters: 'file_name' and 'content'") + + file_path = _resolve_memory_path(file_name) + + try: + os.makedirs(PROJECT_DIR, exist_ok=True) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(content) + logger.info(f"Successfully wrote to memory bank file: {file_name}") + return {"status": "success", "file_path": file_name} + except Exception as e: + logger.error(f"Error writing to memory bank file {file_name}: {e}", exc_info=True) + raise + # --------------------------------------------------------------------------- # Tool registry + MCP schema # --------------------------------------------------------------------------- @@ -462,6 +517,9 @@ TOOLS = { "list_workspace_users": (list_workspace_users, "List alle brukere i Workspace-domenet", {}), "get_emails": (get_emails, "Søk i en brukers e-post", {"type":"object","properties":{"user_key":{"type":"string"},"query":{"type":"string"}},"required":["user_key"]}), "list_calendar_events": (list_calendar_events, "List en brukers kalenderhendelser", {"type":"object","properties":{"user_key":{"type":"string"},"days_ahead":{"type":"integer"}},"required":["user_key"]}), + # Memory Bank + "read_memory_bank": (read_memory_bank, "Reads a file from the project memory bank.", {"type": "object", "properties": {"file_name": {"type": "string"}}, "required": ["file_name"]}), + "write_memory_bank": (write_memory_bank, "Writes a file to the project memory bank.", {"type": "object", "properties": {"file_name": {"type": "string"}, "content": {"type": "string"}}, "required": ["file_name", "content"]}), } # ---------------------------------------------------------------------------