Loading mcp_module/app.py +4 −0 Changes for mcp_module/app.py: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ from fastapi.responses import PlainTextResponse from fastmcp import FastMCP from mcp_module.tools.edge_application import ( get_app_deployments, create_app_deployment, delete_app_definition, delete_app_instance, get_app_definition, Loading Loading @@ -37,6 +39,7 @@ mcp = FastMCP("MCP Server") # Register tools - only audited functions are exposed SAFE_TOOLS: list[Callable[..., Any]] = [ get_app_deployments, create_qod_session_oai, get_qod_session_oai, delete_qod_session_oai, Loading @@ -48,6 +51,7 @@ SAFE_TOOLS: list[Callable[..., Any]] = [ instantiate_app, get_app_instances, delete_app_instance, create_app_deployment, ] for tool in SAFE_TOOLS: Loading mcp_module/json_templates/app_deployment_request.json 0 → 100644 +5 −0 Changes for mcp_module/json_templates/app_deployment_request.json: 5 added lines, 0 removed lines. Original line number Diff line number Diff line { "appDeploymentName": "", "appId": "", "edgeCloudZones": [] } No newline at end of file mcp_module/json_templates/app_instantiate_request.json +2 −11 Changes for mcp_module/json_templates/app_instantiate_request.json: 2 added lines, 11 removed lines. Original line number Diff line number Diff line { "name": "", "appId": "", "appZones": [ { "EdgeCloudZone": { "edgeCloudZoneId": "", "edgeCloudZoneName": "string", "edgeCloudZoneStatus": "unknown", "edgeCloudProvider": "string", "edgeCloudRegion": "string" } } ] "edgeCloudZoneId": "" } No newline at end of file mcp_module/json_templates/app_register_app_definition_request.json +2 −5 Changes for mcp_module/json_templates/app_register_app_definition_request.json: 2 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -6,11 +6,8 @@ "type": "PRIVATEREPO", "imagePath": "" }, "requiredResources": { "infraKind": "container", "numCPU": "100m", "memory": 512 }, "appProvider": "", "requiredResources": {}, "componentSpec": [ { "componentName": "", Loading mcp_module/models/edge_application_models.py +45 −26 Changes for mcp_module/models/edge_application_models.py: 45 added lines, 26 removed lines. Original line number Diff line number Diff line Loading @@ -4,22 +4,33 @@ from pydantic import BaseModel, Field, field_validator class RegisterAppDefinitionInput(BaseModel): name: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{1,63}$", ) appProvider: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{7,63}$", ) version: str = Field(default="1.0.0", max_length=64) repoType: Literal["PUBLICREPO", "PRIVATEREPO"] packageType: Literal["HELM", "CONTAINER"] = Field( ..., description="Allowed package types: HELM or CONTAINER" ) imagePath: str = Field(..., min_length=1) port: int = Field(..., ge=1, le=65535) numCPU: str | None = Field( default=None, min_length=1, description="Optional CPU request, for example 100m or 1", ) memory: int | None = Field( default=None, ge=1, description="Optional memory request in MB", requiredResources: dict = Field( ..., description=( "OEG Kubernetes resources. Required fields: infraKind='kubernetes', " "applicationResources, and isStandalone. Optional fields: " "additionalStorage, version, networking, and addons." ), ) @field_validator("packageType", mode="before") @classmethod def normalize_package_type(cls, value: str) -> str: Loading @@ -32,31 +43,39 @@ class RegisterAppDefinitionInput(BaseModel): class DeleteAppDefinitionInput(BaseModel): sessionId: str = Field(..., min_length=1) appId: str = Field(..., min_length=1) class GetAppDefinitionInput(BaseModel): sessionId: str = Field(..., min_length=1) appId: str = Field(..., min_length=1) class InstantiateAppInput(BaseModel): name: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{1,63}$", ) appId: str = Field(..., min_length=1) edgeCloudZoneIds: list[str] = Field(..., min_length=1) @field_validator("edgeCloudZoneIds", mode="before") @classmethod def normalize_edge_cloud_zone_ids(cls, value): if isinstance(value, str): return [value] return value @field_validator("edgeCloudZoneIds") @classmethod def validate_edge_cloud_zone_ids(cls, value: list[str]) -> list[str]: if any(not zone_id.strip() for zone_id in value): raise ValueError("edgeCloudZoneIds must not contain empty values") return value edgeCloudZoneId: str = Field(..., min_length=1) kubernetesClusterRef: str | None = None subscriptionRequest: dict | None = None class DeleteAppInstanceInput(BaseModel): appInstanceId: str = Field(..., min_length=1) class CreateAppDeploymentInput(BaseModel): appDeploymentName: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{1,63}$", ) appId: str = Field(..., min_length=1) edgeCloudZones: list[str] = Field(..., min_length=1, max_length=100) kubernetesClusterRefs: list[str] | None = Field( default=None, max_length=100, ) subscriptionRequest: dict | None = None No newline at end of file Loading
mcp_module/app.py +4 −0 Changes for mcp_module/app.py: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ from fastapi.responses import PlainTextResponse from fastmcp import FastMCP from mcp_module.tools.edge_application import ( get_app_deployments, create_app_deployment, delete_app_definition, delete_app_instance, get_app_definition, Loading Loading @@ -37,6 +39,7 @@ mcp = FastMCP("MCP Server") # Register tools - only audited functions are exposed SAFE_TOOLS: list[Callable[..., Any]] = [ get_app_deployments, create_qod_session_oai, get_qod_session_oai, delete_qod_session_oai, Loading @@ -48,6 +51,7 @@ SAFE_TOOLS: list[Callable[..., Any]] = [ instantiate_app, get_app_instances, delete_app_instance, create_app_deployment, ] for tool in SAFE_TOOLS: Loading
mcp_module/json_templates/app_deployment_request.json 0 → 100644 +5 −0 Changes for mcp_module/json_templates/app_deployment_request.json: 5 added lines, 0 removed lines. Original line number Diff line number Diff line { "appDeploymentName": "", "appId": "", "edgeCloudZones": [] } No newline at end of file
mcp_module/json_templates/app_instantiate_request.json +2 −11 Changes for mcp_module/json_templates/app_instantiate_request.json: 2 added lines, 11 removed lines. Original line number Diff line number Diff line { "name": "", "appId": "", "appZones": [ { "EdgeCloudZone": { "edgeCloudZoneId": "", "edgeCloudZoneName": "string", "edgeCloudZoneStatus": "unknown", "edgeCloudProvider": "string", "edgeCloudRegion": "string" } } ] "edgeCloudZoneId": "" } No newline at end of file
mcp_module/json_templates/app_register_app_definition_request.json +2 −5 Changes for mcp_module/json_templates/app_register_app_definition_request.json: 2 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -6,11 +6,8 @@ "type": "PRIVATEREPO", "imagePath": "" }, "requiredResources": { "infraKind": "container", "numCPU": "100m", "memory": 512 }, "appProvider": "", "requiredResources": {}, "componentSpec": [ { "componentName": "", Loading
mcp_module/models/edge_application_models.py +45 −26 Changes for mcp_module/models/edge_application_models.py: 45 added lines, 26 removed lines. Original line number Diff line number Diff line Loading @@ -4,22 +4,33 @@ from pydantic import BaseModel, Field, field_validator class RegisterAppDefinitionInput(BaseModel): name: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{1,63}$", ) appProvider: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{7,63}$", ) version: str = Field(default="1.0.0", max_length=64) repoType: Literal["PUBLICREPO", "PRIVATEREPO"] packageType: Literal["HELM", "CONTAINER"] = Field( ..., description="Allowed package types: HELM or CONTAINER" ) imagePath: str = Field(..., min_length=1) port: int = Field(..., ge=1, le=65535) numCPU: str | None = Field( default=None, min_length=1, description="Optional CPU request, for example 100m or 1", ) memory: int | None = Field( default=None, ge=1, description="Optional memory request in MB", requiredResources: dict = Field( ..., description=( "OEG Kubernetes resources. Required fields: infraKind='kubernetes', " "applicationResources, and isStandalone. Optional fields: " "additionalStorage, version, networking, and addons." ), ) @field_validator("packageType", mode="before") @classmethod def normalize_package_type(cls, value: str) -> str: Loading @@ -32,31 +43,39 @@ class RegisterAppDefinitionInput(BaseModel): class DeleteAppDefinitionInput(BaseModel): sessionId: str = Field(..., min_length=1) appId: str = Field(..., min_length=1) class GetAppDefinitionInput(BaseModel): sessionId: str = Field(..., min_length=1) appId: str = Field(..., min_length=1) class InstantiateAppInput(BaseModel): name: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{1,63}$", ) appId: str = Field(..., min_length=1) edgeCloudZoneIds: list[str] = Field(..., min_length=1) @field_validator("edgeCloudZoneIds", mode="before") @classmethod def normalize_edge_cloud_zone_ids(cls, value): if isinstance(value, str): return [value] return value @field_validator("edgeCloudZoneIds") @classmethod def validate_edge_cloud_zone_ids(cls, value: list[str]) -> list[str]: if any(not zone_id.strip() for zone_id in value): raise ValueError("edgeCloudZoneIds must not contain empty values") return value edgeCloudZoneId: str = Field(..., min_length=1) kubernetesClusterRef: str | None = None subscriptionRequest: dict | None = None class DeleteAppInstanceInput(BaseModel): appInstanceId: str = Field(..., min_length=1) class CreateAppDeploymentInput(BaseModel): appDeploymentName: str = Field( ..., max_length=64, pattern=r"^[A-Za-z][A-Za-z0-9_]{1,63}$", ) appId: str = Field(..., min_length=1) edgeCloudZones: list[str] = Field(..., min_length=1, max_length=100) kubernetesClusterRefs: list[str] | None = Field( default=None, max_length=100, ) subscriptionRequest: dict | None = None No newline at end of file