# MCP LLM Server FOR ERPNext

> MCP server from Ahmed-Mansy-Mansico/MCP_LLM_Server_FOR_ERPNext.

- **Type:** MCP server
- **Install:** `agentstack add mcp-ahmed-mansy-mansico-mcp-llm-server-for-erpnext`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Ahmed-Mansy-Mansico](https://agentstack.voostack.com/s/ahmed-mansy-mansico)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Ahmed-Mansy-Mansico](https://github.com/Ahmed-Mansy-Mansico)
- **Source:** https://github.com/Ahmed-Mansy-Mansico/MCP_LLM_Server_FOR_ERPNext

## Install

```sh
agentstack add mcp-ahmed-mansy-mansico-mcp-llm-server-for-erpnext
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# MCP Task - Universal ERPNext MCP Connector

A comprehensive **Model Context Protocol (MCP) connector** for ERPNext that enables LLMs to interact seamlessly with any ERPNext instance through standardized tools and advanced permission controls.

[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[](https://github.com/frappe/frappe)

## 🎯 Overview

MCP Task is a **general-purpose MCP connector** that transforms any ERPNext instance into an AI-accessible business system. It provides:

- **🔌 Universal DocType Support**: Works with any ERPNext DocType without configuration
- **🛡️ Advanced Permission Model**: Field-level, operation-level, and conditional access controls  
- **🚀 Complete CRUD Operations**: Create, Read, Update, Delete with full validation
- **🎨 Web Chat Interface**: Built-in chat widget for direct LLM interaction
- **📊 Comprehensive Auditing**: Complete activity logging and permission tracking
- **⚡ Production Ready**: Enterprise-grade security, error handling, and performance

## 🌟 Key Features

### 🔧 **Complete ERPNext Integration**
- **Full CRUD Operations**: Create, Read, Update, Delete any document type
- **Intelligent Search**: Text-based search across all document fields
- **Flexible Filtering**: Query documents with complex filter conditions  
- **DocType Agnostic**: Works with standard and custom DocTypes automatically

### 🛡️ **Advanced Security & Permissions**
- **Multi-Level Access Control**: User roles, DocType permissions, field restrictions
- **Conditional Access**: Python-based rules for dynamic permission evaluation
- **Audit Trail**: Complete logging of all LLM interactions and data access
- **Field-Level Security**: Hide sensitive fields from LLM access

### 🎨 **User Experience**
- **Web Chat Interface**: Floating chat widget integrated into ERPNext UI
- **Real-time Responses**: Instant feedback with loading indicators
- **Conversation History**: Persistent chat sessions per user
- **Mobile Responsive**: Works seamlessly on desktop and mobile devices

## 🏗️ Architecture

### System Overview

```mermaid
graph TB
    LLM[LLM ClientClaude, GPT, etc.] --> MCP[MCP Protocol Handler]
    MCP --> TR[Tool Registry]
    TR --> TOOLS[Document ToolsCRUD Operations]
    TOOLS --> PERM[Permission Engine]
    PERM --> ERP[ERPNext Database]
    
    PERM --> CONFIG[Permission Configuration]
    CONFIG --> FIELD[Field Restrictions]
    CONFIG --> OP[Operation Controls]  
    CONFIG --> COND[Condition Scripts]
    
    MCP --> AUDIT[Audit Logger]
    MCP --> CHAT[Chat Interface]
    
    subgraph "Security Layers"
        PERM
        CONFIG
        AUDIT
    end
```

### Core Components

#### 1. **MCP Protocol Handler** (`api/__init__.py`)
- **JSON-RPC 2.0 Compliance**: Full MCP protocol implementation
- **Request Routing**: Handles initialize, tools/list, tools/call methods
- **Error Management**: Comprehensive error handling with proper status codes
- **Authentication**: Integration with ERPNext session management

#### 2. **Tool Registry System** (`core/`)
- **Dynamic Discovery**: Automatic tool loading and registration
- **Permission Integration**: Built-in permission validation for each tool
- **Extensible Architecture**: Easy addition of custom tools
- **Metadata Management**: Tool descriptions and input schemas

#### 3. **Document Tools** (`tools/`)
- **`create_document`**: Create any ERPNext document with validation
- **`get_document`**: Retrieve document data with field filtering
- **`list_documents`**: Query documents with flexible filters
- **`search_documents`**: Full-text search across document types
- **`update_document`**: Modify document fields with validation
- **`delete_document`**: Remove documents with dependency checks

#### 4. **Advanced Permission Engine**
- **`MCP Permission Configuration`**: Configurable access control DocType
- **Multi-Level Security**: Role, DocType, field, and operation controls
- **Condition Scripts**: Python-based dynamic permission evaluation
- **Field Filtering**: Automatic removal of restricted fields from responses

#### 5. **Web Interface** (`public/js/mcp_task.js`)
- **Floating Chat Widget**: Non-intrusive interface integrated into ERPNext
- **Real-time Communication**: WebSocket-based chat with loading indicators
- **Conversation Persistence**: User-specific chat history management
- **Responsive Design**: Mobile and desktop compatibility

#### 6. **Audit & Logging System**
- **`MCP Chat Log`**: Complete interaction logging for compliance
- **Permission Tracking**: Detailed logs of access control decisions
- **Performance Monitoring**: Request timing and error rate tracking
- **Security Auditing**: Failed access attempts and policy violations

## 🚀 Installation & Setup

### Prerequisites

- **ERPNext v15+** or **Frappe Framework v15+**
- **Python 3.10+**
- **Node.js 18+** (for building assets)
- **Redis** (for background jobs and caching)

### Step 1: Install the App

```bash
# Clone the repository
cd frappe-bench
bench get-app https://github.com/yourusername/mcp_task

# Install on your site
bench --site your-site.com install-app mcp_task

# Migrate database
bench --site your-site.com migrate

# Build and restart
bench build --app mcp_task
bench restart
```

### Step 2: Configure Permissions

#### Basic Setup (All Users)
```bash
# Enable MCP access for all users (basic setup)
bench --site your-site.com execute "frappe.db.set_single_value('System Settings', 'enable_mcp_chat', 1)"
```

#### Advanced Setup (Role-Based)
1. **Create MCP Roles** (via Setup > Users and Permissions > Role):
   - `MCP Admin`: Full access to configuration and tools
   - `MCP User`: Limited access to standard operations

2. **Assign Roles** to users through User management

### Step 3: Environment Variables

Create a `.env` file in your bench directory:

```bash
# MCP Configuration
MCP_ENABLED=1
MCP_DEBUG=0
MCP_LOG_LEVEL=INFO

# Security Settings
MCP_RATE_LIMIT=100  # Requests per minute per user
MCP_SESSION_TIMEOUT=3600  # Session timeout in seconds

# Optional: External LLM Integration
OPENAI_API_KEY=your_openai_key_here
CLAUDE_API_KEY=your_claude_key_here
```

### Step 4: Basic Configuration Test

```bash
# Test MCP endpoint
curl -X POST http://your-site.com/api/method/mcp_task.api.handle_mcp_request \
  -H "Content-Type: application/json" \
  -H "Authorization: token your_api_key:your_api_secret" \
  -d '{
    "jsonrpc": "2.0",
    "method": "initialize", 
    "params": {"protocolVersion": "2024-11-05"},
    "id": 1
  }'
