Loading mcp_module/tools/edge_application.py +12 −11 Changes for mcp_module/tools/edge_application.py: 12 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ from mcp_module.models.edge_application_models import ( RegisterAppDefinitionInput, ) from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status # Configure logging logging.basicConfig( Loading Loading @@ -70,7 +71,7 @@ async def get_app_definitions( response = await client.get( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch edge application definitions: %s", e) raise Loading Loading @@ -138,7 +139,7 @@ async def register_app_definition( response = await client.post( url, headers=headers, json=payload, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to register app definition: %s", e) raise Loading Loading @@ -169,7 +170,7 @@ async def delete_app_definition( response = await client.delete( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to delete app definition %s: %s", inp.appId, e) raise Loading Loading @@ -203,7 +204,7 @@ async def get_app_definition( response = await client.get( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch app definition %s: %s", inp.appId, e) raise Loading Loading @@ -250,7 +251,7 @@ async def get_edge_cloud_zones( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch edge cloud zones: %s", e) raise Loading Loading @@ -303,7 +304,7 @@ async def instantiate_app( response = await client.post( url, headers=headers, json=payload, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to instantiate app %s: %s", inp.appId, e) raise Loading Loading @@ -343,7 +344,7 @@ async def get_app_instances( response = await client.get( url, headers=headers, params=params, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch app instances: %s", e) raise Loading Loading @@ -374,7 +375,7 @@ async def delete_app_instance( response = await client.delete( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to delete app instance %s: %s", inp.appInstanceId, e) raise Loading Loading @@ -437,7 +438,7 @@ async def create_app_deployment( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to create application deployment: %s", e) raise Loading Loading @@ -490,7 +491,7 @@ async def get_app_deployments( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch application deployments: %s", e) raise Loading Loading @@ -528,7 +529,7 @@ async def delete_app_deployment( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error( "Failed to delete application deployment %s: %s", Loading mcp_module/tools/location.py +2 −1 Changes for mcp_module/tools/location.py: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ from dotenv import load_dotenv from mcp_module.models.location_models import RetrieveLocationInput from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status logger = logging.getLogger("MCP server") Loading Loading @@ -66,7 +67,7 @@ async def retrieve_location( json=payload, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to retrieve device location: %s", e) raise Loading mcp_module/tools/oeg_errors.py 0 → 100644 +29 −0 Changes for mcp_module/tools/oeg_errors.py: 29 added lines, 0 removed lines. Original line number Diff line number Diff line """Expose OEG's CAMARA errors to the model without leaking raw HTTP bodies.""" import httpx from fastmcp.exceptions import ToolError def raise_for_oeg_status(response: httpx.Response) -> None: """Keep successful responses intact; report failed calls as MCP tool errors.""" if 200 <= response.status_code < 300: return code = None message = None try: body = response.json() except ValueError: body = None if isinstance(body, dict): code = body.get("code") message = body.get("message") details = [f"OEG HTTP {response.status_code}"] if isinstance(code, str) and code.strip(): details.append(code) if isinstance(message, str) and message.strip(): details.append(message) else: details.append(response.reason_phrase or "Request failed") raise ToolError(": ".join(details)) mcp_module/tools/qod.py +4 −3 Changes for mcp_module/tools/qod.py: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ logging.basicConfig( level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s" ) from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status logger = logging.getLogger("MCP server") Loading Loading @@ -73,7 +74,7 @@ async def create_qod_session_oai( json=payload, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to create QoD session: %s", e) raise Loading @@ -99,7 +100,7 @@ async def get_qod_session_oai( try: async with httpx.AsyncClient(trust_env=True) as client: response = await client.get(session_url, headers=headers, timeout=15) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to get session %s: %s", inp.sessionId, e) raise Loading Loading @@ -133,7 +134,7 @@ async def delete_qod_session_oai( headers=headers, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to delete session %s: %s", inp.sessionId, e) raise Loading mcp_module/tools/traffic_influence.py +5 −4 Changes for mcp_module/tools/traffic_influence.py: 5 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ from mcp_module.models.traffic_influence_models import ( CreateTrafficInfluenceInput, ) from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status logger = logging.getLogger("MCP server") Loading Loading @@ -74,7 +75,7 @@ async def create_traffic_influence( json=payload, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to create traffic influence: %s", e) raise Loading Loading @@ -117,7 +118,7 @@ async def get_traffic_influences( params=params, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch traffic influences: %s", e) raise Loading Loading @@ -156,7 +157,7 @@ async def get_traffic_influence( headers=headers, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error( "Failed to fetch traffic influence %s: %s", Loading Loading @@ -199,7 +200,7 @@ async def delete_traffic_influence( headers=headers, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error( "Failed to delete traffic influence %s: %s", Loading Loading
mcp_module/tools/edge_application.py +12 −11 Changes for mcp_module/tools/edge_application.py: 12 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ from mcp_module.models.edge_application_models import ( RegisterAppDefinitionInput, ) from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status # Configure logging logging.basicConfig( Loading Loading @@ -70,7 +71,7 @@ async def get_app_definitions( response = await client.get( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch edge application definitions: %s", e) raise Loading Loading @@ -138,7 +139,7 @@ async def register_app_definition( response = await client.post( url, headers=headers, json=payload, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to register app definition: %s", e) raise Loading Loading @@ -169,7 +170,7 @@ async def delete_app_definition( response = await client.delete( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to delete app definition %s: %s", inp.appId, e) raise Loading Loading @@ -203,7 +204,7 @@ async def get_app_definition( response = await client.get( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch app definition %s: %s", inp.appId, e) raise Loading Loading @@ -250,7 +251,7 @@ async def get_edge_cloud_zones( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch edge cloud zones: %s", e) raise Loading Loading @@ -303,7 +304,7 @@ async def instantiate_app( response = await client.post( url, headers=headers, json=payload, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to instantiate app %s: %s", inp.appId, e) raise Loading Loading @@ -343,7 +344,7 @@ async def get_app_instances( response = await client.get( url, headers=headers, params=params, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch app instances: %s", e) raise Loading Loading @@ -374,7 +375,7 @@ async def delete_app_instance( response = await client.delete( url, headers=headers, follow_redirects=True, timeout=15 ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to delete app instance %s: %s", inp.appInstanceId, e) raise Loading Loading @@ -437,7 +438,7 @@ async def create_app_deployment( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to create application deployment: %s", e) raise Loading Loading @@ -490,7 +491,7 @@ async def get_app_deployments( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch application deployments: %s", e) raise Loading Loading @@ -528,7 +529,7 @@ async def delete_app_deployment( follow_redirects=True, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error( "Failed to delete application deployment %s: %s", Loading
mcp_module/tools/location.py +2 −1 Changes for mcp_module/tools/location.py: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ from dotenv import load_dotenv from mcp_module.models.location_models import RetrieveLocationInput from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status logger = logging.getLogger("MCP server") Loading Loading @@ -66,7 +67,7 @@ async def retrieve_location( json=payload, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to retrieve device location: %s", e) raise Loading
mcp_module/tools/oeg_errors.py 0 → 100644 +29 −0 Changes for mcp_module/tools/oeg_errors.py: 29 added lines, 0 removed lines. Original line number Diff line number Diff line """Expose OEG's CAMARA errors to the model without leaking raw HTTP bodies.""" import httpx from fastmcp.exceptions import ToolError def raise_for_oeg_status(response: httpx.Response) -> None: """Keep successful responses intact; report failed calls as MCP tool errors.""" if 200 <= response.status_code < 300: return code = None message = None try: body = response.json() except ValueError: body = None if isinstance(body, dict): code = body.get("code") message = body.get("message") details = [f"OEG HTTP {response.status_code}"] if isinstance(code, str) and code.strip(): details.append(code) if isinstance(message, str) and message.strip(): details.append(message) else: details.append(response.reason_phrase or "Request failed") raise ToolError(": ".join(details))
mcp_module/tools/qod.py +4 −3 Changes for mcp_module/tools/qod.py: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ logging.basicConfig( level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s" ) from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status logger = logging.getLogger("MCP server") Loading Loading @@ -73,7 +74,7 @@ async def create_qod_session_oai( json=payload, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to create QoD session: %s", e) raise Loading @@ -99,7 +100,7 @@ async def get_qod_session_oai( try: async with httpx.AsyncClient(trust_env=True) as client: response = await client.get(session_url, headers=headers, timeout=15) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to get session %s: %s", inp.sessionId, e) raise Loading Loading @@ -133,7 +134,7 @@ async def delete_qod_session_oai( headers=headers, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to delete session %s: %s", inp.sessionId, e) raise Loading
mcp_module/tools/traffic_influence.py +5 −4 Changes for mcp_module/tools/traffic_influence.py: 5 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ from mcp_module.models.traffic_influence_models import ( CreateTrafficInfluenceInput, ) from mcp_module.security.authorization import get_oeg_authorization_headers from mcp_module.tools.oeg_errors import raise_for_oeg_status logger = logging.getLogger("MCP server") Loading Loading @@ -74,7 +75,7 @@ async def create_traffic_influence( json=payload, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to create traffic influence: %s", e) raise Loading Loading @@ -117,7 +118,7 @@ async def get_traffic_influences( params=params, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error("Failed to fetch traffic influences: %s", e) raise Loading Loading @@ -156,7 +157,7 @@ async def get_traffic_influence( headers=headers, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error( "Failed to fetch traffic influence %s: %s", Loading Loading @@ -199,7 +200,7 @@ async def delete_traffic_influence( headers=headers, timeout=15, ) response.raise_for_status() raise_for_oeg_status(response) except httpx.HTTPError as e: logger.error( "Failed to delete traffic influence %s: %s", Loading