Skip to content

LangGraph for SAP ECC data extraction and reporting (Python)

LangGraph for SAP ECC Data Extraction and Reporting (Python)

Section titled “LangGraph for SAP ECC Data Extraction and Reporting (Python)”

Slug: langgraph-sap-ecc-data-extraction-python

Legacy SAP ECC systems often operate as “black boxes,” locking critical operational data behind proprietary protocols like RFC (Remote Function Call). Modern AI agents running on LangGraph struggle to access this data directly.

This guide provides a production-ready Model Context Protocol (MCP) server that acts as a bridge. It uses the pyrfc library to communicate natively with SAP ECC, exposing safe, read-only tools that an autonomous LangGraph agent can use to extract data (e.g., T-Codes, Table reads) and generate financial or inventory reports.

We use a decoupled architecture to keep the “Big Iron” connectivity separate from your AI logic:

  1. SAP ECC: The legacy ERP system (on-premise or private cloud).
  2. MCP Server (Dockerized): Runs pyrfc and FastMCP. It handles the complex RFC handshakes and data type conversion.
  3. LangGraph Agent: Connects to the MCP server via SSE (Server-Sent Events). It uses a streamlined tool loader to access SAP functions.

This server exposes a specific tool sap_read_table which wraps the standard SAP RFC function RFC_READ_TABLE. This allows the agent to query raw SAP tables (like KNA1 for customers or VBAK for sales orders) using natural language logic.

Prerequisites:

  • You must provide SAP NetWeaver RFC SDK libraries (nwrfcsdk) in your environment.
  • pip install fastmcp pyrfc
import os
from fastmcp import FastMCP
from pyrfc import Connection
# Initialize FastMCP
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"),
sysnr=os.getenv("SAP_SYSNR", "00"),
client=os.getenv("SAP_CLIENT", "100"),
user=os.getenv("SAP_USER"),
passwd=os.getenv("SAP_PASSWORD"),
lang=os.getenv("SAP_LANG", "EN")
)
return conn
except Exception as e:
raise RuntimeError(f"Failed to connect to SAP: {str(e)}")
@mcp.tool()
def sap_read_table(table_name: str, row_count: int = 10, fields: list = None) -> str:
"""
Reads data from a standard SAP table using RFC_READ_TABLE.
Args:
table_name: The SAP table to read (e.g., 'KNA1', 'MARA', 'VBAK').
row_count: Number of rows to retrieve (default 10).
fields: List of specific field names to retrieve (optional).
"""
conn = None
try:
conn = get_sap_connection()
options = []
# Prepare fields structure for RFC_READ_TABLE
fields_table = []
if fields:
for f in fields:
fields_table.append({"FIELDNAME": f})
# Call the standard RFC
result = conn.call(
"RFC_READ_TABLE",
QUERY_TABLE=table_name,
ROWCOUNT=row_count,
FIELDS=fields_table,
OPTIONS=options
)
# Process data: SAP returns data in a delimited 'WA' field
data = result.get("DATA", [])
structure = result.get("FIELDS", [])
# Basic parsing (Production would require offset mapping)
parsed_output = []
for entry in data:
parsed_output.append(entry["WA"].strip())
return f"Successfully retrieved {len(data)} rows from {table_name}. \nStructure: {str(structure)}\nRaw Data Sample: {str(parsed_output[:5])}"
except Exception as e:
return f"SAP RFC Error: {str(e)}"
finally:
if conn and conn.alive:
conn.close()
if __name__ == "__main__":
# Binds to 0.0.0.0 to allow Docker networking
mcp.run(transport='sse', host='0.0.0.0', port=8000)

SAP connectivity requires system-level C++ libraries (nwrfcsdk). You cannot just pip install everything; you must mount or copy the SDK into the container.

