frappe-mcp-server

frappe-mcp-server

A secure, audit-logged MCP server for Frappe that exposes specific DocTypes and operations to AI agents with granular permissions and field-level control.

Category
Visit Server

README

MCP Server for Frappe

License: MIT Python 3.10+ Frappe MCP Security Audit Tests

Leggi in Italiano

A secure, audit-logged Model Context Protocol (MCP) server for Frappe. This app allows you to expose specific DocTypes and operations to MCP clients (like AI agents) with strict granular permissions, ensuring secure and controlled access to your Frappe data.

Features

  • Secure Authentication: dedicated MCP User access via Token or API Key.
  • Granular Allowlist: Explicitly allow specific DocTypes and operations (Create, Read, Update, Delete).
  • Field-Level Control: Restrict which fields can be read or written.
  • Audit Logging: Every request is logged with latency, status, and payload summaries.
  • Strict Validation: All filters and inputs are validated against the allowlist.

Installation

  1. Get the app:

    bench get-app https://github.com/mascor/frappe-mcp-server
    
  2. Install on your site:

    bench --site <your-site> install-app mcp_server
    

Configuration

1. Setup MCP User & Settings

You can use the included setup script to quickly configure the server with a default user and token:

bench --site <your-site> execute mcp_server.setup.setup_mcp

This will:

  • Create a user mcp@example.com (if not exists).
  • Generate a secure X-MCP-Token and save it in MCP Server Settings.
  • Enable the MCP Server.

Alternatively, go to MCP Server Settings in Desk and configure manually.

2. Configure Allowlist

By default, no access is allowed. You must explicitly allow DocTypes.

  1. Go to MCP Doctype Allowlist.
  2. Create a new record for the DocType you want to expose (e.g., ToDo).
  3. Check the operations you want to allow (Allow Read, Allow Create, etc.).
  4. (Optional) restricting fields and filters in the child tables for tighter security.

Usage

The server exposes standard MCP tools via the API.

Authentication

The server supports API Key authentication (recommended for MCP clients).

Include the Authorization header in all requests.

Tools

mcp_ping

Health check and version info.

curl -X POST https://<yoursite>/api/method/mcp_server.api.ping \
     -H "Authorization: token <api_key>:<api_secret>"

search_docs

Search for documents with filters.

{
    "doctype": "ToDo",
    "filters": {"status": "Open"}
}

create_doc

Create a new document.

{
    "doctype": "ToDo",
    "data": {
        "description": "New Task from MCP"
    }
}

update_doc

Update an existing document.

{
    "doctype": "ToDo",
    "name": "TODO-0001",
    "data": {
        "status": "Closed"
    }
}

Audit Log

Check MCP Audit Log in Desk to see a history of all requests, including success/failure status, latency, and diffs.

License

MIT

Quick Connect: MCP Client

To connect to this server from an AI Client (like Claude Desktop or Cursor), use the official Python Client:

frappe-mcp-client

Follow the installation and setup instructions in the client repository to get started.

Frappe MCP Server - Test Report

Available Commands

Command Description Parameters
ping Check server connection None
search_docs Search documents doctype (required), filters (optional), fields (optional)
get_doc Get a specific document doctype (required), name (required)
create_doc Create a new document doctype (required), data (required)
update_doc Update an existing document doctype (required), name (required), data (required)
get_meta Get DocType metadata doctype (required)
delete_doc Delete a document doctype (required), name (required)

Test Results Summary

Section A: Standard DocType Operations

Test DocType Operation Status
A1 Note create_doc ✅ PASS
A2 Note get_doc ✅ PASS
A3 Note update_doc ✅ PASS
A4 Note search_docs ✅ PASS
A5 Note delete_doc ✅ PASS
A6 Event create_doc ✅ PASS
A7 Event get_meta ✅ PASS
A8 Event delete_doc ✅ PASS

Section B: Filters and Fields

Test Description Status
B1 search_docs with filters ✅ PASS
B2 search_docs with fields ✅ PASS
B3 search_docs with filters + fields ✅ PASS

Section C: Edge Cases / Error Handling

Test Description Expected Status
C1 get_doc non-existent document 404 Not Found ✅ PASS
C2 create_doc missing required field 417 Expectation Failed ✅ PASS
C3 update_doc non-existent document 404 Not Found ✅ PASS
C4 delete_doc non-existent document 404 Not Found ✅ PASS
C5 get_meta non-existent DocType 403 Forbidden ✅ PASS

Section D: Permissions

Test Description Status
D1 search_docs on allowed DocType (User) ✅ PASS
D2 get_meta on non-allowed DocType (Role) ✅ PASS (403)

🎉 Final Result: 18/18 Tests Passed


Test Examples

1. ping

Check server connection status.

Response:

{
  "status": "ok",
  "site": "your-site.example.com",
  "user": "mcp_user@example.com"
}

2. get_meta

Get the structure of a DocType.

Request:

doctype: "ToDo"

Response:

