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”This guide provides the complete architectural blueprint for connecting an OpenAI Operator (or autonomous agent) to a legacy SAP ECC system using the Model Context Protocol (MCP).
We use pyrfc, the standard Python wrapper for the SAP NetWeaver RFC SDK, to execute BAPIs (Business Application Programming Interfaces). This enables your agent to perform complex ERP tasks—like creating sales orders or checking inventory—without screen scraping.
🏗️ Architecture
Section titled “🏗️ Architecture”We encapsulate the proprietary SAP connectivity inside a Dockerized FastMCP server. This server exposes SAP BAPIs as tools that the OpenAI Operator can invoke via the Model Context Protocol.
The Challenge: “Big Iron” Connectivity
Section titled “The Challenge: “Big Iron” Connectivity”SAP ECC uses the RFC (Remote Function Call) protocol, which is binary and proprietary. It does not speak HTTP or JSON native.
- Solution: A Python adapter using
pyrfc. - Constraint: You cannot simply
pip installthe driver; you must include the SAP NWRFC SDK (C++ libraries) in your Docker container.
🚀 The Server (server.py)
Section titled “🚀 The Server (server.py)”This FastMCP server exposes a generic execute_bapi tool. This allows the Agent to call any whitelisted BAPI dynamically.
import osimport sysfrom fastmcp import FastMCPfrom pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError
# Initialize FastMCP Servermcp = FastMCP("sap-ecc-bapi-server")
# Configuration from Environment VariablesSAP_HOST = os.getenv("SAP_HOST")SAP_SYSNR = os.getenv("SAP_SYSNR", "00")SAP_CLIENT = os.getenv("SAP_CLIENT", "100")SAP_USER = os.getenv("SAP_USER")SAP_PASSWORD = os.getenv("SAP_PASSWORD")
def get_connection(): """Establishes a connection to SAP ECC.""" try: conn = Connection( ashost=SAP_HOST, sysnr=SAP_SYSNR, client=SAP_CLIENT, user=SAP_USER, passwd=SAP_PASSWORD ) return conn except LogonError as e: raise RuntimeError(f"SAP Login Failed: {e}") except CommunicationError as e: raise RuntimeError(f"SAP Network Error: {e}")
@mcp.tool()def execute_bapi(bapi_name: str, parameters: dict = None) -> dict: """ Executes a standard SAP BAPI via RFC.
Args: bapi_name: The exact name of the BAPI (e.g., 'BAPI_CUSTOMER_GETDETAIL2'). parameters: A dictionary of import parameters expected by the BAPI.
Returns: A dictionary containing the export parameters and tables returned by SAP. """ if parameters is None: parameters = {}
conn = None try: conn = get_connection() # The invoke() method in pyrfc calls the remote function result = conn.call(bapi_name, **parameters) return result except (ABAPApplicationError, ABAPRuntimeError) as e: return {"error": "ABAP Error", "details": str(e), "code": 500} except Exception as e: return {"error": "System Error", "details": str(e), "code": 500} finally: if conn and conn.alive: conn.close()
@mcp.tool()def check_connection() -> str: """Ping the SAP server to verify connectivity.""" try: conn = get_connection() info = conn.get_connection_attributes() conn.close() return f"Connected to SAP Release: {info.get('rel')}" except Exception as e: return f"Connection Failed: {e}"
if __name__ == "__main__": # Ensure your container has network access (e.g. via NordLayer) mcp.run(transport='sse', host='0.0.0.0', port=8000)🐳 Dockerfile
Section titled “🐳 Dockerfile”This is the critical part. You must download the SAP NetWeaver RFC SDK 7.50 (Linux x86_64) from the SAP Support Portal. Extract it into a folder named nwrfc in your project directory.
Your project structure should look like this:
.├── Dockerfile├── server.py└── nwrfc/ <-- Extracted SAP SDK (contains lib, include, bin)# Base imageFROM python:3.10-slim
# Install system dependencies required for SAP SDK# 'unzip' and 'gcc' might be needed depending on your specific setupRUN apt-get update && apt-get install -y \ libaio1 \ unzip \ && rm -rf /var/lib/apt/lists/*
# Set up environment variables for SAP NWRFCENV SAPNWRFC_HOME=/usr/local/sap/nwrfcENV PATH="${SAPNWRFC_HOME}/bin:${PATH}"ENV LD_LIBRARY_PATH="${SAPNWRFC_HOME}/lib:${LD_LIBRARY_PATH}"
# Create directory and copy SAP SDK files# ASSUMPTION: You have the SDK extracted in a local 'nwrfc' folderWORKDIR /usr/local/sapCOPY nwrfc/ ./nwrfc/
# Verify the library path is picked upRUN echo "/usr/local/sap/nwrfc/lib" > /etc/ld.so.conf.d/sap.conf && ldconfig
# Application setupWORKDIR /appCOPY server.py .
# Install Python dependencies# pyrfc requires the SDK to be present during installation if building from source,# or use the wheel if you have generated one.# For simplicity, we assume pip can build it because SDK is now in default paths.RUN pip install --no-cache-dir fastmcp pyrfc
# Expose port 8000 for Railway/Docker networkingEXPOSE 8000
# Ensure your container has network access (e.g. via NordLayer)# Run the FastMCP serverCMD ["python", "server.py"]🔌 Client Connectivity
Section titled “🔌 Client Connectivity”Once the server is running, you can connect your OpenAI Operator (or an Agent framework like CrewAI) to it.
Option 1: Using CrewAI (Python)
Section titled “Option 1: Using CrewAI (Python)”This configures a CrewAI agent to use the running Docker container as a tool provider.
from crewai import Agent, Task, Crew# Ensure you have the 'crewai[mcp]' extras installed if required,# or use a generic MCP client wrapper.# Note: Syntax varies by version; below is the standard pattern for MCP tool sources.
# Define the Agentsap_agent = Agent( role='SAP ERP Specialist', goal='Retrieve customer data from SAP ECC', backstory='You are an expert in SAP BAPIs and legacy data structures.', # Connect to the FastMCP server running in Docker mcps=["http://localhost:8000/sse"], verbose=True)
# Define the Task# The agent will automatically discover the 'execute_bapi' toolfetch_customer_task = Task( description="Fetch details for Customer ID '0000012345' using BAPI_CUSTOMER_GETDETAIL2.", expected_output="A JSON summary of the customer's address and credit limit.", agent=sap_agent)
# Run the Crewcrew = Crew(agents=[sap_agent], tasks=[fetch_customer_task])result = crew.kickoff()print(result)Option 2: Generic Python Client (mcp)
Section titled “Option 2: Generic Python Client (mcp)”If you are building a custom operator loop:
import asynciofrom mcp import ClientSession, StdioServerParametersfrom mcp.client.sse import sse_client
async def main(): # Connect to the SSE endpoint exposed by Docker async with sse_client("http://localhost:8000/sse") as (read, write): async with ClientSession(read, write) as session: # Initialize connection await session.initialize()
# List available tools tools = await session.list_tools() print(f"Connected to SAP. Available tools: {[t.name for t in tools.tools]}")
# Call the tool result = await session.call_tool( "execute_bapi", arguments={ "bapi_name": "BAPI_CUSTOMER_GETDETAIL2", "parameters": {"CUSTOMERNO": "0000012345"} } ) print("SAP Response:", result)
if __name__ == "__main__": asyncio.run(main())🔧 Troubleshooting
Section titled “🔧 Troubleshooting”- “ImportError: DLL load failed”: This means
LD_LIBRARY_PATHis incorrect in the Docker container or the SAP SDK libraries (NWRFC) are missing. - Network 10060/WSAECONNREFUSED: The container cannot reach the SAP Host.
- Fix: Ensure you are using a VPN sidecar (like NordLayer) if SAP is behind a corporate firewall.
- Check: Add the comment
# Ensure your container has network access (e.g. via NordLayer)to your deployment scripts.
- Authentication Errors: Verify the
SAP_CLIENT(e.g., 100, 200) matches your ECC instance configuration.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.