Skip to content

Handling SAP ECC RFC Authentication for AI Agents (Python)

Handling SAP ECC RFC Authentication for AI Agents (Python)

Section titled “Handling SAP ECC RFC Authentication for AI Agents (Python)”

Slug: sap-ecc-rfc-authentication-agents-python

Connecting modern AI Agents (CrewAI, AutoGen, LangGraph) to SAP ECC (Enterprise Central Component) is one of the hardest challenges in enterprise automation. Unlike REST or GraphQL, SAP ECC primarily communicates via RFC (Remote Function Call), a proprietary binary protocol over TCP/IP (port 3300+).

Most agents fail here because:

  1. Authentication is Stateful: RFC connections are not stateless HTTP requests; they require a persistent session handle.
  2. Binary Dependency: You cannot just pip install a driver; you need the C++ SAP NetWeaver SDK installed at the OS level.
  3. Network Isolation: SAP ECC usually sits deep in an on-premise DMZ, inaccessible to cloud-hosted agent runners without VPN tunneling.

This guide provides a FastMCP wrapper that turns the complex SAP RFC protocol into a clean, agent-friendly tool interface.


We will deploy a Model Context Protocol (MCP) server that acts as the “translator.”

  1. The Agent speaks JSON (MCP) to our server.
  2. The Server uses pyrfc and the SAP NetWeaver SDK to speak binary RFC to SAP.
  3. Docker encapsulates the messy C++ dependencies.
  • SAP NetWeaver RFC SDK 7.50: You must download this from the SAP Support Portal (requires an S-User ID). You need the Linux implementation.
  • VPN Access: Your container must be able to reach the SAP Application Server IP.

This server exposes a tool read_sap_table that allows an agent to query legacy data structures (like MARA for materials or VBAK for sales orders) without understanding RFC syntax.

import os
import sys
from fastmcp import FastMCP
from pydantic import Field
# Note: pyrfc requires the SAP NW RFC SDK libraries to be in the LD_LIBRARY_PATH
try:
from pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError
except ImportError:
print("CRITICAL: pyrfc not found. Ensure SAP NW RFC SDK is installed.")
sys.exit(1)
# Initialize FastMCP Server
mcp = FastMCP("sap-ecc-gateway")
def get_sap_connection():
"""
Establishes a connection to SAP ECC using environment variables.
"""
try:
conn = Connection(
ashost=os.getenv("SAP_HOST"), # Application Server Host
sysnr=os.getenv("SAP_SYSNR"), # System Number (e.g., "00")
client=os.getenv("SAP_CLIENT"), # Client (e.g., "100")
user=os.getenv("SAP_USER"), # RFC User
passwd=os.getenv("SAP_PASSWORD"), # RFC Password
lang=os.getenv("SAP_LANG", "EN") # Language
)
return conn
except LogonError as e:
raise ValueError(f"SAP Logon Failed: {e}")
except CommunicationError as e:
# Ensure your container has network access (e.g. via NordLayer)
raise ConnectionError(f"Network Error connecting to SAP: {e}")
@mcp.tool()
def read_sap_table(
table_name: str = Field(..., description="The technical name of the SAP table (e.g., 'MARA', 'KNA1')"),
row_count: int = Field(10, description="Max rows to retrieve"),
fields: list[str] = Field(default=["*"], description="List of column names to retrieve")
) -> str:
"""
Executes RFC_READ_TABLE to fetch raw data from SAP ECC.
Useful for looking up customer details, material stock, or order status.
"""
conn = None
try:
conn = get_sap_connection()
# Prepare the fields format for RFC_READ_TABLE
query_fields = []
if "*" in fields:
# Empty list implies all fields in some versions of RFC_READ_TABLE,
# but explicit selection is safer. We'll pass empty to let SAP decide or select specific keys.
pass
else:
query_fields = [{"FIELDNAME": f} for f in fields]
options = [{"TEXT": f"ROWCOUNT = {row_count}"}] if row_count else []
# Call the standard BAPI for table reading
result = conn.call(
"RFC_READ_TABLE",
QUERY_TABLE=table_name,
DELIMITER=";",
FIELDS=query_fields,
ROWCOUNT=row_count
)
# Parse the chaotic 'DATA' return format of RFC_READ_TABLE
data_lines = result.get("DATA", [])
headers = [f["FIELDNAME"] for f in result.get("FIELDS", [])]
output = []
for line in data_lines:
# SAP returns data as a single delimited string in the WA column
raw_row = line.get("WA", "").strip()
row_values = raw_row.split(";")
row_dict = dict(zip(headers, row_values))
output.append(row_dict)
return str(output)
except (ABAPApplicationError, ABAPRuntimeError) as e:
return f"SAP ABAP Error: {e}"
except Exception as e:
return f"System Error: {e}"
finally:
if conn:
conn.close()
if __name__ == "__main__":
# Required for Docker compatibility
mcp.run(transport='sse', host='0.0.0.0', port=8000)

