sap-sales-order-mcp
README.md
# sap-sales-order-mcp
> **Production-ready MCP server for SAP S/4HANA Sales Order Management.**
> Sandbox-first, offline-testable, built on FastMCP.
[](https://python.org)
[](LICENSE)
[](tests/)
[](https://modelcontextprotocol.io)
[](https://api.sap.com/)
A reference implementation showing how to build a **maintainable, testable
MCP server** that connects Claude (or any MCP client) to an enterprise system.
Uses the public SAP API Business Hub sandbox — no on-prem SAP install needed.
**Why this repo exists:** most MCP + SAP examples show a toy server with one
tool and no error handling. This one applies the patterns from Anthropic's
*Claude Certified Architect (Foundations)* curriculum — boundary
descriptions, structured errors, offline mocks, and a tool-selection
reliability harness — to a real (public) SAP API.
---
## 5-Minute Quickstart
```bash
# 1. Clone + install
git clone https://github.com/coding-with-abbi/sap-sales-order-mcp.git
cd sap-sales-order-mcp
pip install -e .
# 2. Smoke-test all 4 tools offline (no API key needed)
python mcp_server.py --selftest
# 3. Add your SAP API key (get it free at api.sap.com)
cp .env.example .env
# Edit .env: SAP_API_KEY=<your key>
# 4. Verify live connection
LIVE_TESTS=1 python -m pytest tests/test_integration_live.py
```
**Add to Claude Desktop** (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"sap-sales-orders": {
"command": "python",
"args": ["/absolute/path/to/sap-sales-order-mcp/mcp_server.py"],
"env": {
"SAP_API_KEY": "your_key_here"
}
}
}
}
```
Restart Claude Desktop, then ask: *"Show me all open sales orders for customer 17100001."*
---
## Tools
Four tools, each with **boundary descriptions** (USE WHEN / DO NOT use) that
guide Claude to pick the right one on ambiguous requests. See
[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design rationale.
| Tool | What it does | Typical prompt |
|---|---|---|
| **`list_sales_orders`** | Paginated list with optional filters (customer, type, status, created-since) | "Show me all open orders" |
| **`get_sales_order`** | Single order header by ID (customer, amounts, status, dates) | "Details for order 1000001" |
| **`get_sales_order_items`** | Line items of an order (material, quantity, price) | "What products are on order 1000001?" |
| **`search_orders_by_customer`** | Convenience wrapper: all orders for a specific customer | "Show orders for customer 17100001" |
Full contracts (docstrings): [src/sap_sales_mcp/tools.py](src/sap_sales_mcp/tools.py).
More prompts + responses: [docs/EXAMPLES.md](docs/EXAMPLES.md).
---
## Architecture Highlights
- **Offline-first.** Unit tests + `--selftest` run against a `MockSAPClient`
with realistic OData v2 fixtures. No API key, no network. Live tests are
opt-in via `LIVE_TESTS=1`.
- **Structured errors.** Every failure returns a `ToolError` with
`errorCategory` (`transient`|`validation`|`business`|`permission`) +
`isRetryable` — never a bare `"failed"` string. Claude can act on them.
- **Boundary descriptions.** Each tool's docstring explicitly states
`USE WHEN` and `DO NOT use for`, with cross-references. A
[tool-selection-reliability harness](tool_selection_harness.py) empirically
verifies that these descriptions guide the model correctly on ambiguous
requests.
- **Retry policy.** Bounded exponential backoff (1s/2s/4s) on transient HTTP
errors only. Never on validation, business, or permission errors.
- **Lazy imports.** The offline codepath is stdlib-only — `httpx`, `mcp`,
`python-dotenv` are imported lazily in live functions. Unit tests run
without them.
- **Path-scoped rules.** `.claude/rules/python.md` and
`.claude/rules/mcp-tool-design.md` load only when editing matching files
— root `CLAUDE.md` stays lean.
---
## Testing
```bash
# Unit tests (offline, always safe)
python -m pytest
# Tool-selection harness (deterministic proxy for LLM tool-picking)
python tool_selection_harness.py
# Integration tests against real SAP sandbox
LIVE_TESTS=1 python -m pytest tests/test_integration_live.py
```
Current status: **53 passed + 5 skipped** (5 skipped = live tests, opt-in).
---
## Documentation
- [`docs/SETUP.md`](docs/SETUP.md) — Full setup guide (SAP API Hub, Claude Desktop, troubleshooting)
- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — Design decisions + CCA-F pattern rationale
- [`docs/EXAMPLES.md`](docs/EXAMPLES.md) — 10 prompt/response examples
- [`docs/NEXT-STEPS.md`](docs/NEXT-STEPS.md) — v2 ideas (create-order with approval gate, OAuth, more domains)
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — How to contribute
---
## Positioning
Built by [Jacob Abb](https://linkedin.com/in/jacob-abb) — AI Consultant &
Engineer specialising in Enterprise-AI (RAG, Voicebots, SAP+GenAI). This
project is part of a public reference portfolio; adapt it for your own SAP
system or use it as a template for other SAP domains (Business Partner,
Purchase Order, Materials).
Related: the patterns here (boundary descriptions, structured errors,
tool-selection harness) come directly from Anthropic's
[Claude Certified Architect – Foundations](https://www.anthropic.com/certification)
curriculum.
---
## Credits
- **SAP** — [API Business Hub](https://api.sap.com/) for the sandbox
- **Anthropic** — [MCP protocol](https://modelcontextprotocol.io) + Claude
Certified Architect curriculum
- **FastMCP** — the Python MCP framework this server is built on
---
## License
[MIT](LICENSE) — use freely, adapt for your production SAP systems, fork it
for other domains. PRs welcome (see [CONTRIBUTING.md](CONTRIBUTING.md)).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues