> ## Documentation Index
> Fetch the complete documentation index at: https://docs.staging.cope-demo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AI shopping agents

> Mount an MCP endpoint on your own server so a buyer's AI agent can build a cart in your store and hand the buyer a COPE checkout link.

# AI shopping agents

A buyer can ask an AI agent to shop for them. With the MCP endpoint in the Checkout SDK, that agent can find your products, build a cart and prepare a checkout in your store, then give the buyer a link to COPE's checkout page. The buyer accepts your terms and pays there themselves. An agent cannot accept terms or pay on the buyer's behalf.

The endpoint runs on your server, under your domain, with your publishable key. It speaks the [Model Context Protocol](https://modelcontextprotocol.io) (MCP), which AI agents use to call tools.

## Requirements

* A COPE publishable key (`cope_pk_live_...`).
* The success and cancel URLs you use for checkout, registered as redirect URLs in the COPE dashboard.
* A server that runs Node.js 20 or later, Bun, Deno, Cloudflare Workers or a Next.js route handler.

## Install

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
npm install cope-sdk @modelcontextprotocol/server zod
npm install @modelcontextprotocol/node   # only for node:http or Express
```

## Create a cart key

The endpoint gives agents an encrypted handle for each cart, so an agent never holds the cart's secret. Create a 32-byte key for that once, and store it as a server-side secret:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { generateCartRefKey } from "cope-sdk/mcp"

console.log(generateCartRefKey())
```

Keep this key out of browsers and source control. Anyone holding it can open and change the carts its handles point to.

## Mount the endpoint

On Node.js:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { createServer } from "node:http"
import { createCopeMcpNodeHandler } from "cope-sdk/mcp/node"

const mcp = createCopeMcpNodeHandler({
  publishableKey: process.env.COPE_PUBLISHABLE_KEY!,
  cartRefKeys: [process.env.COPE_CART_REF_KEY!],
  checkout: {
    successUrl: "https://shop.example.com/thanks",
    cancelUrl: "https://shop.example.com/cart",
  },
  allowedHosts: ["shop.example.com"],
})

createServer((req, res) => {
  if (req.url?.startsWith("/mcp")) return void mcp(req, res)
  res.statusCode = 404
  res.end()
}).listen(3000)
```

On Bun, Deno, Cloudflare Workers or a Next.js route handler, use the fetch handler instead. It does not need `@modelcontextprotocol/node`:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { createCopeMcpHandler } from "cope-sdk/mcp"

const mcp = createCopeMcpHandler({ /* the same options */ })

export function POST(request: Request) {
  return mcp.fetch(request)
}
```

Agents then connect to `https://shop.example.com/mcp`.

## Options

| Option           | Required | Meaning                                                                                                                                         |
| ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `publishableKey` | Yes      | Your `cope_pk_live_...` key                                                                                                                     |
| `cartRefKeys`    | Yes      | Cart keys, base64 or base64url, 32 bytes each. The first one encrypts and all of them decrypt                                                   |
| `checkout`       | Yes      | `successUrl` and `cancelUrl` for the checkout page. Both must be registered redirect URLs                                                       |
| `allowedHosts`   | Yes      | Host names the endpoint answers to. Requests for any other host are refused                                                                     |
| `allowedOrigins` | No       | Browser origins allowed to call the endpoint. Agents that call it from a server are not affected                                                |
| `rateLimit`      | No       | `{ perClientPerMinute, perStorePerMinute }`, 120 and 1200 by default, or `false` if you limit requests yourself. Counted in memory, per process |
| `clientKey`      | No       | How to tell clients apart for the per-client limit, for example from a trusted proxy's header                                                   |

## Tools

| Tool                                     | What the agent can do                                                                                                     |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `get_product`                            | Read a product and its prices                                                                                             |
| `create_cart`                            | Start a cart. Returns a `cartRef` that the other cart tools take                                                          |
| `get_cart`                               | Read the cart with current prices                                                                                         |
| `add_line`, `update_line`, `remove_line` | Change what is in the cart                                                                                                |
| `apply_promo_code`, `remove_promo_code`  | Apply or remove a promo code                                                                                              |
| `set_buyer_identity`                     | Record who is buying and where: email, name, country, postal code, company and VAT ID. Country and postal code decide tax |
| `start_checkout`                         | Prepare the checkout and return the link for the buyer. Calling it again returns the same checkout                        |

When a tool fails, its result includes a `guidance` string telling the agent what to do next.

## Rotate the cart key

1. Add a new key at the front of `cartRefKeys` and deploy. New handles use it, and existing handles still work.
2. After your longest-lived carts have expired, remove the old key and deploy again.

## Security

* The endpoint uses only your publishable key, the same key your storefront already exposes.
* Terms, consents and payment happen on COPE's checkout page, in the buyer's own browser.
