- 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
138 lines
5.6 KiB
Python
138 lines
5.6 KiB
Python
"""
|
|
Module Registry — controls which tool modules are active.
|
|
|
|
Enable/disable via .env:
|
|
ENABLED_MODULES=documents,doctypes,users → whitelist mode
|
|
MODULE_SCHEDULER=false → disable one module
|
|
MODULE_GOVERNANCE=false → disable another
|
|
|
|
Default: all modules enabled.
|
|
"""
|
|
|
|
import os
|
|
from typing import Callable
|
|
from mcp.types import Tool
|
|
|
|
# ── Import all tool modules ──────────────────────────────────────────────────
|
|
from frappe_mcp.tools import (
|
|
foundation,
|
|
doctypes,
|
|
documents,
|
|
document_inspect,
|
|
document_lifecycle,
|
|
custom_fields,
|
|
scripts,
|
|
workflow_tools,
|
|
users,
|
|
admin,
|
|
analytics,
|
|
print_formats,
|
|
email_templates,
|
|
property_setters,
|
|
naming_series,
|
|
bulk_ops,
|
|
files,
|
|
activity,
|
|
dashboards,
|
|
webhooks,
|
|
reports,
|
|
scheduler,
|
|
translations,
|
|
business_actions,
|
|
governance,
|
|
)
|
|
|
|
# ── Module definitions ───────────────────────────────────────────────────────
|
|
# (module_key, module_object, description)
|
|
ALL_MODULES: list[tuple[str, object, str]] = [
|
|
# Level 1 — Foundation
|
|
("foundation", foundation, "L1: ping, session_info, doctype_meta, permissions, modules"),
|
|
# Level 2 — Read
|
|
("doctypes", doctypes, "L1-2: DocType CRUD — create, read, update, list"),
|
|
("documents", documents, "L2-3: Document CRUD — create, read, update, delete, submit, cancel"),
|
|
("document_inspect", document_inspect, "L2: Search, children, linked docs, timeline, count, attachments"),
|
|
# Level 3-4 — Write + Lifecycle
|
|
("document_lifecycle", document_lifecycle, "L3-4: Child rows, rename, amend, duplicate, status, draft save"),
|
|
("custom_fields", custom_fields, "L2/9: Custom Fields — add, edit, remove, list"),
|
|
("scripts", scripts, "L9: Server Scripts + Client Scripts"),
|
|
# Level 5 — Workflow
|
|
("workflow_tools", workflow_tools, "L5: Workflows, transitions, approvals"),
|
|
# Level 6 — Reporting
|
|
("analytics", analytics, "L6: Aggregate, dashboard data, PDF render, number cards"),
|
|
("reports", reports, "L6/9: Query/Script Report CRUD"),
|
|
("print_formats", print_formats, "L6: Print Format templates"),
|
|
# Level 7 — Bulk
|
|
("bulk_ops", bulk_ops, "L7: Bulk create/update/delete/submit/cancel/assign/tag"),
|
|
# Level 8 — Business Actions
|
|
("business_actions", business_actions, "L8: ERPNext shortcuts — Sales, Buying, Stock, HR, Support, Projects"),
|
|
# Level 9 — Admin / System Intelligence
|
|
("users", users, "L9: Users, Roles, DocType permissions"),
|
|
("admin", admin, "L9: Cache, system settings, SQL, workflows, scheduler"),
|
|
("property_setters", property_setters, "L9: Property Setters + Customize Form"),
|
|
("naming_series", naming_series, "L9: Naming Series — patterns and counters"),
|
|
("files", files, "L2/9: File Manager — upload, list, delete, move"),
|
|
("activity", activity, "L2/9: Comments, tags, assignments, ToDo, error logs"),
|
|
("dashboards", dashboards, "L6/9: Dashboards, charts, number cards, workspaces"),
|
|
("webhooks", webhooks, "L9: Webhooks + API Keys"),
|
|
("email_templates", email_templates, "L9: Email Templates + Notifications"),
|
|
("translations", translations, "L9: Translations, Assignment Rules, User Permissions"),
|
|
("scheduler", scheduler, "L9: Scheduled Jobs + Background Jobs"),
|
|
# Level 10 — Safety & Governance
|
|
("governance", governance, "L10: Dry run, validate, risk score, audit log, rollback"),
|
|
]
|
|
|
|
|
|
def _is_module_enabled(key: str) -> bool:
|
|
"""
|
|
Resolution order (first match wins):
|
|
1. MODULE_<KEY>=false → disabled
|
|
2. MODULE_<KEY>=true → enabled
|
|
3. ENABLED_MODULES=a,b → whitelist — only listed enabled
|
|
4. Default: enabled
|
|
"""
|
|
env_key = f"MODULE_{key.upper()}"
|
|
explicit = os.environ.get(env_key, "").strip().lower()
|
|
if explicit == "false":
|
|
return False
|
|
if explicit == "true":
|
|
return True
|
|
|
|
enabled_list = os.environ.get("ENABLED_MODULES", "").strip()
|
|
if enabled_list:
|
|
return key in [m.strip() for m in enabled_list.split(",")]
|
|
|
|
return True
|
|
|
|
|
|
def get_enabled_tools() -> list[Tool]:
|
|
tools: list[Tool] = []
|
|
for key, module, _ in ALL_MODULES:
|
|
if _is_module_enabled(key):
|
|
tools.extend(module.tools())
|
|
return tools
|
|
|
|
|
|
def get_enabled_handlers() -> dict[str, Callable]:
|
|
handlers: dict[str, Callable] = {}
|
|
for key, module, _ in ALL_MODULES:
|
|
if _is_module_enabled(key):
|
|
handlers.update(module.handlers())
|
|
return handlers
|
|
|
|
|
|
def print_module_status():
|
|
print("\nFrappe MCP — Module Status")
|
|
print("=" * 70)
|
|
total_on = 0
|
|
total_all = 0
|
|
for key, module, desc in ALL_MODULES:
|
|
enabled = _is_module_enabled(key)
|
|
count = len(module.tools())
|
|
total_all += count
|
|
if enabled:
|
|
total_on += count
|
|
status = "ON " if enabled else "OFF"
|
|
print(f" [{status}] {key:<22} ({count:>2} tools) {desc}")
|
|
print("=" * 70)
|
|
print(f" Active: {total_on} tools | Total available: {total_all} tools\n")
|