Developer documentation

InkFE MCP connector

A Model Context Protocol server that lets an assistant browse the InkFE print catalog, personalise a business card template, and take a buyer all the way to a Shopify checkout with the print-ready artwork attached.

Getting access

The connector is available to approved assistants and integrators. To request an API key, email orders@inkfe.com with the name of your product and how it will use the connector. Keys can be rotated or revoked on request.

Add the server to any MCP client that supports Streamable HTTP:

{
  "mcpServers": {
    "inkfe": {
      "type": "http",
      "url": "https://www.inkfe.com/api/mcp",
      "headers": { "Authorization": "Bearer <api key>" }
    }
  }
}

Or, from the Claude Code CLI:

claude mcp add --transport http inkfe https://www.inkfe.com/api/mcp --header "Authorization: Bearer <api key>"

Endpoint

  • URL: https://www.inkfe.com/api/mcp
  • Protocol: MCP over Streamable HTTP (stateless)
  • Server name: inkfe-print, version 0.1.0

Send each JSON-RPC 2.0 request as a POST with Content-Type: application/json and Accept: application/json, text/event-stream. Responses are delivered as a single server-sent message event containing the JSON-RPC response. No session id is required.

POST https://www.inkfe.com/api/mcp
Authorization: Bearer <api key>
Content-Type: application/json
Accept: application/json, text/event-stream

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"your-client","version":"1.0"}}}

Tool names and required arguments are stable within a major version. Optional fields and new tools may be added at any time; breaking changes are released under a new version number and announced to key holders in advance.

Authentication

Every request must include your API key in the Authorization header:

Authorization: Bearer <api key>

Requests without a valid key receive 401 Unauthorized. Treat the key like a password: store it in your client's secret configuration, never in prompts, logs or client-side code, and contact support to rotate it if it may have been exposed.

Flow

  1. Discover. Call list_business_card_templates. Show the buyer the preview images and the fields each template needs; use search_products and get_product for any other print product.
  2. Collect. Help the buyer pick a template and gather a value for every required field. Logo fields take a public https PNG or JPEG URL; QR fields take the https URL the code should open.
  3. Design. create_business_card_design applies the values (and logo) to the template, fits the text, renders front and back previews, and returns a design token. Show the buyer both previews before moving on.
  4. Checkout. Once the buyer approves the previews and chooses a value for every option get_product lists (for example Corners and Quantity), create_checkout attaches the print-ready artwork to a Shopify cart and returns the checkout URL. Shipping and payment are collected on that page.

Tools

Every tool returns JSON in a single text content block. Arguments are validated against the schema advertised by tools/list; invalid arguments return an isError result describing the problem.

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_business_card_templates","arguments":{}}}
HTTP/1.1 200 OK
Content-Type: text/event-stream

event: message
data: {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{ \"templates\": [ ... ] }"}]}}

search_products

Free-text search over the public InkFE catalog. Use it to find products other than template business cards, or to confirm a handle before calling get_product.

Input

  • query (string, 1-160 characters) Matched against product titles, types and tags.
  • limit (integer 1-20, default 10) Maximum number of products returned.

Returns

{ products: [{ handle, title, productType, priceRange: { min, max, currency }, options: [{ name, values }], url }] }

Error codes

connector_unavailable, internal_error

get_product

Describes one public product: options with their roles, every purchasable variant with its pack price, whether a back side is printed, and the trim size when known.

Input

  • handle (string, 1-255 characters) The product handle exactly as returned by search_products or list_business_card_templates.

Returns

{ handle, title, productType, hasBack, dimensions: { widthInches, heightInches } | null, options: [{ name, role, values }], variants: [{ variantId, title, selectedOptions, packPrice, currency, availableForSale }], url }

Error codes

product_unavailable, connector_unavailable, internal_error

list_business_card_templates

The starting point for a business card. Lists the Classic templates a buyer can personalise, with preview images, physical size, the product to buy and the fields each template needs.

Input

No arguments.

Returns

{ templates: [{ templateId, name, orientation, widthInches, heightInches, previewUrls: { front, back }, hasBack, fields: [{ attribute, label, side, inputType, required, sampleValue, maxLines? }], productHandle }] }

Error codes

connector_unavailable, internal_error

create_business_card_design

Applies the buyer's field values (and logo, if the template needs one) to a template, fits the text to its printable area, renders both sides as preview images, and returns a design token to redeem with create_checkout.

Input

  • templateId (positive integer) The templateId from list_business_card_templates identifying which Classic business card to design.
  • fields (object, string values, at most 64 keys / 2000 characters each) Every field from the template's `fields` list, keyed by `attribute`, is required. A blank or missing value fails with missing_required_fields.
  • logoUrl (https URL, at most 2048 characters, optional) A public PNG or JPEG image, required only when the template has an imageUrl field.

