How to connect CrewAI to SAP ECC via RFC using Python
How to Connect CrewAI to SAP ECC via RFC (Python)
Section titled “How to Connect CrewAI to SAP ECC via RFC (Python)”Connecting modern AI agents to SAP ECC (Enterprise Central Component) is a classic “Big Iron” problem. While agents speak REST and JSON, SAP ECC natively communicates via the RFC (Remote Function Call) protocol, a proprietary binary interface optimized for the internal networks of the 1990s.
This guide provides a production-ready Model Context Protocol (MCP) server that acts as a bridge. It translates your agent’s natural language requests (e.g., “Check the stock level for material 1045”) into compliant SAP RFC calls using the pyrfc library.
The Architecture
Section titled “The Architecture”We will build a FastMCP server in Python that exposes SAP BAPIs (Business Application Programming Interfaces) as tools. Your CrewAI agent connects to this server via SSE (Server-Sent Events).
Prerequisites
Section titled “Prerequisites”- SAP NW RFC SDK: You cannot simply
pip installthe connectivity layer. You must download the SAP NetWeaver RFC SDK 7.50 (Linux x86_64) from the SAP ONE Support Launchpad (requires an S-User ID). - VPN Access: If your SAP instance is behind a corporate firewall, your Docker container needs a tunnel.
1. The Bridge Server (server.py)
Section titled “1. The Bridge Server (server.py)”This server exposes two tools:
get_user_details: A safe, read-only wrapper aroundBAPI_USER_GET_DETAIL.execute_generic_rfc: A flexible tool that allows the agent to call any RFC (use with caution).
import osimport sysfrom fastmcp import FastMCPfrom pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError
# Initialize FastMCPmcp = FastMCP("SAP-ECC-RFC-Gateway")
def get_sap_connection(): """ Establishes a connection to SAP ECC. Parameters should be loaded from secure environment variables. """ # Ensure your container has network access (e.g. via NordLayer) try: conn = Connection( ashost=os.getenv("SAP_ASHOST", "10.0.0.1"), sysnr=os.getenv("SAP_SYSNR", "00"), client=os.getenv("SAP_CLIENT", "100"), user=os.getenv("SAP_USER", "DEVELOPER"), passwd=os.getenv("SAP_PASSWORD", "password123"), lang=os.getenv("SAP_LANG", "EN") ) return conn except LogonError as e: print(f"SAP Logon Error: {e}", file=sys.stderr) raise except CommunicationError as e: print(f"SAP Network/Communication Error: {e}", file=sys.stderr) raise
@mcp.tool()def get_user_details(username: str) -> dict: """ Retrieves detailed information about an SAP user using BAPI_USER_GET_DETAIL.
Args: username: The SAP User ID (e.g., 'JSMITH'). """ conn = None try: conn = get_sap_connection() result = conn.call("BAPI_USER_GET_DETAIL", USERNAME=username)
# Clean up the return structure for the agent return { "address": result.get("ADDRESS", {}), "defaults": result.get("DEFAULTS", {}), "status": "success" } except (ABAPApplicationError, ABAPRuntimeError) as e: return {"status": "error", "message": str(e)} except Exception as e: return {"status": "error", "message": f"System error: {str(e)}"} finally: if conn and conn.alive: conn.close()
@mcp.tool()def execute_generic_rfc(function_name: str, parameters: dict) -> dict: """ Executes a generic SAP Remote Function Call (RFC). Useful for ad-hoc queries if the agent knows the BAPI signature.
Args: function_name: Name of the RFC/BAPI (e.g., 'STFC_CONNECTION'). parameters: Dictionary of import parameters. """ conn = None try: conn = get_sap_connection() # **SECURITY WARNING**: In production, validate function_name against an allowlist. result = conn.call(function_name, **parameters) return result except Exception as e: return {"error": str(e)} finally: if conn and conn.alive: conn.close()
if __name__ == "__main__": # Binds to 0.0.0.0 to allow access from other Docker containers or host mcp.run(transport='sse', host='0.0.0.0', port=8000)2. Dockerfile
Section titled “2. Dockerfile”Because pyrfc depends on C++ libraries provided by SAP, the Docker build is more complex than a standard Python app.
Structure:
- You must place the unzipped SAP SDK in a folder named
nwrfcsdknext to your Dockerfile. - The
nwrfcsdkfolder should contain thelibdirectory with.sofiles.
FROM python:3.11-slim
# Install system dependencies required by SAP SDK# libaio1 is often required for SAP's asynchronous I/ORUN apt-get update && apt-get install -y \ libaio1 \ && rm -rf /var/lib/apt/lists/*
# --- SAP SDK SETUP ---# Create directory for SAP SDKWORKDIR /usr/local/sap
# Copy the SDK from your local machine into the image# NOTE: You must download 'nwrfc750P_X-xxxxxx.zip' from SAP and extract it hereCOPY nwrfcsdk ./nwrfcsdk
# Setup environment variables so Python can find the C++ libsENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdkENV LD_LIBRARY_PATH=$SAPNWRFC_HOME/lib
# Setup app directoryWORKDIR /app
# Install Python dependencies# 'pyrfc' will look for the headers/libs defined in ENV vars aboveCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txt
# Copy server codeCOPY server.py .
# Expose port 8000 for Railway/Docker networkingEXPOSE 8000
# Start the serverCMD ["python", "server.py"]requirements.txt
Section titled “requirements.txt”fastmcppyrfcuvicorn3. Connecting CrewAI
Section titled “3. Connecting CrewAI”Once your Docker container is running (e.g., mapped to localhost:8000), you configure your CrewAI agent to use the SSE endpoint.
from crewai import Agent, Task, Crewfrom crewai_tools import BaseTool
# Define the connection to your custom SAP MCP Serversap_mcp_source = { "url": "http://localhost:8000/sse", "type": "sse"}
# Create the Agentsap_specialist = Agent( role='SAP ERP Specialist', goal='Retrieve user data from the legacy SAP ECC system', backstory="You are an expert in SAP BAPIs. You help the HR team verify user details in the legacy system.", verbose=True, # The 'mcps' configuration attaches the tools served by your server mcps=[sap_mcp_source])
# Define a Taskverify_user_task = Task( description="Find the address and default settings for SAP user 'DEVELOPER'.", expected_output="A summary of the user's address and format settings.", agent=sap_specialist)
# Run the Crewcrew = Crew( agents=[sap_specialist], tasks=[verify_user_task])
result = crew.kickoff()print(result)Troubleshooting Common Errors
Section titled “Troubleshooting Common Errors”ImportError: libsapnwrfc.so: cannot open shared object file
Section titled “ImportError: libsapnwrfc.so: cannot open shared object file”- Cause: The Docker container cannot find the SAP C++ libraries.
- Fix: Ensure
LD_LIBRARY_PATHis correctly set in the Dockerfile and points to the folder containing.sofiles.
LogonError: RFC_Logon_Failure
Section titled “LogonError: RFC_Logon_Failure”- Cause: Incorrect credentials or Client ID (e.g., client 000 vs 100).
- Fix: Verify the
SAP_CLIENTenvironment variable. RFC requires specific client numbers.
CommunicationError: RFC_COMMUNICATION_FAILURE
Section titled “CommunicationError: RFC_COMMUNICATION_FAILURE”- Cause: The container cannot reach the SAP Host IP.
- Fix: Ensure you are not blocking the RFC ports (usually 3300 + instance number, e.g., 3300 for instance 00). If using a VPN (e.g., NordLayer), ensure the tunnel is active inside the container context.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.