Make your SAP Commerce (Hybris) estate legible to AI agents — the type system, FlexibleSearch, ImpEx and order traces, exposed as safe, typed, read-only tools over the Model Context Protocol.
SAP Commerce is powerful but expertise-gated and opaque.
Inspecting types, writing correct ImpEx, tracing an order — all require deep tribal knowledge and manual HAC/Backoffice clicking.
The combinatorial business-flow matrix and sprawling type system mean new engineers are slow for a long time.
LLMs have no safe, structured way into the platform. So the biggest cost driver on every program stays untouched.
A hardened MCP server that turns the platform into tools an agent can call safely.
LLM / Agent (Claude, Copilot, …)
│ MCP (stdio)
┌───────────▼───────────┐
│ commerce-mcp server │
├────────────────────────┤
│ read-only tool catalogue (zod-typed)
├────────────────────────┤
│ CommerceConnector │
│ ├─ MockConnector (offline, zero-config)
│ └─ LiveConnector (HAC / OCC / read-only DB) *planned
└────────────────────────┘
│
SAP Commerce Cloud (Hybris)
| Tool | What the agent can do |
|---|---|
| describe_type | Get the full definition of any item type. |
| list_types | Discover the type system. |
| run_flexible_search | Run a read-only, row-capped SELECT. |
| validate_impex | Check ImpEx against the live model before it's applied. |
Junior engineers and agents get expert-level access to the estate — the single biggest cost lever on a program.
Read-only tools, SELECT-only enforcement, row caps, planned PII redaction & audit logging. Security is a feature.
A fixture-backed mock connector runs the whole surface with zero config — demos and CI need no live instance.
Once agents speak to Commerce through one safe layer, every other tool (upgrades, tracing, migration) can build on it.
npm install
npm run build
npm start # MCP server on stdio, backed by the offline mock connector
npm test
Early scaffold: the tool surface, safety model and mock connector are real and tested. The live Hybris connector is a documented extension point on the roadmap.
Distilled from the runnable examples/ tutorials, driving the offline MockConnector. The output below is the real captured stdout.
import { MockConnector } from "commerce-mcp/src/mock-connector.js";
import { buildTools } from "commerce-mcp/src/tools/index.js";
const connector = new MockConnector();
const tools = buildTools(connector);
const call = (name: string) => tools.find((t) => t.name === name)!;
console.log("tools:", tools.map((t) => t.name).join(", "));
// describe_type: full type definition (parent, deployment table, attributes).
const product = await call("describe_type").handler({ code: "Product" }) as any;
console.log(`describe_type Product: extends=${product.extends}, table=${product.deploymentTable}, attrs=[${product.attributes.map((a: any) => a.qualifier).join(", ")}]`);
// run_flexible_search: a read-only SELECT returns capped fixture rows.
const res = await call("run_flexible_search").handler({ query: "SELECT {code},{name} FROM {Product}", maxRows: 10 }) as any;
console.log("run_flexible_search:", JSON.stringify(res));
// SAFETY: a mutating statement is rejected before it reaches the backend.
try {
await call("run_flexible_search").handler({ query: "DELETE FROM {Product}", maxRows: 10 });
} catch (err) {
console.log(`DELETE rejected: ${(err as Error).name}: ${(err as Error).message}`);
}
Output:
tools: describe_type, list_types, run_flexible_search, validate_impex
describe_type Product: extends=GenericItem, table=products, attrs=[code, name, catalogVersion]
run_flexible_search: {"columns":["code","name"],"rows":[{"code":"PROD-001","name":"Sample Product"},{"code":"PROD-002","name":"Another Product"}],"rowCount":2,"capped":false,"tookMs":3}
DELETE rejected: ReadOnlyViolationError: Only SELECT queries are permitted through this tool.