SAP GUI Scripting — ADT Fallback & Transaction Automation
When ADT MCP returns "not supported", fall back to SAP GUI Scripting.
Uses mario-andreschak/mcp-sap-gui (TypeScript) or kts982/mcp-sap-gui (Python).
Prerequisites
- SAP GUI installed on the machine running the MCP (no GUI on server-only hosts)
- SAP GUI Scripting enabled: RZ11 →
sapgui/user_scripting → TRUE
- Environment variables set:
SAPGUI_HOST, SAPGUI_USER, SAPGUI_PASSWORD, SAPGUI_CLIENT
- SHDB transaction recorder available for capturing field IDs
1. MCP Configuration
{
"mcp-sap-gui": {
"type": "stdio",
"command": "node",
"args": ["./mcp-sap-gui/dist/index.js"],
"env": {
"SAPGUI_HOST": "${SAPGUI_HOST}",
"SAPGUI_USER": "${SAPGUI_USER}",
"SAPGUI_PASSWORD": "${SAPGUI_PASSWORD}",
"SAPGUI_CLIENT": "${SAPGUI_CLIENT}"
}
}
}
2. Transaction Navigation Map
- Basis/Dev: SM30 (table maint), SE16 (data browser), SPRO (customizing),
SU01 (user admin), PFCG (roles), SU53 (auth check), SNOTE (notes)
- MM: MM01/MM02 (material), ME21N (PO), MIGO (goods receipt), MMBE (stock)
- SD: VA01/VA02 (orders), VL01N (delivery), VF01 (billing)
- FI: FB01 (post doc), FB02 (change doc), FS00 (GL master), F110 (auto payment)
- QM: QA01, QE01, QM01 | PP: CO01, CS01, MD04 | HCM: PA20, PA30, PA40
3. BDC / Batch Input Pattern
# BDC execution helper (illustrative snippet - adapt into your automation)
import win32com.client
def execute_bdc(session, transaction, bdcdata, mode='N'):
"""Execute BDC recording. mode: N=no display, A=all, E=errors only."""
session.StartTransaction(transaction)
for step in bdcdata:
for field_name, field_value in step.get('fields', {}).items():
try:
session.findById(field_name).text = field_value
except Exception as e:
log_field_skip(field_name, str(e))
if step.get('okcode'):
session.findById('wnd[0]').sendVKey(step['okcode'])
return session
# Example: SM30 table maintenance
BDC_SM30 = [
{'fields': {'wnd[0]/usr/txtVIEW-AREA': 'ZROUTER_TMPL'},
'okcode': '0'} # 0 = Enter
]
session = win32com.client.Dispatch("SapGui.ScriptingCtrl")
connection = session.OpenConnection(SAPGUI_HOST)
execute_bdc(connection.Children(0), 'SM30', BDC_SM30)
4. ALV Grid Reading
# ALV grid reader (illustrative snippet)
def read_alv_grid(session, grid_id='wnd[1]/usr/cntlGRID1/shellcont/shell'):
"""Read ALV grid data. Works for MMBE, MB51, ME2M, VA05, FBL1N, KSB1."""
grid = session.findById(grid_id)
headers = [grid.GetColumnHeader(c) for c in range(grid.ColumnCount)]
rows = []
for r in range(grid.RowCount):
rows.append({headers[c]: grid.GetCellValue(r, c)
for c in range(grid.ColumnCount)})
return rows
5. Popup / Modal Handling
# Popup handler (illustrative snippet)
def handle_popup(session, button='OK'):
"""Detect and dismiss modal popup. Returns True if handled."""
try:
popup = session.findById('wnd[1]')
actions = {'OK': 0, 'CANCEL': 12, 'YES': 'btn[0]', 'NO': 'btn[1]'}
act = actions.get(button, 0)
if isinstance(act, int):
popup.sendVKey(act)
else:
popup.findById(act).press()
return True
except Exception:
return False
6. ADT-First Routing Strategy
# Routing strategy (illustrative snippet - real engine: scripts/sap_router.py)
GUI_FALLBACK = [
'SPRO', 'SM30', 'SU01', 'SU53', 'PFCG', 'SNOTE',
'MM01', 'MM02', 'ME21N', 'MIGO', 'MMBE',
'VA01', 'VA02', 'VL01N', 'VF01',
'FB01', 'FB02', 'FS00', 'F110',
'QA01', 'CO01', 'KO01', 'PA20', 'PA30'
]
def route(action, try_adt=True):
"""Route: ADT first → GUI fallback → ZROUTER RFC."""
if try_adt and adt_supports(action):
return {"dest": "ADT", "fallback": "sap-gui-scripting"}
if action.upper() in GUI_FALLBACK:
return {"dest": "SAP GUI", "mcp": "mcp-sap-gui", "tcode": action}
return {"dest": "ZROUTER RFC"}
Pitfalls
- SAP GUI Scripting not enabled:
- Cause:
sapgui/user_scripting is FALSE in RZ11.
- Solution: Set to TRUE via RZ11 and restart SAP GUI.
- Field IDs change across SAP versions:
- Cause: Screen modifications in support packages shift field positions.
- Solution: Use SHDB transaction recorder to capture correct field IDs before scripting.
- Popups break BDC navigation silently:
- Cause: Modal window appears between steps; script tries next field on wrong screen.
- Solution: Call
handle_popup() after every sendVKey in BDC loops.
- Password hardcoded in script:
- Cause: Developer embeds credentials for convenience.
- Solution: Always use environment variables or secure vault — never hardcode.
- BDC mode A floods with screens in production:
- Cause: Mode 'A' shows every screen — useful for debug, terrible for batch.
- Solution: Use mode 'N' (no display) for production, 'E' for error-only visibility.
- No SAP GUI on server host:
- Cause: MCP runs on Linux server without SAP GUI installed.
- Solution: Run GUI MCP on a Windows machine with SAP GUI, or use RFC/BAPI instead.
Verification
# Primary: cross-platform Python check (recommended — works on Windows and Linux)
python scripts/check_gui_scripting.py --host "$SAPGUI_HOST"
# or: npm run gui:check
# Supplementary: bash-only MCP config check
grep -q '"mcp-sap-gui"' .mcp.json && echo "OK: MCP config found" || echo "FAIL: no config"
1---2name: sap-gui-scripting3description: SAP GUI Scripting automation — fallback when ADT cannot handle an operation. Navigates transactions, executes BDC, reads ALV grids, handles popups. Use for SPRO, SU01, SM30, SE16, SNOTE, and any transaction ADT cannot run.4---56# SAP GUI Scripting — ADT Fallback & Transaction Automation78When ADT MCP returns "not supported", fall back to SAP GUI Scripting.9Uses mario-andreschak/mcp-sap-gui (TypeScript) or kts982/mcp-sap-gui (Python).1011## Prerequisites1213- SAP GUI installed on the machine running the MCP (no GUI on server-only hosts)14- SAP GUI Scripting enabled: RZ11 → `sapgui/user_scripting` → TRUE15- Environment variables set: `SAPGUI_HOST`, `SAPGUI_USER`, `SAPGUI_PASSWORD`, `SAPGUI_CLIENT`16- SHDB transaction recorder available for capturing field IDs1718## 1. MCP Configuration1920```json21{22 "mcp-sap-gui": {23 "type": "stdio",24 "command": "node",25 "args": ["./mcp-sap-gui/dist/index.js"],26 "env": {27 "SAPGUI_HOST": "${SAPGUI_HOST}",28 "SAPGUI_USER": "${SAPGUI_USER}",29 "SAPGUI_PASSWORD": "${SAPGUI_PASSWORD}",30 "SAPGUI_CLIENT": "${SAPGUI_CLIENT}"31 }32 }33}34```3536## 2. Transaction Navigation Map3738- **Basis/Dev**: SM30 (table maint), SE16 (data browser), SPRO (customizing),39 SU01 (user admin), PFCG (roles), SU53 (auth check), SNOTE (notes)40- **MM**: MM01/MM02 (material), ME21N (PO), MIGO (goods receipt), MMBE (stock)41- **SD**: VA01/VA02 (orders), VL01N (delivery), VF01 (billing)42- **FI**: FB01 (post doc), FB02 (change doc), FS00 (GL master), F110 (auto payment)43- **QM**: QA01, QE01, QM01 | **PP**: CO01, CS01, MD04 | **HCM**: PA20, PA30, PA404445## 3. BDC / Batch Input Pattern4647```python48# BDC execution helper (illustrative snippet - adapt into your automation)49import win32com.client5051def execute_bdc(session, transaction, bdcdata, mode='N'):52 """Execute BDC recording. mode: N=no display, A=all, E=errors only."""53 session.StartTransaction(transaction)54 for step in bdcdata:55 for field_name, field_value in step.get('fields', {}).items():56 try:57 session.findById(field_name).text = field_value58 except Exception as e:59 log_field_skip(field_name, str(e))60 if step.get('okcode'):61 session.findById('wnd[0]').sendVKey(step['okcode'])62 return session6364# Example: SM30 table maintenance65BDC_SM30 = [66 {'fields': {'wnd[0]/usr/txtVIEW-AREA': 'ZROUTER_TMPL'},67 'okcode': '0'} # 0 = Enter68]69session = win32com.client.Dispatch("SapGui.ScriptingCtrl")70connection = session.OpenConnection(SAPGUI_HOST)71execute_bdc(connection.Children(0), 'SM30', BDC_SM30)72```7374## 4. ALV Grid Reading7576```python77# ALV grid reader (illustrative snippet)78def read_alv_grid(session, grid_id='wnd[1]/usr/cntlGRID1/shellcont/shell'):79 """Read ALV grid data. Works for MMBE, MB51, ME2M, VA05, FBL1N, KSB1."""80 grid = session.findById(grid_id)81 headers = [grid.GetColumnHeader(c) for c in range(grid.ColumnCount)]82 rows = []83 for r in range(grid.RowCount):84 rows.append({headers[c]: grid.GetCellValue(r, c)85 for c in range(grid.ColumnCount)})86 return rows87```8889## 5. Popup / Modal Handling9091```python92# Popup handler (illustrative snippet)93def handle_popup(session, button='OK'):94 """Detect and dismiss modal popup. Returns True if handled."""95 try:96 popup = session.findById('wnd[1]')97 actions = {'OK': 0, 'CANCEL': 12, 'YES': 'btn[0]', 'NO': 'btn[1]'}98 act = actions.get(button, 0)99 if isinstance(act, int):100 popup.sendVKey(act)101 else:102 popup.findById(act).press()103 return True104 except Exception:105 return False106```107108## 6. ADT-First Routing Strategy109110```python111# Routing strategy (illustrative snippet - real engine: scripts/sap_router.py)112GUI_FALLBACK = [113 'SPRO', 'SM30', 'SU01', 'SU53', 'PFCG', 'SNOTE',114 'MM01', 'MM02', 'ME21N', 'MIGO', 'MMBE',115 'VA01', 'VA02', 'VL01N', 'VF01',116 'FB01', 'FB02', 'FS00', 'F110',117 'QA01', 'CO01', 'KO01', 'PA20', 'PA30'118]119120def route(action, try_adt=True):121 """Route: ADT first → GUI fallback → ZROUTER RFC."""122 if try_adt and adt_supports(action):123 return {"dest": "ADT", "fallback": "sap-gui-scripting"}124 if action.upper() in GUI_FALLBACK:125 return {"dest": "SAP GUI", "mcp": "mcp-sap-gui", "tcode": action}126 return {"dest": "ZROUTER RFC"}127```128129## Pitfalls130131- **SAP GUI Scripting not enabled**:132 - Cause: `sapgui/user_scripting` is FALSE in RZ11.133 - Solution: Set to TRUE via RZ11 and restart SAP GUI.134- **Field IDs change across SAP versions**:135 - Cause: Screen modifications in support packages shift field positions.136 - Solution: Use SHDB transaction recorder to capture correct field IDs before scripting.137- **Popups break BDC navigation silently**:138 - Cause: Modal window appears between steps; script tries next field on wrong screen.139 - Solution: Call `handle_popup()` after every `sendVKey` in BDC loops.140- **Password hardcoded in script**:141 - Cause: Developer embeds credentials for convenience.142 - Solution: Always use environment variables or secure vault — never hardcode.143- **BDC mode A floods with screens in production**:144 - Cause: Mode 'A' shows every screen — useful for debug, terrible for batch.145 - Solution: Use mode 'N' (no display) for production, 'E' for error-only visibility.146- **No SAP GUI on server host**:147 - Cause: MCP runs on Linux server without SAP GUI installed.148 - Solution: Run GUI MCP on a Windows machine with SAP GUI, or use RFC/BAPI instead.149150## Verification151152```bash153# Primary: cross-platform Python check (recommended — works on Windows and Linux)154python scripts/check_gui_scripting.py --host "$SAPGUI_HOST"155# or: npm run gui:check156157# Supplementary: bash-only MCP config check158grep -q '"mcp-sap-gui"' .mcp.json && echo "OK: MCP config found" || echo "FAIL: no config"159```