# Use a slim Python base
FROM python:3.11-slim
# Install system dependencies
RUN apt-get update && apt-get install -y \
build-essential \
curl \
&& rm -rf /var/lib/apt/lists/*
# SAP NWRFC SDK SETUP
# Ensure the SDK files are present in the build context under ./nwrfcsdk
COPY ./nwrfcsdk /usr/local/sap/nwrfcsdk
# Update library paths so Python can find the SAP C++ libs
ENV LD_LIBRARY_PATH="/usr/local/sap/nwrfcsdk/lib:${LD_LIBRARY_PATH}"
ENV SAPNWRFC_HOME="/usr/local/sap/nwrfcsdk"
WORKDIR /app
# Install Python dependencies
RUN pip install --no-cache-dir fastmcp pyrfc
# Copy application code
COPY server.py .
# Ensure your container has network access (e.g. via NordLayer)
# SAP servers are usually behind corporate firewalls.
# Required for Railway/Cloud deployment
EXPOSE 8000
CMD ["python", "server.py"]

To keep the agent code clean and decoupled from low-level networking, we use a utility wrapper to load tools from the MCP server URL. This matches the configuration pattern used in other agent frameworks like CrewAI.

agent.py

import asyncio
from typing import List
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from mcp import ClientSession, StdioServerParameters
from mcp.client.sse import sse_client
from langchain_core.tools import tool
# --- MCP Connection Helper ---
async def load_mcp_tools(mcps: List[str]):
"""
Connects to the list of MCP SSE endpoints and returns LangChain-compatible tools.
In a real implementation, this would handle lifecycle management (enter/exit).
For this script, we initialize and return the wrapped tools.
"""
tools = []
for url in mcps:
# Note: In production, you need to manage the session context properly (async with).
# This is a simplified connector for demonstration.
client = sse_client(url)
streams = await client.__aenter__()
session = ClientSession(streams[0], streams[1])
await session.__aenter__()
await session.initialize()
# Fetch tools from server
mcp_tools = await session.list_tools()
# Wrap tool for LangChain
for t in mcp_tools.tools:
@tool(t.name)
async def dynamic_tool(**kwargs):
"""Dynamic MCP Tool Wrapper"""
result = await session.call_tool(t.name, arguments=kwargs)
return result.content[0].text
# Update metadata to match the MCP tool definition
dynamic_tool.description = t.description or "MCP Tool"
tools.append(dynamic_tool)
return tools
# --- Main Agent Workflow ---
async def run_agent():
# Configuration Parameter
mcps = ["http://localhost:8000/sse"]
# 1. Load Tools from MCP Servers
print(f"Connecting to MCP Servers: {mcps}...")
tools = await load_mcp_tools(mcps=mcps)
print(f"Loaded {len(tools)} tools: {[t.name for t in tools]}")
# 2. Define the Agent
llm = ChatOpenAI(model="gpt-4-turbo")
agent_executor = create_react_agent(llm, tools)
# 3. Execute the Workflow
print("--- Starting SAP Extraction ---")
response = await agent_executor.ainvoke({
"messages": [
("user", "Query the SAP table 'VBAK' (Sales Documents). Get the last 3 orders and show me the sales document number and date.")
]
})
# Output the final result
print(f"\nAgent Response:\n{response['messages'][-1].content}")
if __name__ == "__main__":
asyncio.run(run_agent())
  1. mcps Configuration: We define the server endpoints as a list (mcps), making it easy to add multiple SAP gateways (e.g., one for HR, one for Logistics) without changing the core agent logic.
  2. Tool Abstraction: The load_mcp_tools helper handles the SSE handshake and wraps the remote function into a format LangGraph expects, keeping the create_react_agent call clean.
  3. Network Access: Ensure your Docker container exposes port 8000 and the agent script can reach localhost:8000.
  1. Connection Refused: Verify the server is running with host='0.0.0.0' inside Docker.
  2. RFC Errors: If you see RFC_COMMUNICATION_FAILURE, check that the container has VPN access to the SAP host.
  3. Missing SDK: The Docker build will fail if nwrfcsdk is not in the directory. You must download this from the SAP Support Portal.

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

Transparency: This page may contain affiliate links.