Skip to content

AutoGen agents for SAP ECC data updates via RFC (Python)

AutoGen Agents for SAP ECC Data Updates via RFC (Python)

Section titled “AutoGen Agents for SAP ECC Data Updates via RFC (Python)”

Slug: autogen-sap-ecc-data-updates-rfc-python

This guide explains how to enable AutoGen agents to securely update data in SAP ECC systems. We use the Model Context Protocol (MCP) to wrap the complex, stateful SAP RFC protocol into a stateless, agent-friendly interface.

By dockerizing the SAP connectivity layer (which requires specific C++ libraries and SDKs), we allow the AutoGen client to remain lightweight and portable, communicating solely over standard HTTP/SSE.

  1. MCP Server (Docker): Hosts the pyrfc library and SAP NetWeaver SDK. It exposes the SAP BAPI_CUSTOMER_CHANGEFROMDATA (or similar) as a typed tool.
  2. AutoGen Client (Python): Uses a custom bridge to connect to the MCP server. It injects the remote tools into the UserProxyAgent and AssistantAgent so they can autonomously execute SAP updates.

This server handles the heavy lifting of talking to SAP. It binds to 0.0.0.0 to ensure it is accessible from outside the container.

import os
from fastmcp import FastMCP
from pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError
# Initialize FastMCP server
mcp = FastMCP("SAP-ECC-Update-Gateway")
# SAP Connection Configuration
# In production, inject these via Environment Variables
SAP_CONFIG = {
"ashost": os.getenv("SAP_ASHOST", "192.168.1.10"),
"sysnr": os.getenv("SAP_SYSNR", "00"),
"client": os.getenv("SAP_CLIENT", "100"),
"user": os.getenv("SAP_USER", "BTC_AGENT"),
"passwd": os.getenv("SAP_PASSWORD", "Secret123"),
"lang": "EN"
}
@mcp.tool()
def update_customer_credit(customer_id: str, new_limit: float) -> str:
"""
Updates the credit limit for a specific customer in SAP ECC via RFC.
Args:
customer_id: The 10-digit SAP customer number (e.g., '0000101000').
new_limit: The new credit limit amount.
"""
# Ensure your container has network access (e.g. via NordLayer)
conn = None
try:
conn = Connection(**SAP_CONFIG)
# Simplified BAPI call structure for demonstration
# BAPI_CUSTOMER_CHANGEFROMDATA typically requires complex structures.
# Here we map the agent's simple input to the RFC's requirements.
pi_personaldata = {"CITY": "New York"} # Example payload
pi_personaldatax = {"CITY": "X"} # Update flag
result = conn.call(
"BAPI_CUSTOMER_CHANGEFROMDATA",
CUSTOMERNO=customer_id,
PI_PERSONALDATA=pi_personaldata,
PI_PERSONALDATAX=pi_personaldatax
)
# RFCs often require an explicit commit
conn.call("BAPI_TRANSACTION_COMMIT", WAIT="X")
returns = result.get("RETURN", [])
messages = [f"{m['TYPE']}: {m['MESSAGE']}" for m in returns]
return f"SAP Result: {'; '.join(messages)}"
except (ABAPApplicationError, ABAPRuntimeError) as e:
return f"SAP RFC Error: {str(e)}"
except Exception as e:
return f"System Error: {str(e)}"
finally:
if conn:
conn.close()
if __name__ == "__main__":
# LISTEN on 0.0.0.0 to expose ports outside Docker
mcp.run(transport='sse', host='0.0.0.0', port=8000)

You must provide the proprietary SAP NetWeaver SDK in the nwrfcsdk/ directory relative to this Dockerfile.

