ERPNext MCP Server
ERPNext MCP Server
Framework-level MCP Server for Frappe/ERPNext — works like Doppio CLI, not site-specific.
Built by AWS Solution Ltd. | Contact: moocoding@gmail.com
Overview
Unlike typical Frappe apps that install per-site, this MCP server runs at the bench framework level:
One server instance serves all sites on the bench
Site context switches dynamically via tool calls
No installation to each site needed
┌─────────────────────────────────────────────────────┐
│ MCP Client (Claude, Hermes, etc.) │
│ (running on another machine) │
└────────────────────┬────────────────────────────────┘
│ stdio
┌────────────────────▼────────────────────────────────┐
│ ERPNext MCP Server │
│ (this bench) │
│ │
│ • list_sites → all bench sites │
│ • switch_site → change context │
│ • get_document → query current site │
│ • execute_sql → safe SELECT queries │
│ • bench_command → read-only bench operations │
│ • ... + 15 more tools │
└─────────────────────────────────────────────────────┘Prerequisites
Frappe/ERPNext v15+ installed on a bench
Python 3.10+ (uses bench's virtual environment)
MCP client (Claude Code, Hermes Agent, etc.)
Quick Start
1. Verify Python Environment
cd ~/frappe-bench
./env/bin/python --version # Should be Python 3.10+2. Test Locally
# Set your default site
export FRAPPE_SITE=your-site.domain.com
export BENCH_PATH=/path/to/your/frappe-bench
# Run the server
./env/bin/python -m erpnext_mcp_server.mcp.server3. Configure MCP Client
For Claude Code
Add to .mcp.json in your project:
{
"mcpServers": {
"erpnext": {
"command": "python",
"args": ["-m", "erpnext_mcp_server.mcp.server"],
"env": {
"FRAPPE_SITE": "your-site.domain.com",
"BENCH_PATH": "/home/youruser/frappe-bench"
}
}
}
}For Hermes Agent
In your Hermes configuration:
mcp_servers:
erpnext:
command: ssh
args:
- user@your-server
- 'cd /path/to/bench && FRAPPE_SITE=your-site.com ./env/bin/python -m erpnext_mcp_server.mcp.server'For Other MCP Clients
The server uses STDIO transport (stdin/stdout). Any MCP client that supports stdio will work:
{
"mcpServers": {
"erpnext": {
"command": "/path/to/frappe-bench/env/bin/python",
"args": ["-m", "erpnext_mcp_server.mcp.server"],
"env": {
"FRAPPE_SITE": "your-site.domain.com",
"BENCH_PATH": "/path/to/frappe-bench"
}
}
}
}Available Tools
Site Management
Tool | Arguments | Description |
| — | List all sites on this bench |
|
| Switch to a different site |
| — | Get current site name |
Document CRUD
Tool | Arguments | Description |
|
| Get document by ID |
|
| List documents with filters |
|
| Create new document |
|
| Update existing document |
|
| Delete/cancel document |
|
| Count matching documents |
Metadata
Tool | Arguments | Description |
|
| List all DocTypes |
|
| Get field definitions |
Database
Tool | Arguments | Description |
|
| Execute SELECT query (safe) |
|
| Get table structure |
System Info
Tool | Arguments | Description |
| — | System and DB info |
| — | Installed app versions |
|
| Run read-only bench commands |
Workflow
Tool | Arguments | Description |
|
| Submit (docstatus 0→1) |
|
| Cancel submitted doc |
Search
Tool | Arguments | Description |
|
| Search across DocTypes |
Files
Tool | Arguments | Description |
|
| Read file (safe paths only) |
|
| List directory |
Usage Examples
Python Client Test
import subprocess
import json
proc = subprocess.Popen(
["./env/bin/python", "-m", "erpnext_mcp_server.mcp.server"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
cwd="/path/to/frappe-bench",
env={"FRAPPE_SITE": "your-site.domain.com"}
)
# Initialize
init_msg = {
"jsonrpc": "2.0", "id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "test", "version": "1.0"}
}
}
proc.stdin.write((json.dumps(init_msg) + "\n").encode())
proc.stdin.flush()
# List sites
list_msg = {
"jsonrpc": "2.0", "id": 2,
"method": "tools/call",
"params": {"name": "list_sites", "arguments": {}}
}
proc.stdin.write((json.dumps(list_msg) + "\n").encode())
proc.stdin.flush()
proc.stdin.close()
print(proc.stdout.read().decode())Claude Code Usage
Once configured, simply ask Claude:
> List all customers in ERPNext
> Create a new Sales Order for customer ABC
> What is the total outstanding for Invoice INV-001?Claude will use the MCP tools to query ERPNext directly.
Architecture
erpnext_mcp_server/
├── __init__.py
├── hooks.py
├── mcp/
│ ├── __init__.py
│ ├── __main__.py # Entry point
│ ├── server.py # Main MCP server
│ └── config.py # Configuration
└── doctype/ # Settings DocTypes (optional)Design Principles
Framework Level — Runs at bench level, not per-site
Lazy Loading — Frappe imported only when needed
Site Context — Switches context dynamically per tool call
Security First — SQL limited to SELECT, files restricted to safe paths
Security
Restriction | Details |
SQL | Only SELECT queries allowed |
Files | Only |
Bench commands | Read-only operations only |
Site access | Enforced via Frappe permissions |
Environment Variables
Variable | Required | Default | Description |
| Yes | — | Default site name |
| No |
| Bench directory |
| No |
| Disable file logging |
Troubleshooting
"site does not exist" error
# Verify site exists
ls ~/frappe-bench/sites/ | grep your-site
# Check site config
cat ~/frappe-bench/sites/your-site.domain.com/site_config.jsonConnection refused
The server uses stdio transport, not HTTP. Ensure your MCP client is connecting via stdin/stdout pipes.
Permission denied
Ensure the user running the server has:
Read access to bench directory
Database access for the site
Permission to execute bench commands
License
Proprietary - AWS Solution Ltd.
Support
Email: moocoding@gmail.com
Issues: Open an issue in the repository
Built with Frappe Framework | MCP Protocol | STDIO Transport
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ManotLuijiu/erpnext_mcp_server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server