SKILL.md
As tools abaixo aparecem com os nomes que o MCP da Clickmax registra. Se o seu cliente de IA prefixar nomes de tool (
mcp<servidor>,mcp<servidor>, ou outro), use o nome já prefixado que aparecer na sua lista de tools.
When this applies
Use this skill for offer-level commercial control: pricing/currency/checkout variants, cloning the main offer, readiness diagnostics, approval submission, archive/unarchive, and destructive delete.
Not this skill:
- product catalog identity/archive/delete -> use the direct product tools
Key assumptions
- the offer is the sellable variant; one main offer is created with the product
- lifecycle is
draft -> pending_approval -> active offersgetincomplete_reasonis the preflight diagnostic before approval- Sellability gate (internal checkout). An internal-checkout offer becomes approvable only when
offersgetincomplete_reasonreturns empty. For a fresh offer it typically flags:softDescriptor(the ≤15-char name shown on the buyer's card/invoice statement; some gateways trim it further, to ~13 alphanumeric chars),supportPhone,deliverables(what the buyer receives — required forcommunity|course|ebook|physical|other|software|mentorship; NOT forevent|services|consultancy), anddescription.supportEmaildefaults to the account owner's email, so it rarely blocks. External-checkout offers (anyexternalUrl) skip all of these. - Two blockers Max cannot fix:
sellerStatusandbankAccountStatuscome from the seller's own payout onboarding (identity + bank account); no offer edit clears them. Surface them as "finish your seller/payout registration" and stop. - Custom support email = verified flow. The default support email is the account owner's, so
supportEmailrarely blocks. A DIFFERENT address must be registered (offerscreatesupportemail) and then verified by the user clicking a link sent to that inbox (out-of-band). Only afterverifiedAtis set (check viaofferslistsupportemails) can it be attached withoffers_update(offerSupportEmailId); attaching an unverified one fails. Do not register a custom email unless the user explicitly wants one. - Product image ≠ checkout banner — never confuse them.
bannerDesktop/bannerMobile(settable viaoffersupdate) are the checkout's promotional banner art. The product's OWN image (the photo/thumbnail that represents the product) is a SEPARATE slot: it is set by uploading a file to the offer's product-image slot, and NO offer field turns an arbitrary image URL into it —offersupdatecannot set the product image. Never drop a product image intobannerDesktop/bannerMobileas a stand-in; that is a different thing (checkout background art). - Approval is moderated, not automatic.
offerssendtoapprovalmoves a cleared offer to review (pendingapproval); a human moderator turns itactive. Max can complete fields and submit, never self-approve. Checkout sells only anactiveoffer; before that it renders as preview only. offers_createcreates secondary offers only; clone-main is the safer variant pathoffers_updatepreserves the same offer id and existing checkout identity- Offer type matters: internal offers sell through Clickmax checkout; external offers redirect/use
externalUrl - Public checkout identity is exposed as
hash; keep it stable unless the user intentionally creates/clones a different offer - Prices use the smallest currency unit; recurring behavior is controlled by
isRecurrentand payment configuration, not product identity alone quantityItemscontrols delivered/sold quantity semantics for the offer varianttype(offer nature) is a full enum, not a physical/other binary:community | course | ebook | event | physical | other | services | software | consultancy | mentorship. Pick the specific value that matches the product (e.g. a course product's offers usecourse, notother) — never default non-physical offers toother.
Thought process
- Distinguish read/diagnose from variant creation from lifecycle activation.
- Prefer cloning the main offer when the user wants a close derivative.
- Run incomplete-reason diagnostics before approval submission.
- Confirm destructive delete when intent is not already explicit.
Execute guide
- Use
offers_getto inspect one offer by id. - Use
offersgetincomplete_reasonbefore approval to identify every blocking item for that offer id. - Use
offers_createto create a secondary offer under the same product, passing the product id, offer name, price fields in cents, currency, and the intendedpaymentConfig. - Use
offersclonemainofferwhen the user wants a new variant that inherits the current main-offer setup for the product id. It does NOT auto-inherit everything:name,originalPrice, andpaymentConfigare required inputs even though other offer fields are copied — supply them explicitly (reuse the main offer's own values fromoffersgetwhen the user just wants a near-identical clone). - Use
offersupdatewhen the user wants to keep the same offer id and checkout identity while changing commercial fields such as name, price, default installment, currency, orpaymentConfig. This is a FULL REPLACE, not a patch —name,type,productType,currency,originalPrice,defaultInstallment, andsupportPhoneare all required on every call. Calloffersgetfirst and resend the complete set with only the intended field changed; sending just the changed field(s) fails validation on the rest. - Use
offerssendto_approvalonly after blockers are cleared for that offer id. - Use
offersarchiveoroffersunarchivefor lifecycle visibility changes without deleting the offer. - Use
offers_deleteonly for explicit permanent removal and expect failure when transaction history prevents deletion. - Use
offersaddmembershipdeliveryto make an offer deliver a Clickmax members-area classroom (offerId+portalId+classroomId); it adds aninternalmembershipdeliverable so buyers get classroom access. Build the members area first (clickmax-members-area) to get the portal/classroom ids. Adds a deliverable, does not replace existing ones. - Use
offersaddlinkdeliveryto deliver external link(s) the user already has (a hosted PDF, a Drive/Notion page, a third-party course area): passofferId+links([{ title, url }], http(s)). Prefer this overoffersaddmembershipdeliverywhen the deliverable is NOT a Clickmax classroom. Never fabricate the URL — ask the user for it, or offer to build a members area when they have no destination yet. - Use
offersaddfiledeliveryto deliver a file the user uploads (e.g. a PDF). Whendeliverablesis a blocker and the user has the material as a file, OFFER a direct file upload first — let them attach it in the chat and use the publicurlyou get back, plus atitle(optionaldescription). Don't force them to find or host a link for something they can simply upload. Reserveoffersaddlinkdeliveryfor a deliverable that already lives at an external URL, andoffersaddmembership_deliveryfor a Clickmax members-area classroom. - Readiness wizard (make an offer sellable). ASK FIRST, ACT SECOND — never auto-fill or auto-decide. The FIRST step of completing an offer is a single
questionbatch collecting the checklist below (deliverable type + support phone + support email + product image); you MUST NOT calloffersupdate/offersadd*/offerssetproductimage/offerssendtoapprovalbefore you have the user's answers. NEVER guess the deliverable (e.g. silently assume a members area), never auto-fill the phone/email, never skip the image — executing without asking is the WORST failure of this flow, and it keeps happening in long conversations, so treat "I already have enough to just run the tools" as a red flag: ask.offersgetincompletereasonis ONLY a preflight check — do NOT use it as the question list. ALWAYS walk the user through this FIXED checklist; some items are NOT inincompleteReasonyet MUST still be asked (support email has a default, product image is a frontend-only pendency). Ask them (batch the simple ones), then fill each:
- invoice name (softDescriptor) — pre-fill a ≤15-char suggestion for the user to confirm/edit → offersupdate; - support phone (supportPhone) → offersupdate; - support email — ALWAYS ask, even though it is NOT a blocker. Read the offer's current supportEmail via offersget and SHOW it as the default (e.g. "e-mail de suporte atual: [email protected] — manter ou trocar?"); keep it, or if the user gives a different address run the verified-email flow below; - description (min 50 chars — incompleteReason only checks presence, not length, so expand a too-short one before saving) → offersupdate; - deliverable — ONLY when the offer type requires one (community|course|ebook|physical|other|software|mentorship; NOT event|services|consultancy). FIRST ask how the buyer receives it (one select: upload a file/PDF · an external link · a Clickmax members area); do NOT assume the type. THEN branch: file → upload → offersaddfiledelivery; link → ask URL (+ title) → offersaddlinkdelivery; members area → get/create portal+classroom (clickmax-members-area) → offersaddmembershipdelivery; - product image — ALWAYS offer it. It is NEVER in incompleteReason (frontend-only pendency), so you MUST ask proactively: have the user upload an image, then offerssetproductimage (offer id + uploaded URL). Never route it to the banner. Then re-run offersgetincompletereason until empty and offerssendtoapproval. If it returns sellerStatus/bankAccountStatus, stop and route the user to the Carteira Clickmax to finish payout registration — not fixable here. Offer it with a navigation CTA action="open-page" path="/sales/wallet" (the wallet lives at /sales/wallet, NEVER /wallet).
- Custom support email (only if the user wants one different from the account's):
offerscreatesupportemail→ user clicks the link sent to that inbox → confirm viaofferslistsupportemails(verifiedAtset) → attach the id viaoffersupdate(offerSupportEmailId).offersresendsupportemail_validationre-sends the link. The account email already satisfies the gate, so this is optional polish. - Product image: to set or replace the product's main image, collect the image (ask the user to upload it) and then call
offerssetproductimagewith the offer id + the uploaded image URL. Do NOT useoffersupdatefor this, and NEVERbannerDesktop/bannerMobile(separate checkout banner art). It is a common product pendency worth offering during product creation/completion. - Exact param names for the delivery/image tools (call them directly — no need to inspect the schema first):
offerssetproductimagetakesofferId+imageUrl(the param isimageUrl, notimage);offersaddfiledeliverytakesofferId+url+title(+ optionaldescription) for a SINGLE file — it is NOT an array and NOT afilesfield;offersaddlinkdeliverytakesofferId+links, wherelinksIS an array of{ title, url };offersaddmembershipdeliverytakesofferId+portalId+classroomId.
Report
- Start with the offer identity and whether it is main or secondary.
- Then report lifecycle state, commercial settings changed or inspected, and any remaining blockers.
- For approval requests, say clearly
ready for approvalor list each blocking item. - For create/clone/update/archive/unarchive/delete actions, state the action result first and keep follow-up actions opt-in.
Warnings
- Do not create a new secondary offer when the user really wants to modify the existing offer.
- Approval is not automatic; diagnostics matter. It is moderated by a human — never report an offer as approved/live just because it was submitted.
sellerStatus/bankAccountStatusblockers are the seller's payout onboarding; no offer edit clears them.- Never fabricate deliverable content — ask the user for the link, or build a members area; do not invent a URL or auto-generate files.
- Route images by intent: an image FOR the product ("add an image to product X", "imagem do produto") →
offerssetproductimage, NEVER the banner. Only usebannerDesktop/bannerMobile(viaoffersupdate) when the user explicitly asks for checkout banner art. A "product image" request must never end up inoffers_update. - Delete can be blocked by transaction history.
Anti-patterns
- Treating product and offer as the same object.
- Sending to approval without checking blockers.
- Treating
externalUrlor checkouthashas cosmetic fields.