OpenAI Operator handling SAP ECC RFC errors and retries
OpenAI Operator: Robust SAP ECC RFC Error Handling
Section titled “OpenAI Operator: Robust SAP ECC RFC Error Handling”Legacy infrastructure is brittle. When you connect a modern AI Agent—like the OpenAI Operator—to a 25-year-old SAP ECC system, “happy path” coding isn’t enough. SAP Gateways timeout, RFC connections drop, and work processes get maxed out.
If your AI Agent doesn’t know how to handle an RFC_COMMUNICATION_FAILURE, it will hallucinate a failure or crash entirely.
This guide provides a production-hardened Model Context Protocol (MCP) server designed specifically for the OpenAI Operator. It wraps SAP RFC calls in intelligent retry logic using the tenacity library, ensuring your agents are resilient against the flakiness of legacy “Big Iron.”
The Architecture
Section titled “The Architecture”We are building a FastMCP server that exposes a tool to the OpenAI Operator. This tool connects to SAP ECC using the standard pyrfc library.
Critically, we implement Exponential Backoff for transient network errors but Fail Fast logic for authentication errors.
Prerequisites
Section titled “Prerequisites”- SAP NWRFC SDK: You must have the SAP NetWeaver RFC SDK (Linux version) downloaded from the SAP ONE Support Launchpad.
- Docker: To containerize the application.
- Python 3.11+: The runtime environment.
The Code (server.py)
Section titled “The Code (server.py)”This server exposes a single tool: get_material_details. It wraps the standard SAP BAPI BAPI_MATERIAL_GET_DETAIL.
Notice the @retry decorator. It is configured to:
- Retry only on
CommunicationError(network blips, gateway timeouts). - Never retry on
LogonError(wrong password) orABAPRuntimeError(bad code). - Wait 2 seconds, then 4, then 8 (exponential backoff) before giving up.
import osimport sysfrom fastmcp import FastMCPfrom pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationErrorfrom tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
# Initialize FastMCPmcp = FastMCP("sap-ecc-gateway")
# SAP Connection parameters from Environment VariablesSAP_CONFIG = { "ashost": os.getenv("SAP_ASHOST"), "sysnr": os.getenv("SAP_SYSNR"), "client": os.getenv("SAP_CLIENT"), "user": os.getenv("SAP_USER"), "passwd": os.getenv("SAP_PASSWD"), "lang": "EN"}
# Ensure your container has network access (e.g. via NordLayer) to reach the SAP Gateway IP.
def sap_connection_factory(): """Creates and returns a raw pyrfc connection.""" return Connection(**SAP_CONFIG)
@retry( retry=retry_if_exception_type(CommunicationError), stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))def reliable_bapi_call(material_id: str): """ Executes the BAPI call with built-in retry logic for network flakes. """ conn = sap_connection_factory() try: # Zero-pad material ID if necessary (standard SAP requirement) mat_id_padded = material_id.zfill(18)
result = conn.call( "BAPI_MATERIAL_GET_DETAIL", MATERIAL=mat_id_padded, PLANT=os.getenv("SAP_PLANT", "1000") ) return result except (LogonError, ABAPRuntimeError) as e: # Do not retry these. Fail immediately. raise e except CommunicationError as e: # This will trigger the @retry logic print(f"Network glitch detected: {e}. Retrying...") raise e finally: # Always close the connection to free up SAP work processes conn.close()
@mcp.tool()def get_material_status(material_id: str) -> str: """ Retrieves the status and basic details of a material from SAP ECC. Handles network retries automatically.
Args: material_id: The alphanumeric ID of the material (e.g., "RM-1234"). """ try: data = reliable_bapi_call(material_id)
# Parse return messages for business logic errors return_msgs = data.get("RETURN", {}) if return_msgs and return_msgs.get("TYPE") == "E": return f"SAP Business Error: {return_msgs.get('MESSAGE')}"
material_data = data.get("MATERIAL_GENERAL_DATA", {}) desc = material_data.get("MATL_DESC", "No Description") type_ = material_data.get("MATL_TYPE", "Unknown")
return f"Material: {material_id} | Description: {desc} | Type: {type_}"
except LogonError: return "Error: SAP Login Failed. Check credentials." except ABAPRuntimeError as e: return f"Error: SAP ABAP Crash. {str(e)}" except CommunicationError: return "Error: Could not reach SAP Gateway after 3 attempts." except Exception as e: return f"Unknown System Error: {str(e)}"
if __name__ == "__main__": mcp.run()The Container (Dockerfile)
Section titled “The Container (Dockerfile)”Integrating pyrfc requires the underlying C++ libraries provided by SAP. You cannot install pyrfc without them.
Preparation:
- Create a folder named
nwrfcsdkin your project root. - Extract the contents of the SAP NetWeaver RFC SDK zip file into this folder. It should contain
libandincludesubdirectories.
FROM python:3.11-slim
# Install system dependencies required for SAP NWRFC SDKRUN apt-get update && apt-get install -y --no-install-recommends \ uuid-dev \ && rm -rf /var/lib/apt/lists/*
# Set working directoryWORKDIR /app
# Copy SAP NWRFC SDK files# Expects a local folder 'nwrfcsdk' containing the extracted SAP libraryCOPY nwrfcsdk /usr/local/sap/nwrfcsdk
# Configure SAP Environment VariablesENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdkENV LD_LIBRARY_PATH=$SAPNWRFC_HOME/lib:$LD_LIBRARY_PATH
# Install Python Dependencies# We install standard libraries + FastMCP# pyrfc requires the SDK to be present during installRUN pip install --no-cache-dir \ fastmcp \ tenacity \ pyrfc==3.3.0
# Copy the server codeCOPY server.py .
# Expose the Railway/FastMCP portEXPOSE 8000
# Run the MCP serverCMD ["python", "server.py"]Deployment Notes
Section titled “Deployment Notes”1. Network Access
Section titled “1. Network Access”SAP systems usually sit behind corporate firewalls. This Docker container must run in an environment that has a direct line of sight to the SAP Gateway (Port 33xx).
- Local Dev: Use a VPN (NordLayer, Tailscale) on your host machine.
- Cloud: Deploy this container into a VPC peered with your on-prem network, or use a mesh overlay network.
2. Why Fail Fast on Auth?
Section titled “2. Why Fail Fast on Auth?”If LogonError occurs, it means the password is wrong or the account is locked. Retrying will not fix this; it will only lock the SAP user account further due to repeated failed attempts (SAP usually locks after 3-5 failed tries). Our code explicitly catches this to protect the service account.
3. Usage with OpenAI Operator
Section titled “3. Usage with OpenAI Operator”Once running, this server exposes an SSE (Server-Sent Events) endpoint. You can inspect the tools using:
mcp inspect server.pyWhen connecting the OpenAI Operator, point it to your deployed URL (e.g., https://sap-mcp-app.up.railway.app/sse). The Agent will automatically discover the get_material_status tool and use it to answer user queries like “Is raw material RM-5500 active in the system?”
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.