SAP Sandbox MCP Server
README.md
# SAP Sandbox MCP Server
Connects Claude to SAP's free, public S/4HANA Cloud sandbox (via the SAP
Business Accelerator Hub) using the Model Context Protocol. Lets you ask
Claude natural-language questions against real SAP OData structures —
sales orders, purchase orders, goods receipts, supplier invoices — and run
a **3-way match reconciliation** across them, without needing your own SAP
system.
This is a portfolio/demo project. It only touches SAP's **public, read-only
sandbox test data** — no real company data, no write operations, no cost.
---
## Tools
| Tool | What it does |
|---|---|
| `get_sales_orders` | Fetch sales orders, optionally filtered by Sold-To Party |
| `get_purchase_orders` | Fetch purchase orders, optionally filtered by supplier |
| `get_purchase_order_items` | Fetch PO line items (ordered quantity, net price) |
| `get_material_documents` | Fetch material document headers (goods movements) |
| `get_material_document_items` | Fetch material document line items, optionally filtered by PO |
| `get_supplier_invoice_items` | Fetch supplier invoice lines tied back to a PO |
| `three_way_match` | Reconcile Ordered vs. Received vs. Invoiced quantity for one PO, line by line |
| `query_sap_odata` | General-purpose fallback — query any OData service/entity set directly |
`three_way_match` is the core tool: give it a purchase order number and it
pulls the PO items, material document items, and supplier invoice items for
that PO, nets everything to a per-line-item quantity, and flags any line
where invoiced quantity exceeds received quantity.
---
## 1. Get a free SAP API key
1. Go to **https://api.sap.com** and register/sign in with a free SAP
Community account.
2. Search for an API package that includes a sandbox — e.g. search
"Sales Order" or "Purchase Order".
3. Open an API (e.g. the Sales Order API under the SAP S/4HANA Cloud
package). Look for a **"Try Out"** or **sandbox** option.
4. Once logged in, the API key is shown automatically when you use
"Try it out" (or under your account/API key settings) — copy it.
**Important:** SAP periodically deprecates and replaces its OData
services. For example, the original V2 Purchase Order API
(`API_PURCHASEORDER_PROCESS_SRV`) has been marked deprecated in favor of
a newer V4 API. Before relying on any service path in `sap_mcp_server.py`,
confirm on api.sap.com that it's still live and still has an active
sandbox — swap in whatever's current if not.
## 2. Install dependencies
```bash
cd sap-mcp-server
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
```
## 3. Add your API key
```bash
cp .env.example .env
```
Open `.env` and paste your key in place of `your_api_key_here`.
## 4. Connect it to Claude Code (simplest path)
From this project folder:
```bash
claude mcp add --transport stdio sap-sandbox -- python sap_mcp_server.py
```
(Use the full path to `sap_mcp_server.py` if you run this from somewhere
else, and make sure it points at the same Python environment where you
installed the requirements — e.g. the `venv` you just created.)
Verify it connected:
```bash
claude mcp list
```
You should see `sap-sandbox` listed. Then just ask Claude Code things like:
> Use the sap-sandbox server to get me the first 5 sales orders.
## 4b. Or connect it to Claude Desktop
Claude Desktop's local MCP setup now goes through a "Desktop Extensions"
(`.mcpb`) packaging system rather than hand-editing a JSON config file
directly. For the current official steps, see:
- https://support.claude.com/en/articles/10949351-getting-started-with-local-mcp-servers-on-claude-desktop
- Packaging docs: https://github.com/anthropics/mcpb
Claude Code is the faster path to a working demo; only bother with the
Desktop Extension packaging if you specifically want a GUI chat demo to
show someone.
## 5. Test it
Try prompts like:
- "Get me the first 5 sales orders from the SAP sandbox"
- "Find purchase orders for supplier 1000"
- "Run three_way_match against purchase order 4500000013"
- "Use query_sap_odata to pull [some other entity you found on api.sap.com]"
If a tool call errors out, the most likely cause is that SAP has changed
or deprecated the service path / entity set — check the current details
on api.sap.com and update the values in `sap_mcp_server.py`.
---
## What this catches
Running `three_way_match` across the sandbox POs surfaced a genuine
over-invoicing case: one PO had several line items where the invoiced
quantity came back at roughly 3x the received quantity — e.g. a line
received in full but invoiced for triple that amount. That's exactly the
kind of variance a real P2P reconciliation process is supposed to catch
before an invoice gets paid, and it showed up from ordinary sandbox test
data, not a contrived example.
A smaller design decision worth calling out: `received_qty_net` is
computed as a **signed sum** of material document line quantities
(`DebitCreditCode == 'S'` adds, anything else subtracts), rather than
trusting a single "is this cancelled" flag on the document. Reversals in
the sandbox data don't reliably show up as a clean cancelled-flag pair —
summing signed quantities nets them out correctly regardless. The
tradeoff is verifiability: to be sure a given `received_qty_net` isn't
hiding a receipt-then-reversal that happens to net to the same number as
a single clean receipt, you still need to check the raw material document
lines (`GoodsMovementType`, `DebitCreditCode`, `GoodsMovementIsCancelled`,
`ReversedMaterialDocument`) directly — `three_way_match` gives you the
net number, not the movement history.
---
## Known limitations / next steps
- **Pagination gap.** `three_way_match` fetches PO items, material
document items, and invoice items with `top=100` per call. That's a
stopgap, not real pagination — it covers every sandbox PO seen so far
(a handful of items x a few GR/invoice documents each), but a PO with
more history than that would silently truncate rather than error.
Proper cursor-based pagination across all three calls is a known
follow-up.
- **Read-only.** Every tool here is a `GET` against the SAP sandbox. There
are no create/update/delete tools — this connector can't post a goods
receipt, change a PO, or write anything back to SAP.
---
## Disclaimer
This project only touches SAP's public, read-only sandbox test data
exposed via the SAP Business Accelerator Hub — no real company data, no
write operations, no cost to run.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues