SAP S/4HANA MCP server
Prebuilt SnapLogic agentic-tool pipelines that let an LLM read from and act on SAP S/4HANA, callable as MCP tools via Pipeline Execute. Published in the SnapLogic pattern catalog.
Overview
This pack gives an agent full access to SAP S/4HANA through three complementary paths: the OData v2 business APIs for reading and writing standard business objects, the HANA database for direct SQL queries and table-level writes, and the BAPI/RFC layer for function modules not covered by OData. One server covers entity-level work, ad-hoc reporting, and transactional function calls.
For setup instructions, see SnapLogic MCP Server quickstart.
Example Prompts
- Run BAPI_MATERIAL_AVAILABILITY for material MAT-001 in plant 1000
- Check stock availability for this material using the BAPI layer
- Execute BAPI_COMPANYCODE_GETLIST
- Call the material availability function module for these three plants
- Run BAPI_MATERIAL_AVAILABILITY for material MAT-001, plant 1000, unit PC
- Execute a BAPI function module with these import parameters
- Check whether this material is available in plant 1000
- Call BAPI_CUSTOMER_GETLIST for the German sales organisation
- Delete the row with ID 999 from ZTMP_TEST
- Remove the test customer CUST-100 from my staging table
Tools
| Tool Name | Functions |
|---|---|
| SAPBAPIExecute | Call a SAP BAPI or RFC function module with a parameter map (parent/child variant). |
| SAPBAPIExecuteChild | SAPBAPI Execute Child |
| SAPBAPIExecuteFlat | Call a SAP BAPI or RFC function module with a parameter map (single-pipeline variant). |
| SAPHANADeleteRecord | Delete rows from a SAP HANA table matching a SQL condition. |
| SAPHANADescribe | List the columns, types and nullability of a SAP HANA table from SYS.TABLE_COLUMNS. |
| SAPHANAExecuteSQL | Run an arbitrary read SQL statement against SAP HANA and return the result set. |
| SAPHANAInsertRecord | Insert a row into a SAP HANA table from a field map. |
| SAPHANAInsertRecordChild | SAPHANA Insert Record Child |
| SAPHANAQuery | Select rows from a SAP HANA table by schema, table, WHERE clause, ORDER BY and row limit. |
| SAPHANAUpdateRecord | Update rows in a SAP HANA table matching a SQL condition with a field map. |
| SAPHANAUpdateRecordChild | SAPHANA Update Record Child |
| SAPS4HANAODataAction | Invoke a bound OData action or function import on an S/4HANA service. |
| SAPS4HANAODataCreate | Create a new entity in an S/4HANA OData collection from a field map. |
| SAPS4HANAODataDelete | Delete an S/4HANA OData entity by its keyed URL. |
| SAPS4HANAODataDescribe | Fetch the $metadata schema of an S/4HANA OData service to discover its entities and fields. |
| SAPS4HANAODataQuery | Query an S/4HANA OData entity collection with $filter, $select, $orderby, $top and $skip. |
| SAPS4HANAODataRead | Read one S/4HANA OData entity by its keyed URL, optionally narrowing the fields returned. |
| SAPS4HANAODataUpdate | Patch selected fields on an existing S/4HANA OData entity. |
Set up the MCP Server tools
- Download sap-s4hana_tools.zip.
- In SnapLogic Designer, open the target project space (or create one), then choose Import Project / Import Pipelines and select the downloaded sap-s4hana_tools.zip. Designer unpacks each pipeline into the project.
- Attach the required account to the connectivity snaps (see Connection Setup).
- Expose the project as an MCP server — each pipeline becomes a tool named after its label. New to this? Start with the MCP quickstart, then use the MCP Server Pipeline Builder to generate the server from the imported pipelines.
Configure account
Attach an SAP HANA database account to the SAP HANA snaps in Designer after import.
These pipelines ship without credentials by design — attach a valid account in Designer before the tools will execute.
See the SnapLogic account documentation for this connector: Configuring Sap Hana Accounts.
SAPBAPIExecute
Calls a SAP BAPI or RFC function module by name and returns its results. Use this for operations that only exist in the function-module layer, such as availability checks or legacy transactional modules with no OData equivalent.
| Parameter | Type | Default | Description |
|---|---|---|---|
| bapi* | string | — | Name of the BAPI or RFC function module to call, e.g. BAPI_MATERIAL_AVAILABILITY; passed to the child pipeline and echoed in the summary. |
| params* | object | — | Map of import parameters for the function module, e.g. {PLANT: '1000', MATERIAL: 'MAT-001', UNIT: 'PC'}. |
* Required parameter.
Try asking:
- Run BAPI_MATERIAL_AVAILABILITY for material MAT-001 in plant 1000
- Check stock availability for this material using the BAPI layer
- Execute BAPI_COMPANYCODE_GETLIST
- Call the material availability function module for these three plants
SAPBAPIExecuteChild
Lets the LLM sapbapi execute child, exposed as an MCP tool callable via Pipeline Execute.
| Parameter | Type | Default | Description |
|---|---|---|---|
| bapi | string | — | — |
SAPBAPIExecuteFlat
Calls a SAP BAPI or RFC function module by name and returns its results, using a single self-contained pipeline. Choose this variant for simpler deployment; use SAPBAPIExecute if you prefer the parent/child pipeline structure.
| Parameter | Type | Default | Description |
|---|---|---|---|
| bapi* | string | — | Name of the BAPI or RFC function module to call, e.g. BAPI_MATERIAL_AVAILABILITY. |
| params* | object | — | Map of import parameters for the function module, e.g. {PLANT: '1000', MATERIAL: 'MAT-001', UNIT: 'PC'}. |
* Required parameter.
Try asking:
- Run BAPI_MATERIAL_AVAILABILITY for material MAT-001, plant 1000, unit PC
- Execute a BAPI function module with these import parameters
- Check whether this material is available in plant 1000
- Call BAPI_CUSTOMER_GETLIST for the German sales organisation
SAPHANADeleteRecord
Deletes rows from a SAP HANA table that match a condition you specify. Use this for targeted cleanup of test or staging data in custom tables; the condition controls which rows are removed.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name | string | — | Schema of the target table, e.g. SAPHANADB. Omit to fall back to the account's default schema. |
| table_name* | string | — | Table to delete rows from, e.g. ZTMP_TEST; it is named in the confirmation summary. |
| delete_condition* | string | — | SQL condition selecting which rows are deleted, e.g. ID = 999. |
* Required parameter.
Try asking:
- Delete the row with ID 999 from ZTMP_TEST
- Remove the test customer CUST-100 from my staging table
- Clear out the rows in ZTMP_TEST where the status is FAILED
SAPHANADescribe
Returns the column names, data types, and nullability for a SAP HANA table. Use this before writing queries or inserting data to confirm the real column names and types.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name* | string | — | Schema of the table to describe, matched against SYS.TABLE_COLUMNS.SCHEMA_NAME, e.g. SAPHANADB. |
| table_name* | string | — | Table whose columns are listed, matched against SYS.TABLE_COLUMNS.TABLE_NAME, e.g. VBAK. |
* Required parameter.
Try asking:
- What columns does VBAK have?
- Describe the SAPHANADB.MARA table
- Which fields in this custom table are nullable?
- Show me the data types on the ZTMP_CUSTOMERS table before I insert into it
SAPHANAExecuteSQL
Runs an arbitrary read-only SQL statement against SAP HANA and returns the result rows. Use this for analysis and reporting queries that require joins, aggregations, or subqueries; for write operations, use the insert, update, or delete tools.
| Parameter | Type | Default | Description |
|---|---|---|---|
| sql_statement* | string | — | SQL statement executed against SAP HANA, e.g. SELECT VBELN, ERDAT FROM SAPHANADB.VBAK WHERE ERDAT > 20250101. |
| query_type | string | Read |
Statement type label, defaulting to Read; the snap is pinned to Read execution, so changing this value does not change behaviour. |
* Required parameter.
Try asking:
- Run a SQL query joining VBAK and VBAP to get order lines with their headers
- Total net order value by month from VBAK for this year
- Give me the top 20 materials by open order quantity, with SQL
- Count sales orders per sales organisation in SAPHANADB
SAPHANAInsertRecord
Inserts a row into a SAP HANA table using a field map you provide. Use this for staging tables and custom Z-tables; for standard business objects, use the OData create tool so S/4HANA validation runs.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name* | string | — | Schema of the target table, passed through to the insert child pipeline, e.g. SAPHANADB. |
| table_name* | string | — | Table the row is inserted into, e.g. ZTMP_CUSTOMERS; it is named in the confirmation summary. |
| record* | object | — | Field map for the new row, e.g. {CUSTOMER_ID, NAME, REGION}; its keys become the inserted columns. |
* Required parameter.
Try asking:
- Insert a customer row into ZTMP_CUSTOMERS: CUST-100, Acme Corp, EMEA
- Add a record to the staging table in SAPHANADB
- Write these three fields into my custom HANA table
SAPHANAInsertRecordChild
Lets the LLM saphana insert record child, exposed as an MCP tool callable via Pipeline Execute.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name | string | — | — |
| table_name | string | — | — |
SAPHANAQuery
Queries rows from a SAP HANA table by specifying the schema, table, a WHERE condition, and sort order, without writing SQL. Use this when the data you need lives in a HANA table and is not exposed through an OData service.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name | string | — | HANA schema holding the table, e.g. SAPHANADB. Omit to fall back to the account's default schema. |
| table_name* | string | — | Table to select rows from, e.g. VBAK. |
| where_clause | string | — | SQL WHERE condition applied to the select, e.g. ERDAT > 20250101. Omit to return unfiltered rows. |
| order_by | string | — | Column or comma-separated columns to sort the result by, e.g. ERDAT. Omit for unordered results. |
| limit_rows | string | 100 |
Maximum number of rows to return (default 100). |
* Required parameter.
Try asking:
- Show me sales order headers from VBAK created after 20250101
- List the first 50 rows of SAPHANADB.MARA ordered by material number
- Query the custom customer table for everything in the EMEA region
- How many rows in VBAK have a net value over 100000? Show me the top ones by date
SAPHANAUpdateRecord
Updates rows in a SAP HANA table that match a condition, applying a field map of new values. For standard business objects, use the OData update tool instead so S/4HANA validations and document flow are respected.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name* | string | — | Schema of the target table, passed through to the update child pipeline, e.g. SAPHANADB. |
| table_name* | string | — | Table whose rows are updated, e.g. ZTMP_CUSTOMERS; it is named in the confirmation summary. |
| update_condition* | string | — | SQL condition selecting which rows are updated, e.g. CUSTOMER_ID = CUST-100. |
| fields* | object | — | Map of column values applied to every matching row, e.g. {NAME: 'Acme Corporation', REGION: 'APAC'}. |
* Required parameter.
Try asking:
- Update ZTMP_CUSTOMERS where CUSTOMER_ID = 'CUST-100' to set the region to APAC
- Rename that customer in my HANA staging table to 'Acme Corporation'
- Set the status column to PROCESSED for the rows loaded yesterday
SAPHANAUpdateRecordChild
Lets the LLM saphana update record child, exposed as an MCP tool callable via Pipeline Execute.
| Parameter | Type | Default | Description |
|---|---|---|---|
| schema_name | string | — | — |
| table_name | string | — | — |
| update_condition | string | — | — |
SAPS4HANAODataAction
Invokes a bound OData action or function import on an S/4HANA service, for operations that change document state rather than field values. Use this for actions like releasing a purchase order or cancelling a document, which a standard create or update cannot perform.
| Parameter | Type | Default | Description |
|---|---|---|---|
| action_url* | string | — | URL of the bound action or function import to call, e.g. .../API_PURCHASEORDER_PROCESS_SRV/Release. |
| http_method | string | POST |
HTTP method used for the call (default POST). |
| body | object | — | Action parameters, serialised as the JSON request body, e.g. {PurchaseOrder: '4500000001'}. Omit to send no body. |
* Required parameter.
Try asking:
- Release purchase order 4500000001
- Call the cancel action on sales order 0000001234
- Post the goods receipt action for this delivery
- Trigger the approval function import on this purchase requisition
SAPS4HANAODataCreate
Creates a new entity in an S/4HANA OData collection, such as a business partner, sales order, or purchase requisition. Use this to open business objects through the supported API rather than writing to tables directly.
| Parameter | Type | Default | Description |
|---|---|---|---|
| service_url* | string | — | URL of the OData collection the new entity is POSTed to, e.g. .../API_BUSINESS_PARTNER/A_BusinessPartner. |
| record* | object | — | Field map for the new entity, serialised as the JSON request body, e.g. {BusinessPartnerCategory, BusinessPartnerFullName}. |
* Required parameter.
Try asking:
- Create a new business partner called 'Test Partner Corp' in category 1
- Add a sales order for customer 100023 in sales organisation 1710
- Register a new supplier in S/4HANA with these details
- Create a purchase requisition item for material MAT-001, quantity 10
SAPS4HANAODataDelete
Deletes an S/4HANA OData entity by its keyed URL. Use this for explicit cleanup of specific records such as test data or mistaken creations, since S/4HANA business rules often block deletion on live documents.
| Parameter | Type | Default | Description |
|---|---|---|---|
| entity_url* | string | — | Keyed URL of the entity to delete, e.g. .../A_BusinessPartner('9999999'); it is echoed back in the confirmation summary. |
* Required parameter.
Try asking:
- Delete the test business partner 9999999 I created earlier
- Remove that duplicate entity from the business partner API
- Delete sales order 0000009999 from S/4HANA
SAPS4HANAODataDescribe
Fetches the metadata schema for an S/4HANA OData service, revealing its entity types, property names, and data types. Call this first when working with an unfamiliar service to get the real field names before writing queries or filters.
| Parameter | Type | Default | Description |
|---|---|---|---|
| metadata_url* | string | — | URL of the service $metadata document to fetch, e.g. https://host/sap/opu/odata/sap/API_BUSINESS_PARTNER/$metadata. |
* Required parameter.
Try asking:
- What fields does the business partner API expose?
- Show me the metadata for API_SALES_ORDER_SRV
- Which entity sets are available in the purchase order service?
- What is the correct property name for the customer number in this service?
SAPS4HANAODataQuery
Queries an S/4HANA OData entity collection and returns matching records, supporting filter, field selection, sorting, and paging. Use this when the user wants a list of business objects matching a condition, rather than a single known record.
| Parameter | Type | Default | Description |
|---|---|---|---|
| service_url* | string | — | Full URL of the OData entity collection to query, e.g. https://host/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner. |
| filter | string | — | OData $filter expression, e.g. BusinessPartnerCategory eq 1. Omit for no filter. |
| select_fields | string | — | Comma-separated property list sent as $select, e.g. BusinessPartner,BusinessPartnerFullName. Omit to return all properties. |
| orderby | string | — | OData $orderby clause, e.g. BusinessPartner asc. Omit to leave ordering to the service. |
| top | string | 100 |
Maximum entities to return, sent as $top (default 100). |
| skip | string | — | Number of entities to skip, sent as $skip for paging. Omit to start at the first page. |
* Required parameter.
Try asking:
- List the business partners in category 1, just the partner number and full name
- Show me the 50 most recent sales orders, sorted by creation date descending
- Find purchase orders for supplier 100000 using the purchase order API
- Get the next 100 business partners after the first page
- Which sales orders have a net value greater than 10000?
SAPS4HANAODataRead
Fetches a single S/4HANA OData entity by its keyed URL and returns its fields. Use this when the user names a specific record and wants its details, rather than searching a collection.
| Parameter | Type | Default | Description |
|---|---|---|---|
| service_url* | string | — | Keyed URL of the single entity to read, e.g. .../A_BusinessPartner('1000001'). |
| select_fields | string | — | Comma-separated property list sent as $select, e.g. BusinessPartner,BusinessPartnerFullName. Omit to return all properties. |
* Required parameter.
Try asking:
- Show me business partner 1000001
- Get the full detail for sales order 0000001234
- Pull just the name and category for business partner 1000001
- What does purchase order 4500000001 look like in S/4HANA?
SAPS4HANAODataUpdate
Updates specific fields on an existing S/4HANA OData entity by its keyed URL. Use this when the user wants to change individual properties on a named record without resubmitting the whole object.
| Parameter | Type | Default | Description |
|---|---|---|---|
| entity_url* | string | — | Keyed URL of the entity to patch, e.g. .../A_BusinessPartner('1000001'). |
| fields* | object | — | Map of properties to change, serialised as the PATCH body, e.g. {BusinessPartnerFullName: 'Acme Corporation'}. |
* Required parameter.
Try asking:
- Rename business partner 1000001 to 'Acme Corporation'
- Update the delivery date on sales order 0000001234
- Change the payment terms on supplier 100000
- Set the full name of business partner 1000001 to the new legal entity name