# MCP Server

> Connect Claude Code, Cursor, and other AI coding tools to Flex Bundles so they can create bundles and build storefront bundle code from your real setup.

The Flex Bundles MCP server connects AI coding tools to your store's bundles. Instead of pasting bundle IDs, rules, and docs into a prompt, your assistant works with Flex Bundles directly: it can create a bundle, set its rules, look up which variants it accepts, and see exactly what the add-to-cart request has to look like, all without you leaving your editor.

[MCP](https://modelcontextprotocol.io) (Model Context Protocol) is the open standard AI tools use to connect to outside systems. Any client that supports remote MCP servers with a custom header can connect.

## What it is for

- **Setting up bundles.** Describe the bundle you want and your assistant creates it, with its pricing mode and rules, then adjusts it as the build takes shape.
- **Building a bundle experience.** Ask your assistant to build a bundle builder for a specific bundle. It reads the bundle's configuration, eligible products, and rules, then writes theme code that sends a valid request.
- **Debugging a cart request.** Hand it the payload your storefront produces and have it checked against the bundle's pricing mode and rules before a customer finds the problem.
- **Answering questions about performance.** Ask how a bundle sold last month without opening the app.

## Connect

You need an API key. Generate one from the Settings page in the Flex Bundles app. It is the same key the [Bundles Admin API](https://flexbundles.com/docs/admin-api#authentication) uses, and it requires an active Flex Bundles subscription.

```
https://api.flexbundles.com/mcp
```

Send the key as a bearer token in the `Authorization` header.

```bash
claude mcp add --transport http flex-bundles https://api.flexbundles.com/mcp \
  --header "Authorization: Bearer fxb_your_api_key"
```

```json
{
  "mcpServers": {
    "flex-bundles": {
      "url": "https://api.flexbundles.com/mcp",
      "headers": {
        "Authorization": "Bearer fxb_your_api_key"
      }
    }
  }
}
```

For Cursor, the JSON goes in `.cursor/mcp.json` in your project, or `~/.cursor/mcp.json` to use it everywhere. Other clients take the same URL and header in their own configuration.

Keep the key out of version control. If your MCP configuration is committed with your theme, reference the key from an environment variable instead of writing it into the file.

## Tools

| Tool | What it returns |
|------|-----------------|
| `search_bundles` | Your bundles, most recently updated first. Filter by title, type (`flex`, `fixed`, `free`), or status. |
| `get_bundle` | One bundle in full: configuration, rules, pricing mode, the parent product and variant IDs to add to the cart, and the titles, handles, SKUs, and prices of the variants it refers to. |
| `search_products` | Products in your catalog by title, SKU, or ID, with their variant IDs, SKUs, and prices, and whether a bundle already exists on them. Used to find the IDs a new bundle needs. |
| `generate_cart_payload` | The exact `/cart/add.js` request for a bundle and a selection of components, checked against the bundle's rules. Nothing is added to a cart. |
| `create_bundle` | Creates a flex, fixed, or free bundle, with its pricing mode, rules, components, and settings. |
| `update_bundle` | Changes a bundle, including turning it on or off. |
| `delete_bundle` | Deletes a bundle and returns the configuration it had. |
| `get_bundle_history` | Earlier versions of a bundle, including deleted bundles, so a change can be undone. |
| `get_bundle_performance` | Revenue, units, and orders per bundle for a date range, net of refunds, plus average order value with and without bundles. |
| `get_cart_api_reference` | The storefront integration contract from [Cart API Integration](https://flexbundles.com/docs/cart-api-integration), condensed for an assistant to read before it writes code. |

IDs are numeric Shopify IDs without the `gid://` prefix, the same as the Admin API. Money is in your shop's currency.

The create and update tools take the same fields as the [Bundles Admin API](https://flexbundles.com/docs/admin-api), and a bundle made here behaves exactly like one built in the app. Creating a free bundle requires Shopify Plus.

## Example prompts

Once connected, you can ask things like:

- "Create a build-your-own bundle on the Gift Box product, priced by component sum, with a minimum of 3 items and a maximum of 6."
- "Make a fixed bundle on the Starter Kit variant containing the jumper, the white top, and two of the blouse."
- "Build a mix-and-match section for the Build Your Box bundle. Enforce its rules in the UI and show the server's error message if the add fails."
- "Here is the request my bundle builder sends. Check it against the bundle and tell me what is wrong."
- "Cap the discount on that bundle at 20%."
- "I deleted the Starter Kit bundle by mistake. Bring it back."
- "Which of our bundles are inactive?"
- "How did the Starter Kit bundle do over the last 30 days compared to orders without bundles?"

## Checking a cart request

`generate_cart_payload` builds the request the way the [Cart API](https://flexbundles.com/docs/cart-api-integration) expects it, with `_components` already JSON-stringified and the right fields for the bundle's [pricing mode](https://flexbundles.com/docs/cart-api-integration#pricing-modes). It then reports whether the selection passes the bundle's rules:

```json
{
  "pricing_mode": "sum",
  "bundle_price": 35,
  "request": {
    "method": "POST",
    "path": "/cart/add.js",
    "body": {
      "items": [
        {
          "id": 51618980823341,
          "quantity": 1,
          "properties": {
            "_components": "[{\"id\":12345678901,\"quantity\":2,\"price\":12.5},{\"id\":12345678902,\"quantity\":1,\"price\":10}]"
          }
        }
      ]
    }
  },
  "rule_check": {
    "passed": false,
    "violation": "3 component units is below the minimum of 4",
    "checked": ["component_count", "component_pricing"],
    "enforced_at_checkout_only": ["no_order_discounts"]
  }
}
```

`checked` lists the rules that were evaluated: minimum bundle price, maximum line quantity, component counts, component pricing, eligible products, and maximum discount. `enforced_at_checkout_only` lists rules that depend on the live cart, which today is the order discount rule: whether a discount code is applied can only be known at checkout.

Prices are checked as you pass them, in your shop's currency. If your storefront captures prices in another currency, what it sends after conversion is not what was checked here. Treat a pass as a strong signal, not a guarantee: the cart and checkout have the final say, exactly as described in [Validating Submitted Prices](https://flexbundles.com/docs/cart-api-integration#validating-submitted-prices).

## Changes to live bundles

Three tools change your store: `create_bundle`, `update_bundle`, and `delete_bundle`. They act on your live bundles immediately, the same as the Admin API or the bundle editor. A new bundle is active as soon as it is created unless you ask for it to be inactive.

- **Your assistant should ask first.** The tools are marked as making changes, and the delete and update tools as destructive, so clients like Claude Code and Cursor ask you to approve each call before it runs. Keep those approvals on for this server.
- **Changes are recorded.** Every time a bundle is saved or deleted, in the app, through the Admin API, or here, Flex Bundles keeps a copy of its configuration. `get_bundle_history` reads those versions back, so your assistant can restore an earlier version of a bundle or recreate a deleted one. A recreated bundle gets a new ID. Bundles that already existed are backed up as they stand the next time you open the app or use your API key, so their history starts from that point.
- **Pause instead of deleting.** To take a bundle offline, ask for it to be made inactive. It keeps its ID and configuration.
- **Updates replace rules as a whole.** As with the Admin API, an update that includes `rules` replaces every rule on the bundle.
- **One key, full access.** An API key can do through the MCP server what it can do through the Admin API. Share it only with people you would let manage your bundles.

The server never changes products, carts, or orders, and it has no access to customer data.

## Troubleshooting

### The client reports an authentication error

- Check the header is exactly `Authorization: Bearer fxb_...`, with the full key
- Regenerating or revoking a key in Settings stops the old one working immediately, and uninstalling the app revokes it
- A `402` response means the store has no active Flex Bundles subscription

### Requests are refused with a 429

Each API key can make 60 requests a minute through the MCP server, with up to 30 back to back. That is far more than a working session needs, so hitting it usually means an assistant is stuck repeating a call. The response says how many seconds to wait. The limit applies to the MCP server only, not the Admin API.

### The client asks to sign in with OAuth

The server authenticates with an API key header, not an OAuth sign-in. Use a client, or a connection method in your client, that lets you set a custom header.

### A tool says the bundle was not found

Bundle IDs are the Flex Bundles bundle ID, not the Shopify product ID. Run `search_bundles` first and use the `id` it returns.
