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:
378
plugins/openpanel/handlers/funnels.py
Normal file
378
plugins/openpanel/handlers/funnels.py
Normal file
@@ -0,0 +1,378 @@
|
||||
"""Funnels Handler - OpenPanel funnel analytics (8 tools)"""
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from plugins.openpanel.client import OpenPanelClient
|
||||
|
||||
def get_tool_specifications() -> list[dict[str, Any]]:
|
||||
"""Return tool specifications for ToolGenerator (8 tools)"""
|
||||
return [
|
||||
{
|
||||
"name": "list_funnels",
|
||||
"method_name": "list_funnels",
|
||||
"description": "List all funnels defined for a project.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {"project_id": {"type": "string", "description": "Project ID"}},
|
||||
"required": ["project_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_funnel",
|
||||
"method_name": "get_funnel",
|
||||
"description": "Get funnel details and current conversion data.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"funnel_id": {"type": "string", "description": "Funnel ID"},
|
||||
"date_range": {
|
||||
"type": "string",
|
||||
"description": "Date range. Common: today, yesterday, 7d, 14d, 30d, 60d, 90d, 6m, 12m, all",
|
||||
"default": "30d",
|
||||
},
|
||||
},
|
||||
"required": ["project_id", "funnel_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "create_funnel",
|
||||
"method_name": "create_funnel",
|
||||
"description": "Create a new funnel to track user journey through steps.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"name": {"type": "string", "description": "Funnel name"},
|
||||
"steps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string", "description": "Step name"},
|
||||
"event": {
|
||||
"type": "string",
|
||||
"description": "Event name for this step",
|
||||
},
|
||||
"filters": {
|
||||
"type": "array",
|
||||
"description": "Optional filters for this step",
|
||||
},
|
||||
},
|
||||
"required": ["name", "event"],
|
||||
},
|
||||
"description": "Funnel steps in sequence",
|
||||
"minItems": 2,
|
||||
"maxItems": 10,
|
||||
},
|
||||
"window_days": {
|
||||
"type": "integer",
|
||||
"description": "Conversion window in days",
|
||||
"default": 14,
|
||||
"maximum": 90,
|
||||
},
|
||||
},
|
||||
"required": ["project_id", "name", "steps"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "update_funnel",
|
||||
"method_name": "update_funnel",
|
||||
"description": "Update an existing funnel's configuration.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"funnel_id": {"type": "string", "description": "Funnel ID"},
|
||||
"name": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "New funnel name",
|
||||
},
|
||||
"steps": {
|
||||
"anyOf": [{"type": "array"}, {"type": "null"}],
|
||||
"description": "New funnel steps",
|
||||
},
|
||||
"window_days": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"description": "New conversion window",
|
||||
},
|
||||
},
|
||||
"required": ["project_id", "funnel_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "delete_funnel",
|
||||
"method_name": "delete_funnel",
|
||||
"description": "Delete a funnel.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"funnel_id": {"type": "string", "description": "Funnel ID to delete"},
|
||||
},
|
||||
"required": ["project_id", "funnel_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "get_funnel_conversion",
|
||||
"method_name": "get_funnel_conversion",
|
||||
"description": "Get detailed conversion rates for each funnel step.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"funnel_id": {"type": "string", "description": "Funnel ID"},
|
||||
"date_range": {
|
||||
"type": "string",
|
||||
"description": "Date range. Common: today, yesterday, 7d, 14d, 30d, 60d, 90d, 6m, 12m, all",
|
||||
"default": "30d",
|
||||
},
|
||||
},
|
||||
"required": ["project_id", "funnel_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_funnel_breakdown",
|
||||
"method_name": "get_funnel_breakdown",
|
||||
"description": "Get funnel breakdown by segment (country, device, etc.).",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"funnel_id": {"type": "string", "description": "Funnel ID"},
|
||||
"breakdown_by": {
|
||||
"type": "string",
|
||||
"enum": ["country", "device", "browser", "os", "referrer"],
|
||||
"description": "Dimension to break down by",
|
||||
},
|
||||
"date_range": {
|
||||
"type": "string",
|
||||
"description": "Date range. Common: today, yesterday, 7d, 14d, 30d, 60d, 90d, 6m, 12m, all",
|
||||
"default": "30d",
|
||||
},
|
||||
},
|
||||
"required": ["project_id", "funnel_id", "breakdown_by"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "compare_funnels",
|
||||
"method_name": "compare_funnels",
|
||||
"description": "Compare conversion rates between multiple funnels.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {"type": "string", "description": "Project ID"},
|
||||
"funnel_ids": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Funnel IDs to compare",
|
||||
"minItems": 2,
|
||||
"maxItems": 5,
|
||||
},
|
||||
"date_range": {
|
||||
"type": "string",
|
||||
"description": "Date range. Common: today, yesterday, 7d, 14d, 30d, 60d, 90d, 6m, 12m, all",
|
||||
"default": "30d",
|
||||
},
|
||||
},
|
||||
"required": ["project_id", "funnel_ids"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
]
|
||||
|
||||
# =====================
|
||||
# Funnel Functions (8)
|
||||
# =====================
|
||||
|
||||
async def list_funnels(client: OpenPanelClient, project_id: str) -> str:
|
||||
"""List all funnels for a project"""
|
||||
try:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"note": "Funnel listing requires dashboard tRPC API. Use OpenPanel dashboard to view funnels.",
|
||||
"message": "Funnel list request processed",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def get_funnel(
|
||||
client: OpenPanelClient, project_id: str, funnel_id: str, date_range: str = "30d"
|
||||
) -> str:
|
||||
"""Get funnel details with conversion data"""
|
||||
try:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel_id": funnel_id,
|
||||
"date_range": date_range,
|
||||
"note": "Funnel details require dashboard tRPC API. Use OpenPanel dashboard to view funnel data.",
|
||||
"message": "Funnel data request processed",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def create_funnel(
|
||||
client: OpenPanelClient,
|
||||
project_id: str,
|
||||
name: str,
|
||||
steps: list[dict[str, Any]],
|
||||
window_days: int = 14,
|
||||
) -> str:
|
||||
"""Create a new funnel"""
|
||||
try:
|
||||
# Validate steps
|
||||
if len(steps) < 2:
|
||||
return json.dumps(
|
||||
{"success": False, "error": "Funnel must have at least 2 steps"},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
funnel_config = {"name": name, "steps": steps, "window_days": window_days}
|
||||
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel": funnel_config,
|
||||
"note": "Funnel creation requires dashboard tRPC API. Use OpenPanel dashboard to create funnels.",
|
||||
"message": f"Funnel '{name}' configuration created with {len(steps)} steps",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def update_funnel(
|
||||
client: OpenPanelClient,
|
||||
project_id: str,
|
||||
funnel_id: str,
|
||||
name: str | None = None,
|
||||
steps: list[dict[str, Any]] | None = None,
|
||||
window_days: int | None = None,
|
||||
) -> str:
|
||||
"""Update an existing funnel"""
|
||||
try:
|
||||
updates = {}
|
||||
if name:
|
||||
updates["name"] = name
|
||||
if steps:
|
||||
updates["steps"] = steps
|
||||
if window_days:
|
||||
updates["window_days"] = window_days
|
||||
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel_id": funnel_id,
|
||||
"updates": updates,
|
||||
"note": "Funnel updates require dashboard tRPC API. Use OpenPanel dashboard to modify funnels.",
|
||||
"message": "Funnel update configuration created",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def delete_funnel(client: OpenPanelClient, project_id: str, funnel_id: str) -> str:
|
||||
"""Delete a funnel"""
|
||||
try:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel_id": funnel_id,
|
||||
"note": "Funnel deletion requires dashboard tRPC API. Use OpenPanel dashboard to delete funnels.",
|
||||
"message": "Funnel deletion request processed",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def get_funnel_conversion(
|
||||
client: OpenPanelClient, project_id: str, funnel_id: str, date_range: str = "30d"
|
||||
) -> str:
|
||||
"""Get funnel conversion rates"""
|
||||
try:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel_id": funnel_id,
|
||||
"date_range": date_range,
|
||||
"note": "Conversion data requires dashboard tRPC API. Use OpenPanel dashboard for detailed conversion analysis.",
|
||||
"message": "Funnel conversion request processed",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def get_funnel_breakdown(
|
||||
client: OpenPanelClient,
|
||||
project_id: str,
|
||||
funnel_id: str,
|
||||
breakdown_by: str,
|
||||
date_range: str = "30d",
|
||||
) -> str:
|
||||
"""Get funnel breakdown by segment"""
|
||||
try:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel_id": funnel_id,
|
||||
"breakdown_by": breakdown_by,
|
||||
"date_range": date_range,
|
||||
"note": "Funnel breakdown requires dashboard tRPC API. Use OpenPanel dashboard for segmented analysis.",
|
||||
"message": f"Funnel breakdown by {breakdown_by} request processed",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
|
||||
async def compare_funnels(
|
||||
client: OpenPanelClient, project_id: str, funnel_ids: list[str], date_range: str = "30d"
|
||||
) -> str:
|
||||
"""Compare multiple funnels"""
|
||||
try:
|
||||
return json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"project_id": project_id,
|
||||
"funnel_ids": funnel_ids,
|
||||
"date_range": date_range,
|
||||
"note": "Funnel comparison requires dashboard tRPC API. Use OpenPanel dashboard for comparison views.",
|
||||
"message": f"Comparison request for {len(funnel_ids)} funnels processed",
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False)
|
||||
Reference in New Issue
Block a user