Home » Free ACP Payments Module » MCP Tools

MCP Commerce Tools Reference

The ACP Payment Module exposes seven MCP tools that together cover a complete conversational purchase: search_products, get_product, add_to_cart, view_cart, update_cart_item, remove_from_cart, and checkout. Six are always registered, and checkout appears when a checkout service is configured. Every tool returns a short human-readable summary followed by structured JSON, prices are always integer cents computed server-side, and because the transport is stateless, the cart_id returned by add_to_cart must be passed back on every later cart call.

How the Tools Are Designed for Agents

MCP tools succeed or fail on their descriptions, because the description is the only manual the agent reads. The module leans into that: each tool description states its contract, including the stateless cart rule, what an id refers to, and when to use a line id instead of a product id. Errors come back as readable messages with machine codes (missing, invalid, out_of_stock) and the MCP error flag set, so an agent can recover gracefully, retry with a fresh cart, pick a variant, or tell the shopper an item is unavailable, rather than stalling. Tool results pair a one-line summary (for the conversation) with a JSON body (for the agent's reasoning), a format that works well across MCP clients.

The transport behind the tools is streamable HTTP in stateless JSON mode: each request gets a fresh protocol session over a shared, long-lived commerce core, which is what allows any number of server instances to serve the same shoppers, and what makes the cart_id handshake necessary. State lives in the cart store, not the connection.

search_products

Inputs: query (optional string), limit (optional positive integer), offset (optional non-negative integer). Returns: a count summary and a products array.

With no query, it lists the catalog in order, paginated by limit and offset. With a query, it case-insensitively matches against each product's title, description, and id. The match is simple substring search, deliberate, predictable, and fast for the catalog sizes this module targets, which also means writing searchable titles and descriptions in your products file directly improves agent accuracy. Unavailable products still appear in results (with available: false), so an agent can explain that something exists but cannot be bought right now.

get_product

Inputs: product_id (string). Returns: the full product, including its variants.

The detail call an agent makes before adding to a cart, primarily to discover variant ids and prices. Asking for an unknown id returns a missing error naming the id, which agents reliably interpret as a cue to search again rather than retry.

add_to_cart

Inputs: product_id (string), variant_id (optional string), quantity (integer, default 1), cart_id (optional string). Returns: the full updated cart.

The workhorse. Omit cart_id and a new cart is created, with its id in the response, every later call must include it. If the product defines variants, variant_id is required and the error message says exactly that. Adding the same product and variant again increments the existing line rather than duplicating it. Quantities must be whole numbers from 1 up to 1,000,000, a bound that keeps totals far inside safe integer math. The returned cart always carries server-computed line amounts and totals, never client math, and every add re-validates price and availability against the live catalog.

view_cart

Inputs: cart_id (string). Returns: the cart with lines and totals.

More interesting than it looks: a cart read is also a reconciliation. Each line's price and title are re-derived from the current catalog, lines whose product vanished or became unavailable are dropped, and totals are rebuilt, so the cart an agent shows the shopper is always priced at this moment, not at add time. An expired or unknown cart_id returns a missing error, carts expire after the configured TTL (an hour by default), and the agent should simply start a new one.

update_cart_item and remove_from_cart

Inputs: cart_id, line_id, and for update a quantity (positive integer). Returns: the updated cart.

Both address a cart line by its line_id, the id of the row inside the cart, not the product id, and the descriptions warn agents about exactly that mix-up. Updating sets the line's quantity outright (it does not add), removing deletes the line, and both recompute the cart afterward. Using a product id where a line id belongs produces a missing error rather than a wrong edit.

checkout

Inputs: cart_id (string), buyer_email (optional string), buyer_name (optional string). Returns: checkout_session_id, payment_url, and the total in cents.

Registered only when a checkout service is configured, and the reason the rest of the tools exist. It converts the cart's lines into a checkout session, re-pricing once more against the catalog, creates a direct payment with the configured provider, and returns the hosted payment URL, with Stripe configured, a real Stripe Checkout page, the shopper opens to pay. The session enters in_progress, which freezes its pricing while the payment is live. Confirmation then arrives through the Stripe webhook, which completes the session and fires the order webhook to your systems. An empty cart fails with a clear validation error instead of creating an unpayable session.

The buyer fields are a courtesy, not a requirement: an email passed here rides along on the session and the order payload, useful when your fulfillment needs a destination address for a license key. The hosted Stripe page collects the authoritative payment details either way. Why this tool uses a hosted URL rather than charging directly is a deliberate trust decision, an MCP client cannot grant a delegated payment token, and shoppers should type card details only into Stripe, the trade-offs are laid out in payment modes.

A Complete Conversation, Tool by Tool

A shopper says they want the team license. The agent calls search_products with query license, sees pro-license with two variants, and calls get_product to confirm the team variant id and price. It calls add_to_cart with the product id, variant_id "pro-team", and no cart id, getting back cart c-123 with one line and a total. The shopper adds a credit pack, so the agent calls add_to_cart again with cart_id "c-123" and product_id "credits-1000". They change their mind on quantity, the agent calls update_cart_item with the credit line's line_id and quantity 2, then view_cart to read back the final totals in plain dollars. Satisfied, the agent calls checkout with the cart id and the shopper's email, receives a payment URL, and posts it in the chat. The shopper pays on the Stripe page, the webhook completes the session, and the seller's systems receive the order, the whole sale happened inside one conversation, with the module guaranteeing every number the agent quoted.

Embedding note: these tools register onto any McpServer instance with one call, registerCommerceTools(server, commerce, checkout), so they can sit alongside your product's existing tools. The wiring is shown step by step in the embedding guide.

Error Codes Agents Will See

Every failure path returns a consistent Error (code): message shape with the MCP error flag set. The codes worth knowing: missing means an id did not resolve, an unknown product, an expired cart, or a line id that is not in the cart, and the right agent move is to re-search or rebuild. invalid covers contract violations like buying a variant product without a variant id, a non-integer quantity, or checking out an empty cart, and the message always names the rule that was broken. out_of_stock means the product exists but has available set to false. Payment-stage failures surface as payment_declined and requires_3ds, which an agent should relay to the shopper rather than retry, the card holder has to act. Because the codes are stable strings, an embedding team can also branch on them programmatically when wrapping the tools in their own UX.

One operational behavior deserves a note: when a product disappears from the catalog while sitting in a cart, the line is dropped silently from the cart read, but the same situation in a checkout session generates a buyer-visible warning message attached to the session. The cart is treated as scratch space, the checkout as a quote the shopper is about to pay, so the closer money gets, the louder the module is about changes.