This is the most critical part. You cannot run pyrfc on a standard Python image without the SAP C++ libraries (nwrfcsdk).

Structure Assumption: You have downloaded the SAP NW RFC SDK for Linux (x86_64) and extracted it to a folder named nwrfcsdk in your project root.

FROM python:3.11-slim-bookworm
WORKDIR /app
# Install system dependencies
# gcc and make are required if pyrfc needs to compile bindings (wheel vs source)
RUN apt-get update && apt-get install -y \
gcc \
g++ \
make \
&& rm -rf /var/lib/apt/lists/*
# -----------------------------------------------------------
# SAP SDK SETUP
# -----------------------------------------------------------
# Copy the downloaded SAP NetWeaver SDK into the container
# Ensure you have the 'nwrfcsdk' folder in your build context
COPY nwrfcsdk /usr/local/sap/nwrfcsdk
# Setup Environment variables for SAP SDK
ENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdk
ENV PATH=$PATH:$SAPNWRFC_HOME/bin
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SAPNWRFC_HOME/lib
# Create the configuration file for the dynamic linker
RUN echo "/usr/local/sap/nwrfcsdk/lib" > /etc/ld.so.conf.d/nwrfcsdk.conf \
&& ldconfig
# -----------------------------------------------------------
# Install Python Dependencies
# We install cython first as it's often a build requirement for pyrfc
RUN pip install --no-cache-dir cython
RUN pip install --no-cache-dir pyrfc fastmcp uvicorn
# Copy Server Code
COPY server.py .
# Ensure your container has network access (e.g. via NordLayer)
# This is crucial for reaching on-prem SAP instances.
# Expose the SSE port
EXPOSE 8000
# Run the MCP Server
CMD ["python", "server.py"]

Once your Docker container is running, you can connect your agent framework to the SAP bridge.

CrewAI supports MCP tools natively via the mcps parameter.

from crewai import Agent, Task, Crew
from crewai.project import CrewBase
# Define the SAP Agent
sap_analyst = Agent(
role='SAP Data Analyst',
goal='Retrieve material master data from the legacy ECC system',
backstory='You are an expert in SAP T-Codes and database schema.',
# Connect to the FastMCP server running in Docker
mcps=["http://localhost:8000/sse"],
verbose=True
)
task = Task(
description="Find the description for Material Number 'MAT-2024-X' from the MARA table.",
agent=sap_analyst,
expected_output="The material description."
)
crew = Crew(agents=[sap_analyst], tasks=[task])
result = crew.kickoff()
print(result)

If you need a manual connection or are using a different framework, use the sseclient approach to verify the stream.

import httpx
from mcp import ClientSession
from mcp.client.sse import sse_client
async def query_sap():
# Connect to the Docker container
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 SAP tools
tools = await session.list_tools()
print(f"Connected to SAP Bridge. Tools: {[t.name for t in tools.tools]}")
# Execute the SAP Query
result = await session.call_tool(
"read_sap_table",
arguments={
"table_name": "MARA",
"row_count": 1,
"fields": ["MATNR", "MAKTX"]
}
)
print(f"SAP Data: {result.content}")
# Run in an async loop
# import asyncio; asyncio.run(query_sap())
Error CodeMeaningFix
ImportError: libsapnwrfc.soOS cannot find the SAP SDK.Check LD_LIBRARY_PATH in Dockerfile and ensure ldconfig ran.
RFC_ERROR_LOGON_FAILUREBad Credentials.Verify SAP_USER and SAP_PASSWORD in env vars. Account might be locked.
NI_ECONN_REFUSEDNetwork Isolation.The container cannot reach port 3300 on the SAP host. Check VPN/NordLayer/Firewall.

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

Transparency: This page may contain affiliate links.