The Tool Management System in Frappe Assistant Core provides administrators with granular control over which AI assistant tools are available to users. This system allows you to:
- Enable/Disable individual tools - Control which tools are exposed to the MCP client
- Configure role-based access - Restrict specific tools to certain user roles
- Categorize tools - Understand tool capabilities through automatic category detection
- Manage tool visibility - Hide sensitive or experimental tools from users
Each tool has an individual configuration record that stores:
| Field | Description |
|---|---|
| Tool Name | Unique identifier (e.g., get_document, create_document) |
| Plugin Name | The plugin providing this tool (e.g., core, data_science) |
| Enabled | Toggle to show/hide tool from MCP tools/list |
| Tool Category | Operation type: read_only, write, read_write, privileged |
| Role Access Mode | Allow All or Restrict to Listed Roles |
| Role Access | Child table of roles with access (when restricted) |
Tools are automatically categorized based on their code analysis:
| Category | Color | Description | Example Tools |
|---|---|---|---|
| Read Only | 🟢 Green | Only reads data, no modifications | get_document, list_documents, search_documents |
| Write | 🟡 Yellow | Creates or modifies data | create_document, update_document |
| Read & Write | 🔵 Blue | Both reads and modifies data | Mixed operation tools |
| Privileged | 🟠 Orange | Elevated access - delete, execute code, run queries | delete_document, run_python_code, query_and_analyze |
When using "Restrict to Listed Roles" mode, this child table specifies which roles can access the tool:
| Field | Description |
|---|---|
| Role | Link to Frappe Role |
| Allow Access | Checkbox to grant access |
- Navigate to FAC Admin page (
/app/fac-admin) - Click on the Tools tab to see all available tools
- Or directly access the Tool Configuration list at
/app/fac-tool-configuration
- Go to FAC Admin → Tools tab
- Find the tool you want to toggle
- Click the Enable/Disable toggle
- Changes take effect immediately
- Navigate to
/app/fac-tool-configuration - Click on the tool you want to configure
- Toggle the Enabled checkbox
- Click Save
The FAC Admin page provides bulk actions for enabling/disabling multiple tools by category:
- Go to FAC Admin → Individual Tools tab
- In the Bulk Actions bar at the top:
- Select a Category (Read Only, Write, Read & Write, Privileged) or leave as "Select Category" for all
- Optionally select a Plugin to filter by plugin
- Click Enable or Disable to toggle all matching tools
Examples:
- Disable all privileged tools: Select "Privileged" → Click "Disable"
- Enable all read-only tools in core plugin: Select "Read Only" + "Core" → Click "Enable"
- Disable all tools in data_science plugin: Leave category empty + Select "Data Science" → Click "Disable"
To enable/disable specific tools by name:
# Using the API
import frappe
from frappe_assistant_core.assistant_core.doctype.fac_tool_configuration.fac_tool_configuration import bulk_toggle_tools
# Disable multiple tools
result = bulk_toggle_tools(
tool_names=["run_python_code", "query_and_analyze"],
enabled=False
)
print(result)
# {'success': True, 'total': 2, 'success_count': 2, 'failures': [], 'message': '2 of 2 tools updated'}To enable/disable tools by category:
from frappe_assistant_core.api.admin_api import bulk_toggle_tools_by_category
# Enable all read-only tools
result = bulk_toggle_tools_by_category(category="read_only", enabled=True)
# {'success': True, 'total': 12, 'toggled': [...], 'failed': [], 'message': '12 tools enabled'}
# Disable all privileged tools
result = bulk_toggle_tools_by_category(category="privileged", enabled=False)
# Disable all write tools in data_science plugin only
result = bulk_toggle_tools_by_category(
category="write",
enabled=False,
plugin_name="data_science"
)
# Enable all tools in visualization plugin (any category)
result = bulk_toggle_tools_by_category(
category=None, # or omit this parameter
enabled=True,
plugin_name="visualization"
)Available Categories:
read_only- Tools that only read datawrite- Tools that create or modify dataread_write- Tools that both read and modify dataprivileged- Tools with elevated access (delete, execute code, run queries)
- Open the tool configuration (e.g.,
/app/fac-tool-configuration/delete_document) - Change Role Access Mode to
Restrict to Listed Roles - In the Role Access table, add the roles that should have access:
- Click Add Row
- Select the Role (e.g.,
System Manager) - Check Allow Access
- Click Save
Example: Restrict delete_document to System Manager only
Tool Name: delete_document
Role Access Mode: Restrict to Listed Roles
Role Access:
┌─────────────────┬──────────────┐
│ Role │ Allow Access │
├─────────────────┼──────────────┤
│ System Manager │ ✓ │
└─────────────────┴──────────────┘
- Set Role Access Mode to
Allow All - The Role Access table will be hidden
- All users can access the tool (subject to other permission checks)
The system uses a multi-layer detection approach (in order of priority):
1. Hardcoded Lists (fastest, most reliable)
└── PRIVILEGED_TOOLS, READ_ONLY_TOOLS, WRITE_TOOLS in tool_category_detector.py
2. AST Code Analysis (automatic)
└── Parses tool source code looking for perm_type="read", perm_type="write", etc.
3. Default Fallback
└── If nothing detected → "read_write"
If your tool uses standard Frappe permission patterns, the AST analyzer will detect the category automatically:
# This will be detected as "read_only"
def execute(self, arguments):
frappe.has_permission("Sales Invoice", perm_type="read")
# or
self.validate_document_access("Customer", "CUST-001", perm_type="read")
# This will be detected as "write"
def execute(self, arguments):
frappe.has_permission("Sales Invoice", perm_type="write")Add tools to the hardcoded lists in tool_category_detector.py when:
| Scenario | Action |
|---|---|
Tool doesn't use perm_type in code |
Add to hardcoded list |
| AST detection is incorrect | Add to override list |
| Tool does complex/mixed operations | Safer to hardcode |
| Critical tools (delete, execute code) | Always hardcode |
Location: frappe_assistant_core/utils/tool_category_detector.py
PRIVILEGED_TOOLS = {"delete_document", "run_python_code", ...}
READ_ONLY_TOOLS = {"get_document", "list_documents", ...}
WRITE_TOOLS = {"create_document", "update_document", ...}If the auto-detection is incorrect and you don't want to modify code:
- Open the tool configuration
- Check Category Manually Overridden
- Select the correct Tool Category from the dropdown
- Click Save
The auto_detected_category field shows what the system detected, while tool_category shows the effective category.
from frappe_assistant_core.assistant_core.doctype.fac_tool_configuration.fac_tool_configuration import get_tool_access_status
# Check if current user can access a tool
result = get_tool_access_status("delete_document")
print(result)
# {
# 'tool_name': 'delete_document',
# 'user': 'user@example.com',
# 'has_access': True,
# 'enabled': True,
# 'role_access_mode': 'Allow All',
# 'tool_category': 'privileged'
# }from frappe_assistant_core.assistant_core.doctype.fac_tool_configuration.fac_tool_configuration import toggle_tool
# Disable a tool
result = toggle_tool("run_python_code", enabled=False)
print(result)
# {'success': True, 'tool_name': 'run_python_code', 'enabled': 0, 'message': "Tool 'run_python_code' disabled"}from frappe_assistant_core.assistant_core.doctype.fac_tool_configuration.fac_tool_configuration import bulk_toggle_tools
# Enable multiple tools
result = bulk_toggle_tools(
tool_names=["get_document", "list_documents", "search_documents"],
enabled=True
)from frappe_assistant_core.utils.tool_category_detector import get_category_info
info = get_category_info("privileged")
print(info)
# {
# 'label': 'Privileged',
# 'color': 'orange',
# 'icon': 'fa-shield-alt',
# 'description': 'This tool has elevated access - can delete data, execute code, or run database queries'
# }-
Restrict privileged tools - Tools like
run_python_code,query_and_analyze, anddelete_documentshould be restricted to trusted roles only -
Review tool access regularly - Periodically audit which roles have access to which tools
-
Use category-based policies - Consider disabling all
privilegedcategory tools for non-admin users -
Test access changes - After modifying role access, test with a user in that role to confirm the expected behavior
-
Cache invalidation - Tool configuration changes automatically clear relevant caches
-
Batch operations - Use
bulk_toggle_tools()for multiple changes instead of individual calls -
Auto-sync on migrate - New tools are automatically discovered and configured during
bench migrate
# Restrict run_python_code to System Manager only
config = frappe.get_doc("FAC Tool Configuration", "run_python_code")
config.role_access_mode = "Restrict to Listed Roles"
config.role_access = []
config.append("role_access", {"role": "System Manager", "allow_access": 1})
config.save()# Get all read_only tools
read_only_tools = frappe.get_all(
"FAC Tool Configuration",
filters={"tool_category": "read_only"},
pluck="tool_name"
)
# Configure each to allow the new role
for tool_name in read_only_tools:
config = frappe.get_doc("FAC Tool Configuration", tool_name)
config.role_access_mode = "Restrict to Listed Roles"
config.append("role_access", {"role": "Data Analyst", "allow_access": 1})
config.append("role_access", {"role": "System Manager", "allow_access": 1})
config.save()# Get tools from visualization plugin
viz_tools = frappe.get_all(
"FAC Tool Configuration",
filters={"plugin_name": "visualization"},
pluck="tool_name"
)
# Disable all
from frappe_assistant_core.assistant_core.doctype.fac_tool_configuration.fac_tool_configuration import bulk_toggle_tools
bulk_toggle_tools(viz_tools, enabled=False)- Check if tool is enabled - Verify
enabled = 1in FAC Tool Configuration - Check plugin status - Ensure the parent plugin is enabled in FAC Plugin Configuration
- Check role access - If using restricted mode, verify your role is in the list
- Clear cache - Run
bench clear-cacheto refresh tool registry
- Check role_access_mode - Verify it's set correctly
- Check role membership - Ensure user has the required role
- Check tool enabled - Disabled tools always deny access
- Check plugin enabled - Tools from disabled plugins are not accessible
- Check hardcoded lists - Some tools are pre-categorized in
tool_category_detector.py - Use manual override - Check "Category Manually Overridden" and select the correct category
- Check source code - Ensure
perm_typeis used consistently in the tool's execute method
- Clear caches - Tool configurations clear caches automatically, but try
bench clear-cache - Refresh plugin manager - Use
refresh_plugin_manager()to reload all tools - Check database - Verify the change was saved using
frappe.get_doc()
Tool Management works in conjunction with the Plugin Management System:
┌─────────────────────────────────────┐
│ FAC Plugin Configuration │
│ (Plugin-level enable/disable) │
└──────────────────┬──────────────────┘
│
│ Plugin must be enabled
▼
┌─────────────────────────────────────┐
│ FAC Tool Configuration │
│ (Tool-level enable/disable) │
│ (Role-based access control) │
└──────────────────┬──────────────────┘
│
│ Tool must be enabled + role access
▼
┌─────────────────────────────────────┐
│ MCP tools/list │
│ (Final list exposed to client) │
└─────────────────────────────────────┘
Key Points:
- If a plugin is disabled, all its tools are hidden (regardless of tool configuration)
- If a tool is disabled, it's hidden even if the plugin is enabled
- Role access is checked after enable/disable status
- System Manager always has access to all enabled tools
When you run bench migrate, the system automatically syncs tool and plugin configurations:
| Action | Behavior |
|---|---|
| New tool added | Creates FAC Tool Configuration with enabled=1 |
| Tool removed | Deletes orphan FAC Tool Configuration record |
| New plugin added | Creates FAC Plugin Configuration |
| Plugin removed | Deletes orphan FAC Plugin Configuration record |
| Existing configs | Preserved (user changes are NOT overwritten) |
bench migrate
│
├── _sync_plugin_configurations()
│ ├── Discover plugins from /plugins/ directory
│ ├── Create FAC Plugin Configuration for new plugins
│ └── Delete orphan configs for removed plugins
│
└── _sync_tool_configurations()
├── Discover tools from enabled plugins
├── Discover external tools from assistant_tools hook
├── Create FAC Tool Configuration for new tools
├── Auto-detect tool categories
└── Delete orphan configs for removed tools
Tools from external Frappe apps are discovered via the assistant_tools hook:
# your_app/hooks.py
assistant_tools = [
"your_app.assistant_tools.my_tool.MyTool",
]Important: External tools require the custom_tools plugin to be enabled:
- External tools are assigned
plugin_name = "custom_tools" - If
custom_toolsplugin is disabled, external tools won't load - The plugin is auto-created on
bench migrateif it doesn't exist
| Version | Changes |
|---|---|
| 2.2.0 | Initial release of Tool Management System |
| - FAC Tool Configuration DocType | |
| - FAC Tool Role Access child table | |
| - Automatic category detection | |
| - Role-based access control | |
| - Auto-sync on bench migrate |
- Plugin Management Guide - Managing plugins
- Tool Reference - Complete tool documentation
- Architecture Overview - System architecture
- Security Framework - Security details