mcp4odata
An MCP (Model Context Protocol) server that exposes SAP S/4HANA OData services as tools for LLMs. Deployed on SAP Cloud Foundry (BTP).
Overview
LLM / MCP Client
│ Bearer token (XSUAA)
▼
mcp4odata (CF app)
│ SAP Cloud SDK → BTP Destination Service
▼
SAP S/4HANA (CE_SALESORDER_0001, OData v4)
- Inbound auth: XSUAA Bearer token validation via
@sap/xssec - Outbound connectivity: SAP Cloud SDK
executeHttpRequest()with BTP Destination Service - Two MCP transports: Streamable HTTP (MCP 2025-11-25) and SSE fallback (MCP 2024-11-05)
Tools
salesorder_get_list
Retrieves a list of S/4HANA sales order headers.
| Parameter | Type | Required | Description |
|---|---|---|---|
soldToParty |
string | No | Filter by customer number, e.g. 10100001 |
salesOrganization |
string | No | Filter by sales org, e.g. 1710 |
top |
integer | No | Max results, 1–100 (default: 20) |
Returns: array of sales order headers — order number, type, sold-to party, total net amount, currency, requested delivery date.
salesorder_create
Creates a new S/4HANA sales order with one or more line items (deep-insert POST).
Header fields
| Parameter | Type | Required | Description |
|---|---|---|---|
salesOrderType |
string | Yes | Order type, e.g. OR |
salesOrganization |
string | Yes | Sales org, e.g. 1710 |
distributionChannel |
string | Yes | Distribution channel, e.g. 10 |
organizationDivision |
string | Yes | Division, e.g. 00 |
soldToParty |
string | Yes | Customer number, e.g. 10100001 |
transactionCurrency |
string | No | ISO currency, e.g. USD (defaults from customer master) |
purchaseOrderByCustomer |
string | No | Customer PO number |
requestedDeliveryDate |
string | No | Delivery date, YYYY-MM-DD |
Item fields (at least one item required)
| Parameter | Type | Required | Description |
|---|---|---|---|
material |
string | Yes | Product number, e.g. MZ-FG-M500 |
requestedQuantity |
string | Yes | Quantity as a string, e.g. 5 |
requestedQuantitySAPUnit |
string | Yes | SAP unit of measure, e.g. EA, KG |
plant |
string | No | Delivering plant, e.g. 1710 |
salesOrderItemCategory |
string | No | Item category, e.g. TAN (derived from config if omitted) |
salesOrderItemText |
string | No | Line item description (defaults to material description) |
Returns: created sales order header including the generated order number.
Endpoints
| Endpoint | Auth | Description |
|---|---|---|
POST/GET/DELETE /mcp |
Bearer (XSUAA) | Streamable HTTP transport — MCP 2025-11-25 |
GET /sse |
Bearer (XSUAA) | SSE transport — MCP 2024-11-05 |
POST /messages |
Bearer (XSUAA) | SSE message posting |
GET /health |
None | Health check (used by CF) |
Local Development
Prerequisites
- Node.js 20+
- SAP BTP subaccount with XSUAA and Destination service instances
Setup
npm install
cp .env.example .env
# Fill in VCAP_SERVICES with your XSUAA and Destination credentials
.env structure (see .env.example for the full template):
VCAP_SERVICES='{ "xsuaa": [...], "destination": [...] }'
S4_DESTINATION_NAME=S4HANA_SALESORDER
PORT=3000
Run
npm run dev # tsx watch mode
npm run build # compile TypeScript → dist/
Test with MCP Inspector
Point the inspector at http://localhost:3000/mcp with a valid XSUAA Bearer token.
BTP Destination Configuration
Create an HTTP destination in the BTP cockpit with:
| Field | Value |
|---|---|
| Name | S4HANA_SALESORDER (or your S4_DESTINATION_NAME) |
| Type | HTTP |
| URL | Your S/4HANA base URL |
| Authentication | OAuth2ClientCredentials |
| Token Service URL | XSUAA token endpoint for S/4HANA |
The SAP Cloud SDK reads the Destination service binding from VCAP_SERVICES, fetches the destination, and injects the Authorization header automatically.
Cloud Foundry Deployment
Prerequisites
brew install cloudfoundry/tap/cf-cli@8
cf login -a https://api.cf.<region>.hana.ondemand.com
cf target -o <org> -s <space>
Create required service instances
cf create-service xsuaa application xsuaa-mcp4odata -c xsuaa-config.json
cf create-service destination lite destination-mcp4odata
Deploy
npm run build
cf push
cf logs mcp4odata --recent
Useful CF commands
cf env mcp4odata # inspect bound service credentials
cf set-env mcp4odata S4_DESTINATION_NAME # override env variable
cf restage mcp4odata # restage after env changes
Project Structure
src/
├── server.ts # Express app, MCP transports, route setup
├── auth/
│ └── middleware.ts # XsuaaTokenVerifier — inbound Bearer token validation
├── odata/
│ └── client.ts # getSalesOrders(), createSalesOrder() via SAP Cloud SDK
└── tools/
├── get-sales-orders.ts # salesorder_get_list tool
└── create-sales-order.ts # salesorder_create tool
manifest.yml # CF deployment manifest
.env.example # Local dev environment template
Tech Stack
| Layer | Technology |
|---|---|
| MCP Framework | @modelcontextprotocol/sdk |
| OData HTTP | @sap-cloud-sdk/http-client |
| Destination resolution | @sap-cloud-sdk/connectivity |
| Inbound auth | @sap/xssec, @sap/xsenv |
| Web server | Express 5 |
| Language | TypeScript (Node.js 20+) |
| Deployment | SAP Cloud Foundry |