OpenAI Operator for SAP ECC BAPI integration via `pyrfc`
OpenAI Operator for SAP ECC BAPI integration via pyrfc
Section titled “OpenAI Operator for SAP ECC BAPI integration via pyrfc”The Knowledge Gap
Section titled “The Knowledge Gap”Integrating modern OpenAI Operators with SAP ECC is one of the most challenging tasks in legacy modernization. While OpenAI’s models excel at reasoning and JSON manipulation, SAP ECC communicates via the RFC (Remote Function Call) protocol, a proprietary binary standard from the 1990s.
Agents natively speak HTTP/REST. They do not speak RFC.
To bridge this, we use the Model Context Protocol (MCP) to wrap the Python pyrfc library. This allows an OpenAI Operator to “plug in” to your SAP mainframe as if it were a local function call, enabling autonomous agents to read customer data, create sales orders, or check inventory levels in real-time.
Prerequisites
Section titled “Prerequisites”1. SAP NetWeaver RFC SDK
Section titled “1. SAP NetWeaver RFC SDK”The pyrfc library depends on the C++ SAP NetWeaver RFC SDK. You cannot pip install this component alone.
- Download the SAP NW RFC SDK 7.50 from the SAP Support Portal (requires an S-User ID).
- Extract it to a folder named
nwrfcsdkin your project root. - Your folder structure should look like this:
/project├── nwrfcsdk/ <-- The extracted SDK│ ├── include/│ └── lib/├── Dockerfile└── server.py
2. Network Access
Section titled “2. Network Access”Your container must have line-of-sight to the SAP Application Server (port 3300-3399).
- VPN: If SAP is on-premise, your container runner (Railway, AWS ECS) needs a VPN connection (e.g., via NordLayer or Tailscale sidecar).
- Allowlist: Ensure the SAP Gateway ACL (
secinfo/reginfo) permits connections from your agent’s IP.
The Code (server.py)
Section titled “The Code (server.py)”This MCP server exposes a generalized tool execute_bapi that allows the OpenAI Operator to call any enabled BAPI by name.
import osimport sysfrom fastmcp import FastMCPfrom pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError
# Initialize FastMCPmcp = FastMCP("SAP-ECC-Gateway")
def get_sap_connection(): """Helper to establish a connection to SAP ECC.""" # Ensure your container has network access (e.g. via NordLayer) try: conn = Connection( ashost=os.getenv("SAP_HOST"), # e.g., 192.168.1.10 sysnr=os.getenv("SAP_SYSNR"), # e.g., 00 client=os.getenv("SAP_CLIENT"), # e.g., 100 user=os.getenv("SAP_USER"), # Technical User passwd=os.getenv("SAP_PASSWORD"), # Password lang=os.getenv("SAP_LANG", "EN") # Language ) return conn except Exception as e: raise RuntimeError(f"Failed to connect to SAP: {str(e)}")
@mcp.tool()def check_connection() -> str: """ Verifies the agent can reach the SAP ECC instance. Returns the system release info if successful. """ try: conn = get_sap_connection() # Ping the backend to ensure liveliness conn.ping() # Get system info sys_info = conn.call("RFC_SYSTEM_INFO") conn.close() return f"Connected successfully to SAP System: {sys_info.get('RFCSI_RESUL', 'Unknown')}" except Exception as e: return f"Connection Failed: {str(e)}"
@mcp.tool()def execute_bapi(function_name: str, parameters: dict = None) -> dict: """ Executes a standard SAP BAPI or RFC function module.
Args: function_name: The exact name of the BAPI (e.g., 'BAPI_MATERIAL_GET_DETAIL') parameters: A dictionary of input parameters (IMPORTS/TABLES) required by the BAPI. Example: {"MATERIAL": "000000000000123456"} """ if parameters is None: parameters = {}
conn = None try: conn = get_sap_connection()
# Get function description to validate inputs (optional but recommended for robust apps) func_desc = conn.get_function_description(function_name)
# Execute the call result = conn.call(function_name, **parameters)
return { "status": "success", "data": result }
except (ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError) as e: return { "status": "error", "error_type": type(e).__name__, "message": str(e), "key": getattr(e, 'key', 'N/A'), "details": getattr(e, 'message', 'N/A') } except Exception as e: return { "status": "critical_error", "message": str(e) } finally: if conn and conn.alive: conn.close()
if __name__ == "__main__": mcp.run()The Container (Dockerfile)
Section titled “The Container (Dockerfile)”This Dockerfile is critical. It sets up the Linux environment to support the proprietary SAP C++ binaries.
# Use a slim Python baseFROM python:3.11-slim-bookworm
# Install system dependencies required by SAP NWRFC SDK# uuid-dev and libncurses5 are common requirements for the SDK binariesRUN apt-get update && apt-get install -y \ gcc \ g++ \ make \ uuid-dev \ && rm -rf /var/lib/apt/lists/*
# Set up the working directoryWORKDIR /app
# COPY the SAP NW RFC SDK into the container# IMPORTANT: You must have the 'nwrfcsdk' folder in the same directory as this DockerfileCOPY 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# 'pyrfc' will fail to install if it cannot find the SDK files or valid gccCOPY requirements.txt .RUN pip install --no-cache-dir pyrfc fastmcp
# Copy application codeCOPY server.py .
# REQUIRED: Expose port 8000 for Railway/Fly.io compatibilityEXPOSE 8000
# Start the MCP serverCMD ["python", "server.py"]requirements.txt
Section titled “requirements.txt”Create a file named requirements.txt next to your Dockerfile:
pyrfc==3.3fastmcp==0.1.1Deployment & Usage
Section titled “Deployment & Usage”1. Build the Image
Section titled “1. Build the Image”Because of the manual SDK requirement, you must build the image locally or use a build pipeline that has access to the SDK files.
docker build -t sap-mcp-agent .2. Run Locally
Section titled “2. Run Locally”docker run -p 8000:8000 \ -e SAP_HOST=10.0.0.5 \ -e SAP_SYSNR=00 \ -e SAP_CLIENT=100 \ -e SAP_USER=mcp_agent \ -e SAP_PASSWORD=secret \ sap-mcp-agent3. Usage with OpenAI Operator
Section titled “3. Usage with OpenAI Operator”When configuring your Operator (e.g., via the OpenAI API tools definition or a framework like LangChain), the MCP server exposes the schema automatically. The Operator will see:
- check_connection: “Verifies the agent can reach the SAP ECC instance.”
- execute_bapi: “Executes a standard SAP BAPI or RFC function module.”
Example Prompt to Agent:
“Check if Material 100-200 exists in SAP using BAPI_MATERIAL_GET_DETAIL. If it exists, tell me the material description.”
The Agent will autonomously:
- Call
execute_bapiwith{"function_name": "BAPI_MATERIAL_GET_DETAIL", "parameters": {"MATERIAL": "100-200"}}. - Parse the JSON result from SAP.
- Respond to you with the description.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.