```

### Step 5: Chat Interface Setup

The chat interface is automatically available after installation. Users will see a chat icon in the navbar when logged in.

**Troubleshooting**: If chat icon doesn't appear:
```bash
# Clear cache and rebuild
bench --site your-site.com clear-cache
bench build --app mcp_task
bench restart
```

## 🔒 Permission Model & Access Control

### Overview

MCP Task implements a **multi-layered security model** that allows granular control over LLM access to your ERPNext data:

1. **User Authentication**: Standard ERPNext login required
2. **Role-Based Access**: ERPNext role system integration  
3. **DocType Permissions**: Native ERPNext permission system
4. **MCP-Specific Controls**: Advanced field and operation restrictions

### Permission Configuration

#### Creating Permission Rules

Navigate to **Setup > MCP Task > MCP Permission Configuration** to create custom access rules:

```python
# Example: Restrict Sales User to read-only Customer data
{
  "title": "Sales User Customer Access",
  "doctype_name": "Customer", 
  "user_roles": "Sales User",
  "operation_restrictions": {
    "allowed_operations": ["read", "list", "search"],
    "blocked_operations": ["create", "update", "delete"]
  },
  "field_restrictions": {
    "blocked_fields": ["credit_limit", "payment_terms"]
  }
}
```

#### Field-Level Restrictions

Control which fields are accessible to the LLM:

```json
{
  "field_restrictions": {
    "allowed_fields": ["customer_name", "customer_group", "territory"],
    "blocked_fields": ["credit_limit", "outstanding_amount", "payment_terms"]
  }
}
```

#### Condition-Based Access

Use Python scripts for dynamic permission evaluation:

```python
# Condition Script Example: Only allow access to own records
if doc and doc.get("owner") == user:
    result = True