{
  "doctype": "ToDo",
  "fields": [
    {
      "fieldname": "status",
      "label": "Status",
      "fieldtype": "Select",
      "options": "Open\\nClosed\\nCancelled",
      "reqd": 0,
      "default": "Open"
    },
    {
      "fieldname": "priority",
      "label": "Priority",
      "fieldtype": "Select",
      "options": "High\\nMedium\\nLow",
      "reqd": 0,
      "default": "Medium"
    },
    {
      "fieldname": "date",
      "label": "Due Date",
      "fieldtype": "Date",
      "reqd": 0,
      "default": "Today"
    },
    {
      "fieldname": "description",
      "label": "Description",
      "fieldtype": "Text Editor",
      "reqd": 1
    }
  ],
  "issingle": 0,
  "istable": 0
}

3. create_doc

Create a new document.

Request:

doctype: "ToDo"
data: {
  "status": "Open",
  "priority": "High",
  "description": "Test task created via MCP"
}

Response:

{
  "name": "abc123xyz",
  "owner": "mcp_user@example.com",
  "creation": "2026-01-21 10:18:41.295624",
  "modified": "2026-01-21 10:18:41.295624",
  "modified_by": "mcp_user@example.com",
  "docstatus": 0,
  "status": "Open",
  "priority": "High",
  "date": "2026-01-21",
  "description": "Test task created via MCP",
  "doctype": "ToDo"
}

4. search_docs

Search for documents with optional filters and fields.

Request (basic):

doctype: "ToDo"

Response:

[
  {"name": "todo001"},
  {"name": "todo002"},
  {"name": "todo003"}
]

Request (with filters and fields):

doctype: "ToDo"
filters: {"status": "Open"}
fields: ["name", "status", "priority", "description"]

Response:

[
  {
    "name": "todo001",
    "status": "Open",
    "priority": "Medium",
    "description": "Test task 1"
  },
  {
    "name": "todo002",
    "status": "Open",
    "priority": "High",
    "description": "Test task 2"
  }
]

5. get_doc

Get a specific document by name.

Request:

doctype: "ToDo"
name: "abc123xyz"

Response:

{
  "name": "abc123xyz",
  "owner": "mcp_user@example.com",
  "status": "Open",
  "priority": "High",
  "date": "2026-01-21",
  "description": "Test task created via MCP",
  "creation": "2026-01-21 10:18:41.295624",
  "modified": "2026-01-21 10:18:41.295624",
  "modified_by": "mcp_user@example.com",
  "docstatus": 0
}

6. update_doc

Update an existing document.

Request:

doctype: "ToDo"
name: "abc123xyz"
data: {
  "status": "Closed",
  "priority": "Low"
}

Response:

{
  "name": "abc123xyz",
  "owner": "mcp_user@example.com",
  "creation": "2026-01-21 10:18:41.295624",
  "modified": "2026-01-21 10:18:59.096886",
  "modified_by": "mcp_user@example.com",
  "docstatus": 0,
  "status": "Closed",
  "priority": "Low",
  "date": "2026-01-21",
  "description": "Test task created via MCP",
  "doctype": "ToDo"
}

7. delete_doc

Delete a document.

Request:

doctype: "ToDo"
name: "abc123xyz"

Response:

{
  "status": "deleted",
  "name": "abc123xyz"
}

Error Response (document not found):

HTTP 404 Not Found

Setup Requirements

  1. Install the MCP Server app on your Frappe site

    bench get-app https://github.com/[repo]/frappe-mcp-server
    bench --site [your-site] install-app mcp_server
    
  2. Create an API user (e.g., mcp_user@example.com)

  3. Generate API keys for the user

    • Go to User → API Access → Generate Keys
  4. Assign appropriate roles to the API user (e.g., System Manager)

  5. Configure the Allowlist

    • Go to "MCP Doctype Allowlist"
    • Add DocTypes you want to expose via MCP
    • Configure allowed operations (Read, Create, Update, Delete, Meta)
  6. Configure the MCP client with the API credentials


Allowlist Configuration

The MCP Server uses an Allowlist to control which DocTypes are accessible. For each DocType you can configure:

Option Description
Allow Read (Get, Search) Permits get_doc and search_docs
Allow Create Permits create_doc
Allow Update Permits update_doc
Allow Delete Permits delete_doc
Allow Meta (Schema) Permits get_meta
Max Page Length Limits results for search_docs (0 = default)
Allowed Fields (Read) Restrict which fields are returned (empty = all)
Allowed Filters Restrict which fields can be used in filters (empty = all)

Error Codes

HTTP Code Meaning Common Causes
200 Success Operation completed
403 Forbidden DocType not in Allowlist or operation not permitted
404 Not Found Document or DocType does not exist
417 Expectation Failed Validation error (e.g., missing required field)
500 Internal Server Error Server-side error (check logs)

Troubleshooting

Issue Cause Solution
403 Forbidden Missing permissions Assign roles to API user or add @frappe.whitelist() decorator
403 Forbidden on all calls Missing Allowlist entry Add DocType to MCP Doctype Allowlist
403 Forbidden on specific operation Operation not enabled Enable the operation in Allowlist
403 Forbidden with filters Filter field not allowed Add field to Allowed Filters or leave empty for all
404 Not Found Document doesn't exist Verify document name
417 Expectation Failed Module not found Install/reinstall the MCP Server app
417 Expectation Failed Validation error Check required fields in DocType
500 Internal Server Error Code error Run bench --site [site] logs

