"""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)