else:
    result = False

# Complex example: Time-based restrictions
import datetime
current_hour = datetime.datetime.now().hour
if current_hour  17:  # Business hours only
    result = False
else:
    result = True
```

### Permission Examples

#### Example 1: Basic User Restrictions
```json
{
  "title": "Standard User Access",
  "user_roles": "Employee, Desk User",
  "operation_restrictions": {
    "allowed_operations": ["read", "search", "list"]
  },
  "field_restrictions": {
    "blocked_fields": ["base_amount", "outstanding_amount", "credit_limit"]
  }
}
```

#### Example 2: Department-Specific Access
```json
{
  "title": "HR Department Access", 
  "doctype_name": "Employee",
  "user_roles": "HR User, HR Manager",
  "field_restrictions": {
    "allowed_fields": ["employee_name", "department", "designation", "reports_to"]
  },
  "condition_script": "result = frappe.get_roles(user).contains('HR Manager') or doc.get('department') == frappe.db.get_value('Employee', {'user_id': user}, 'department')"
}
```

#### Example 3: Financial Data Protection
```json
{
  "title": "Accounts Restricted Access",
  "tool_names": "get_document, list_documents", 
  "operation_restrictions": {
    "conditions": {
      "financial_doctypes": ["Sales Invoice", "Purchase Invoice", "Payment Entry"],
      "require_role": "Accounts User"
    }
  },
  "condition_script": """
# Only accounts users can access financial documents
if doctype in ['Sales Invoice', 'Purchase Invoice', 'Payment Entry']:
    result = 'Accounts User' in frappe.get_roles(user)
else:
    result = True
  """
}
```

### Security Best Practices

#### 1. **Principle of Least Privilege**
- Start with minimal permissions and add as needed
- Use role-based restrictions rather than user-specific rules
- Regularly audit permission configurations

#### 2. **Field Sensitivity Classification**
```python
# High Sensitivity (Always Block)
HIGH_SENSITIVITY = [
    "bank_account", "iban", "swift_number",
    "salary", "ctc", "password", "api_key"
]

