- Implemented server and client script management tools in `frappe_mcp/tools/scripts.py` - Added translation and user permission management tools in `frappe_mcp/tools/translations.py` - Created user and role management tools in `frappe_mcp/tools/users.py` - Developed webhook and API key management tools in `frappe_mcp/tools/webhooks.py` - Introduced workflow management tools in `frappe_mcp/tools/workflow_tools.py` - Added `pyproject.toml` for project metadata and dependencies
221 lines
8.2 KiB
Python
221 lines
8.2 KiB
Python
"""Email Template tools — create, list, update Frappe Email Templates and Notifications."""
|
|
|
|
import json
|
|
from mcp.types import Tool
|
|
from frappe_mcp.client.frappe_api import FrappeClient
|
|
|
|
|
|
def tools() -> list[Tool]:
|
|
return [
|
|
Tool(
|
|
name="frappe_list_email_templates",
|
|
description="List all Email Templates in the system.",
|
|
inputSchema={
|
|
"type": "object",
|
|
"properties": {
|
|
"limit": {"type": "integer", "default": 30},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_get_email_template",
|
|
description="Get a specific Email Template including subject and body.",
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_create_email_template",
|
|
description=(
|
|
"Create a new Email Template. Subject and response support Jinja2. "
|
|
"Access doc fields with {{ doc.field_name }}."
|
|
),
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["name", "subject", "response"],
|
|
"properties": {
|
|
"name": {"type": "string", "description": "Template name/ID"},
|
|
"subject": {"type": "string", "description": "Email subject (Jinja2 supported)"},
|
|
"response": {"type": "string", "description": "Email body HTML (Jinja2 supported)"},
|
|
"use_html": {"type": "integer", "default": 1},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_update_email_template",
|
|
description="Update an Email Template's subject or body.",
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
"subject": {"type": "string"},
|
|
"response": {"type": "string"},
|
|
"updates": {"type": "object"},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_list_notifications",
|
|
description="List Frappe Notifications (automated email/Slack alerts on DocType events).",
|
|
inputSchema={
|
|
"type": "object",
|
|
"properties": {
|
|
"document_type": {"type": "string", "description": "Filter by DocType"},
|
|
"enabled": {"type": "integer", "description": "1 = enabled only"},
|
|
"limit": {"type": "integer", "default": 30},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_create_notification",
|
|
description=(
|
|
"Create a Frappe Notification — triggers an email/Slack/system message "
|
|
"on a DocType event or date condition."
|
|
),
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["name", "document_type", "event", "subject", "message"],
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
"document_type": {"type": "string"},
|
|
"event": {
|
|
"type": "string",
|
|
"enum": [
|
|
"New", "Save", "Submit", "Cancel", "Days Before",
|
|
"Days After", "Value Change", "Method", "Custom",
|
|
],
|
|
},
|
|
"subject": {"type": "string", "description": "Email subject (Jinja2)"},
|
|
"message": {"type": "string", "description": "Email body (Jinja2 HTML)"},
|
|
"send_to_all_assignees": {"type": "integer", "default": 0},
|
|
"recipients": {
|
|
"type": "array",
|
|
"description": "List of recipient rows: [{\"receiver_by_document_field\": \"email\"}]",
|
|
"items": {"type": "object"},
|
|
},
|
|
"condition": {"type": "string", "description": "Python expression e.g. doc.status == 'Open'"},
|
|
"channel": {
|
|
"type": "string",
|
|
"enum": ["Email", "Slack", "System Notification", "SMS"],
|
|
"default": "Email",
|
|
},
|
|
"enabled": {"type": "integer", "default": 1},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_update_notification",
|
|
description="Enable, disable, or update a Notification.",
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
"enabled": {"type": "integer"},
|
|
"subject": {"type": "string"},
|
|
"message": {"type": "string"},
|
|
"updates": {"type": "object"},
|
|
},
|
|
},
|
|
),
|
|
]
|
|
|
|
|
|
def handlers() -> dict:
|
|
return {
|
|
"frappe_list_email_templates": _list_email_templates,
|
|
"frappe_get_email_template": _get_email_template,
|
|
"frappe_create_email_template": _create_email_template,
|
|
"frappe_update_email_template": _update_email_template,
|
|
"frappe_list_notifications": _list_notifications,
|
|
"frappe_create_notification": _create_notification,
|
|
"frappe_update_notification": _update_notification,
|
|
}
|
|
|
|
|
|
async def _list_email_templates(args: dict) -> str:
|
|
client = FrappeClient()
|
|
result = await client.get_list(
|
|
"Email Template",
|
|
fields=["name", "subject", "modified"],
|
|
limit=args.get("limit", 30),
|
|
)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _get_email_template(args: dict) -> str:
|
|
client = FrappeClient()
|
|
result = await client.get_doc("Email Template", args["name"])
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _create_email_template(args: dict) -> str:
|
|
client = FrappeClient()
|
|
payload = {
|
|
"name": args["name"],
|
|
"subject": args["subject"],
|
|
"response": args["response"],
|
|
"use_html": args.get("use_html", 1),
|
|
}
|
|
result = await client.create_doc("Email Template", payload)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _update_email_template(args: dict) -> str:
|
|
client = FrappeClient()
|
|
updates = args.get("updates", {})
|
|
for field in ("subject", "response"):
|
|
if field in args:
|
|
updates[field] = args[field]
|
|
result = await client.update_doc("Email Template", args["name"], updates)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _list_notifications(args: dict) -> str:
|
|
client = FrappeClient()
|
|
filters = []
|
|
if dt := args.get("document_type"):
|
|
filters.append(["document_type", "=", dt])
|
|
if "enabled" in args:
|
|
filters.append(["enabled", "=", args["enabled"]])
|
|
result = await client.get_list(
|
|
"Notification",
|
|
fields=["name", "document_type", "event", "channel", "enabled"],
|
|
filters=filters if filters else None,
|
|
limit=args.get("limit", 30),
|
|
)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _create_notification(args: dict) -> str:
|
|
client = FrappeClient()
|
|
payload = {
|
|
"name": args["name"],
|
|
"document_type": args["document_type"],
|
|
"event": args["event"],
|
|
"subject": args["subject"],
|
|
"message": args["message"],
|
|
"channel": args.get("channel", "Email"),
|
|
"enabled": args.get("enabled", 1),
|
|
"send_to_all_assignees": args.get("send_to_all_assignees", 0),
|
|
"recipients": args.get("recipients", []),
|
|
"condition": args.get("condition", ""),
|
|
}
|
|
result = await client.create_doc("Notification", payload)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _update_notification(args: dict) -> str:
|
|
client = FrappeClient()
|
|
updates = args.get("updates", {})
|
|
for field in ("enabled", "subject", "message"):
|
|
if field in args:
|
|
updates[field] = args[field]
|
|
result = await client.update_doc("Notification", args["name"], updates)
|
|
return json.dumps(result, indent=2)
|