Initial commit: MCP Hub Community Edition v3.0.0
Community edition generated from private repo via sync pipeline. Includes 9 plugins (WordPress, WooCommerce, WP Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus) with ~587 tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
629
plugins/appwrite/handlers/functions.py
Normal file
629
plugins/appwrite/handlers/functions.py
Normal file
@@ -0,0 +1,629 @@
|
||||
"""
|
||||
Functions Handler - manages Appwrite serverless functions
|
||||
|
||||
Phase I.4: 14 tools
|
||||
- Functions: 5 (list, get, create, update, delete)
|
||||
- Deployments: 5 (list, get, create, delete, activate)
|
||||
- Executions: 4 (list, get, create, delete)
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from plugins.appwrite.client import AppwriteClient
|
||||
|
||||
def get_tool_specifications() -> list[dict[str, Any]]:
|
||||
"""Return tool specifications for ToolGenerator (14 tools)"""
|
||||
return [
|
||||
# =====================
|
||||
# FUNCTIONS (5)
|
||||
# =====================
|
||||
{
|
||||
"name": "list_functions",
|
||||
"method_name": "list_functions",
|
||||
"description": "List all serverless functions in the project.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"queries": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "Query strings for filtering",
|
||||
},
|
||||
"search": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Search term to filter functions",
|
||||
},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_function",
|
||||
"method_name": "get_function",
|
||||
"description": "Get function details including deployment status and configuration.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {"function_id": {"type": "string", "description": "Function ID"}},
|
||||
"required": ["function_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "create_function",
|
||||
"method_name": "create_function",
|
||||
"description": "Create a new serverless function.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {
|
||||
"type": "string",
|
||||
"description": "Unique function ID. Use 'unique()' for auto-generation",
|
||||
},
|
||||
"name": {"type": "string", "description": "Function name"},
|
||||
"runtime": {
|
||||
"type": "string",
|
||||
"description": "Runtime (e.g., 'node-18.0', 'python-3.9', 'php-8.0', 'ruby-3.0')",
|
||||
"examples": [
|
||||
"node-18.0",
|
||||
"node-20.0",
|
||||
"python-3.9",
|
||||
"python-3.11",
|
||||
"php-8.0",
|
||||
"php-8.2",
|
||||
"ruby-3.0",
|
||||
"go-1.21",
|
||||
"dart-3.0",
|
||||
"rust-1.70",
|
||||
],
|
||||
},
|
||||
"execute": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "Execution permissions (e.g., ['any', 'users'])",
|
||||
},
|
||||
"events": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "Events to trigger function (e.g., ['databases.*.collections.*.documents.*.create'])",
|
||||
},
|
||||
"schedule": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Cron schedule (e.g., '0 * * * *' for every hour)",
|
||||
},
|
||||
"timeout": {
|
||||
"type": "integer",
|
||||
"description": "Execution timeout in seconds",
|
||||
"default": 15,
|
||||
"minimum": 1,
|
||||
"maximum": 900,
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Enable function",
|
||||
"default": True,
|
||||
},
|
||||
"logging": {
|
||||
"type": "boolean",
|
||||
"description": "Enable logging",
|
||||
"default": True,
|
||||
},
|
||||
"entrypoint": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Entrypoint file (e.g., 'src/main.js')",
|
||||
},
|
||||
"commands": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Build commands",
|
||||
},
|
||||
},
|
||||
"required": ["function_id", "name", "runtime"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "update_function",
|
||||
"method_name": "update_function",
|
||||
"description": "Update function configuration.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"name": {"type": "string", "description": "Function name"},
|
||||
"runtime": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "New runtime",
|
||||
},
|
||||
"execute": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "New execution permissions",
|
||||
},
|
||||
"events": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "New trigger events",
|
||||
},
|
||||
"schedule": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "New cron schedule",
|
||||
},
|
||||
"timeout": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"description": "New timeout",
|
||||
},
|
||||
"enabled": {
|
||||
"anyOf": [{"type": "boolean"}, {"type": "null"}],
|
||||
"description": "Enable/disable function",
|
||||
},
|
||||
},
|
||||
"required": ["function_id", "name"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "delete_function",
|
||||
"method_name": "delete_function",
|
||||
"description": "Delete a function and all its deployments.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID to delete"}
|
||||
},
|
||||
"required": ["function_id"],
|
||||
},
|
||||
"scope": "admin",
|
||||
},
|
||||
# =====================
|
||||
# DEPLOYMENTS (5)
|
||||
# =====================
|
||||
{
|
||||
"name": "list_deployments",
|
||||
"method_name": "list_deployments",
|
||||
"description": "List all deployments of a function.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"queries": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "Query strings for filtering",
|
||||
},
|
||||
"search": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Search term",
|
||||
},
|
||||
},
|
||||
"required": ["function_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_deployment",
|
||||
"method_name": "get_deployment",
|
||||
"description": "Get deployment details including build status and logs.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"deployment_id": {"type": "string", "description": "Deployment ID"},
|
||||
},
|
||||
"required": ["function_id", "deployment_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "delete_deployment",
|
||||
"method_name": "delete_deployment",
|
||||
"description": "Delete a deployment.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"deployment_id": {"type": "string", "description": "Deployment ID to delete"},
|
||||
},
|
||||
"required": ["function_id", "deployment_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "activate_deployment",
|
||||
"method_name": "activate_deployment",
|
||||
"description": "Activate a deployment (set as the active version for the function).",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"deployment_id": {"type": "string", "description": "Deployment ID to activate"},
|
||||
},
|
||||
"required": ["function_id", "deployment_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "get_active_deployment",
|
||||
"method_name": "get_active_deployment",
|
||||
"description": "Get the currently active deployment for a function.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {"function_id": {"type": "string", "description": "Function ID"}},
|
||||
"required": ["function_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
# =====================
|
||||
# EXECUTIONS (4)
|
||||
# =====================
|
||||
{
|
||||
"name": "list_executions",
|
||||
"method_name": "list_executions",
|
||||
"description": "List execution history for a function.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"queries": {
|
||||
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
|
||||
"description": "Query strings for filtering",
|
||||
},
|
||||
"search": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Search term",
|
||||
},
|
||||
},
|
||||
"required": ["function_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_execution",
|
||||
"method_name": "get_execution",
|
||||
"description": "Get execution details including response, logs, and timing.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"execution_id": {"type": "string", "description": "Execution ID"},
|
||||
},
|
||||
"required": ["function_id", "execution_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "execute_function",
|
||||
"method_name": "execute_function",
|
||||
"description": "Execute a function immediately.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"body": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Request body (JSON string)",
|
||||
},
|
||||
"async_execution": {
|
||||
"type": "boolean",
|
||||
"description": "Run asynchronously (don't wait for response)",
|
||||
"default": False,
|
||||
},
|
||||
"path": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Custom execution path",
|
||||
},
|
||||
"method": {
|
||||
"type": "string",
|
||||
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
||||
"description": "HTTP method",
|
||||
"default": "POST",
|
||||
},
|
||||
"headers": {
|
||||
"anyOf": [{"type": "object"}, {"type": "null"}],
|
||||
"description": "Custom headers",
|
||||
},
|
||||
},
|
||||
"required": ["function_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "delete_execution",
|
||||
"method_name": "delete_execution",
|
||||
"description": "Delete an execution log entry.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"function_id": {"type": "string", "description": "Function ID"},
|
||||
"execution_id": {"type": "string", "description": "Execution ID to delete"},
|
||||
},
|
||||
"required": ["function_id", "execution_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
]
|
||||
|
||||
# =====================
|
||||
# HANDLER FUNCTIONS
|
||||
# =====================
|
||||
|
||||
async def list_functions(
|
||||
client: AppwriteClient, queries: list[str] | None = None, search: str | None = None
|
||||
) -> str:
|
||||
"""List all functions."""
|
||||
try:
|
||||
result = await client.list_functions(queries=queries, search=search)
|
||||
functions = result.get("functions", [])
|
||||
|
||||
response = {
|
||||
"success": True,
|
||||
"total": result.get("total", len(functions)),
|
||||
"functions": functions,
|
||||
}
|
||||
return json.dumps(response, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def get_function(client: AppwriteClient, function_id: str) -> str:
|
||||
"""Get function by ID."""
|
||||
try:
|
||||
result = await client.get_function(function_id)
|
||||
return json.dumps({"success": True, "function": result}, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def create_function(
|
||||
client: AppwriteClient,
|
||||
function_id: str,
|
||||
name: str,
|
||||
runtime: str,
|
||||
execute: list[str] | None = None,
|
||||
events: list[str] | None = None,
|
||||
schedule: str | None = None,
|
||||
timeout: int = 15,
|
||||
enabled: bool = True,
|
||||
logging: bool = True,
|
||||
entrypoint: str | None = None,
|
||||
commands: str | None = None,
|
||||
) -> str:
|
||||
"""Create a new function."""
|
||||
try:
|
||||
result = await client.create_function(
|
||||
function_id=function_id,
|
||||
name=name,
|
||||
runtime=runtime,
|
||||
execute=execute,
|
||||
events=events,
|
||||
schedule=schedule,
|
||||
timeout=timeout,
|
||||
enabled=enabled,
|
||||
logging=logging,
|
||||
entrypoint=entrypoint,
|
||||
commands=commands,
|
||||
)
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"message": f"Function '{name}' created successfully",
|
||||
"function": result,
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def update_function(
|
||||
client: AppwriteClient,
|
||||
function_id: str,
|
||||
name: str,
|
||||
runtime: str | None = None,
|
||||
execute: list[str] | None = None,
|
||||
events: list[str] | None = None,
|
||||
schedule: str | None = None,
|
||||
timeout: int | None = None,
|
||||
enabled: bool | None = None,
|
||||
) -> str:
|
||||
"""Update function."""
|
||||
try:
|
||||
result = await client.update_function(
|
||||
function_id=function_id,
|
||||
name=name,
|
||||
runtime=runtime,
|
||||
execute=execute,
|
||||
events=events,
|
||||
schedule=schedule,
|
||||
timeout=timeout,
|
||||
enabled=enabled,
|
||||
)
|
||||
return json.dumps(
|
||||
{"success": True, "message": "Function updated successfully", "function": result},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def delete_function(client: AppwriteClient, function_id: str) -> str:
|
||||
"""Delete function."""
|
||||
try:
|
||||
await client.delete_function(function_id)
|
||||
return json.dumps(
|
||||
{"success": True, "message": f"Function '{function_id}' deleted successfully"}, indent=2
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def list_deployments(
|
||||
client: AppwriteClient,
|
||||
function_id: str,
|
||||
queries: list[str] | None = None,
|
||||
search: str | None = None,
|
||||
) -> str:
|
||||
"""List function deployments."""
|
||||
try:
|
||||
result = await client.list_deployments(
|
||||
function_id=function_id, queries=queries, search=search
|
||||
)
|
||||
deployments = result.get("deployments", [])
|
||||
|
||||
response = {
|
||||
"success": True,
|
||||
"function_id": function_id,
|
||||
"total": result.get("total", len(deployments)),
|
||||
"deployments": deployments,
|
||||
}
|
||||
return json.dumps(response, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def get_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str:
|
||||
"""Get deployment by ID."""
|
||||
try:
|
||||
result = await client.get_deployment(function_id, deployment_id)
|
||||
return json.dumps({"success": True, "deployment": result}, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def delete_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str:
|
||||
"""Delete deployment."""
|
||||
try:
|
||||
await client.delete_deployment(function_id, deployment_id)
|
||||
return json.dumps(
|
||||
{"success": True, "message": f"Deployment '{deployment_id}' deleted successfully"},
|
||||
indent=2,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def activate_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str:
|
||||
"""Activate deployment."""
|
||||
try:
|
||||
result = await client.update_deployment(function_id, deployment_id)
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"message": f"Deployment '{deployment_id}' activated successfully",
|
||||
"deployment": result,
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def get_active_deployment(client: AppwriteClient, function_id: str) -> str:
|
||||
"""Get active deployment for function."""
|
||||
try:
|
||||
func = await client.get_function(function_id)
|
||||
deployment_id = func.get("deployment")
|
||||
|
||||
if not deployment_id:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"message": "No active deployment",
|
||||
"function_id": function_id,
|
||||
"active_deployment": None,
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
|
||||
deployment = await client.get_deployment(function_id, deployment_id)
|
||||
return json.dumps(
|
||||
{"success": True, "function_id": function_id, "active_deployment": deployment},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def list_executions(
|
||||
client: AppwriteClient,
|
||||
function_id: str,
|
||||
queries: list[str] | None = None,
|
||||
search: str | None = None,
|
||||
) -> str:
|
||||
"""List function executions."""
|
||||
try:
|
||||
result = await client.list_executions(
|
||||
function_id=function_id, queries=queries, search=search
|
||||
)
|
||||
executions = result.get("executions", [])
|
||||
|
||||
response = {
|
||||
"success": True,
|
||||
"function_id": function_id,
|
||||
"total": result.get("total", len(executions)),
|
||||
"executions": executions,
|
||||
}
|
||||
return json.dumps(response, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def get_execution(client: AppwriteClient, function_id: str, execution_id: str) -> str:
|
||||
"""Get execution by ID."""
|
||||
try:
|
||||
result = await client.get_execution(function_id, execution_id)
|
||||
return json.dumps({"success": True, "execution": result}, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def execute_function(
|
||||
client: AppwriteClient,
|
||||
function_id: str,
|
||||
body: str | None = None,
|
||||
async_execution: bool = False,
|
||||
path: str | None = None,
|
||||
method: str = "POST",
|
||||
headers: dict[str, str] | None = None,
|
||||
) -> str:
|
||||
"""Execute function."""
|
||||
try:
|
||||
result = await client.create_execution(
|
||||
function_id=function_id,
|
||||
body=body,
|
||||
async_execution=async_execution,
|
||||
path=path,
|
||||
method=method,
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
response = {
|
||||
"success": True,
|
||||
"execution_id": result.get("$id"),
|
||||
"status": result.get("status"),
|
||||
"status_code": result.get("responseStatusCode"),
|
||||
"duration": result.get("duration"),
|
||||
"response_body": result.get("responseBody"),
|
||||
"logs": result.get("logs"),
|
||||
"errors": result.get("errors"),
|
||||
}
|
||||
|
||||
if async_execution:
|
||||
response["message"] = "Function execution started asynchronously"
|
||||
else:
|
||||
response["message"] = "Function executed successfully"
|
||||
|
||||
return json.dumps(response, indent=2, ensure_ascii=False)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
|
||||
async def delete_execution(client: AppwriteClient, function_id: str, execution_id: str) -> str:
|
||||
"""Delete execution."""
|
||||
try:
|
||||
await client.delete_execution(function_id, execution_id)
|
||||
return json.dumps(
|
||||
{"success": True, "message": f"Execution '{execution_id}' deleted successfully"},
|
||||
indent=2,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2)
|
||||
Reference in New Issue
Block a user