# Base Python image
FROM python:3.10-slim
# Install system dependencies for SAP SDK
RUN apt-get update && apt-get install -y \
gcc \
g++ \
make \
&& rm -rf /var/lib/apt/lists/*
# Setup SAP NetWeaver SDK
# You must download 'nwrfcsdk' from SAP Support Portal and place it in the build context
COPY nwrfcsdk /usr/local/sap/nwrfcsdk
# Configure library paths
ENV SAPNWRFC_HOME=/usr/local/sap/nwrfcsdk
ENV LD_LIBRARY_PATH=$SAPNWRFC_HOME/lib
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy server code
COPY server.py .
# Expose port 8000 for the MCP SSE transport
EXPOSE 8000
# Ensure your container has network access (e.g. via NordLayer)
CMD ["python", "server.py"]

requirements.txt:

fastmcp==0.2.1
pyrfc==3.3.0
uvicorn

Since AutoGen does not yet natively support the mcps parameter like CrewAI, we implement a lightweight MCPBridge class. This allows us to pass mcps configuration cleanly and handles the tool registration for both the User Proxy and the Assistant.

import asyncio
import os
from contextlib import AsyncExitStack
from typing import List, Dict, Any
from autogen import AssistantAgent, UserProxyAgent
from mcp import ClientSession, StdioServerParameters
from mcp.client.sse import sse_client
from mcp.types import CallToolResult
# 1. Helper Class to Bridge MCP Tools to AutoGen
class MCPAutoGenBridge:
def __init__(self, mcps: List[str]):
"""
Args:
mcps: List of MCP SSE endpoints (e.g. ["http://localhost:8000/sse"])
"""
self.mcps = mcps
self.stack = AsyncExitStack()
self.sessions = []
async def initialize(self):
"""Connects to all MCP servers and fetches tools."""
tools_map = {}
for url in self.mcps:
# Connect via SSE
transport = await self.stack.enter_async_context(sse_client(url=url))
session = await self.stack.enter_async_context(
ClientSession(transport[0], transport[1])
)
await session.initialize()
self.sessions.append(session)
# Fetch tools
mcp_tools = await session.list_tools()
for tool in mcp_tools.tools:
# Create a closure to capture the specific session and tool name
async def tool_wrapper(customer_id: str, new_limit: float, _session=session, _tool_name=tool.name) -> str:
result = await _session.call_tool(
_tool_name,
arguments={"customer_id": customer_id, "new_limit": new_limit}
)
return "\n".join([c.text for c in result.content if c.type == 'text'])
# Store wrapper with metadata for registration
tools_map[tool.name] = {
"func": tool_wrapper,
"description": tool.description or "MCP Tool"
}
return tools_map
async def close(self):
await self.stack.aclose()
# 2. Main Agent Workflow
async def run_agents():
# Define Configuration with mcps argument
bridge = MCPAutoGenBridge(mcps=["http://localhost:8000/sse"])
try:
# Initialize bridge and get tools
tools = await bridge.initialize()
print(f"Loaded MCP Tools: {list(tools.keys())}")
# Configure AutoGen Agents
config_list = [{"model": "gpt-4", "api_key": os.getenv("OPENAI_API_KEY")}]
assistant = AssistantAgent(
name="SAP_Agent",
llm_config={"config_list": config_list},
system_message="You are an SAP administrator. Use the available tools to update customer records."
)
user_proxy = UserProxyAgent(
name="User_Proxy",
human_input_mode="NEVER",
code_execution_config=False,
max_consecutive_auto_reply=1
)
# Register MCP tools with AutoGen
for name, data in tools.items():
func = data["func"]
desc = data["description"]
# Register for execution (UserProxy runs the tool)
user_proxy.register_for_execution(name=name)(func)
# Register for LLM (Assistant knows about the tool)
assistant.register_for_llm(name=name, description=desc)(func)
# Start the conversation
await user_proxy.a_initiate_chat(
assistant,
message="Please update the credit limit for customer 0000101000 to 75000."
)
finally:
await bridge.close()
if __name__ == "__main__":
asyncio.run(run_agents())
  • mcps Argument: The MCPAutoGenBridge accepts a list of SSE endpoints, allowing you to easily scale to multiple MCP servers (e.g., one for SAP, one for Oracle) just by adding URLs to the list.
  • Tool Registration: The bridge dynamically wraps the remote MCP functions into Python async functions that AutoGen can natively understand and execute.
  • Security: Credentials remain safely inside the Docker container; the Agent only sees the function signature update_customer_credit(customer_id, new_limit).

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

Transparency: This page may contain affiliate links.