Skip to content

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”

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.

The pyrfc library depends on the C++ SAP NetWeaver RFC SDK. You cannot pip install this component alone.

  1. Download the SAP NW RFC SDK 7.50 from the SAP Support Portal (requires an S-User ID).
  2. Extract it to a folder named nwrfcsdk in your project root.
  3. Your folder structure should look like this:
    /project
    ├── nwrfcsdk/ <-- The extracted SDK
    │ ├── include/
    │ └── lib/
    ├── Dockerfile
    └── server.py

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.

This MCP server exposes a generalized tool execute_bapi that allows the OpenAI Operator to call any enabled BAPI by name.

import os
import sys
from fastmcp import FastMCP
from pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError
# Initialize FastMCP
mcp = 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()

This Dockerfile is critical. It sets up the Linux environment to support the proprietary SAP C++ binaries.

# Use a slim Python base
FROM python:3.11-slim-bookworm
# Install system dependencies required by SAP NWRFC SDK
# uuid-dev and libncurses5 are common requirements for the SDK binaries
RUN apt-get update && apt-get install -y \
gcc \
g++ \
make \
uuid-dev \
&& rm -rf /var/lib/apt/lists/*
# Set up the working directory
WORKDIR /app
# COPY the SAP NW RFC SDK into the container
# IMPORTANT: You must have the 'nwrfcsdk' folder in the same directory as this Dockerfile
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
# 'pyrfc' will fail to install if it cannot find the SDK files or valid gcc
COPY requirements.txt .
RUN pip install --no-cache-dir pyrfc fastmcp
# Copy application code
COPY server.py .
# REQUIRED: Expose port 8000 for Railway/Fly.io compatibility
EXPOSE 8000
# Start the MCP server
CMD ["python", "server.py"]

Create a file named requirements.txt next to your Dockerfile:

pyrfc==3.3
fastmcp==0.1.1

Because of the manual SDK requirement, you must build the image locally or use a build pipeline that has access to the SDK files.

Terminal window
docker build -t sap-mcp-agent .
Terminal window
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-agent

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:

  1. Call execute_bapi with {"function_name": "BAPI_MATERIAL_GET_DETAIL", "parameters": {"MATERIAL": "100-200"}}.
  2. Parse the JSON result from SAP.
  3. Respond to you with the description.

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

Transparency: This page may contain affiliate links.