ERP Adapter
БесплатноНе проверенERP-agnostic MCP adapter with drop-in connectors for ERPNext and Dolibarr, supporting multi-tenant deployments with per-request connection credentials.
Описание
ERP-agnostic MCP adapter with drop-in connectors for ERPNext and Dolibarr, supporting multi-tenant deployments with per-request connection credentials.
README
ERP-agnostic MCP adapter layer.
Drop-in adapters for ERPNext, Dolibarr, and more — designed to be embedded
inside a multi-tenant MCP server. Every adapter takes an explicit
ErpConnection (no env vars, no globals) so the same process can serve N
tenants connected to N different ERPs.
Status — v0.1.0. Adapter contract, static tool catalog,
@casys/mcp-serverstdio/http projection, ERPNext Customer/Item/Sales Invoice/Sales Order/Quotation tools, and Dolibarr Thirdparty/Product/Invoice/Order/Proposal tools.
Usage
import {
buildAdapter,
type ErpConnection,
ErpToolsClient,
} from "@casys/mcp-erp";
const connection: ErpConnection = {
erpType: "erpnext",
apiUrl: "https://erp.example.com",
apiKey: "<frappe api_key>",
apiSecret: "<frappe api_secret>",
sandbox: false,
};
const adapter = await buildAdapter(connection);
const tools = adapter.tools(); // ErpToolDefinition[]
const result = await adapter.callTool("erpnext.customer_list", {
limit: 20,
limitStart: 0,
}, {
tenantId: "acme",
actorSubject: null,
});
await adapter.dispose();
Registering with @casys/mcp-server
ErpToolsClient is the MCP projection layer, mirroring EInvoiceToolsClient in
mcp-einvoice. Adapters stay agnostic; MCP servers register the projected tools
and handlers at the boundary.
import { McpApp } from "@casys/mcp-server";
import {
buildAdapter,
erpToolErrorMapper,
ErpToolsClient,
} from "@casys/mcp-erp";
const adapter = await buildAdapter(connection);
const toolsClient = new ErpToolsClient({
tenantId: "acme",
actorSubject: null,
});
const app = new McpApp({
name: "mcp-erp-acme",
version: "0.1.0",
validateSchema: true,
backpressureStrategy: "queue",
toolErrorMapper: erpToolErrorMapper,
});
toolsClient.registerTools(app, adapter);
await app.start(); // stdio — works on Deno AND Node (npm build)
// HTTP with port ownership (Deno AND Node — npm build uses node:http instead of Deno.serve):
// await app.startHttp({ port: 3020, hostname: "localhost" });
// HTTP embedded in an existing framework (Deno AND Node — npm build supported):
// const handler = await app.getFetchHandler();
// // handler is a Web-standard fetch function; mount it in Hono, Express, etc.
Node.js / npm — both
startHttp()andgetFetchHandler()work on Node. The npm build replacesDeno.servewith anode:httpadapter sostartHttp()binds a real TCP port. UsegetFetchHandler()when you want to mount the handler inside an existing Node HTTP framework (Hono, Express, etc.) instead.
For a local HTTP smoke test against a hosted or local ERP instance:
deno task serve -- --config ./mcp-erp.config.json --port=3020
MCP Apps viewers
createErpMcpApp() registers four bundled MCP Apps viewers under
ui://mcp-erp/*. The list, invoice, and detail viewers read provider-agnostic
display data; provider-native payloads stay beside that display contract for
callers that need them:
ui://mcp-erp/doclist-viewer
ui://mcp-erp/invoice-viewer
ui://mcp-erp/diagnostics-viewer
ui://mcp-erp/detail-viewer
erpnext.ping and dolibarr.ping point to diagnostics-viewer and return the
ERP type, API URL, tenant context, and exposed tool surface. Provider-native
list tools point to doclist-viewer. erpnext.sales_invoice_get and
dolibarr.invoice_get point to invoice-viewer. ERPNext sales orders and
quotations plus Dolibarr orders and proposals point to detail-viewer.
Detail/invoice viewers read structuredContent.data first and fall back to the
root payload for legacy callers. The normalized data object uses shared fields
such as name, status, currency, grand_total, net_total,
total_taxes_and_charges, dates, parties, and items. Native records are kept
as siblings, not interpreted by viewers:
// Dolibarr invoice detail
{
data: mappedInvoice,
invoice: nativeDolibarrInvoice,
_native: nativeDolibarrInvoice,
}
// Dolibarr order/proposal detail
{
data: mappedDocument,
order: nativeDolibarrOrder, // or proposal: nativeDolibarrProposal
_native: nativeDolibarrDocument,
}
Compatibility note: detail-style consumers should prefer content.data. The
root fallback remains for older viewer payloads, and Dolibarr invoice callers
that previously consumed the native invoice can use content.invoice or
content._native.
Current tool surface
Read-only provider-native tools shipped now:
erpnext.ping
erpnext.customer_list
erpnext.customer_get
erpnext.item_list
erpnext.item_get
erpnext.sales_invoice_list
erpnext.sales_invoice_get
erpnext.sales_order_list
erpnext.sales_order_get
erpnext.quotation_list
erpnext.quotation_get
dolibarr.ping
dolibarr.thirdparty_list
dolibarr.thirdparty_get
dolibarr.product_list
dolibarr.product_get
dolibarr.invoice_list
dolibarr.invoice_get
dolibarr.order_list
dolibarr.order_get
dolibarr.proposal_list
dolibarr.proposal_get
Public surface (v0.1.0)
// Connection
type ErpConnection
type ErpType
const ERP_TYPES
function isKnownErpType(value: string): value is ErpType
// Adapter contract
interface ErpAdapter
type ErpAdapterFactory
interface ErpToolDefinition
interface ErpToolCallContext
interface ErpToolCallResult
interface ErpToolAnnotations
interface ErpToolMeta
class UnknownToolError
// MCP projection, registry & factories
class ErpToolsClient
function erpToolErrorMapper(error, toolName): string | null
async function buildAdapter(connection: ErpConnection): Promise<ErpAdapter>
const REGISTERED_ERP_TYPES
function getErpToolDefinitions(erpType): ErpToolDefinition[]
function registerErpViewers(app): { registered: string[]; skipped: string[] }
function createErpnextAdapter(connection): ErpAdapter
function createDolibarrAdapter(connection): ErpAdapter
const ERP_VIEWERS
const ERP_DOCLIST_META
const ERP_INVOICE_META
const ERP_DIAGNOSTICS_META
const ERP_DETAIL_META
class FrappeApiError
class DolibarrApiError
Why this exists
This package is the OSS adapter layer. Authentication, multi-tenancy, audit, DCR
proxy and dashboard live in the proprietary erp-platform SaaS that
consumes this package. Splitting them keeps each side honest:
- This package : agnostic protocol/adapters. No tenant model, no Zitadel, no
DB. Receives
ErpConnectionper call. erp-platform: multi-tenant Fresh+Prisma+Zitadel platform that resolves a tenant → credentials →ErpConnectionand dispatches MCP calls through this adapter layer.
Design choices
- One package, not two. mcp-einvoice splits into
core+mcp; we keep things in a single package until we have ≥2 consumers that would benefit from the split. - Explicit
ErpConnection, not env-based. Per-tenant safety in a single Deno process. - Decoupled from
@casys/mcp-serverSDK shape. Adapters returnErpToolDefinition(JSON Schema + name + description). Consumers project this into the SDK format at boundary time. Same pattern asEInvoiceToolsClientin mcp-einvoice. - Scope ruthless. v0.1 focuses on ERPNext and Dolibarr read-only tools
first. Lifecycle mutations and normalized tools wait until the native API
mapping is proven on both adapters. No
Odoo, noSAP, until that foundation is boring.
Roadmap
See ROADMAP.md for the alpha-to-beta product roadmap.
Related projects
- mcp-einvoice — sibling OSS package, same pattern, e-invoicing domain.
- mcp-erpnext — mono-cible ERPNext MCP server (env-based singleton). Different scope: useful pattern reference, but not a runtime dependency of this package.
erp-platform(private) — the SaaS that consumes this package.
License
MIT — see LICENSE.
Установка ERP Adapter
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/casys-ai/mcp-erpFAQ
ERP Adapter MCP бесплатный?
Да, ERP Adapter MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для ERP Adapter?
Нет, ERP Adapter работает без API-ключей и переменных окружения.
ERP Adapter — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить ERP Adapter в Claude Desktop, Claude Code или Cursor?
Открой ERP Adapter на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare ERP Adapter with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
