Files
mcphub/plugins/coolify/handlers/services.py
airano-ir d8a0805412
Some checks failed
Release / Test before release (push) Has been cancelled
Release / Publish to PyPI (push) Has been cancelled
Release / Publish to Docker Hub (push) Has been cancelled
Release / Create GitHub Release (push) Has been cancelled
feat(F.7b): tool access UI + unified keys page (v3.9.0)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:00:42 +02:00

502 lines
18 KiB
Python

"""Service Handler — manages Coolify services (Docker Compose), lifecycle, and env vars."""
import json
from typing import Any
from plugins.coolify.client import CoolifyClient
def get_tool_specifications() -> list[dict[str, Any]]:
"""Return tool specifications for ToolGenerator."""
return [
{
"name": "list_services",
"category": "read",
"method_name": "list_services",
"description": "List all Coolify services.",
"schema": {
"type": "object",
"properties": {},
},
"scope": "read",
},
{
"name": "get_service",
"category": "read",
"method_name": "get_service",
"description": "Get details of a specific Coolify service by UUID.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
},
"required": ["uuid"],
},
"scope": "read",
},
{
"name": "create_service",
"category": "crud",
"method_name": "create_service",
"description": (
"Create a Coolify service from a predefined template. "
"Requires project_uuid, server_uuid, environment, and service type."
),
"schema": {
"type": "object",
"properties": {
"project_uuid": {
"type": "string",
"description": "Project UUID",
"minLength": 1,
},
"server_uuid": {
"type": "string",
"description": "Server UUID",
"minLength": 1,
},
"environment_name": {
"type": "string",
"description": "Environment name (e.g., 'production')",
"minLength": 1,
},
"type": {
"type": "string",
"description": (
"Service type from Coolify templates "
"(e.g., 'plausible-analytics', 'minio', 'grafana')"
),
"minLength": 1,
},
"name": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Service name",
},
"description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Service description",
},
"instant_deploy": {
"type": "boolean",
"description": "Deploy immediately after creation",
"default": False,
},
},
"required": [
"project_uuid",
"server_uuid",
"environment_name",
"type",
],
},
"scope": "write",
},
{
"name": "update_service",
"category": "crud",
"method_name": "update_service",
"description": "Update a Coolify service settings.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
"name": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Service name",
},
"description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Service description",
},
"docker_compose_raw": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Raw Docker Compose YAML content",
},
},
"required": ["uuid"],
},
"scope": "write",
},
{
"name": "delete_service",
"category": "system",
"method_name": "delete_service",
"description": (
"Delete a Coolify service permanently. "
"Optionally clean up volumes and Docker resources."
),
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
"delete_configurations": {
"type": "boolean",
"description": "Delete configurations",
"default": True,
},
"delete_volumes": {
"type": "boolean",
"description": "Delete volumes",
"default": True,
},
"docker_cleanup": {
"type": "boolean",
"description": "Run Docker cleanup",
"default": True,
},
},
"required": ["uuid"],
},
"scope": "admin",
},
{
"name": "start_service",
"category": "lifecycle",
"method_name": "start_service",
"description": "Start a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
},
"required": ["uuid"],
},
"scope": "write",
},
{
"name": "stop_service",
"category": "lifecycle",
"method_name": "stop_service",
"description": "Stop a running Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
},
"required": ["uuid"],
},
"scope": "write",
},
{
"name": "restart_service",
"category": "lifecycle",
"method_name": "restart_service",
"description": "Restart a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
},
"required": ["uuid"],
},
"scope": "write",
},
{
"name": "list_service_envs",
"category": "read_sensitive",
"sensitivity": "sensitive",
"method_name": "list_service_envs",
"description": "List environment variables for a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
},
"required": ["uuid"],
},
"scope": "read",
},
{
"name": "create_service_env",
"category": "env",
"sensitivity": "sensitive",
"method_name": "create_service_env",
"description": "Create an environment variable for a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
"key": {
"type": "string",
"description": "Environment variable key",
"minLength": 1,
},
"value": {
"type": "string",
"description": "Environment variable value",
},
"is_preview": {
"type": "boolean",
"description": "Preview deployment only",
"default": False,
},
},
"required": ["uuid", "key", "value"],
},
"scope": "write",
},
{
"name": "update_service_env",
"category": "env",
"sensitivity": "sensitive",
"method_name": "update_service_env",
"description": "Update an environment variable for a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
"key": {
"type": "string",
"description": "Environment variable key",
"minLength": 1,
},
"value": {
"type": "string",
"description": "New value",
},
"is_preview": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Preview deployment only",
},
},
"required": ["uuid", "key", "value"],
},
"scope": "write",
},
{
"name": "update_service_envs_bulk",
"category": "env",
"sensitivity": "sensitive",
"method_name": "update_service_envs_bulk",
"description": "Bulk update environment variables for a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
"data": {
"type": "array",
"description": "Array of env var objects with key and value",
"items": {
"type": "object",
"properties": {
"key": {"type": "string"},
"value": {"type": "string"},
"is_preview": {"type": "boolean"},
},
"required": ["key", "value"],
},
},
},
"required": ["uuid", "data"],
},
"scope": "write",
},
{
"name": "delete_service_env",
"category": "env",
"sensitivity": "sensitive",
"method_name": "delete_service_env",
"description": "Delete an environment variable from a Coolify service.",
"schema": {
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "Service UUID",
"minLength": 1,
},
"env_uuid": {
"type": "string",
"description": "Environment variable UUID",
"minLength": 1,
},
},
"required": ["uuid", "env_uuid"],
},
"scope": "write",
},
]
# --- Handler Functions ---
async def list_services(client: CoolifyClient) -> str:
"""List all services."""
services = await client.list_services()
result = {"success": True, "count": len(services), "services": services}
return json.dumps(result, indent=2, ensure_ascii=False)
async def get_service(client: CoolifyClient, uuid: str) -> str:
"""Get service details."""
service = await client.get_service(uuid)
result = {"success": True, "service": service}
return json.dumps(result, indent=2, ensure_ascii=False)
async def create_service(client: CoolifyClient, **kwargs) -> str:
"""Create a service from template."""
data = {k: v for k, v in kwargs.items() if v is not None}
service = await client.create_service(data)
result = {
"success": True,
"message": "Service created successfully",
"service": service,
}
return json.dumps(result, indent=2, ensure_ascii=False)
async def update_service(client: CoolifyClient, uuid: str, **kwargs) -> str:
"""Update service settings."""
data = {k: v for k, v in kwargs.items() if v is not None and k != "uuid"}
service = await client.update_service(uuid, data)
result = {
"success": True,
"message": f"Service '{uuid}' updated successfully",
"service": service,
}
return json.dumps(result, indent=2, ensure_ascii=False)
async def delete_service(
client: CoolifyClient,
uuid: str,
delete_configurations: bool = True,
delete_volumes: bool = True,
docker_cleanup: bool = True,
) -> str:
"""Delete a service."""
result_data = await client.delete_service(
uuid,
delete_configurations=delete_configurations,
delete_volumes=delete_volumes,
docker_cleanup=docker_cleanup,
)
result = {"success": True, "message": f"Service '{uuid}' deleted", "data": result_data}
return json.dumps(result, indent=2, ensure_ascii=False)
async def start_service(client: CoolifyClient, uuid: str) -> str:
"""Start a service."""
result_data = await client.start_service(uuid)
result = {"success": True, "message": f"Service '{uuid}' starting", "data": result_data}
return json.dumps(result, indent=2, ensure_ascii=False)
async def stop_service(client: CoolifyClient, uuid: str) -> str:
"""Stop a service."""
result_data = await client.stop_service(uuid)
result = {"success": True, "message": f"Service '{uuid}' stopping", "data": result_data}
return json.dumps(result, indent=2, ensure_ascii=False)
async def restart_service(client: CoolifyClient, uuid: str) -> str:
"""Restart a service."""
result_data = await client.restart_service(uuid)
result = {"success": True, "message": f"Service '{uuid}' restarting", "data": result_data}
return json.dumps(result, indent=2, ensure_ascii=False)
async def list_service_envs(client: CoolifyClient, uuid: str) -> str:
"""List service environment variables."""
envs = await client.list_service_envs(uuid)
result = {"success": True, "count": len(envs), "envs": envs}
return json.dumps(result, indent=2, ensure_ascii=False)
async def create_service_env(
client: CoolifyClient,
uuid: str,
key: str,
value: str,
is_preview: bool = False,
) -> str:
"""Create service environment variable."""
data = {"key": key, "value": value, "is_preview": is_preview}
result_data = await client.create_service_env(uuid, data)
result = {
"success": True,
"message": f"Env var '{key}' created",
"data": result_data,
}
return json.dumps(result, indent=2, ensure_ascii=False)
async def update_service_env(
client: CoolifyClient,
uuid: str,
key: str,
value: str,
is_preview: bool | None = None,
) -> str:
"""Update service environment variable."""
data = {"key": key, "value": value}
if is_preview is not None:
data["is_preview"] = is_preview
result_data = await client.update_service_env(uuid, data)
result = {
"success": True,
"message": f"Env var '{key}' updated",
"data": result_data,
}
return json.dumps(result, indent=2, ensure_ascii=False)
async def update_service_envs_bulk(client: CoolifyClient, uuid: str, data: list[dict]) -> str:
"""Bulk update service environment variables."""
result_data = await client.update_service_envs_bulk(uuid, data)
result = {
"success": True,
"message": f"Bulk update {len(data)} env vars",
"data": result_data,
}
return json.dumps(result, indent=2, ensure_ascii=False)
async def delete_service_env(client: CoolifyClient, uuid: str, env_uuid: str) -> str:
"""Delete service environment variable."""
await client.delete_service_env(uuid, env_uuid)
result = {"success": True, "message": f"Env var '{env_uuid}' deleted"}
return json.dumps(result, indent=2, ensure_ascii=False)