This repository contains an MCP (Model Context Protocol) server that exposes tools for working with Commerce APIs. It supports both a custom CAP OData backend (BTP mode) and SAP Commerce Cloud's native OCC v2 REST API (OCC mode).
It supports two common ways of running:
- Local development: Run the server locally and use the MCP Inspector to explore and call tools.
- SAP BTP (Cloud Foundry): Build and deploy as an MTA, using BTP services (e.g., Destination and XSUAA) for connectivity and authentication.
I highly recommend to go through the complete README file and then start step by step
BACKEND_MODE (mock/BTP/OCC, case-insensitive) is the single switch that selects which backend the server talks to. It defaults to BTP if unset.
- Node.js (for
npx): Required to run the MCP Inspector (@modelcontextprotocol/inspector) locally. - SAP BTP subaccount (Cloud Foundry): You have access to a BTP subaccount with a Cloud Foundry org/space and can log in using
cf login.Not required if running locally with
BACKEND_MODE=mockorBACKEND_MODE=OCC. - Commerce OData APIs available (BTP mode only):
- Commerce OData APIs are already deployed/running and reachable from where you run this MCP server (local or BTP). You can either create a simple e-commerce application using standard CAP template or create your own.
- Create a destination for the commerce APIs with name - COMMERCE_API_DESTINATION.
Not required if running locally with
BACKEND_MODE=mockorBACKEND_MODE=OCC. - SAP Commerce Cloud OCC access (OCC mode only): an OAuth2 client_credentials client registered against your Commerce Cloud tenant's authorization server, and a base site ID. See Option 3: OCC Backend below.
Destination name default:
- Default Destination name is COMMERCE_API_DESTINATION which can be updated from envrironment variables
- Install Python 3.13 and verify
Install Python 3.13.x from python.org.
Verify:
python3.13 --version
which python3.13- Go to VSCode and open terminal. Create and activate a virtual environment
macOS/Linux:
python3.13 -m venv .venv
source .venv/bin/activateWindows (PowerShell):
python -m venv .venv
.venv\Scripts\Activate.ps1Verify venv is active and using expected Python:
which python
python --version
python -m pip --version- Install fastMCP
pip install "fastmcp<3"- Install dependencies
pip install -r requirements.txt- Verify version
fastmcp versionOn Windows, this command may print the version info correctly and then raise a
UnicodeEncodeErrorfrom an emoji in an "update available" banner. That crash is cosmetic (a Windows console encoding issue in FastMCP's own update check) — if the version numbers printed above it, the install is fine.
You are all set!
-
Login to the BTP subaccount using
cf login -
Build application and deploy to BTP
mbt build && cf deploy mta_archives/commerce-mcp-server_1.0.0.mtar-
The MBT build will create the required resources and deploy the MCP server in the subaccount dev space.
-
Run the below MCP client which will list all the tools of the MCP. Ensure you have your .env set up properly as per the
.env-template
python scripts/check_remote_mcp.py- You will receive the list of tools
Connected.
Tools: ['mcp_ping']
mcp_ping: {'status': 'success', 'message': 'MCP service is reachable.'}- Get the vcap services
cf env commerce-mcp-server-
Create
vcap.jsonat the root of your folder. Copy the full JSON under VCAP_SERVICES and save it as vcap.json. -
Set env variables
export VCAP_SERVICES="$(cat vcap.json)"- Check if the VCAP_SERVICES are loaded using below command
echo $VCAP_SERVICESThere are two ways to run the MCP server locally.
Make sure you've completed Local Set up first (venv created, fastmcp and requirements.txt installed) and activated your virtual environment.
Default (no uv required) — run the Inspector directly via npx against your virtualenv's Python (requires Node.js for npx):
macOS/Linux:
npx -y @modelcontextprotocol/inspector .venv/bin/python src/server.pyWindows (PowerShell):
npx -y @modelcontextprotocol/inspector .venv\Scripts\python.exe src/server.pyAlternative (only if you have uv installed) — fastmcp dev shells out to uv run under the hood:
fastmcp dev src/server.pyEither command opens the same MCP Inspector UI in your browser, at a URL printed in the terminal (e.g. http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=...). Use that exact URL (with the token) to connect.
No SAP BTP account or deployed Commerce APIs needed. The server serves sample payloads from assets/payloads/.
- Create a
.envfile in the project root using the.env-templateand set:
ENVIRONMENT=local
BACKEND_MODE=mock
-
Run the MCP Inspector using one of the commands from Running the MCP Inspector above.
-
This opens the MCP Inspector in your browser. All tools (
get_products,get_categories,get_products_by_category,get_retailers) return mock data immediately.
Pre-requisite - Commerce OData APIs application must be deployed on BTP with DESTINATION - COMMERCE_API_DESTINATION.
- Create a
.envfile in the project root using the.env-templateand set:
ENVIRONMENT=local
BACKEND_MODE=BTP
DESTINATION_NAME=COMMERCE_API_DESTINATION
-
Follow the VCAP SERVICES section to load your service credentials.
-
Run the MCP Inspector using one of the commands from Running the MCP Inspector above.
-
This opens the MCP Inspector in your browser.
-
Browse through the tools and run them.
No SAP BTP account needed. The server calls SAP Commerce Cloud's native OCC v2 REST API directly, using its own OAuth2 client_credentials.
- Create a
.envfile in the project root using the.env-templateand set:
ENVIRONMENT=local
BACKEND_MODE=OCC
OCC_BASE_URL=https://api.your-tenant.commerce.ondemand.com
OCC_TOKEN_URL=https://api.your-tenant.commerce.ondemand.com/authorizationserver/oauth/token
OCC_CLIENT_ID=your-client-id
OCC_CLIENT_SECRET=your-client-secret
OCC_BASE_SITE_ID=your-base-site-id
OCC_SCOPE, OCC_FIELDS, OCC_PAGE_SIZE, OCC_LANG, OCC_CURRENCY are optional — see .env-template for defaults. The OCC_TOKEN_URL path shown (/authorizationserver/oauth/token) is a common SAP Commerce Cloud convention — confirm the exact URL with your Commerce Cloud admin/OAuth client configuration.
-
Run the MCP Inspector using one of the commands from Running the MCP Inspector above.
-
This opens the MCP Inspector in your browser.
get_productsandget_products_by_categorycall OCC'sproducts/searchendpoint.get_categoriesandget_retailersare not supported in OCC mode — they return{"status": "error", "message": "...not supported in OCC mode..."}, since stock OCC has no equivalent to the custom CAP OData service's flat categories list / retailers (BusinessPartners) concepts. -
If a required
OCC_*environment variable is missing or empty, the server fails fast at startup with aRuntimeErrornaming the exact missing variable.
-
Start the Debug launch configuration.
-
In Terminal 1 (debug console/terminal), verify the server is running and the MCP endpoint is available:
http://0.0.0.0:8080/mcp -
Open second terminal and load the xsuaa service credentials (You will get it from subaccount xsuaa service instance)
export MCP_URL=http://0.0.0.0:8080/mcp
export MCP_XSUAA_AUTH_URL=https://<subaccount>.authentication.us10.hana.ondemand.com/oauth/token
export MCP_XSUAA_CLIENT_ID=<clientID>
export MCP_XSUAA_CLIENT_SECRET=<clientSecret>- Get
MCP_XSUAA_TOKEN(XSUAA client credentials)
If you see KeyError: 'access_token', the token endpoint returned an error JSON (so there is no access_token field). First, inspect the raw response:
curl -i -sS -X POST "$MCP_XSUAA_AUTH_URL" \
-u "$MCP_XSUAA_CLIENT_ID:$MCP_XSUAA_CLIENT_SECRET" \
-H "Accept: application/json" \
-d "grant_type=client_credentials"Then export the token:
export MCP_XSUAA_TOKEN=$(
curl -sS -X POST "$MCP_XSUAA_AUTH_URL" \
-u "$MCP_XSUAA_CLIENT_ID:$MCP_XSUAA_CLIENT_SECRET" \
-H "Accept: application/json" \
-d "grant_type=client_credentials" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])'
)- Initialize and capture SID
SID=$(
curl -i -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0.1.0"}}}' \
| awk -F': ' 'tolower($1)=="mcp-session-id"{print $2}' | tr -d '\r'
)
echo "SID=[$SID]"- If SID prints, run the below command
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}'- List tools
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'- Set debug point in the
mcp_pingtool and run the below command
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"mcp_ping","arguments":{}}}'- Call
get_productstool
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d "{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"tools/call\",\"params\":{\"name\":\"get_products\",\"arguments\":{}}}"- Call get_categories tool
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"get_categories","arguments":{}}}'- Call get_products_by_category tool
CATEGORY_ID="a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c3d"
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d "{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"tools/call\",\"params\":{\"name\":\"get_products_by_category\",\"arguments\":{\"category_id\":\"$CATEGORY_ID\"}}}"- Call get_retailers tool
curl -sS -X POST "$MCP_URL" \
-H "Authorization: Bearer $MCP_XSUAA_TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"get_retailers","arguments":{}}}'