From 2a37ae3aa4a1ee1b36d2630e32be71701e7236c5 Mon Sep 17 00:00:00 2001 From: Irina Rueegg Date: Wed, 6 May 2026 19:25:48 +0200 Subject: [PATCH] Docstring anpassungen mcp server --- backend/agent/mcp_server_adapter.py | 2 +- backend/agent/mcp_server_config.json | 6 +-- .../servers/mcp_server_code_execution.py | 33 +++++---------- .../agent/servers/mcp_server_file_search.py | 40 +++++++++++++++++++ .../agent/servers/mcp_server_web_search.py | 4 ++ 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/backend/agent/mcp_server_adapter.py b/backend/agent/mcp_server_adapter.py index c3c779b..b95e457 100644 --- a/backend/agent/mcp_server_adapter.py +++ b/backend/agent/mcp_server_adapter.py @@ -1,6 +1,6 @@ import asyncio import json -import os +# import os import numpy as np from typing import List, Dict, Any from pathlib import Path diff --git a/backend/agent/mcp_server_config.json b/backend/agent/mcp_server_config.json index 087e5cb..83075a6 100644 --- a/backend/agent/mcp_server_config.json +++ b/backend/agent/mcp_server_config.json @@ -1,15 +1,15 @@ -{"Filemanager": { +{"FileSearchServer": { "command": "python", "args": ["servers/mcp_server_file_search.py"] }, -"WebSearch": { +"WebSearchServer": { "command": "python", "args": ["servers/mcp_server_web_search.py"], "env": { "DDGS_API_KEY": "your_ddgs_api_key_here" } }, -"CodeExecution": { +"CodeExecutionServer": { "command": "python", "args": ["servers/mcp_server_code_execution.py"] } diff --git a/backend/agent/servers/mcp_server_code_execution.py b/backend/agent/servers/mcp_server_code_execution.py index 7f610b7..62d1879 100644 --- a/backend/agent/servers/mcp_server_code_execution.py +++ b/backend/agent/servers/mcp_server_code_execution.py @@ -6,7 +6,7 @@ from mcp.server.fastmcp import FastMCP EXEC_TIMEOUT = 10 # seconds before killing the subprocess MAX_OUTPUT_LENGTH = 3000 # max characters of stdout+stderr to return -mcp = FastMCP("SafeExecServer") +mcp = FastMCP("CodeExecutionServer") BLOCKED_IMPORTS = { # Filesystem access: @@ -41,15 +41,11 @@ def check_code_safety(code: str) -> str | None: """ Statically analyze Python code for forbidden imports and builtins with ast. + Args: + code: The Python code to analyze. - Parameters - ---------- - code : str - The Python code to check. - - Returns - ------- - str or None + Returns: + str or None Error message if forbidden code found, None if safe. """ @@ -79,21 +75,14 @@ def run_python_sandboxed(code: str) -> str: """ Run Python code in a sandboxed subprocess. - Defense layers: - 1. Static analysis (check_code_safety) - 2. Subprocess isolation (child process) - 3. Timeout (killed after EXEC_TIMEOUT seconds) - 4. Output truncation (max MAX_OUTPUT_LENGTH chars) + Static analysis (check_code_safety), Subprocess isolation (child process) + Timeout (killed after EXEC_TIMEOUT seconds), Output truncation (max MAX_OUTPUT_LENGTH chars) - Parameters - ---------- - code : str - The Python code to execute. + Args: + code: The Python code to execute in str format. - Returns - ------- - str - Combined stdout+stderr, or an error message. + Returns: + Combined stdout+stderr, or an error message in str format. """ static_safety = check_code_safety(code) diff --git a/backend/agent/servers/mcp_server_file_search.py b/backend/agent/servers/mcp_server_file_search.py index 55d3231..8257b93 100644 --- a/backend/agent/servers/mcp_server_file_search.py +++ b/backend/agent/servers/mcp_server_file_search.py @@ -44,6 +44,9 @@ def read_file(path: str) -> str: Args: path: Relative path to the file within the project directory. + + Returns: + The file content as a string, or an error message if the file cannot be read. """ try: resolved = _safe_path(path) @@ -60,6 +63,40 @@ def read_file(path: str) -> str: except UnicodeDecodeError: return f"Error: '{path}' is not a text file (binary content)." +@mcp.tool() +def write_file(path: str, content: str) -> str: + """Write content to a .py or .txt file in the allowed directory. + Args: + path: Relative path to the file within the allowed directory. + content: The content to write to the file. + + Returns: + A success or error message. + """ + + try: + resolved = _safe_path(path) + except ValueError as e: + return f"Error: {e}" + + + if resolved.suffix not in (".py", ".txt"): + return f"ERROR: can only write .py and .txt files, got '{resolved.suffix}'." + + try: + resolved.parent.mkdir(parents=True, exist_ok=True) + resolved.write_text(content, encoding="utf-8") + return f"OK: wrote {len(content)} chars to {path}." + + except FileNotFoundError as e: + print(f"FileNotFoundError for {path}: {e}") + return f"Error: {e}" + except PermissionError as e: + print(f"PermissionError for {path}: {e}") + return f"Error: {e}" + except Exception as e: + return f"Error: {e}" + @mcp.tool() def search_files(query: str) -> str: @@ -67,6 +104,9 @@ def search_files(query: str) -> str: Args: query: The search term (case-insensitive). + + Returns: + A formatted string of search results, or a message if no matches found. """ query_lower = query.lower() results = [] diff --git a/backend/agent/servers/mcp_server_web_search.py b/backend/agent/servers/mcp_server_web_search.py index 8b92731..0c15132 100644 --- a/backend/agent/servers/mcp_server_web_search.py +++ b/backend/agent/servers/mcp_server_web_search.py @@ -47,6 +47,8 @@ def web_search(query: str, max_results: int = 5) -> str: Args: query: The search query. max_results: Maximum number of results to return (default 5). + Returns: + A formatted string of search results, or a message if no matches found. """ try: from ddgs import DDGS @@ -74,6 +76,8 @@ def fetch_page(url: str) -> str: Args: url: The URL to fetch. + Returns: + The text content of the fetched page, or an error message. """ try: url = _validate_url(url)