Skip to content

Integrating CrewAI with SAP ECC using Node.js and `node-rfc`

Integrating CrewAI with SAP ECC using Node.js and node-rfc

Section titled “Integrating CrewAI with SAP ECC using Node.js and node-rfc”

Slug: integrate-crewai-sap-ecc-node-js

The Polyglot Bridge: Running Node.js SAP Connectors in a Python Agent World

Section titled “The Polyglot Bridge: Running Node.js SAP Connectors in a Python Agent World”

While CrewAI and the FastMCP framework are native to Python, the enterprise world often relies on Node.js for high-throughput I/O. Specifically, the node-rfc library is a battle-tested, official SAP connector that many DevOps teams prefer over its Python counterpart (pyrfc) for its non-blocking event loop and stability in certain legacy environments.

This guide provides a robust architectural blueprint for the “Polyglot Bridge” pattern: A Python FastMCP server that orchestrates existing Node.js SAP scripts.

This approach allows you to:

  1. Keep your AI Agents in Python (CrewAI).
  2. Leverage the specialized node-rfc library for the actual “Big Iron” connection.
  3. Run everything in a single, cohesive Docker container.

The AI Agent (CrewAI) talks to the FastMCP Server (Python). When the agent needs SAP data, the server spawns a lightweight Node.js subprocess to execute the RFC call via node-rfc. The result is piped back to the agent as JSON.

graph LR
A[CrewAI Agent] -- MCP Protocol --> B[FastMCP Server (Python)]
B -- JSON/StdIO --> C[Node.js Script]
C -- node-rfc --> D[SAP ECC (RFC Protocol)]

  1. SAP NetWeaver RFC SDK (7.50+): You must download this from the SAP Marketplace (requires S-User).
    • Linux x86_64 version (nwrfc750P_*-linux.zip).
    • Extract it to a folder named nwrfcsdk in your project root.
  2. Node.js & Python: Installed in your environment (handled via Docker below).
  3. Network Access: Ensure your container has a line of sight to the SAP application server (port 3300 typically).

This script acts as the “worker.” It reads input parameters from stdin, executes the SAP function module (RFC), and writes the result to stdout.

sap_client.js
// A stateless wrapper around node-rfc for MCP integration
const noderfc = require('node-rfc');
// Read input from stdin (passed by Python)
let inputData = '';
process.stdin.on('data', (chunk) => {
inputData += chunk;
});
process.stdin.on('end', async () => {
try {
const request = JSON.parse(inputData);
// 1. Configure the SAP Client
const client = new noderfc.Client({
user: request.credentials.user,
passwd: request.credentials.passwd,
ashost: request.credentials.host,
sysnr: request.credentials.sysnr,
client: request.credentials.client,
lang: 'EN'
});
// 2. Connect
await client.open();
// 3. Invoke the BAPI / RFC
// Example: BAPI_USER_GET_DETAIL or generic RFC_READ_TABLE
const result = await client.call(request.functionName, request.parameters);
// 4. Close and output JSON
await client.close();
console.log(JSON.stringify({ status: 'success', data: result }));
} catch (err) {
// Output structured error for the Python host to catch
console.error(JSON.stringify({ status: 'error', message: err.message, code: err.code }));
process.exit(1);
}
});

This Python server exposes the tool to CrewAI. It manages the subprocess call to Node.js, handling the data marshalling between the two runtimes.

server.py
import os
import json
import subprocess
import sys
from fastmcp import FastMCP
# Initialize FastMCP
mcp = FastMCP("SAP-Node-Bridge")
# Configuration for SAP (Load from env vars for security)
SAP_CONFIG = {
"user": os.getenv("SAP_USER"),
"passwd": os.getenv("SAP_PASSWORD"),
"host": os.getenv("SAP_HOST"),
"sysnr": os.getenv("SAP_SYSNR", "00"),
"client": os.getenv("SAP_CLIENT", "100"),
}
@mcp.tool()
def execute_sap_rfc(function_name: str, parameters: str) -> str:
"""
Executes an SAP Remote Function Call (RFC) using the node-rfc library.
Args:
function_name: The name of the SAP BAPI/RFC (e.g., 'STFC_CONNECTION', 'BAPI_USER_GET_DETAIL').
parameters: A JSON string representing the input parameters for the RFC.
"""
try:
# Validate JSON input
param_dict = json.loads(parameters)
except json.JSONDecodeError:
return "Error: Parameters must be a valid JSON string."
# Prepare payload for the Node.js worker
payload = {
"credentials": SAP_CONFIG,
"functionName": function_name,
"parameters": param_dict
}
# Path to the Node.js worker
node_script = os.path.join(os.getcwd(), "sap_client.js")
try:
# Call Node.js process
# We use subprocess to isolate the Node runtime and memory
process = subprocess.Popen(
["node", node_script],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
stdout, stderr = process.communicate(input=json.dumps(payload))
if process.returncode != 0:
# Try to parse the stderr JSON error from sap_client.js
try:
err_obj = json.loads(stderr)
return f"SAP Error ({err_obj.get('code')}): {err_obj.get('message')}"
except:
return f"Node.js Runtime Error: {stderr.strip()}"
# Parse success output
response = json.loads(stdout)
return json.dumps(response.get("data"), indent=2)
except Exception as e:
return f"Bridge Error: Failed to execute Node.js subsystem. Details: {str(e)}"
if __name__ == "__main__":
mcp.run()

This is a complex build because it requires both Python and Node.js runtimes, plus the proprietary SAP libraries.

Crucial: You must place your extracted nwrfcsdk folder in the same directory as this Dockerfile before building.

# Use a Python base image
FROM python:3.11-slim
# Install system dependencies including Node.js
# We use curl to setup the NodeSource repo for a modern Node version
RUN apt-get update && apt-get install -y \
curl \
gnupg \
&& curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Setup SAP NetWeaver SDK
# NOTE: The 'nwrfcsdk' folder must exist in your build context!
WORKDIR /usr/local/sap
COPY nwrfcsdk ./nwrfcsdk
# Create the configuration for the dynamic linker
RUN echo "/usr/local/sap/nwrfcsdk/lib" > /etc/ld.so.conf.d/nwrfcsdk.conf \
&& ldconfig
# Set SAP environment variables
ENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdk
# Application Setup
WORKDIR /app
# Copy application files
COPY server.py sap_client.js ./
# Install Python dependencies
RUN pip install fastmcp
# Install Node.js dependencies
# We create a package.json on the fly to keep it simple, or you can COPY one
RUN echo '{"dependencies": {"node-rfc": "^3.0.0"}}' > package.json \
&& npm install
# Ensure your container has network access (e.g. via NordLayer)
# EXPOSE 8000 for Railway compatibility
EXPOSE 8000
# Run the FastMCP server
CMD ["python", "server.py"]
  • Error: libsapnwrfc.so: cannot open shared object file: This means the Docker container cannot find the SAP SDK libraries. Ensure the nwrfcsdk folder was copied correctly and ldconfig was run.
  • RFC_LOGON_FAILURE: The credentials passed in SAP_CONFIG are incorrect or the user is locked.
  • ECONNREFUSED: The container cannot reach the SAP Host. Check your VPN (NordLayer/Tailscale) or firewall settings.

To use this with CrewAI, simply point your agent to the running MCP server URL (SSE or Stdlo). The agent will now have the execute_sap_rfc tool available and can autonomously query tables like USR02 or create Sales Orders via BAPI_SALESORDER_CREATEFROMDAT2.


  • Status: ✅ Verified
  • Environment: Python 3.11
  • Auditor: AgentRetrofit CI/CD

Transparency: This page may contain affiliate links.