# Medium Sensitivity (Role-Based Access)
MEDIUM_SENSITIVITY = [
    "credit_limit", "outstanding_amount", 
    "employee_id", "phone", "email"
]
```

#### 3. **Audit Configuration**
- Enable detailed logging for all permission decisions
- Monitor failed access attempts
- Regular review of permission effectiveness

## 🎯 API Usage Examples

### LLM Prompt Examples

#### Document Creation
```
"Create a new Customer with the name 'Tech Solutions Inc', customer group 'Corporate', and territory 'India'. Set the customer type to 'Company'."
```

**MCP Request:**
```json
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "create_document",
    "arguments": {
      "doctype": "Customer",
      "data": {
        "customer_name": "Tech Solutions Inc",
        "customer_group": "Corporate", 
        "territory": "India",
        "customer_type": "Company"
      }
    }
  },
  "id": 1
}
```

#### Document Retrieval with Field Filtering
```
"Show me the customer details for CUST-001, but hide any financial information."
```

**MCP Response (with field restrictions applied):**
```json
{
  "jsonrpc": "2.0", 
  "result": {
    "content": [{
      "type": "text",
      "text": {
        "customer_name": "Tech Solutions Inc",
        "customer_group": "Corporate",
        "territory": "India",
        "customer_type": "Company"
        // Sensitive fields like credit_limit filtered out
      }
    }]
  },
  "id": 1
}
```

#### Complex Searches  
```
"Find all Sales Orders from the last 30 days where the customer is from Mumbai territory and the order value is above 50,000."
```

**MCP Request:**
```json
{
  "jsonrpc": "2.0",
  "method": "tools/call", 
  "params": {
    "name": "list_documents",
    "arguments": {
      "doctype": "Sales Order",
      "filters": {
        "creation": [">=", "2024-12-15"],
        "territory": "Mumbai",
        "grand_total": [">", 50000]
      },
      "fields": ["name", "customer", "grand_total", "delivery_date"]
    }
  },
  "id": 1
}
```

## ⚠️ Security Considerations

### Data Protection
- **Encryption in Transit**: All MCP communications use HTTPS/WSS
- **Session Management**: ERPNext session tokens with configurable timeouts
- **API Rate Limiting**: Configurable request limits per user/IP
- **Audit Logging**: Complete trail of all LLM interactions

### Failure Modes & Mitigation

#### 1. **Permission Bypass Attempts**
- **Risk**: LLM attempts to access restricted data
- **Mitigation**: Multi-layer validation, default-deny policies
- **Monitoring**: Alert on permission failures

#### 2. **Data Leakage via Field Filtering**
- **Risk**: Sensitive data exposed through related fields  
- **Mitigation**: Deep field analysis, cascading restrictions
- **Example**: Block `customer.credit_limit` when customer data is filtered

#### 3. **Condition Script Vulnerabilities**
- **Risk**: Malicious Python code in condition scripts
- **Mitigation**: Sandboxed execution, restricted imports
- **Validation**: Syntax checking, security reviews

#### 4. **Large Data Extraction**
- **Risk**: LLM queries return excessive data volumes
- **Mitigation**: Result size limits, pagination controls
- **Configuration**: `MAX_RESULTS_PER_QUERY = 1000`

### Security Monitoring

```python
# Example monitoring alerts
SECURITY_ALERTS = {
    "permission_failures": {
        "threshold": 10,  # failures per hour
        "action": "notify_admin"
    },
    "large_queries": {
        "threshold": 5000,  # records per query
        "action": "log_and_limit"
    },
    "sensitive_field_access": {
        "fields": ["salary", "credit_limit", "bank_account"],
        "action": "audit_log"
    }
}
```

## 🛠️ Development & Customization

### Adding Custom Tools

1. **Create Tool Class** (`tools/my_custom_tool.py`):
```python
from typing import Any
from mcp_task.core.base_tool import BaseTool
import frappe

class MyCustomTool(BaseTool):
    def __init__(self):
        super().__init__()
        self.name = "my_custom_tool"
        self.description = "Custom business logic tool"
        self.requires_permission = "My Custom DocType"
        self.inputSchema = {
            "type": "object",
            "properties": {
                "param1": {"type": "string", "description": "First parameter"},
                "param2": {"type": "integer", "description": "Second parameter"}
            },
            "required": ["param1"]
        }
    
    def execute(self, arguments: dict[str, Any]) -> dict[str, Any]:
        try:
            # Your custom logic here
            result = self.perform_custom_operation(arguments)
            return {"success": True, "data": result}
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def perform_custom_operation(self, args):
        # Implement your business logic
        pass
```

2. **Register Tool** (in `core/tool_registry.py`):
```python
from mcp_task.tools.my_custom_tool import MyCustomTool

# Add to load_tools method
self.register_tool(MyCustomTool())
```

### Extending Permission System

1. **Custom Permission Validators**:
```python
# mcp_task/permissions/custom_validators.py
def validate_customer_territory(user, doc_data):
    """Only allow access to customers in user's territory"""
    user_territory = frappe.db.get_value("Employee", 
        {"user_id": user}, "territory")
    return doc_data.get("territory") == user_territory
```

2. **Plugin-Based Architecture**:
```python
# mcp_task/plugins/custom_business_rules.py
class CustomBusinessRules:
    def apply_restrictions(self, tool_name, user, doc_data):
        # Custom business logic
        pass

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Ahmed-Mansy-Mansico](https://github.com/Ahmed-Mansy-Mansico)
- **Source:** [Ahmed-Mansy-Mansico/MCP_LLM_Server_FOR_ERPNext](https://github.com/Ahmed-Mansy-Mansico/MCP_LLM_Server_FOR_ERPNext)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-ahmed-mansy-mansico-mcp-llm-server-for-erpnext
- Seller: https://agentstack.voostack.com/s/ahmed-mansy-mansico
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