Security Notes

  • Only DocTypes explicitly added to the Allowlist are accessible
  • Each operation (Read, Create, Update, Delete, Meta) must be explicitly enabled
  • API authentication is required for all operations
  • Consider restricting sensitive DocTypes (User, Role, etc.) in production

Security Audit Report

Overview

The Frappe MCP Server has undergone comprehensive security testing to ensure it is safe for production use. All 15 security tests have passed successfully.


Security Test Results

Authentication & Authorization

Test Description Result
S1 Sensitive fields (password, api_key, api_secret) not accessible ✅ PASS
S2 System DocTypes (DocType) blocked ✅ PASS
S3 Role DocType blocked ✅ PASS
S4 System Settings blocked ✅ PASS
S5 Email Account (credentials) blocked ✅ PASS
S6 Allowlist self-modification blocked ✅ PASS

Injection Attacks

Test Description Result
S7 SQL Injection in filters ✅ PASS
S8 SQL Injection in document name ✅ PASS
S12 XSS in document content ✅ PASS (sanitized)
S14 Path Traversal attack ✅ PASS

Data Protection

Test Description Result
S9 Error Log access blocked ✅ PASS
S10 Scheduled Job Log access blocked ✅ PASS
S11 File DocType access blocked ✅ PASS
S13 Sensitive fields auto-filtered from User ✅ PASS
S15 Privilege escalation prevented ✅ PASS

Security Features

1. Allowlist-Based Access Control

Only DocTypes explicitly added to the MCP Doctype Allowlist are accessible via the API. Each DocType can be configured with granular permissions:

  • Allow Read (Get, Search)
  • Allow Create
  • Allow Update
  • Allow Delete
  • Allow Meta (Schema)

2. Automatic Sensitive Field Filtering

The following fields are automatically removed from all API responses, regardless of user permissions or Allowlist configuration:

  • api_key
  • api_secret
  • password
  • new_password
  • reset_password_key

This server-side filter prevents credential leakage even if the User DocType is in the Allowlist.

3. Input Sanitization

  • SQL Injection Protection: All user inputs are parameterized through Frappe's ORM
  • XSS Protection: HTML content is automatically sanitized (e.g., <script>&lt;script&gt;)
  • Path Traversal Protection: DocType names are validated against the Allowlist

4. Protected System DocTypes

The following sensitive DocTypes are blocked by default (not in Allowlist):

  • DocType - System schema
  • Role - Permission roles
  • System Settings - Global configuration
  • Email Account - Email credentials
  • Error Log - System errors (may contain sensitive data)
  • Scheduled Job Log - Background job logs
  • File - Uploaded files
  • MCP Doctype Allowlist - Prevents self-modification

Security Best Practices

For Production Deployment

  1. Minimize Allowlist: Only add DocTypes that are strictly necessary
  2. Restrict Operations: Enable only required operations (Read/Create/Update/Delete)
  3. Use Field Restrictions: Limit which fields can be read or used in filters
  4. Separate API User: Create a dedicated user for MCP with minimal roles
  5. Monitor Access: Regularly review API access logs
  6. Rotate API Keys: Periodically regenerate API credentials

Allowlist Configuration Example

DocType: Customer
├── Allow Read: ✅
├── Allow Create: ❌
├── Allow Update: ❌
├── Allow Delete: ❌
├── Allow Meta: ✅
├── Allowed Fields: ["name", "customer_name", "email"]
└── Allowed Filters: ["name", "customer_name"]

This configuration allows read-only access to Customer records with restricted fields.


Tested Attack Vectors

SQL Injection

# Attempted attack
search_docs(doctype="ToDo", filters={"status": "Open'; DROP TABLE tabToDo; --"})

# Result: Query safely parameterized, no data loss

XSS (Cross-Site Scripting)

# Attempted attack
create_doc(doctype="ToDo", data={"description": "<script>alert('XSS')</script>"})

# Result: Content sanitized to "&lt;script&gt;alert('XSS')&lt;/script&gt;"

Path Traversal

# Attempted attack
get_doc(doctype="../../../etc/passwd", name="root")

# Result: 403 Forbidden (DocType not in Allowlist)

Privilege Escalation

# Attempted attack
update_doc(doctype="User", name="attacker@example.com", data={"user_type": "Administrator"})

# Result: 403 Forbidden (Update not allowed on User DocType)

Compliance Summary

Category Status
Authentication ✅ API Key/Secret required
Authorization ✅ Allowlist-based access control
Data Protection ✅ Sensitive fields auto-filtered
Input Validation ✅ SQL/XSS/Path Traversal protected
Audit Trail ✅ Standard Frappe logging

Final Result

╔══════════════════════════════════════════════════════════════╗
║                    SECURITY AUDIT PASSED                     ║
║                                                              ║
║                    15/15 Tests Successful                    ║
║                                                              ║
║          ✅ Ready for Production Deployment                  ║
╚══════════════════════════════════════════════════════════════╝

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured