mcp4odata
README.md
# 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
```bash
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
```bash
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
```bash
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
```bash
cf create-service xsuaa application xsuaa-mcp4odata -c xsuaa-config.json
cf create-service destination lite destination-mcp4odata
```
### Deploy
```bash
npm run build
cf push
cf logs mcp4odata --recent
```
### Useful CF commands
```bash
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 |
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues