diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5da5e809..6d1a3c91 100755 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -43,7 +43,7 @@ Backend loop phases (see `server/__main__.py` and `server/plugin.py`): `once`, ` ## Conventions & helpers to reuse - Settings: add/modify via `ccd()` in `server/initialise.py` or per‑plugin manifest. Never hardcode ports or secrets; use `get_setting_value()`. -- Logging: use `logger.mylog(level, [message])`; levels: none/minimal/verbose/debug/trace. +- Logging: use `mylog(level, [message])`; levels: none/minimal/verbose/debug/trace. `none` is used for most important messages that should always appear, such as exceptions. - Time/MAC/strings: `helper.py` (`timeNowDB`, `normalize_mac`, sanitizers). Validate MACs before DB writes. - DB helpers: prefer `server/db/db_helper.py` functions (e.g., `get_table_json`, device condition helpers) over raw SQL in new paths. diff --git a/server/api_server/api_server_start.py b/server/api_server/api_server_start.py index aeb91bbc..7725d013 100755 --- a/server/api_server/api_server_start.py +++ b/server/api_server/api_server_start.py @@ -169,10 +169,12 @@ def log_request_info(): @app.errorhandler(404) def not_found(error): + # Get the requested path from the request object instead of error.description + requested_url = request.path if request else "unknown" response = { "success": False, "error": "API route not found", - "message": f"The requested URL {error.description if hasattr(error, 'description') else ''} was not found on the server.", + "message": f"The requested URL {requested_url} was not found on the server.", } return jsonify(response), 404 @@ -485,6 +487,11 @@ def api_wakeonlan(): if not dev or not dev.get('devMac'): return jsonify({"success": False, "message": "ERROR: Device not found", "error": "MAC not resolved"}), 404 mac = dev.get('devMac') + + # Validate that we have a valid MAC address + if not mac: + return jsonify({"success": False, "message": "ERROR: Missing device MAC or IP", "error": "Bad Request"}), 400 + return wakeonlan(mac) @@ -787,7 +794,8 @@ def get_last_events(): # Create fresh DB instance for this thread event_handler = EventInstance() - return event_handler.get_last_n(10) + events = event_handler.get_last_n(10) + return jsonify({"success": True, "count": len(events), "events": events}), 200 @app.route('/events/', methods=['GET']) diff --git a/server/api_server/mcp_endpoint.py b/server/api_server/mcp_endpoint.py index 773cd2c2..e9e07bee 100644 --- a/server/api_server/mcp_endpoint.py +++ b/server/api_server/mcp_endpoint.py @@ -71,7 +71,8 @@ def get_openapi_spec(): r.raise_for_status() _openapi_spec_cache = r.json() return _openapi_spec_cache - except Exception: + except Exception as e: + mylog("none", [f"[MCP] Failed to fetch OpenAPI spec: {e}"]) return None @@ -140,11 +141,13 @@ def process_mcp_request(data): try: json_content = api_res.json() content.append({'type': 'text', 'text': json.dumps(json_content, indent=2)}) - except Exception: + except Exception as e: + mylog("none", [f"[MCP] Failed to parse API response as JSON: {e}"]) content.append({'type': 'text', 'text': api_res.text}) is_error = api_res.status_code >= 400 return {'jsonrpc': '2.0', 'id': msg_id, 'result': {'content': content, 'isError': is_error}} except Exception as e: + mylog("none", [f"[MCP] Error calling tool {tool_name}: {e}"]) return {'jsonrpc': '2.0', 'id': msg_id, 'result': {'content': [{'type': 'text', 'text': f"Error calling tool: {str(e)}"}], 'isError': True}} if method == 'ping': return {'jsonrpc': '2.0', 'id': msg_id, 'result': {}} @@ -180,7 +183,7 @@ def mcp_sse(): else: return '', 202 except Exception as e: - mylog("none", f'SSE POST processing error: {e}') + mylog("none", [f"[MCP] SSE POST processing error: {e}"]) return jsonify({'status': 'ok', 'message': 'MCP SSE endpoint active'}), 200 session_id = uuid.uuid4().hex