CrewAI agents processing complex SAP ECC data structures with Node.js `node-rfc`
CrewAI Agents Processing Complex SAP ECC Data Structures with Node.js node-rfc
Section titled “CrewAI Agents Processing Complex SAP ECC Data Structures with Node.js node-rfc”Slug: crewai-sap-ecc-complex-data-node-js
The Integration Challenge
Section titled “The Integration Challenge”Modern AI agents like CrewAI operate primarily in Python. However, many enterprise SAP integrations are built on the robust, asynchronous Node.js ecosystem using SAP’s official node-rfc library. node-rfc is particularly adept at handling high-concurrency scenarios and complex, nested BAPI structures that can sometimes be cumbersome in other languages.
This guide provides a “Polyglot” architectural pattern: a Python-based FastMCP server that acts as a bridge, orchestrating a high-performance Node.js worker to handle the heavy lifting of SAP data processing.
Why this Architecture?
Section titled “Why this Architecture?”- CrewAI Compatibility: CrewAI tools work natively with Python.
- Legacy Reuse: Leverage existing Node.js SAP scripts without rewriting them.
- Handling Complexity:
node-rfcoffers excellent handling of deep SAP tables and structures (e.g., deeply nestedBAPI_SALESORDER_CREATEFROMDAT2payloads).
1. The Node.js Worker (sap_client.js)
Section titled “1. The Node.js Worker (sap_client.js)”This script connects to SAP ECC, executes a BAPI that requires complex table inputs, and returns the result as JSON. It runs as a standalone process invoked by the Python server.
Features:
- Uses
node-rfcfor direct NWRFC connectivity. - Handles nested structures (like
ORDER_ITEMS_INandORDER_PARTNERS). - Outputs strictly formatted JSON for the Python parent to consume.
const nwrfc = require('node-rfc');
// Load environment variables for SAP connectionconst client = new nwrfc.Client({ ashost: process.env.SAP_HOST, sysnr: process.env.SAP_SYSNR, client: process.env.SAP_CLIENT, user: process.env.SAP_USER, passwd: process.env.SAP_PASSWORD, lang: 'EN'});
async function runSAPTransaction() { try { await client.open();
// Example: Reading complex BOM (Bill of Materials) structure // Or creating a Sales Order with nested tables. // Here we simulate a BAPI that requires a table input.
// Input: A complex structure simulating a Sales Order creation payload // In a real agent scenario, these would be passed via command line args const inputData = { ORDER_HEADER_IN: { DOC_TYPE: 'TA', SALES_ORG: '1000', DISTR_CHAN: '10', DIVISION: '00' }, ORDER_ITEMS_IN: [ { ITM_NUMBER: '000010', MATERIAL: 'MAT-2025-X', TARGET_QTY: '10' }, { ITM_NUMBER: '000020', MATERIAL: 'MAT-2025-Y', TARGET_QTY: '5' } ], ORDER_PARTNERS: [ { PARTN_ROLE: 'AG', PARTN_NUMB: '000001000' } ] };
// Invoke the BAPI (Example: BAPI_SALESORDER_SIMULATE) // We use SIMULATE here to be safe, but CREATE follows the same pattern. const result = await client.call('BAPI_SALESORDER_SIMULATE', { ORDER_HEADER_IN: inputData.ORDER_HEADER_IN, ORDER_ITEMS_IN: inputData.ORDER_ITEMS_IN, ORDER_PARTNERS: inputData.ORDER_PARTNERS });
// Transform result for the Agent // Agents prefer clean JSON without SAP-specific metadata overhead const output = { status: 'success', order_value: result.NET_VALUE_EX || '0.00', return_messages: result.RETURN.map(r => ({ type: r.TYPE, message: r.MESSAGE, code: r.NUMBER })) };
console.log(JSON.stringify(output));
} catch (err) { console.error(JSON.stringify({ status: 'error', message: err.message, code: err.code || 'UNKNOWN' })); process.exit(1); } finally { if (client.isOpen) { await client.close(); } }}
runSAPTransaction();2. The Python MCP Server (server.py)
Section titled “2. The Python MCP Server (server.py)”This Python server adheres to the FastMCP specification. It exposes a tool process_complex_sap_order to the AI Agent. When called, it executes the Node.js script using subprocess.
import jsonimport subprocessimport osfrom fastmcp import FastMCP
# Initialize FastMCP servermcp = FastMCP("sap-ecc-node-bridge")
@mcp.tool()def process_complex_sap_order(customer_id: str, materials: list[str]) -> str: """ Processes a complex SAP order simulation via a Node.js worker using node-rfc.
Args: customer_id: The SAP Customer Number (e.g., '000001000') materials: A list of material IDs to include in the order. """
# Path to the Node.js worker script node_script = "./sap_client.js"
# In a production scenario, we might pass arguments via CLI flags or stdin. # For this demo, the Node script has hardcoded logic or uses env vars, # but we will simulate passing context by setting environment variables # for this specific subprocess call.
env = os.environ.copy() env["SAP_TARGET_CUSTOMER"] = customer_id env["SAP_TARGET_MATERIALS"] = ",".join(materials)
try: # Execute the Node.js script # Ensure your container has network access (e.g. via NordLayer) to reach the SAP Host result = subprocess.run( ["node", node_script], capture_output=True, text=True, env=env, check=True )
# Parse the JSON output from Node.js try: data = json.loads(result.stdout) return json.dumps(data, indent=2) except json.JSONDecodeError: return f"Error decoding Node.js output: {result.stdout}"
except subprocess.CalledProcessError as e: # Capture stderr from Node.js if it failed return f"Node.js Worker Failed: {e.stderr}" except Exception as e: return f"System Error: {str(e)}"
if __name__ == "__main__": mcp.run()3. The Dockerfile
Section titled “3. The Dockerfile”This is a multi-stage or hybrid build. We need a base image that supports Python (for FastMCP) but also allows the installation of Node.js and the SAP NWRFC SDK.
Critical Note: You cannot simply npm install node-rfc. You must download the SAP NWRFC SDK (Linux x64) from the SAP Marketplace and place the nwrfcsdk folder in your project root before building. This is due to SAP licensing restrictions.
# Use a Python base imageFROM python:3.11-slim
# Install system dependencies including those required for Node.js and SAP SDKRUN apt-get update && apt-get install -y \ curl \ gnupg \ libaio1 \ unzip \ && rm -rf /var/lib/apt/lists/*
# Install Node.js 18.xRUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ && apt-get install -y nodejs
# Setup Application DirectoryWORKDIR /app
# --- SAP NWRFC SDK SETUP ---# CRITICAL: You must provide the 'nwrfcsdk' folder in your build context.# Download from SAP Marketplace: SAP NW RFC SDK 7.50 for Linux on x86_64COPY nwrfcsdk /usr/local/sap/nwrfcsdk
# Configure SAP Environment VariablesENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdkENV LD_LIBRARY_PATH=$SAPNWRFC_HOME/lib# ---------------------------
# Copy Node.js dependenciesCOPY package.json ./# Install node-rfc (will compile against the SDK copied above)RUN npm install
# Copy Python dependencies# We install 'fastmcp'RUN pip install fastmcp
# Copy application codeCOPY sap_client.js .COPY server.py .
# EXPOSE the standard MCP port for Railway/Cloud deploymentEXPOSE 8000
# Ensure your container has network access (e.g. via NordLayer)# Run the Python MCP serverCMD ["python", "server.py"]package.json
Section titled “package.json”Include this file in your root so the Dockerfile can npm install:
{ "name": "sap-node-bridge", "version": "1.0.0", "dependencies": { "node-rfc": "^3.0.0" }}How it Works
Section titled “How it Works”- Agent Request: The CrewAI agent (running elsewhere or locally) connects to this MCP server and asks to
process_complex_sap_order. - Bridge:
server.pyreceives the request. It formats the data into environment variables or a JSON payload. - Execution:
server.pyspawns anodeprocess runningsap_client.js. - SAP Logic: The Node.js script uses the
node-rfcC++ bindings to perform a high-performance RFC call to the SAP ECC system, passing complex nested tables (ORDER_ITEMS_IN). - Response: The Node script prints the result to
stdout, which the Python server captures and returns to the Agent.
This approach allows you to “Retrofit” modern AI capabilities onto battle-tested Node.js integration scripts without a complete rewrite.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.