Frappe MCP Server
A Model Context Protocol (MCP) Server for Frappe Framework / ERPNext, enabling AI models (like Claude) to securely interact with your Frappe instances through a standardized protocol.
Built with @modelcontextprotocol/sdk and powered by frappe-js-sdk.
🎯 Overview
This MCP server bridges AI models and Frappe, allowing you to:
- Read & manipulate documents via CRUD operations
- Call whitelisted Python methods on the backend
- Manage files (upload, download, attach)
- Handle authentication with multiple auth modes
- Orchestrate workflows (state transitions, history)
- Generate reports & analytics with custom filters
- Monitor background jobs and task queues
- Stream real-time events via Socket.io
- Generate PDFs & formatted documents
- Bulk import/export data
---
✨ Features
Phase 1: Document Tools
- CRUD Operations: Create, retrieve, update, delete documents
- Listing & Filtering: Paginated queries with complex filters
- Field Operations: Get/set individual fields, rename documents
- Single DocTypes: Retrieve values from single-type documents
- Document Lifecycle: Submit and cancel documents
Phase 2: Method Calling & Helpers
- Generic RPC: Call any whitelisted Python method path
- Link Field Search: Autocomplete search for Link fields
- List Views: Fetch report/list view data
- Form Metadata: Retrieve DocType schemas
- Dashboard Data: Fetch chart and number card values
Phase 3: File Management
- Upload Files: Via base64 or remote URL
- List Attachments: View all files attached to a document
- Download Files: Retrieve as base64
- Attach to Documents: Link files to specific document fields
- File Deletion: Remove file records
Phase 4: Authentication & User Management
- Login/Logout: Session management
- User Info: Profile details and permissions
- Dynamic Credential Switching: Change auth context on the fly
- Permission Lookup: Check user DocType permissions
- Password Reset: Trigger password reset workflows
Phase 5: Workflow Engine
- State Queries: Get current workflow state
- Allowed Actions: List possible transitions
- State Transitions: Apply workflow actions
- Audit Trail: Retrieve workflow history logs
Phase 6: Reporting & Analytics
- Run Reports: Execute Query/Script/Builder reports
- Custom Filters: Apply filters to report queries
- CSV Export: Export reports as CSV strings
- Dashboard Charts: Load chart data with filters
- Number Cards: Get values from dashboard metrics
Phase 7: Background Jobs
- List Jobs: View job queue entries
- Job Status: Check individual job status
- Force Execution: Enqueue tasks immediately
Phase 8: Advanced Features
- Real-time Events: Subscribe to Socket.io events
- Publish Events: Emit real-time events
- Desktop Notifications: Retrieve unread bell notifications
- Print Formats: Render HTML-formatted documents
- PDF Generation: Generate binary PDFs (returned as base64)
- Data Import/Export: Bulk import/export with templates
- Email Integration: Send emails and log communications
- Bulk Edit: Update multiple records at once
---
🔐 Authentication
The server supports multiple authentication methods:
| Method | Use Case | Config | |--------|----------|--------| | API Key/Secret | Server-to-server, highest security | FRAPPE_API_KEY + FRAPPE_API_SECRET | | Bearer Token | OAuth / token-based auth | FRAPPE_TOKEN | | Username/Password | Session cookie-based auth | FRAPPE_USERNAME + FRAPPE_PASSWORD | | Dynamic Switching | Change credentials per-call | switch_user tool |
Environment Configuration
Create a .env file in the root directory:
# Required: Your Frappe instance URL
FRAPPE_URL=https://your-instance.frappe.cloud
# Choose ONE authentication method:
# Option 1: API Key & Secret (Recommended)
FRAPPE_API_KEY=your_api_key
FRAPPE_API_SECRET=your_api_secret
# Option 2: OAuth Bearer Token
FRAPPE_TOKEN=your_bearer_token
# Option 3: Username & Password
FRAPPE_USERNAME=administrator
FRAPPE_PASSWORD=admin_password
# Optional: Logging level (debug, info, warn, error)
LOG_LEVEL=info
---
📚 Tools Reference
The server exposes 50+ tools organized in 8 phases. Here's a quick reference:
Document Tools (Phase 1)
create_document- Create new recordsget_document- Fetch single documentupdate_document- Modify existing recordsdelete_document- Remove recordslist_documents- Query with filters & paginationget_document_count- Count matching recordsget_field_value/set_field_value- Field-level operationsrename_document- Change document IDget_single_value- Get Single DocType fieldssubmit_document- Submit for approvalcancel_document- Cancel submitted docs
Method Calling (Phase 2)
call_method- Generic RPC to any whitelisted methodsearch_link- Autocomplete for Link fieldsget_list_view- Report/list view dataget_form_meta- DocType schemavalidate_document- Check if document existsget_dashboard_data- Dashboard metrics
File Management (Phase 3)
upload_file- Upload (base64 or URL)list_attachments- View document attachmentsdownload_file- Download as base64delete_file- Remove file recordsattach_file_to_document- Link files to docs
Authentication (Phase 4)
login_user- Start sessionlogout_user- End sessionget_current_user- Current user inforeset_password- Trigger password resetget_user_info- Full profile detailsget_user_permissions- DocType permissionsswitch_user- Change auth credentials
Workflows (Phase 5)
get_workflow_state- Current stateget_workflow_actions- Allowed transitionsworkflow_transition- Apply actionget_workflow_history- Audit trail
Reports (Phase 6)
run_query_report- Execute reportsget_report_columns- Report schemaexport_report- Export as CSVget_dashboard_chart- Chart dataget_number_card- Card metrics
Jobs (Phase 7)
list_jobs- Job queue entriesget_job_status- Check job statusenqueue_job- Force execution
Advanced (Phase 8)
subscribe_to_events- Listen for realtime eventspublish_realtime_event- Emit eventsget_notifications- Unread notificationsget_print_format- Render HTML formatgenerate_pdf- Generate PDF (base64)import_data- Bulk data importexport_data- Bulk data exportdownload_template- Get import templatesend_email- Send mailcreate_communication- Log email historyget_email_queue- Check email statusget_print_settings- System print configbulk_edit- Update multiple records
---
📖 Resources
MCP Resources expose Frappe data as dynamic URIs that AI models can reference and read:
| URI Pattern | Description | |-------------|-------------| | schema://{doctype} | Full DocType metadata schema | | schema://{doctype}/fields | List of field definitions | | data://{doctype}/{name} | Live document data | | report://{report_name} | Report definition & settings | | workflow://{doctype} | Workflow state transitions | | user://me | Current authenticated user profile |
Example: An AI can reference schema://Customer to understand the Customer DocType structure before creating one.
---
🤖 Prompts
AI prompt templates for common workflows:
| Prompt | Arguments | Purpose | |--------|-----------|---------| | create_sales_order | customer, item_code, qty, rate | Guided sales order creation | | approve_purchase | doctype, name, action | Purchase approval workflow | | generate_monthly_report | report_name, fiscal_year | Monthly analytics generation | | onboard_new_employee | employee_name, department, role | HR employee onboarding |
---
🚀 Getting Started
Prerequisites
- Node.js 20+
- npm or yarn
- Access to a Frappe instance
Installation
# Clone the repository
git clone <repo-url>
cd frappe-mcp-server
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Edit .env with your Frappe instance details
Development
Run the server in development mode with auto-reloading:
npm run dev
The server starts on the configured transport (default: SSE on port 3000).
Build
Compile TypeScript to JavaScript for production:
npm run build
Output: dist/index.js
Production
Run the compiled production build:
npm run start
---
🧪 Testing
Unit Tests
Run automated tests using Vitest:
npm run test
Tests verify:
- Tool schema validation
- Input parameter checking
- Tool routing logic
- Resource templates
- Prompt builders
Manual Testing with MCP Inspector
Use the official MCP Inspector to visually test tools, resources, and prompts:
Development Server
npx -y @modelcontextprotocol/inspector npx tsx src/index.ts
Production Build
npx -y @modelcontextprotocol/inspector node dist/index.js
Then open the URL (typically http://localhost:5173) in your browser to:
- Browse all available tools
- Call tools with test parameters
- View resources
- Preview prompts
---
🐳 Docker Deployment
Quick Start
Build and run using Docker Compose:
# Set your Frappe instance URL
export FRAPPE_URL=https://your-instance.frappe.cloud
# Start the container
docker-compose up -d
The server runs on http://localhost:3000 with health checks enabled.
Docker Build
Build the image manually:
docker build -t frappe-mcp-server:latest .
Run:
docker run -p 3000:3000 \
-e FRAPPE_URL=https://your-instance.frappe.cloud \
-e LOG_LEVEL=info \
frappe-mcp-server:latest
Multi-User Mode (SSE)
The server supports multi-user SSE (Server-Sent Events) mode. Each client can:
- Connect over HTTP with credentials in headers
- Have isolated sessions via
AsyncLocalStorage - Dynamically switch authentication
---
🔧 Configuration
MCP Transport
The server supports two MCP transports:
- Stdio (default for CLI/integration)
- Single-user, embedded mode
- No HTTP overhead
- SSE (HTTP Server-Sent Events)
- Multi-user, client-server mode
- Better for cloud deployments
- Port: 3000 (configurable)
Logging
Control verbosity with LOG_LEVEL environment variable:
debug- Verbose debugging infoinfo- Standard operation logs (default)warn- Warnings onlyerror- Errors only
---
📁 Project Structure
src/
├── index.ts # MCP server entry point
├── config.ts # Environment & configuration
├── core/
│ ├── frappe-client.ts # frappe-js-sdk wrapper
│ └── error-handler.ts # Error handling
├── tools/
│ ├── index.ts # Tool registry & routing
│ ├── document-tools.ts # CRUD operations
│ ├── method-tools.ts # RPC method calling
│ ├── file-tools.ts # File management
│ ├── auth-tools.ts # Authentication
│ ├── workflow-tools.ts # Workflow engine
│ ├── report-tools.ts # Reporting
│ ├── job-tools.ts # Background jobs
│ └── advanced-tools.ts # Advanced features
├── resources/
│ └── index.ts # Resource templates & reader
├── prompts/
│ └── index.ts # AI prompt templates
├── types/
│ ├── frappe.ts # Frappe types
│ └── index.ts
└── utils/
└── logger.ts # Structured logging
tests/
└── unit/
└── tools.test.ts # Tool tests
---
🤝 Integration
With Claude (ChatGPT-compatible)
Configure your MCP client to connect to this server. Example for Claude Desktop:
- Add to Claude's MCP config
- Point to
http://localhost:3000(SSE mode) - Provide authentication headers with each request
With Other AI Models
Any MCP-compatible client can integrate by connecting to the server's stdio or SSE transport.
---
📝 License
MIT
---
🔗 Related Projects
- frappe-js-sdk - JavaScript SDK for Frappe
- Model Context Protocol - MCP specification
- Frappe Framework - The Frappe platform
---
🔌 Integration with Claude Desktop
Remote VM Server Setup
This MCP server is designed to run on a separate VM server. To connect Claude Desktop to your remote instance:
- Deploy to VM (see Docker Deployment below)
- Configure Claude Desktop by editing your
claude_desktop_config.json:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Option 1: Using mcp-remote (with headers support)
{
"mcpServers": {
"frappe-mcp": {
"command": "npx",
"args": [
"mcp-remote",
"-u",
"http://your-vm-server.com:3000",
"-H",
"X-Frappe-Api-Key=your_api_key",
"-H",
"X-Frappe-Api-Secret=your_api_secret"
]
}
}
}
Option 2: Using @modelcontextprotocol/inspector (with headers)
{
"mcpServers": {
"frappe-mcp": {
"command": "sh",
"args": [
"-c",
"curl -N http://your-vm-server.com:3000 -H 'X-Frappe-Api-Key: your_api_key' -H 'X-Frappe-Api-Secret: your_api_secret'"
]
}
}
}
[!IMPORTANT] Replace: -
http://your-vm-server.com:3000with your actual VM server URL -your_api_keyandyour_api_secretwith your Frappe API credentials - Restart Claude Desktop after configuration changes
---
🐳 Docker Deployment
The project includes a multi-stage Dockerfile and docker-compose.yml to compile and containerize the server for VM deployment.
Build & Deploy to VM
- Build the Docker image:
docker build -t frappe-mcp-server:latest .
- Push to Docker registry (e.g., Docker Hub, private registry):
docker tag frappe-mcp-server:latest your-registry/frappe-mcp-server:latest
docker push your-registry/frappe-mcp-server:latest
- On the VM, pull and run:
docker pull your-registry/frappe-mcp-server:latest
docker run -d \
--name frappe-mcp \
-p 3000:3000 \
-e FRAPPE_URL=https://your-frappe-instance.frappe.cloud \
-e LOG_LEVEL=info \
your-registry/frappe-mcp-server:latest
[!NOTE] No credentials in environment variables: Credentials are passed per-connection via HTTP headers by the client. The server supports two header formats: - Recommended:
X-Frappe-Api-Key+X-Frappe-Api-Secretheaders - Alternative:Authorization: token API_KEY:API_SECRETheader Only theFRAPPE_URLneeds to be set as an environment variable on the VM.
Using Docker Compose on VM
# On your local machine, copy docker-compose.yml to your VM:
scp docker-compose.yml user@your-vm:/home/user/
# SSH into VM
ssh user@your-vm
# Set environment variables (only FRAPPE_URL, no credentials needed)
export FRAPPE_URL=https://your-frappe-instance.frappe.cloud
# Start the service
docker-compose up -d
The compose config will expose port 3000 and automatically handle health checks. Clients connect via HTTP headers with their credentials.
---
🔐 Authentication Flow
Environment Variables (Server-level)
FRAPPE_URL- Required: Your Frappe instance URLFRAPPE_API_KEY/FRAPPE_API_SECRET- Optional, only needed if no credentials in headersLOG_LEVEL- Optional, logging verbosity
Request Headers (Client-level, per-connection)
The client sends credentials in one of two formats:
Option 1: Recommended `` X-Frappe-Api-Key: your_api_key X-Frappe-Api-Secret: your_api_secret ``
Option 2: Standard Bearer Token `` Authorization: token your_api_key:your_api_secret ``
This enables multi-user SSE mode where each client connection has isolated authentication.











