mage-os-mcp
# mage-os-mcp
[](https://github.com/nicolasperic/mage-os-mcp/actions/workflows/ci.yml)
[](LICENSE)
An open-source [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that lets AI agents **shop and query a Magento / Mage-OS store**. It connects to a store's public **storefront GraphQL API**, so any Magento 2.4+ / Mage-OS store can use it — no module to install, no admin credentials required for the core catalog tools.
> **Mage-OS B2B initiative:** this server is a reuse candidate for the community B2B suite's MCP adapter.
> - [`docs/b2b-reuse-review.md`](docs/b2b-reuse-review.md) — adopt / adapt / replace review of this server.
> - [`docs/b2b-mcp-requirements.md`](docs/b2b-mcp-requirements.md) — the RFC's MCP requirements mapped to progress.
> - [`docs/b2b-auth-model.md`](docs/b2b-auth-model.md) — entities, ER diagram and the operation state machine.
> - [`docs/b2b-community-feedback.md`](docs/b2b-community-feedback.md) — RFC discussion feedback and what it changes here.
> - Work in progress lives on the `b2b-delegated-auth` branch (`src/auth/`).
> Point Claude (or any MCP client) at your store and ask: _"Find me a waterproof jacket under $100 and tell me if it's in stock."_
## Why another Magento MCP?
Most existing Magento MCP servers are either **developer tooling** (help you write Magento code), **admin/BI dashboards** (REST + admin token), or **coupled to a commercial SaaS**. `mage-os-mcp` is deliberately different:
- **Shopper-first.** A small, curated, read-first toolset focused on the "let an AI agent shop" use case — quality over surface area.
- **API-based & portable.** Talks to the storefront GraphQL endpoint. Works against any store, self-hosted or cloud. No Magento module to deploy.
- **GraphQL-first.** Uses the storefront GraphQL API where practical; REST/direct only where GraphQL genuinely can't do it.
- **Truly open — MIT licensed.** Fork it, ship it, build on it.
## Status
Early v1. Working tools:
| Tool | Description | API |
|---|---|---|
| `search_products` | Free-text catalog search → SKU, name, price, stock, image | GraphQL |
| `get_product` | Full product detail by SKU → description, pricing, discounts, stock, categories, media | GraphQL |
| `check_stock` | Batch availability check for up to 100 SKUs → in-stock flag + low-stock qty | GraphQL |
| `browse_categories` | Store category tree (departments + subcategories) with product counts | GraphQL |
| `get_category_products` | List products in a category by `uid`, with pagination & sorting | GraphQL |
| `create_guest_cart` | Start an anonymous shopping cart → returns a `cart_id` | GraphQL |
| `add_to_cart` | Add products (SKU + quantity) to a guest cart; per-item errors surfaced | GraphQL |
| `view_cart` | View a guest cart's line items and totals by `cart_id` | GraphQL |
| `login` | Authenticate a customer (email + password) → returns a `session_id` | GraphQL |
| `logout` | Revoke a `session_id` immediately | — |
| `get_customer` | Logged-in customer's profile & saved addresses (by `session_id`) | GraphQL |
| `get_order_status` | Logged-in customer's orders — status, totals, items, tracking | GraphQL |
| `set_shipping_address` | Checkout step 1: set guest email + address → available shipping methods | GraphQL |
| `set_shipping_method` | Checkout step 2: pick a shipping method → available payment methods + totals | GraphQL |
| `set_payment_method` | Checkout step 3: pick a payment method → confirm totals | GraphQL |
| `place_order` | Checkout final step: submit the cart → returns the order number | GraphQL |
| `get_my_company` | Authenticated customer's **B2B company** + team roster (optional) | GraphQL |
| `get_requisition_lists` | Authenticated customer's **B2B requisition lists** + items (optional) | GraphQL |
> **Note on B2B:** `get_my_company` and `get_requisition_lists` require the store to expose B2B data over GraphQL — the open-source [Orangecat B2B suite](https://github.com/olivertar/m2_b2bsdk) plus the companion modules ([`Orangecat_CompanyGraphQl`](https://github.com/nicolasperic/mage-os-b2b-graphql), [`Orangecat_ProductListsGraphQl`](https://github.com/nicolasperic/mage-os-b2b-requisition-graphql)). On stores without them, the tools return `supported: false` instead of erroring, so they stay safe to include against any store.
> **Prices are self-describing.** Every monetary value is returned as an envelope —
> `{ amount, currency, tax_mode, price_view, catalog_id, location_id }` — not a bare
> number. A storefront renders prices for a human who can see the context; an MCP
> client can't, and an agent handed `49.99` will repeat it as fact and be wrong for
> whichever audience sees the other tax treatment. Declare your store's treatment
> with `MAGENTO_TAX_MODE=incl|excl`; left unset we report `"unknown"` rather than
> guess. Catalog reads also surface **quantity price breaks** (`tier_pricing`) from
> native `price_tiers` — quoting a unit price without knowing 100+ drops it 30% is
> misleading, not merely incomplete.
> **Sessions:** `login` returns an opaque `session_id`; the underlying credential is held server-side and never returned. Sessions carry a scoped context with expiry and can be revoked (`logout`) — see the delegated-access model in [`docs/b2b-auth-model.md`](docs/b2b-auth-model.md).
> **Governance & audit:** every tool call is audited — a redacted, append-only record of who / what / outcome / timing — via a pluggable sink (`MCP_AUDIT`, `MCP_AUDIT_CHAIN` for tamper-evidence). This is the access-control + audit-trail foundation for adopting an MCP under SOC 2-style compliance. See [`src/governance/`](src/governance/README.md).
### End-to-end shopping flow
The tools compose into a complete "AI shops the store" journey:
```
search_products / browse_categories → discover
get_product / check_stock → evaluate
create_guest_cart → add_to_cart → build a basket
set_shipping_address → (returns shipping options)
set_shipping_method → (returns payment options + totals)
set_payment_method → place_order → order number 🎉
```
> **Note on checkout:** the flow uses Magento's **guest checkout** mutations. `place_order` is **irreversible** — an agent should confirm the totals with the user first (the tool description instructs it to). Offline payment methods (e.g. `checkmo`, Check / Money Order) work out of the box; online gateways that need client-side tokenization are out of scope.
> **Note on carts:** the cart tools use Magento's **guest cart** mutations (no login required). `add_to_cart` currently targets **simple products** by SKU; configurable/bundle products (which need selected options) are reported back in `user_errors` and are a planned enhancement.
> **Note on authentication:** `login` exchanges credentials for a Magento customer token via `generateCustomerToken`. The **token is stored server-side (in memory) and never returned** to the client — tools take an opaque `session_id` instead, so the raw credential stays out of the model's context. Sessions live for the server process lifetime; if it restarts, log in again.
## Requirements
- Node.js >= 20
- A reachable Magento 2.4+ / Mage-OS store with the storefront GraphQL endpoint enabled (the default)
## Setup
```bash
git clone https://github.com/<you>/mage-os-mcp.git
cd mage-os-mcp
npm install
cp .env.example .env # then edit .env
npm run build
```
### Configuration
Configuration is via environment variables (see `.env.example`):
| Variable | Required | Default | Description |
|---|---|---|---|
| `MAGENTO_BASE_URL` | ✅ | — | Store base URL, no trailing `/graphql`. e.g. `https://app.mage-os.test` |
| `MAGENTO_STORE_CODE` | | `default` | Store view code, sent as the `Store` header |
| `MAGENTO_INSECURE_TLS` | | `false` | `true` to accept self-signed certs (local Warden/Docker). **Never** in production. |
| `MAGENTO_TIMEOUT_MS` | | `15000` | Per-request timeout in milliseconds |
## Running
```bash
# Development (no build step, via tsx)
npm run dev
# Production
npm run build && npm start
```
The server speaks MCP over **stdio**. `stdout` is reserved for the protocol; logs go to `stderr`.
### Try it with the MCP Inspector
```bash
npm run inspect
```
## Testing
Unit tests (Vitest) run each tool against a mocked GraphQL client, so they need
no live store:
```bash
npm test # builds, then runs the suite once
npm run test:watch
```
CI (GitHub Actions) type-checks, builds, and tests on Node 20 & 22 for every
push and pull request — see [`.github/workflows/ci.yml`](.github/workflows/ci.yml).
### Use with Claude Desktop / Claude Code
Add to your MCP client config (e.g. Claude Desktop `claude_desktop_config.json`):
```json
{
"mcpServers": {
"mage-os": {
"command": "node",
"args": ["/absolute/path/to/mage-os-mcp/dist/index.js"],
"env": {
"MAGENTO_BASE_URL": "https://app.mage-os.test",
"MAGENTO_INSECURE_TLS": "true"
}
}
}
}
```
## Architecture
```
src/
├── index.ts # MCP server: registers tools, wires stdio transport
├── config.ts # env-based config loader
├── magento/
│ ├── client.ts # GraphQL client (Store header, TLS/timeout handling)
│ └── queries.ts # GraphQL documents (one place to review what we ask for)
└── tools/
├── searchProducts.ts # search_products
└── getProduct.ts # get_product
```
Each tool is a small, testable function that takes the GraphQL client + validated args and returns a plain JSON object. `index.ts` handles MCP registration and serialization. Adding a tool = one file in `tools/` + one query in `queries.ts` + one `registerTool` call.
## License
MIT — see [LICENSE](LICENSE).
TDQS
Scored across 11 tools
Every tool targets a distinct resource and action: catalog search vs. category browsing, product detail vs. stock check, and cart creation vs. cart viewing are clearly separated. Customer tools (login, get_customer, get_order_status) are also unambiguous in their scope.
The vast majority of tools follow a consistent verb_noun snake_case pattern (search_products, get_product, check_stock, add_to_cart, view_cart). The only deviation is 'login', which is a bare verb without an object, but this is a common and acceptable exception.
With 11 tools, the server is well-scoped for a storefront assistant. Each tool covers a meaningful step in catalog browsing, cart management, or customer account access without redundancy or bloat.
The catalog and customer account surfaces are well covered, but the cart workflow is incomplete: there is no way to update quantities or remove items, and there is no checkout or order placement tool. This creates a notable dead end after building a cart.