Frappe Js Mcp Server — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Frappe Js Mcp Server (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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.
This MCP server bridges AI models and Frappe, allowing you to:
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 |
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=infoThe server exposes 50+ tools organized in 8 phases. Here's a quick reference:
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 docscall_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 metricsupload_file - Upload (base64 or URL)list_attachments - View document attachmentsdownload_file - Download as base64delete_file - Remove file recordsattach_file_to_document - Link files to docslogin_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 credentialsget_workflow_state - Current stateget_workflow_actions - Allowed transitionsworkflow_transition - Apply actionget_workflow_history - Audit trailrun_query_report - Execute reportsget_report_columns - Report schemaexport_report - Export as CSVget_dashboard_chart - Chart dataget_number_card - Card metricslist_jobs - Job queue entriesget_job_status - Check job statusenqueue_job - Force executionsubscribe_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 recordsMCP 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.
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 |
# 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 detailsRun the server in development mode with auto-reloading:
npm run devThe server starts on the configured transport (default: SSE on port 3000).
Compile TypeScript to JavaScript for production:
npm run buildOutput: dist/index.js
Run the compiled production build:
npm run startRun automated tests using Vitest:
npm run testTests verify:
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.jsThen open the URL (typically http://localhost:5173) in your browser to:
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 -dThe server runs on http://localhost:3000 with health checks enabled.
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:latestThe server supports multi-user SSE (Server-Sent Events) mode. Each client can:
AsyncLocalStorageThe server supports two MCP transports:
Control verbosity with LOG_LEVEL environment variable:
debug - Verbose debugging infoinfo - Standard operation logs (default)warn - Warnings onlyerror - Errors onlysrc/
├── 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 testsConfigure your MCP client to connect to this server. Example for Claude Desktop:
http://localhost:3000 (SSE mode)Any MCP-compatible client can integrate by connecting to the server's stdio or SSE transport.
MIT
This MCP server is designed to run on a separate VM server. To connect Claude Desktop to your remote instance:
claude_desktop_config.json:%APPDATA%\Claude\claude_desktop_config.json~/Library/Application Support/Claude/claude_desktop_config.json~/.config/Claude/claude_desktop_config.jsonOption 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
The project includes a multi-stage Dockerfile and docker-compose.yml to compile and containerize the server for VM deployment.
docker build -t frappe-mcp-server:latest .docker tag frappe-mcp-server:latest your-registry/frappe-mcp-server:latest
docker push your-registry/frappe-mcp-server:latestdocker 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 the FRAPPE_URL needs to be set as an environment variable on the 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 -dThe compose config will expose port 3000 and automatically handle health checks. Clients connect via HTTP headers with their credentials.
FRAPPE_URL - Required: Your Frappe instance URLFRAPPE_API_KEY / FRAPPE_API_SECRET - Optional, only needed if no credentials in headersLOG_LEVEL - Optional, logging verbosityThe client sends credentials in one of two formats:
Option 1: Recommended
X-Frappe-Api-Key: your_api_key
X-Frappe-Api-Secret: your_api_secretOption 2: Standard Bearer Token
Authorization: token your_api_key:your_api_secretThis enables multi-user SSE mode where each client connection has isolated authentication.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.