ERP MCP Server
The server's read-only tool contract is designed to plug into Odoo as the ERP data source, letting Claude answer questions about customers, stock, orders, invoices and payments by porting the pre-written queries to Odoo's PostgreSQL schema while keeping the tool names, parameters and JSON output unchanged.
Provides a documented path to run against a PostgreSQL-based ERP: swapping the SQLite demo connection for a PostgreSQL driver (read-only reporting replica or read-only views) and rewriting the fixed parameterized queries, so the stock, order status, customer balance, overdue orders and KPI tools work against live business data.
Recognized as an accounting-platform target with a REST API: the same read-only tools and Claude Skills (weekly sales summary, payment reminder drafts) can be repointed at QuickBooks Online data for revenue, receivables and customer balance questions.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ERP MCP Server Which products are below reorder level?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ERP MCP Agent
Ask your ERP questions in plain English, safely. This project connects Claude to business data (customers, stock, orders, invoices, payments) through a read-only MCP server. Staff can ask "Which products are below reorder level?" or "Is Oakhurst over its credit limit?" in Claude Desktop and get answers from live data. Two Claude Skills turn recurring office work (a weekly sales summary, customer payment reminders) into one-sentence requests.
The demo runs on a realistic, fully synthetic ERP database. The same pattern plugs into SQL Server, PostgreSQL or an existing ERP such as Netsis, Logo or Odoo (see Adapting it to your ERP).
π¬ Demo video: 2-minute walkthrough β link coming soon
flowchart LR
U([Employee]) --> CD[Claude Desktop<br/>+ Skills]
CD <-->|MCP| S[ERP MCP server<br/>5 read-only tools]
S -->|parameterized SELECT| D[(ERP database)]
S -->|every call| L[[Audit log]]What it can do
Tool | Answers questions like | Parameters |
| "Which products are below reorder level?" "How many 18V drills do we have?" |
|
| "What's the status of order SO-1537?" |
|
| "What is Foxglove's open balance? Are they over their credit limit?" |
|
| "Which orders are late?" "Any delayed orders for Stonegate?" |
|
| "How did revenue this quarter compare to last quarter?" "Top 5 customers in September?" |
|
get_kpi metrics: revenue, top_products, top_customers, avg_order_value, overdue_receivables.
Skill | Ask | Produces |
| "Prepare this week's sales summary." | One-page manager report: revenue vs last week, top 5 products, stock at risk, late orders, overdue receivables, 3 action items |
| "Draft a payment reminder for Foxglove." | A polite email draft (never sent) plus internal review notes |
Sample outputs: docs/sample-outputs.md
Related MCP server: legacy-db-mcp
Quick start (about 5 minutes)
Requirements: Python 3.11+, Claude Desktop, Git.
1. Install
Windows (PowerShell)
git clone https://github.com/burakOzden1/erp-mcp-agent.git
cd erp-mcp-agent
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
.\.venv\Scripts\python.exe scripts\seed_db.pymacOS / Linux
git clone https://github.com/burakOzden1/erp-mcp-agent.git
cd erp-mcp-agent
python3 -m venv .venv
.venv/bin/python -m pip install -e ".[dev]"
.venv/bin/python scripts/seed_db.pyseed_db.py creates data/erp_demo.db and prints the row counts and the planted
demo situations (9 products below reorder level, 12 late orders, 6 customers with
partially paid overdue invoices, 2 customers over their credit limit).
2. Connect Claude Desktop
Open Claude Desktop β Settings β Developer β Edit Config and add the server
under mcpServers (keep any servers you already have):
Windows
{
"mcpServers": {
"erp-demo": {
"command": "C:\\path\\to\\erp-mcp-agent\\.venv\\Scripts\\erp-mcp.exe"
}
}
}macOS
{
"mcpServers": {
"erp-demo": {
"command": "/path/to/erp-mcp-agent/.venv/bin/erp-mcp"
}
}
}Fully quit Claude Desktop (tray / menu bar β Quit) and reopen it. The five
erp-demo tools appear under the tools icon in a new chat.
3. Add the Skills (optional)
python scripts/package_skills.pyThis writes dist/skills/weekly-sales-summary.zip and dist/skills/customer-email-draft.zip.
In Claude Desktop, go to Settings β Capabilities, make sure code execution is on,
and upload both zips under Skills.
Example questions and answers
With the default dataset (data as of 2026-10-31):
Question | Expected answer (abridged) |
Which products are below reorder level? | 9 products. Most critical: SE-0012 Safety Glasses Economy (0 in stock, reorder level 75) and PT-0004 Cordless Drill 18V (1 in stock, reorder level 10). |
What's the status of order SO-1537? | Shipped 2026-10-19, 16 days late (promised 2026-10-15). 6 lines, $4,550.02. Invoice INV-10526 is unpaid, due 2026-12-03. |
Show me customers with overdue invoices. | $26,599.80 overdue across 6 customers. Largest: Larkspur Building Services $5,910.94; Starling Industrial Supply has the oldest invoice (87 days). |
Is Oakhurst over its credit limit? | Yes. Open balance $8,374.96 vs a $5,000 limit; $5,877.08 is overdue. |
How did revenue this quarter compare to last quarter? | Q4 so far (October) $100,451.98 vs Q3 $310,513.09. The quarter is only one month old, so like-for-like (October vs July) is β23.8%. |
Prepare this week's sales summary. | See sample output. |
Draft a payment reminder email for Foxglove. | See sample output. |
Typos are handled: asking about "Oakhust" returns "Did you mean: Oakhurst Facilities Group (C-0007)?"
Security approach
Giving an AI model access to business data needs to be boring and predictable. This server is designed so that the worst a confused prompt can do is read a limited amount of data, and every read is recorded.
Read-only by construction. The database is opened with SQLite's
mode=roandPRAGMA query_only = ON. Tools carry MCPreadOnlyHint/destructiveHint=falseannotations. Tests confirm thatINSERT,UPDATE,DELETEandDROPfail.No free-form SQL. Claude cannot send SQL. Each tool runs one pre-written query with bound parameters; the KPI tool accepts only a fixed list of metrics.
Bounded results. List tools return at most 50 rows and say when more exist.
Audit trail. Every tool call (successful or not) is appended to
logs/audit.jsonl:{"ts": "2026-10-28T18:26:45.327+00:00", "tool": "get_stock", "params": {"query": "", "category": null, "below_reorder_only": true}, "row_count": 9, "duration_ms": 2.29, "status": "ok"}Human in the loop. The email Skill only drafts; a person reviews and sends.
Local by default. The server runs on your machine over stdio. No ports are opened, and the demo needs no credentials.
More detail: docs/architecture.md.
Adapting it to your ERP
The tool contract (names, parameters, JSON shape), audit log and Skills are
independent of the database. Moving to a real system touches two files:
db.py (connection) and queries.py (SQL).
Pick the access path. Connect to a reporting replica or read-only views rather than the production schema. Create a dedicated database user with
SELECTpermission on those views only.Map the concepts. Every ERP has the same six building blocks: customer accounts, items/stock, sales orders and lines, invoices, and payments. Document which tables or views hold each, plus the status codes for open/shipped/delivered/cancelled.
Swap the connection. Replace
sqlite3withpyodbc(SQL Server),psycopg(PostgreSQL) or the ERP's API/ODBC driver. Keep the read-only guarantees at the database-user level.Port the queries. Rewrite the SQL in
queries.pyfor the new schema and keep the returned JSON fields the same, so Claude and the Skills need no changes.Add business rules. Multi-currency, branches or warehouses, VAT, credit control rules: add them as tool parameters or new fixed metrics, never as free SQL.
Harden for production. Add authentication if the server is exposed over HTTP, ship the audit log to your log platform, and apply row-level filters per user or role.
Typical targets: Microsoft SQL Server based ERPs (e.g. Netsis, Logo), PostgreSQL based systems (e.g. Odoo), or accounting platforms with REST APIs (e.g. QuickBooks Online).
Project structure
erp-mcp-agent/
βββ src/erp_mcp/
β βββ server.py # MCP server and the 5 tool definitions
β βββ queries.py # parameterized SQL and KPI logic
β βββ db.py # read-only connection
β βββ audit.py # JSON Lines audit log
βββ skills/
β βββ weekly-sales-summary/SKILL.md
β βββ customer-email-draft/SKILL.md
βββ scripts/
β βββ seed_db.py # builds the synthetic ERP database
β βββ package_skills.py
βββ tests/ # pytest: queries, MCP protocol, audit, skills, data integrity
βββ docs/ # architecture, demo script, sample outputsDevelopment
python -m pytest # 52 tests, about 2 seconds
python scripts/seed_db.py --as-of today # re-anchor the demo data to today's dateConfiguration via environment variables: ERP_DB_PATH (database file) and
ERP_AUDIT_LOG (log file).
Windows: quit Claude Desktop before re-running
pip install. While Claude Desktop runs the server, Windows locks.venv\Scripts\erp-mcp.exeand the reinstall fails halfway.
Built with the official MCP Python SDK (mcp 2.3).
License
MIT
Available Tools
5 toolsget_customer_balanceCustomer balanceARead-onlyIdempotent
Get a customer's account balance (accounts receivable).
Use for "What is Oakhurst's open balance?", "Is C-0034 over its credit limit?" or before drafting a payment reminder. Returns contact details, credit limit, invoiced, paid, open and overdue amounts, each overdue invoice with days overdue, and counts of open/overdue orders.
Inputs: customer (required). Returns: object
get_kpiBusiness KPIsARead-onlyIdempotent
Calculate a business KPI for a date range from a fixed list of metrics.
Use for "How did revenue this quarter compare to last quarter?", "Top 5 products last month", "Average order value in 2026" or "How much is overdue?". Example: metric='revenue', period_start='2026-10-01', period_end='2026-12-31', compare_previous=true. Partial periods include a like-for-like comparison.
Inputs: metric (required), period_end (required), period_start (required), limit, +1 more. Returns: object
get_order_statusOrder statusARead-onlyIdempotent
Get the full status of one sales order.
Use for "What's the status of order SO-1042?" or "Has SO-1509 been invoiced or paid?". Returns header (customer, dates, status, lateness), order lines, and the invoice with payments and outstanding amount.
Inputs: order_no (required). Returns: object
get_stockStock lookupARead-onlyIdempotent
Look up product stock levels.
Use for questions like "How many cordless drills do we have?", "Which products are below reorder level?" or "Show stock for Safety Equipment". Returns stock quantity, reorder level, shortfall and units sold in the last 90 days. Results are sorted with the most critical stock first (max 50 rows).
Inputs: query, category, below_reorder_only. Returns: object
list_overdue_ordersOverdue ordersARead-onlyIdempotent
List sales orders that are late: promised date passed but not yet delivered.
Use for "Which orders are late?", "Show orders more than 14 days late" or "Does Foxglove have any delayed orders?". Sorted by days late, max 50 rows, with total value of the late orders.
Inputs: customer, min_days_late. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogβ¦
TDQS
Scored across 5 tools
Each tool targets a distinct ERP query area: order status, customer balance, overdue orders, stock, and KPIs. There is some possible overlap between get_order_status, list_overdue_orders, and get_kpi for overdue-related questions, but the descriptions clarify different scopes and outputs.
All names use consistent snake_case verb_noun structure: get_order_status, get_customer_balance, list_overdue_orders, get_stock, get_kpi. The use of get_ vs list_ is predictable and semantically appropriate.
Five tools is well-scoped for an ERP reporting/query server, with each tool covering a clear analytical need. There are no redundant tools and the surface feels appropriately focused rather than padded.
The surface covers key read-only ERP workflows: order status, receivables, overdue orders, stock, and KPI reporting. Minor gaps exist around broader lookup operations such as listing customers/products or searching orders, but core agent queries are covered.
Maintenance
Related MCP Connectors
Read and write Sage Intacct from Claude or ChatGPT. Write tools are flagged for approval.
Securely query and analyze business data, dashboards, projections, alerts, and knowledge.
Read and write NetSuite and run SuiteQL from Claude or ChatGPT. Write tools flagged for approval.
Claude, connected to your own Oracle EPM. Each person as themselves, every call checked and logged.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceProvides structured, read-mostly access to small-business back-office data including customers, invoices, and account notes, allowing Claude to query overdue invoices, revenue summaries, and more.MIT
- AlicenseAqualityCmaintenanceLets an LLM explore a cryptic legacy ERP schema in plain language through a semantic layer (table listing, column descriptions, published dictionary) and run single read-only SELECT queries that return capped results. Enforces safety at the database engine level: only reads are authorized, sensitive columns are masked to NULL, queries are aborted after a few seconds, and every call is written to an append-only audit log.3MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to explore and report on Oracle-based ERP databases via read-only schema discovery, guarded ad-hoc SQL, and curated reports.5MIT
- AlicenseAqualityCmaintenanceEnables Claude to answer questions about a small business's own data by providing predefined sales, customer, refund, and inventory tools, plus a guarded read-only SQL query tool with audit logging.6MIT