Skip to main content
Glama
Plaaasma

Printify MCP

by Plaaasma
README.md
# Printify MCP

An MCP server for running a print-on-demand store from an AI assistant: create products
on Printify, price them from their production cost, publish them, push them to every
Shopify sales channel, and render ad creative from the product mockups.

Fork of [TSavo/printify-mcp](https://github.com/TSavo/printify-mcp), substantially
extended. See [Differences from upstream](#differences-from-upstream).

## Why it exists

The Printify API alone gets you about two thirds of a working pipeline. The gaps that
this fills, each found by hitting it in production:

- **Prices are hand-typed.** Printify reports each variant's production cost, but nothing
  derives a price from it. `set_prices` does, in margin, markup or fixed mode, rounding
  upward so rounding never eats the target margin.
- **Publishing reaches one channel.** Printify publishes to Shopify's *Online Store*
  publication and stops. TikTok, Google & YouTube, Pinterest, Shop and POS stay
  unpublished until something else pushes them. `publish_to_sales_channels` does that.
- **Printify guesses the product type wrong.** A flask arrives typed "Mug", a candle as
  "Home Decor". Downstream channels map their taxonomy from that field.
  `set_product_category` derives it from Shopify's own category.
- **Ad creative is manual.** `create_product_carousel` and `create_product_ads` build
  vertical posts from the product's real mockups.

## Install

```bash
git clone https://github.com/<you>/printify-mcp.git
cd printify-mcp
npm install
npm run build
cp .env.example .env      # then fill in PRINTIFY_API_KEY
```

Register it with your MCP client. For Claude Code:

```json
{
  "mcpServers": {
    "printify": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/printify-mcp/dist/index.js"]
    }
  }
}
```

The server resolves `.env` from its own package directory, not the working directory, so
it works no matter where the host launches it from.

Only `PRINTIFY_API_KEY` is required. Shopify and Replicate credentials unlock the
sales-channel and image-generation tools respectively; without them those tools refuse
with setup instructions rather than failing obscurely.

## Tools

**Shops and catalog** — `get_printify_status`, `list_shops`, `switch_shop`,
`get_blueprints`, `get_blueprint`, `get_print_providers`, `get_variants`,
`get_defaults`, `set_default`

**Products** — `list_products`, `get_product`, `create_product`, `update_product`,
`delete_product`, `publish_product`, `unpublish_product`, `get_product_mockups`,
`upload_image`

**Pipeline** — `create_and_publish` runs create → price → publish → fan out to sales
channels → fix category in one call, reporting each stage separately so a partial failure
tells you exactly how far it got.

**Pricing** — `set_prices` (margin / markup / fixed, `dryRun` to preview)

**Sales channels** *(Shopify credentials)* — `list_sales_channels`,
`publish_to_sales_channels`, `get_channel_sales`, `list_channel_products`

**Categories** *(Shopify credentials)* — `suggest_product_category`,
`set_product_category`, `audit_product_categories`

**Creative** — `create_product_carousel` (numbered 1080×1920 photo slides),
`create_product_ads` (three vertical video variants; needs ffmpeg on PATH)

**Orders** — `get_orders`, `get_order`, `get_orders_by_day`, `get_orders_by_hour`,
`get_orders_by_month`, `get_orders_in_range`

**Webhooks** — `list_webhooks`, `create_webhook`, `delete_webhook`

**Images** *(Replicate)* — `generate_image`, `generate_and_upload_image`

**Docs** — `how_to_use` with a topic (`pipeline`, `product_creation`, `blueprints`,
`print_providers`, `variants`, `images`, `publishing`, `image_generation`) returns the
reference an agent should read before guessing.

## Notes worth knowing

- **Never publish a product twice.** Publishing an already-published product creates a
  second channel listing and orphans the first — no Printify link, still purchasable,
  unfulfillable. `publish_product` refuses unless `republish` is passed.
- **`external.id` is not reliably a Shopify product ID.** Immediately after publishing it
  can carry a `printify.me` handle. The channel tools wait until it points at the
  configured store; pass `shopifyProductId` to skip the lookup.
- **Errors are real errors.** No tool returns empty or placeholder data to paper over a
  failed request. A bad API key fails loudly at startup rather than quietly serving
  fabricated shops.
- Creative is built from product photography and text — no generative model touches it,
  so the output carries no AI provenance metadata.

## Differences from upstream

Added: order history and range queries, cost-based pricing, Shopify sales-channel
publishing, channel sales reporting, product-category correction, photo carousels and
video ads, tags/key features/sales-channel properties on create, print placement
(x/y/scale/angle plus image stacking), duplicate-title guard, and the `create_and_publish`
pipeline.

Fixed: `list_products` passed `(limit, page)` into a `(page, limit)` signature; the
products list silently returned an empty page on failure; a rejected API key produced two
fake shops and reported success; `update_product` forwarded camelCase variant keys the API
ignores, so price updates reported success and changed nothing; `publish_product` sent a
partial payload where Printify requires all seven flags.

## Requirements

Node 18+. ffmpeg on PATH for `create_product_ads` (the carousel tool does not need it).

## License

ISC, as upstream. See [LICENSE](LICENSE) — copyright TSavo, retained for the original
work.