Returns

{ designToken, designId, templateId, revisionId, expiresAt, previews: [{ side, url, expiresInSeconds: 300, width, height }], warnings: [{ attribute, layerId, code: "text_shrunk", fromFontSize, toFontSize }], nextStep }, plus the same two preview images attached as PNG image content blocks.

Error codes

unknown_template, missing_required_fields, unknown_field, value_too_long, unsupported_characters, logo_required, logo_fetch_failed, logo_unsupported, rate_limited, connector_unavailable, internal_error

create_checkout

Turns a design token from create_business_card_design plus the buyer's chosen pack options and email into a Shopify checkout URL, with the print-ready artwork attached to the line item.

Input

  • designToken (string, 1-4096 characters) The designToken returned by create_business_card_design for the design the buyer approved.
  • selectedOptions (array of { name, value }, 1-8 entries, unique names, each 1-255 characters) Every customer-facing option get_product lists for the business card product, keyed by option name with the buyer's chosen value exactly as listed.
  • buyer ({ email, name? }) email is used for the Shopify guest cart; name (at most 120 characters) is optional and kept for reference only.

Returns

{ checkoutUrl, cartId, designAssetId, lineItem: { productTitle, variantTitle, packPrice, currency, selectedOptions }, instructions }

Error codes

design_token_invalid, design_token_expired, design_not_found, unknown_template, product_unavailable, variant_unavailable, rate_limited, storage_failed, cart_create_failed, connector_unavailable, internal_error

Error envelope

A failed tool call is still HTTP 200 and a JSON-RPC result: the result has isError: true and its single text block is a JSON envelope with a stable code, a human-readable message and optional details.

{
  "content": [
    {
      "type": "text",
      "text": "{\"error\":{\"code\":\"product_unavailable\",\"message\":\"This product is not available for purchase.\",\"details\":{\"handle\":\"unknown-handle\"}}}"
    }
  ],
  "isError": true
}
CodeMeaning
connector_unavailableThe connector is temporarily unavailable. Retry later.
internal_errorAn unexpected error on our side. Retry the call; contact support if it persists.
product_unavailableThe handle is unknown or the product is not sold publicly. details.handle echoes the request.
unknown_templateThe templateId is not in the connector's template list.
missing_required_fieldsOne or more required fields were blank. details.attributes lists them.
unknown_fieldA field key the template does not have (or logoUrl was given for a template with no logo field). details.attribute names it.
value_too_longA value does not fit its layer even at the smallest allowed size. details.attribute names it.
unsupported_charactersA value contains characters the template font cannot print. details.attribute names it.
logo_required / logo_fetch_failed / logo_unsupportedThe template needs a logo, the logo URL could not be fetched (https only, 10 MiB cap), or the image is not a readable PNG or JPEG between 32 and 8000 pixels on each side.
design_token_invalid / design_token_expired / design_not_foundThe design token is malformed, older than seven days, or its stored design no longer exists.
variant_unavailableNo purchasable variant matches selectedOptions. details.selectedOptions and details.availableOptions echo the request and the product's real options.
rate_limitedThe rate limit for this key or design was exceeded. details.retryAfterSeconds says when to retry.
storage_failed / cart_create_failedThe artwork could not be stored, or the cart could not be created. cart_create_failed carries details.userErrors.

Rate limits and timeouts

  • create_business_card_design: 20 calls per minute per API key.
  • create_checkout: 3 calls per hour per design and 8 per hour per buyer email. Each call creates a new cart; reuse the returned checkoutUrl rather than calling again.
  • Exceeding a limit returns rate_limited with details.retryAfterSeconds.
  • Requests time out after 300 seconds.
  • search_products queries are limited to 160 characters and 20 results.
  • Logo images must be publicly reachable over https, PNG or JPEG, at most 10 MiB, and between 32 and 8000 pixels on each side.

Data handling

  • A design token is valid for 7 days. The field values and preview images behind it are retained for that period so the token can be redeemed; preview URLs themselves expire after 5 minutes, and the same images are returned inline with the response.
  • When a checkout is created, the print-ready artwork is attached to the cart and retained with the resulting order for production and reorders, exactly as for designs made on inkfe.com.
  • The buyer's email is used to start the checkout; shipping and payment details are collected on the checkout page and never pass through the connector.
  • Logo images are fetched once from the URL you provide and stored only as part of the design.

Support

Questions about keys, the template list or an order placed through the connector: orders@inkfe.com. Include the tool name and error code from the response; never include your API key.

To report a security issue, email the same address with "Security" in the subject line.

Your design changed

Your design changed elsewhere. Refresh to load the currently saved design.