Tool Management System Guide
Overview
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
Key Components
1. FAC Tool Configuration DocType
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) |
2. Tool Categories
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 |
3. FAC Tool Role Access (Child Table)
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 |
User Guide
Accessing Tool Management
- 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
Enabling/Disabling Tools
From FAC Admin Page
- Go to FAC Admin → Tools tab
- Find the tool you want to toggle
- Click the Enable/Disable toggle
- Changes take effect immediately
From Tool Configuration DocType
- Navigate to
/app/fac-tool-configuration - Click on the tool you want to configure
- Toggle the Enabled checkbox
- Click Save
Bulk Operations
From FAC Admin UI
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"
Using the API - By Tool Names
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'}Using the API - By Category
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)
Configuring Role-Based Access
Restricting a Tool to Specific Roles
- 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 │ ✓ │
└─────────────────┴──────────────┘Allowing All Users
- 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)
Understanding Tool Categories
Category Detection Hierarchy
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"When Auto-Detection Works
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")When to Use Hardcoded Lists
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", ...}Manual Override via UI
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.
API Reference
Check Tool Access
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'
# }Toggle a Single Tool
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"}Bulk Toggle Tools
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
)Get Category Information
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'
# }Best Practices
Security Recommendations
Restrict privileged tools - Tools like
run_python_code,query_and_analyze, anddelete_documentshould be restricted to trusted roles onlyReview tool access regularly - Periodically audit which roles have access to which tools
Use category-based policies - Consider disabling all
privilegedcategory tools for non-admin usersTest access changes - After modifying role access, test with a user in that role to confirm the expected behavior
Performance Considerations
Cache invalidation - Tool configuration changes automatically clear relevant caches
Batch operations - Use
bulk_toggle_tools()for multiple changes instead of individual callsAuto-sync on migrate - New tools are automatically discovered and configured during
bench migrate
Common Scenarios
Scenario 1: Disable Code Execution for All Non-Admins
# 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()Scenario 2: Enable Only Read Tools for a New Role
# 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()Scenario 3: Disable All Visualization Tools
# 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)Troubleshooting
Tool Not Appearing in MCP tools/list
- 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
Tool Access Denied
- 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
Category Not Detecting Correctly
- 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
Changes Not Taking Effect
- 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()
Integration with Plugin System
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
Automatic Sync on Bench Migrate
When you run bench migrate, the system automatically syncs tool and plugin configurations:
What Happens on Migrate
| 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) |
Sync Flow
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 toolsExternal/Custom 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 History
| 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 |
Related Documentation
- Plugin Management Guide - Managing plugins
- Tool Reference - Complete tool documentation
- Architecture Overview - System architecture
- Security Framework - Security details