| name | erp-integration |
| description | Integrate with enterprise resource planning systems including SAP S/4HANA, Oracle NetSuite, and Microsoft Dynamics 365. Covers procurement, supply chain, financials, and manufacturing data flows. |
| license | Apache 2.0 |
| tags | ["erp","sap","netsuite","dynamics-365","enterprise","supply-chain","procurement"] |
| difficulty | advanced |
| time_to_master | 14-24 weeks |
| version | 1.0.0 |
ERP Integration
Overview
Enterprise Resource Planning (ERP) systems are the operational backbone of large organizations, managing financials, procurement, inventory, manufacturing, and HR. SAP, Oracle NetSuite, and Microsoft Dynamics 365 collectively serve 80%+ of the enterprise market. Integrating AI agents with ERP systems unlocks intelligent procurement, demand forecasting, and real-time operational visibility.
When to Use This Skill
- Building connectors between AI agents and SAP/NetSuite/Dynamics 365
- Automating procurement workflows (purchase orders, vendor management)
- Implementing real-time inventory and supply chain visibility
- Creating financial consolidation and reporting integrations
- Designing data pipelines from ERP to data warehouses
Core Concepts
ERP Platform Comparison
| Platform | Market | API Style | Auth | Best For |
|---|
| SAP S/4HANA | Enterprise | OData v4, REST | OAuth 2.0, X.509 | Manufacturing, logistics |
| Oracle NetSuite | Mid-market | SuiteTalk (SOAP), REST | Token-Based Auth | Growing companies |
| Dynamics 365 | Mid-enterprise | OData v4, REST | Azure AD OAuth | Microsoft ecosystem |
Core ERP Modules
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Financials │ │ Procurement │ │Manufacturing│
│ (GL, AP, │ │ (PO, Vendor,│ │ (BOM, Work │
│ AR) │ │ Sourcing) │ │ Orders) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
▼ ▼ ▼
┌────────────────────────────────────────────────┐
│ Shared Data Layer │
│ (Materials, Vendors, Customers, Cost Centers) │
└────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Inventory │ │ Supply │ │ HR & │
│ Management │ │ Chain │ │ Payroll │
└─────────────┘ └─────────────┘ └─────────────┘
Integration Architecture
┌──────────┐ ┌──────────────┐ ┌───────────┐
│ AI Agent │────►│ Integration │────►│ ERP │
│ (MCP) │ │ Layer │ │ System │
└──────────┘ │ (API Gateway)│ └───────────┘
│ │
│ • Auth mgmt │
│ • Rate limit │
│ • Transform │
│ • Caching │
└──────────────┘
Implementation Guide
SAP S/4HANA OData API
const purchaseOrders = await fetch(
`${sapBaseUrl}/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder?` +
new URLSearchParams({
"$filter": `PurchaseOrderDate ge datetime'${startDate}' and PurchasingOrganization eq '1000'`,
"$select": "PurchaseOrder,PurchaseOrderDate,Supplier,PurchaseOrderNetAmount,Currency",
"$orderby": "PurchaseOrderDate desc",
"$top": "20",
}),
{
headers: {
Authorization: `Bearer ${sapToken}`,
Accept: "application/json",
},
}
);
const newPO = await fetch(
`${sapBaseUrl}/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder`,
{
method: "POST",
headers: {
Authorization: `Bearer ${sapToken}`,
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken,
},
body: JSON.stringify({
PurchaseOrderType: "NB",
Supplier: "VENDOR001",
PurchasingOrganization: ,
: ,
: ,
: [{
: ,
: ,
: ,
: ,
: ,
: ,
}],
}),
}
);
Oracle NetSuite SuiteQL
const query = `
SELECT
t.tranid AS po_number,
t.trandate,
e.companyname AS vendor,
t.foreigntotal AS amount,
t.status
FROM transaction t
JOIN entity e ON t.entity = e.id
WHERE t.type = 'PurchOrd'
AND t.trandate >= TO_DATE('2026-01-01', 'YYYY-MM-DD')
ORDER BY t.trandate DESC
FETCH FIRST 20 ROWS ONLY
`;
const results = await fetch(`${nsBaseUrl}/services/rest/query/v1/suiteql`, {
method: "POST",
headers: {
Authorization: nsAuthHeader,
"Content-Type": "application/json",
Prefer: "transient",
},
body: JSON.stringify({ q: query }),
});
ERP MCP Server Pattern
server.tool(
"get_purchase_orders",
"Query recent purchase orders with status and amounts",
{
status: z.enum(["open", "approved", "received", "closed", "all"]).default("open"),
vendor: z.string().optional(),
minAmount: z.number().optional(),
limit: z.number().default(10),
},
async ({ status, vendor, minAmount, limit }) => {
const orders = await erpClient.queryPurchaseOrders({
status, vendor, minAmount, limit,
});
const totalValue = orders.reduce((sum, po) => sum + po.amount, 0);
return {
content: [{
type: "text",
text: `${orders.length} Purchase Orders (${status}) | Total: $${totalValue.toLocaleString()}\n\n` +
orders.map(po =>
`PO-${po.number} | ${po.vendor} | $${po.amount.toLocaleString()} | | `
).(),
}],
};
}
);
server.(
,
,
{
: z.().(),
: z.().(),
: z.().(),
},
({ materialId, warehouse, belowReorderPoint }) => {
inventory = erpClient.({
materialId, warehouse, belowReorderPoint,
});
{
: [{
: ,
: inventory.(
+
).(),
}],
};
}
);
Common Integration Patterns
| Pattern | Description | Use Case |
|---|
| Real-time sync | Webhooks/events for immediate updates | Order status changes |
| Batch ETL | Scheduled bulk data extraction | Nightly financial sync |
| Request-reply | On-demand queries | AI agent asks for PO status |
| Event-driven | Publish events for downstream consumption | New PO triggers approval workflow |
Best Practices
- Never bypass ERP business logic — always use the API, not direct DB access
- Cache master data — materials, vendors, and cost centers change infrequently
- Handle SAP CSRF tokens — fetch token before each write operation
- Use batch APIs for bulk operations — individual calls are rate-limited
- Map custom fields carefully — ERP systems are heavily customized per organization
- Test in sandbox/QA — ERP changes can cascade across modules
Resources
Changelog
| Version | Date | Changes |
|---|
| 1.0.0 | 2026-03-31 | Initial documentation |