Prepare the server locally
Run this once before adding it to Claude Code.
npm install
npm run buildRegister it in Claude Code
claude mcp add -e "VCAP_SERVICES=${VCAP_SERVICES}" -e "S4_DESTINATION_NAME=${S4_DESTINATION_NAME}" mcp4odata -- node /path/to/mcp4odata/dist/server.jsReplace any placeholder paths in the command with the real path on your machine.
VCAP_SERVICESS4_DESTINATION_NAME+ 1 optionalMake your agent remember this setup
mcp4odata's config, env vars, and the gotchas you hit — recalled in every future Claude Code, Cursor, and Codex session.
npx conare@latestFree · one command · indexes the sessions already on disk. Set up in the browser instead →
What it does
- Exposes SAP S/4HANA OData v4 services as LLM tools
- Supports secure inbound authentication via XSUAA Bearer tokens
- Integrates with SAP BTP Destination Service using SAP Cloud SDK
- Supports both Streamable HTTP and SSE MCP transports
- Enables deep-insert POST operations for sales order creation
Tools 2
salesorder_get_listRetrieves a list of S/4HANA sales order headers.salesorder_createCreates a new S/4HANA sales order with one or more line items.Environment Variables
VCAP_SERVICESrequiredJSON string containing XSUAA and Destination service credentialsS4_DESTINATION_NAMErequiredThe name of the BTP destination configured for S/4HANAPORTPort for the server to listen onTry it
Original README from horsemanjackyliu/mcp4odata
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-sale