> ## Documentation Index
> Fetch the complete documentation index at: https://agentmall.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP tools

> Tools on the AgentMall MCP server.

Server: `https://mcp.getagentmall.com`. Every tool needs an organization API key. Inputs are `snake_case`. Walmart only (`mrc_walmart`). Prices and totals are integer cents.

Auth failures (`unauthorized`, `invalid_key`), the 15 requests a second per key limit (`rate_limited`), and the search cap (`daily_limit_reached`) are in [Auth and keys](https://agentmall.mintlify.site/auth-and-keys.md). A missing cart or checkout id is `session_not_found`. A cart that timed out, was cancelled or was checked out is `session_expired` (HTTP 410): start a new cart with `create_cart`.

Returns and refunds are not available. `commit_unknown` means the order may have been placed: call `get_order` and do not retry.

## Catalog

### `search_catalog`

Keyword search. Default `source` is `oxylabs`: Walmart's result page, reranked, about 5 seconds. Channel3 is asked at the same time; when its titles match and it answers first, the response is `source: "catalog"` in about 1 second. `source: "catalog"` is that index only. `source: "merchant"` reads Walmart search in the session browser and needs `session_id`.

A repeat of the same `oxylabs` or `catalog` query within 15 minutes returns `cached_at`. Merchant search is not cached. An empty default search falls back to Channel3 with `relevance: "low"`.

| Input | Type | Required |
| - | - | - |
| `merchant_id` | string | Yes |
| `query` | string | Yes |
| `source` | `"oxylabs"` \| `"catalog"` \| `"merchant"` | No |
| `session_id` | string | When source is merchant |

Returns up to 10 `products`: `id`, `merchant_id`, `title`, `brand`, `url`, `image_url`, `price`, `currency`, `availability` (`in_stock`, `out_of_stock`, or `null`). `oxylabs` and `catalog` also return `relevance` (`ok` or `low`) and a `hint` when relevance is low. Check titles before using a result.

| Code | What to do |
| - | - |
| `invalid_input` | Send a query. Merchant search needs `session_id`. |
| `merchant_unavailable` | Use `mrc_walmart`. |
| `provider_unavailable` | Wait and retry. |
| `catalog_unavailable` | That source is not configured. |

### `get_product`

Reads one product page. Returns `product` in the search shape, plus `reviews` (`rating`, `count`) when the page has them. When the product has selectable options (size, colour, pack count), the response includes `options` and `variants`.

`options` is the list of axes: `[{ name, values: [{ label, available }] }]`. `variants` is every combination: `[{ id, url, options: [{ name, label }], price, unit_price, availability, featured }]`. `price` and `unit_price` are integer cents when the merchant provides per-variant pricing, otherwise `null`. The variant the `url` pointed at is `featured: true`. Use the variant `id` in `update_cart` `line_items[].item.id` and its `url` in `line_items[].item.url`.

| Input | Type | Required |
| - | - | - |
| `merchant_id` | string | Yes |
| `session_id` | string | Yes |
| `url` | string | Yes |

| Code | What to do |
| - | - |
| `invalid_input` | Pass a product `url` and `session_id`. |
| `merchant_unavailable` | Use `mrc_walmart`. |

### `lookup_catalog`

Reads up to 10 pages in one call, one after another. Each id is a search `id` or `url`. A Walmart item id reads `https://www.walmart.com/ip/<id>`.

| Input | Type | Required |
| - | - | - |
| `merchant_id` | string | Yes |
| `session_id` | string | Yes |
| `ids` | string\[] | Yes, 1 to 10 |

Returns `products` and `failed` (`{ id, error }` per page). One bad page does not fail the call. An id that is neither an item id nor a product url fails the call with `invalid_input` before any page opens. `merchant_unavailable` if the merchant is not Walmart.

## Cart

A cart keeps one browser across its cart and checkout calls, including after a failed `create_checkout`. If that browser is gone, the call runs in a new one, which may be signed out with a different merchant cart, and the result or error has `browser_released: true`. Call `get_cart` before going on.

### `create_cart`

Starts an empty cart. The cart `id` is the id for later calls.

| Input | Type | Required |
| - | - | - |
| `shopper_id` | string | Yes |
| `merchant_id` | string | Yes |
| `account` | `"guest"` \| `"platform"` | No |

`guest` (default) is a new browser. Sign in with Evervault-encrypted email and password (`ev:…`). `platform` reuses the seeded signed-in AgentMall Walmart context and clears that shared cart.

| Code | What to do |
| - | - |
| `invalid_input` | `shopper_id` is required. |
| `merchant_unavailable` | Use `mrc_walmart`. |
| `platform_context_unavailable` | No seeded context. Create a guest cart instead. |

`cart_clear_failed` means the clear stopped partway. The error has `removed` and `left`. Call `create_cart` again to keep clearing.

### `get_cart`

Reads the live merchant cart. `session_id` is the cart id.

Returns `{ id, merchant_id, currency, line_items, totals }`. A line is `{ id, item, quantity, totals }`. `item` is `{ id, title, price, url }`. `totals` is merchandise only (`subtotal` and `total`). A line the merchant marks as currently unavailable carries `available: false` and a zero price. Remove it before checkout. A block page in place of the cart is `merchant_blocked`. Wait and retry. `update_cart` returns the same error when the clear hits that page.

| Code | What to do |
| - | - |
| `session_not_found` | Pass a cart id. |

### `update_cart`

Replaces the cart: clear, add each line, then read. An empty `line_items` only clears. A failed add stops the call. Each add has a 90-second server-side deadline. If the merchant does not respond in time the call returns `timeout`.

| Input | Type | Required |
| - | - | - |
| `id` | string | Yes |
| `line_items` | array | Yes |

Each line is `{ item: { id, url }, quantity, options }`. `url` is the product page. `quantity` is a whole number from 1 to 12. `options` is optional and names the size, colour, or pack, for example `{ "Clothing Size": "M" }`. List each product once.

| Code | What to do |
| - | - |
| `invalid_input` | Each line needs `item.id`, `item.url`, and a quantity. |
| `quantity_invalid` | Use a whole number of at least 1. |
| `quantity_above_max` | At most 12. |
| `already_in_cart` | Put the quantity on one line. |
| `option_required` | A size, colour, or pack is still open. The error lists each combination. Send `options` for the one the shopper wants. |
| `option_not_found` | That choice is not on the product. |
| `product_not_found` | The url is not a Walmart product page. |
| `product_unavailable` | Walmart will not sell it. The line is not added. |
| `timeout` | The add took too long. Call `get_cart` to see whether the item landed, then retry if it did not. |

`cart_clear_failed` means the clear stopped partway, before any add. The error has `removed` and `left`. Call again to keep clearing.

### `cancel_cart`

Returns the cart as last stored, then releases the browser. Pass `id`, the cart id.

| Code | What to do |
| - | - |
| `session_not_found` | Pass a cart id. |

## Sign-in

### `sign_in`

On a guest cart, pass `email` and `password` as Evervault `ev:` ciphertext (from `pnpm manager credentials collect`). Never send plaintext. A guest call without encrypted credentials returns `invalid_input` and does not open the browser. A platform cart uses `WALMART_EMAIL` / `WALMART_PASSWORD` as `ev:` ciphertext. With no encrypted platform account it returns `sign_in_unavailable` (`retry: "never"`, `next: "create_checkout"`).

Returns `{ signed_in: true }`, or `{ status: "challenge_required" }` when Walmart needs an SMS code. A challenge is a result, not an error. Then call `submit_sign_in_otp`.

| Code | What to do |
| - | - |
| `invalid_input` | Guest sign-in needs `ev:` email/password. |
| `sign_in_unavailable` | No encrypted account on a platform cart. |
| `sign_in_failed` | Retry once. |
| `credentials_required` | No encrypted Walmart login is configured. |
| `session_not_found` | Pass a cart id. |

### `submit_sign_in_otp`

Submits the SMS code after a challenge. Pass `cart_id` and `code`. Returns `{ signed_in: true }`.

| Code | What to do |
| - | - |
| `challenge_required` | No pending code. Call `sign_in` first. |
| `invalid_input` | `code` must be at least 6 digits. |
| `sign_in_failed` | The code was rejected. |

### `sign_out`

Signs the merchant account out. Pass `session_id` (the cart id).

| Code | What to do |
| - | - |
| `sign_out_failed` | Retry once. |

## Checkout

`create_checkout`, `get_checkout`, `update_checkout`, and `cancel_checkout` use the cart id. Checkout `id` and `cart_id` are that same id.

`fulfillment.delivery_date` is the date parsed from the delivery line already on the checkout: `{ earliest, latest, text }`. `latest` is null for one day. The field is null when that line has no readable date, and it is not part of `review_hash`.

### `create_checkout`

Opens checkout and returns it: `status`, `line_items`, `totals`, `fulfillment.methods`, `review_hash`. Nothing is placed.

| Input | Type | Required |
| - | - | - |
| `cart_id` | string | Yes |

| Code | What to do |
| - | - |
| `cart_empty` | Add lines with `update_cart` first. Don't retry. |
| `checkout_not_ready` | Retry once. |
| `sign_in_required` | Sign in, or pass an address on `update_checkout`. |
| `challenge_required` | Call `submit_sign_in_otp`, then try again. |
| `out_of_stock` | Remove `unavailable_items`, then try again. |
| `totals_unstable` | Retry once. |

`out_of_stock` means Walmart sent checkout back to the cart. `unavailable_items` lists the lines it flagged as `{ id, title }`. It is missing when those lines could not be read.

`totals_unstable` means the checkout total could not be verified against the line breakdown. `totals` has `unreadable` (the label that could not be parsed) or the `subtotal`, `tax`, `fees`, and `total` that were read, with `null` for any row that was missing.

### `get_checkout`

Re-reads the open checkout. Does not change the page. Pass `id`.

| Code | What to do |
| - | - |
| `not_on_review` | Call `create_checkout` first. |
| `review_unreadable` | The review page could not be read. |

### `update_checkout`

Writes an address, selects shipping, delivery, or pickup, or adds a vaulted card. Pass `id` and at least one of `fulfillment.address`, `fulfillment.method`, or `payment.instruments`. Returns the checkout, including a new `review_hash` and `fulfillment.methods`.

To show estimated shipping and tax before asking for a card, call `create_checkout`, then `update_checkout` with only `fulfillment.address` (and optionally `fulfillment.method`). The returned `totals` include subtotal, tax, and total with no card. Treat those as estimates until `complete_checkout`. `status` stays `incomplete` until payment is also set. `get_checkout` re-reads the same figures.

`fulfillment.address` is a US postal address: `street_address`, `address_locality`, `address_region`, `postal_code`, `address_country`, plus optional `first_name`, `last_name`, `extended_address`, `phone_number`. One of the names is required.

`fulfillment.method` is `{ id, kind, label }`. `kind` is `shipping`, `delivery`, or `pickup`. Use an id from `fulfillment.methods`. Time slots are not listed.

A card instrument is `{ id, handler_id: "dev.agentmall.card", type: "card", selected, credential: { type: "ciphertext", value } }` (Evervault `ev:…`). Collect cards in the console `/vault` page. The call does not take a raw card number.

| Code | What to do |
| - | - |
| `invalid_input` | Pass an address, a method, or an encrypted card. A card needs a `ciphertext` value. |
| `invalid_address` | US addresses only. |
| `delivery_method_not_found` | Use a method id from the checkout. |
| `address_vault_failed` | The address could not be saved. |
| `vault_tokenize_failed` | The card token could not be saved. |

### `cancel_checkout`

Leaves checkout without placing. Pass `id`. Returns the checkout with `status: "canceled"`. The cart stays open.

| Code | What to do |
| - | - |
| `not_on_review` | There is no open checkout. |
| `checkout_cancel_failed` | The browser did not leave checkout. |

### `complete_checkout`

Places the order when `review_hash` and `total_minor` still match the live review. One approval, one merchant commit. Not retried after submit may have happened.

| Input | Type | Required |
| - | - | - |
| `id` | string | Yes |
| `review_hash` | string | Yes |
| `total_minor` | integer | Yes |

Returns the checkout with `status: "completed"`, `order.id` and `test`. The cart session ends. With a test key (`am_test_`), the review is still read and checked, but nothing is submitted to the merchant: the order is stored as placed with `test: true`, `order.permalink_url` is empty, and there is no fee. A live key (`am_live_`) returns `test: false`.

| Code | What to do |
| - | - |
| `review_changed` | Nothing placed. Read the checkout again and confirm the new review. |
| `review_mismatch` / `total_mismatch` | Nothing placed. Read the checkout again. |
| `review_required` | Pass `review_hash` and `total_minor`. |
| `commit_unknown` | Do not retry. Call `get_order`. |
| `checkout_not_ready` | Checkout did not open. Retry once. |

`review_changed` also carries `review` (the live review), `reason` and `changes`. Each part of the review is hashed. `changes` lists the parts whose hash differs, as `{ field, before, after }`. `field` is `items`, `quantities`, `address`, `delivery`, `payment` or `total`. `reason` is the first part that differs, in this order:

| `reason` | What changed | What an automation should do |
| - | - | - |
| `item_unavailable` | An item was added or removed | Remove it or pick a replacement, then read the checkout and ask the user again |
| `quantity_changed` | The same items have a different quantity | Set the quantity, then read the checkout and ask the user again |
| `address_changed` | The address on the review is different | Check the address on `update_checkout`, then ask the user again |
| `delivery_changed` | The delivery method is different | Pass the method again on `update_checkout`, then ask the user again |
| `payment_changed` | A different card is on the order | Pass the card again on `update_checkout`, then ask the user again |
| `price_changed` | The total moved | Compare the new total with the user's limit, then ask again if it is higher |
| `unknown` | No saved review to compare, or nothing moved | Call `get_checkout` and ask the user again |

A price moves whenever an item, address or delivery moves, so `price_changed` is only the `reason` when nothing else changed. Read `changes` for every part that moved.

```json theme={null}
{
  "error": {
    "code": "review_changed",
    "reason": "item_unavailable",
    "changes": [{ "field": "items", "before": ["123", "456"], "after": ["456"] }]
  }
}
```

## Order

### `get_order`

Reads an order by platform `id` from `complete_checkout`. No session. Totals are cents. When the page has no total, or there is no merchant order to open, the stored order total is used. A failed live read is an error, not the stored row.

Returns `{ id, checkout_id, merchant_id, status, merchant_status, currency, totals, permalink_url, test }`. `status` is `completed` or `canceled` once placed, `pending` while the order is being placed, `failed` when the order was not placed, and `unknown` when the outcome is not yet known. `merchant_status` is the page text when the page has one. `test` is `true` for an order placed with a test key. A test order is returned as stored and the merchant is not opened.

| Code | What to do |
| - | - |
| `order_not_found` | Use the `order.id` from `complete_checkout`. |
| `unauthorized` | The key has no order history. |
| `order_unreadable` | The order exists. The page could not be read. |
| `operator_unavailable` | Retry later. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.