- 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
165 lines
6.0 KiB
Python
165 lines
6.0 KiB
Python
"""
|
|
Property Setter + Customize Form tools.
|
|
Property Setters override DocType field properties without touching core — the safe
|
|
way to customize standard DocTypes (e.g. Sales Order, Customer).
|
|
"""
|
|
|
|
import json
|
|
from mcp.types import Tool
|
|
from frappe_mcp.client.frappe_api import FrappeClient
|
|
|
|
|
|
def tools() -> list[Tool]:
|
|
return [
|
|
Tool(
|
|
name="frappe_list_property_setters",
|
|
description="List all Property Setters, optionally filtered by DocType.",
|
|
inputSchema={
|
|
"type": "object",
|
|
"properties": {
|
|
"doc_type": {"type": "string"},
|
|
"field_name": {"type": "string"},
|
|
"property": {"type": "string"},
|
|
"limit": {"type": "integer", "default": 50},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_create_property_setter",
|
|
description=(
|
|
"Override a property of a DocType field (or the DocType itself) without modifying core. "
|
|
"Common properties: reqd, hidden, read_only, default, options, label, bold, in_list_view, "
|
|
"in_standard_filter, description, depends_on, mandatory_depends_on, read_only_depends_on."
|
|
),
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["doc_type", "property", "value", "property_type"],
|
|
"properties": {
|
|
"doc_type": {"type": "string", "description": "DocType to customize"},
|
|
"field_name": {"type": "string", "description": "Fieldname to override (empty for DocType-level)"},
|
|
"property": {"type": "string", "description": "Property to override e.g. 'reqd', 'hidden'"},
|
|
"value": {"type": "string", "description": "New value"},
|
|
"property_type": {
|
|
"type": "string",
|
|
"description": "Data type: Check, Data, Int, Select, Text, etc.",
|
|
"default": "Check",
|
|
},
|
|
"row_name": {"type": "string", "description": "For child table row overrides"},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_remove_property_setter",
|
|
description="Remove a Property Setter, restoring the DocType's original property value.",
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {"type": "string", "description": "Property Setter document name"},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_get_customize_form",
|
|
description=(
|
|
"Get the full customization state of a DocType — all Property Setters, "
|
|
"Custom Fields, and effective field properties merged."
|
|
),
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["doc_type"],
|
|
"properties": {
|
|
"doc_type": {"type": "string"},
|
|
},
|
|
},
|
|
),
|
|
Tool(
|
|
name="frappe_reset_customization",
|
|
description=(
|
|
"Remove ALL customizations (Property Setters + Custom Fields) from a DocType, "
|
|
"restoring it to its original state. Destructive — use with caution."
|
|
),
|
|
inputSchema={
|
|
"type": "object",
|
|
"required": ["doc_type"],
|
|
"properties": {
|
|
"doc_type": {"type": "string"},
|
|
},
|
|
},
|
|
),
|
|
]
|
|
|
|
|
|
def handlers() -> dict:
|
|
return {
|
|
"frappe_list_property_setters": _list_property_setters,
|
|
"frappe_create_property_setter": _create_property_setter,
|
|
"frappe_remove_property_setter": _remove_property_setter,
|
|
"frappe_get_customize_form": _get_customize_form,
|
|
"frappe_reset_customization": _reset_customization,
|
|
}
|
|
|
|
|
|
async def _list_property_setters(args: dict) -> str:
|
|
client = FrappeClient()
|
|
filters = []
|
|
if dt := args.get("doc_type"):
|
|
filters.append(["doc_type", "=", dt])
|
|
if fn := args.get("field_name"):
|
|
filters.append(["field_name", "=", fn])
|
|
if prop := args.get("property"):
|
|
filters.append(["property", "=", prop])
|
|
result = await client.get_list(
|
|
"Property Setter",
|
|
fields=["name", "doc_type", "field_name", "property", "value"],
|
|
filters=filters if filters else None,
|
|
limit=args.get("limit", 50),
|
|
)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _create_property_setter(args: dict) -> str:
|
|
client = FrappeClient()
|
|
payload = {
|
|
"doc_type": args["doc_type"],
|
|
"field_name": args.get("field_name", ""),
|
|
"property": args["property"],
|
|
"value": args["value"],
|
|
"property_type": args.get("property_type", "Check"),
|
|
"row_name": args.get("row_name", ""),
|
|
"doctype_or_field": "DocField" if args.get("field_name") else "DocType",
|
|
}
|
|
result = await client.create_doc("Property Setter", payload)
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _remove_property_setter(args: dict) -> str:
|
|
client = FrappeClient()
|
|
result = await client.delete_doc("Property Setter", args["name"])
|
|
return json.dumps(result, indent=2)
|
|
|
|
|
|
async def _get_customize_form(args: dict) -> str:
|
|
client = FrappeClient()
|
|
result = await client.call_method(
|
|
"frappe.desk.form.load.getdoc",
|
|
doctype="Customize Form",
|
|
name="Customize Form",
|
|
)
|
|
# fetch the form for this specific doctype
|
|
form_result = await client.call_method(
|
|
"frappe.client.get",
|
|
doctype="Customize Form",
|
|
filters={"doc_type": args["doc_type"]},
|
|
)
|
|
return json.dumps(form_result, indent=2)
|
|
|
|
|
|
async def _reset_customization(args: dict) -> str:
|
|
client = FrappeClient()
|
|
result = await client.call_method(
|
|
"frappe.custom.doctype.customize_form.customize_form.reset_customization",
|
|
doc_type=args["doc_type"],
|
|
)
|
|
return json.dumps(result, indent=2)
|