Skip to content

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.”

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.

  1. SAP NWRFC SDK: You must have the SAP NetWeaver RFC SDK (Linux version) downloaded from the SAP ONE Support Launchpad.
  2. Docker: To containerize the application.
  3. Python 3.11+: The runtime environment.

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:

  1. Retry only on CommunicationError (network blips, gateway timeouts).
  2. Never retry on LogonError (wrong password) or ABAPRuntimeError (bad code).
  3. Wait 2 seconds, then 4, then 8 (exponential backoff) before giving up.
import os
import sys
from fastmcp import FastMCP
from pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
# Initialize FastMCP
mcp = FastMCP("sap-ecc-gateway")
# SAP Connection parameters from Environment Variables
SAP_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()

Integrating pyrfc requires the underlying C++ libraries provided by SAP. You cannot install pyrfc without them.

Preparation:

  1. Create a folder named nwrfcsdk in your project root.
  2. Extract the contents of the SAP NetWeaver RFC SDK zip file into this folder. It should contain lib and include subdirectories.
FROM python:3.11-slim
# Install system dependencies required for SAP NWRFC SDK
RUN apt-get update && apt-get install -y --no-install-recommends \
uuid-dev \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Copy SAP NWRFC SDK files
# Expects a local folder 'nwrfcsdk' containing the extracted SAP library
COPY nwrfcsdk /usr/local/sap/nwrfcsdk
# Configure SAP Environment Variables
ENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdk
ENV 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 install
RUN pip install --no-cache-dir \
fastmcp \
tenacity \
pyrfc==3.3.0
# Copy the server code
COPY server.py .
# Expose the Railway/FastMCP port
EXPOSE 8000
# Run the MCP server
CMD ["python", "server.py"]

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.

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.

Once running, this server exposes an SSE (Server-Sent Events) endpoint. You can inspect the tools using:

Terminal window
mcp inspect server.py

When 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?”


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

Transparency: This page may contain affiliate links.