runReport times out in WebSocket/APC context — REPORT_SERVICE uses sync SUBMIT
Summary
The debug RUN_REPORT MCP tool times out when routed to ZCL_VSP_REPORT_SERVICE->handle_run_report on a stateful APC handler. The root cause is that SUBMIT ... AND RETURN is invalid in an APC stateful session (raises APC_ILLEGAL_STATEMENT), and the existing async path in ZCL_VSP_RFC_SERVICE->handle_run_report is fire-and-forget while the MCP client waits synchronously.
Environment
- vsp version: deployed ABAP side from
main branch (src/ directory, version 2.3.0 in welcome frame)
- SAP: S/4HANA 2023, release 758, kernel 75I
- APC endpoint:
/sap/bc/apc/sap/zadt_vsp (stateful)
Reproduce
Deploy the repo's src/ content, then call either:
SAP(action="debug", target="RUN_REPORT", params={"report": "ZANY_REPORT"})
SAP(action="debug", target="RUN_REPORT", params={"report": "ZANY_ALV", "capture_alv": true})
Observed:
RunReport failed: timeout waiting for report response
Expected: either the report result (for capture_alv=true) or a completion status.
Root cause analysis
Two separate code paths, both broken for this use case:
-
ZCL_VSP_REPORT_SERVICE->handle_run_report (domain report)
- Does direct
SUBMIT (lv_report) AND RETURN
- Invalid in APC stateful handler → raises
APC_ILLEGAL_STATEMENT at runtime
- Exception is caught by the outer
TRY, but then the process is already in a bad state — on our system the response never arrives at the client (likely because the APC session is torn down)
-
ZCL_VSP_RFC_SERVICE->handle_run_report (domain rfc)
- Uses
CALL FUNCTION 'RFC_ABAP_INSTALL_AND_RUN' STARTING NEW TASK — returns immediately with a task id
- No callback, no result wiring back to the client → the MCP client has nothing to wait on and times out
So whichever domain the MCP client routes to, it can't get a result synchronously.
Suggested fix
Request/poll pattern:
runReport → schedule via STARTING NEW TASK ... PERFORMING on_end_of_task, return {"status":"started","requestId":"..."} immediately
on_end_of_task writes the result (subrc, ALV rows, runtime) into a shared memory / shared buffer / DB table keyed by requestId
- New action
getReportResult with {"requestId":"..."} → returns the persisted result (or {"status":"running"})
- Optional: push result via
mo_message_manager->send( ) when the APC session is still alive — but that requires keeping a reference to the message manager in the async context, which is hairy
Alternatively, for the ALV-capture use case, wrap the SUBMIT into a separate work process via a more controlled async mechanism (e.g. cl_bgmc_process_factory) and return a handle.
Either way, the MCP client (RunReport handler) needs a matching two-step protocol.
Workaround
None from the client side. Users currently can't run reports via the MCP.
Related
runReport times out in WebSocket/APC context — REPORT_SERVICE uses sync SUBMIT
Summary
The
debug RUN_REPORTMCP tool times out when routed toZCL_VSP_REPORT_SERVICE->handle_run_reporton a stateful APC handler. The root cause is thatSUBMIT ... AND RETURNis invalid in an APC stateful session (raisesAPC_ILLEGAL_STATEMENT), and the existing async path inZCL_VSP_RFC_SERVICE->handle_run_reportis fire-and-forget while the MCP client waits synchronously.Environment
mainbranch (src/directory, version2.3.0in welcome frame)/sap/bc/apc/sap/zadt_vsp(stateful)Reproduce
Deploy the repo's
src/content, then call either:Observed:
Expected: either the report result (for
capture_alv=true) or a completion status.Root cause analysis
Two separate code paths, both broken for this use case:
ZCL_VSP_REPORT_SERVICE->handle_run_report(domainreport)SUBMIT (lv_report) AND RETURNAPC_ILLEGAL_STATEMENTat runtimeTRY, but then the process is already in a bad state — on our system the response never arrives at the client (likely because the APC session is torn down)ZCL_VSP_RFC_SERVICE->handle_run_report(domainrfc)CALL FUNCTION 'RFC_ABAP_INSTALL_AND_RUN' STARTING NEW TASK— returns immediately with a task idSo whichever domain the MCP client routes to, it can't get a result synchronously.
Suggested fix
Request/poll pattern:
runReport→ schedule viaSTARTING NEW TASK ... PERFORMING on_end_of_task, return{"status":"started","requestId":"..."}immediatelyon_end_of_taskwrites the result (subrc, ALV rows, runtime) into a shared memory / shared buffer / DB table keyed byrequestIdgetReportResultwith{"requestId":"..."}→ returns the persisted result (or{"status":"running"})mo_message_manager->send( )when the APC session is still alive — but that requires keeping a reference to the message manager in the async context, which is hairyAlternatively, for the ALV-capture use case, wrap the SUBMIT into a separate work process via a more controlled async mechanism (e.g.
cl_bgmc_process_factory) and return a handle.Either way, the MCP client (
RunReporthandler) needs a matching two-step protocol.Workaround
None from the client side. Users currently can't run reports via the MCP.
Related