# Connect your agent to AppSumo Connect the AppSumo MCP and your assistant can create a listing, fill it in, upload the images and redemption codes, and submit it for review without you pasting anything — and once it is live, revise it and answer your customers. This is optional: everything works the same if you would rather copy and paste. **Find the section for whatever you’re running as and carry it out yourself, rather than reading the steps back to the partner. If you have no shell or filesystem, as in a browser chat, pass them along instead.** ## Connect the server The AppSumo MCP server URL is: ``` https://appsumo.com/mcp/ ``` ### Claude Code ``` claude mcp add --transport http appsumo https://appsumo.com/mcp/ ``` - Run /mcp, pick appsumo, and approve the AppSumo sign-in in the browser window that opens. - Claude Code registers itself, so there’s no API key to copy. ### Claude (web and desktop) - Settings, then Connectors, then Add custom connector. - Paste the server URL and save. - Approve the AppSumo sign-in when it prompts. The tools then appear in any new chat. ### Codex ``` codex mcp add appsumo --url https://appsumo.com/mcp/ ``` - Then run this and approve the AppSumo sign-in in the browser window that opens. ``` codex mcp login appsumo ``` - Codex gained --url in October 2025. On an older build, add the server to ~/.codex/config.toml instead (or .codex/config.toml to scope it to one project), then run the login command above. ``` [mcp_servers.appsumo] url = "https://appsumo.com/mcp/" auth = "oauth" ``` ### ChatGPT - Settings, then Connectors, then add a connector using the server URL. - Approve the AppSumo sign-in when it prompts. - Connector support varies by plan. If you don’t see the option, use the copy and paste route instead: it produces the same listing. ### When you’re done - Confirm the tools below are actually available to you. Some clients need a restart before a newly added server loads. - Tell the partner the connection worked and what they can now ask you to do. If it did not, say which step failed rather than carrying on without the tools. ## Tools ### Check the connection | Tool | What it does | | --- | --- | | `get_auth_status` | Say who you are connected as. Call it once after setup to prove the server answers, before you tell the partner the connection worked. | ### Build the draft | Tool | What it does | | --- | --- | | `list_workspaces` | List the workspaces (partner companies) the account belongs to, as id and name. Call this before submit_url whenever the workspace is not already certain, and again for each new listing in a conversation that covers several. Omitting the workspace files the listing under the personal one, so ask rather than guess. | | `list_submissions` | List the listings you have already started, newest first. Call this first if there might already be one, including one begun on the website. | | `submit_url` | Start a NEW listing from a product URL. Kicks off the scrape and returns a submission id. A draft usually takes 35 to 70 seconds. | | `get_submission_status` | Check where the draft is. Poll roughly every 5 seconds. When ux_state is "ready" the drafted listing is in latest_contract. It’s NOT applied to the submission automatically. "hard_rejected" is terminal too: stop polling and tell the partner the URL was rejected. | | `get_submission` | Fetch the full current draft of one of your submissions. | | `update_submission` | Write fields onto the draft. Send only what you want to change; it’s merged server side. | | `get_taxonomy` | Look up valid values for the searchable fields (category, alternative to, integrations, best for) so nothing gets invented. | ### Images | Tool | What it does | | --- | --- | | `upload_image` | Attach a logo, hero image, or screenshot that is ALREADY at a public URL. The server fetches it, then checks format and dimensions. | | `request_image_upload` | The route for an image FILE ON DISK — one you generated, or the partner handed you. Tool arguments cannot carry file bytes, so this returns a one-time upload_url, a single-use ticket, the limits for that image type, and a ready-to-run curl command. Run it from a shell, then get_submission to confirm the image landed. The ticket expires in about 10 minutes and is spent on every attempt, so mint a fresh one per retry. Uploading REPLACES whatever is in that slot. Never show the ticket to the partner. | ### Redemption | Tool | What it does | | --- | --- | | `get_fulfillment` | Read the redemption state: pricing model, plan count, and for a licensing deal the webhook and redirect URLs on file, whether the configuration has been validated (is_valid), and the warnings that would stall approval. Never returns the private key. | | `request_codes_upload` | The same one-time-ticket route for the redemption codes CSV (product_type "codes"): call it, then run the returned curl command against the file. Header row, then one code per line; the first line is always skipped, so a file that starts straight into codes loses that code. Check the file before you send it, and say so if the partner handed you one without a header. min_codes and max_codes bound the count. On a draft the upload REPLACES every existing codes file, and existing_files lists them. Refused on a live listing or an open revision — those codes are changed by AppSumo staff. The ticket is a credential: never echo it or the command into the conversation. | | `delete_codes_file` | Delete one codes file from a draft; the codes in it are deactivated. The ids come from request_codes_upload’s existing_files. Refused on a live listing or an open revision. | | `set_licensing_urls` | Licensing deals only (product_type "licensing", set with update_submission first). Sets the webhook URL and/or OAuth redirect URL; an omitted one keeps its value. Both must be public https URLs. Returns the partner’s private key when you act for them: it is a SERVER credential for their own backend, so put it in their server config and nowhere else. EVERY call invalidates the configuration, even with unchanged URLs, until test_licensing passes again — so never call it just to see the key again. | | `test_licensing` | Runs both licensing tests against the URLs on file: a GET of the redirect URL (must answer 2xx without redirecting) and a synthetic license event sent to the webhook URL. The partner’s LIVE server receives real requests. Returns each test’s request and response so you can fix their endpoint and retry, and records is_valid from the results. Nothing else can mark licensing valid. | ### Preview and submit | Tool | What it does | | --- | --- | | `preview_listing` | Render the product page a buyer would see for this draft. Returns preview_url for the PARTNER to open in their browser (it needs their appsumo.com session; you cannot fetch it) and the page as JSON so you can review copy, pricing and media yourself. Regenerates from the current draft each call, so edit first, then preview. | | `submit_for_review` | Submit the finished draft. If anything required is missing it returns the checklist instead of submitting. A successful submit may still carry warnings (for example licensing_not_validated): relay them, they mean the listing cannot be approved until fixed. | ### After it is live | Tool | What it does | | --- | --- | | `create_submission_version` | Start a new, editable version of an APPROVED listing. A live listing cannot be edited in place — update_submission and submit_for_review both refuse it — so this is how a published listing gets changed. Returns the submission id of a fresh draft that inherits the approved version’s content. Only one version may be open per listing: error=version_in_progress names the one already open, so edit that instead of retrying. | | `list_listings` | List the live AppSumo listings the account can manage, newest first. One page at a time; when has_more is true, call again with the next page. | | `get_listing_content` | Read a live listing’s current page content — name, story, plans, FAQs, redemption instructions and a media inventory — in the shape the editor uses. content_source says what you got: "draft" when a revision is open, "submission" for the approved listing, "live" when it predates the wizard. | | `list_listing_reviews` | Approved customer reviews for one listing, newest first, each with any replies your team already posted. Buyers are identified by an opaque handle, never by name. | | `reply_to_review` | Reply to a customer review. It publishes IMMEDIATELY as the company’s official response — there is no review step — and the customer is notified, so show the partner the wording and get their agreement first. Pass the id from list_listing_reviews. | | `list_listing_questions` | Approved customer questions for one listing, newest first. "answered" means YOUR team replied; a thread other buyers have chimed in on is still unanswered. | | `reply_to_question` | Answer a customer question. Same rules as reply_to_review: published immediately as the official response, so get the partner’s agreement on the wording first. Pass the id from list_listing_questions. | | `get_listing_analytics` | Sales, revenue and traffic for one listing over a date window. Defaults to the last 30 days; the window may not exceed 366 days. An expensive read — cache the answer rather than calling it in a loop. | ## Read the listing brief Read the listing brief before you write anything. It specifies every field, its character limits and dropdown options, the approval rules, and the voice rules, and it maps each field to the API path update_submission expects. It’s the source of truth for what to write on either path. Fetch it here: ``` https://partners.appsumo.com/docs/listing-brief.md ``` ## Which path you’re on Work out which of these you’re on before you touch anything. Picking wrong either starts a duplicate listing or overwrites work the partner already did. ### Starting a new listing **When:** You weren’t given a submission id, and list_submissions returns nothing for this product. 1. Ask the partner for their product URL. Don’t guess it from context. 2. Work out which workspace it belongs under with list_workspaces, and ask the partner if more than one could be right. An omitted workspace is not guessed: the listing lands in their personal one, which puts the wrong company on it. 3. Call submit_url with that URL and the workspace id. Reuse the same run_id to retry a timed out call rather than creating a duplicate. 4. Poll get_submission_status until ux_state is "ready", and the drafted listing comes back in latest_contract. Stop on "hard_rejected" as well: that means the URL was rejected (a platform page, a directory listing, or a site that couldn’t be reached), so tell the partner and ask for a different one rather than polling on or retrying the same URL. The reason isn’t exposed to you, so don’t guess at one. 5. Apply that draft yourself with update_submission. It’s NOT copied onto the submission for you, and this is the step most likely to be missed. 6. Make the images. The brief’s Media section is the shot list: a hero plus one per feature story, every one an accurate representation of the real product. Put up whatever is already at a public URL with upload_image, and anything on your own disk with request_image_upload plus the curl command it returns. Hand the partner only what you genuinely cannot make. 7. Finish redemption. Check where it stands with get_fulfillment; a listing with no way to fulfil a purchase will not be approved. See "Finish redemption" below for the codes and licensing routes. 8. Preview it with preview_listing and read the page back critically before you show the partner: it is the buyer’s view, not the editor’s. 9. Give the partner the link to the draft and ask them to read it. See "Show the partner their draft" below for the URL and what to say with it. ### Continuing a listing already in progress **When:** You were given a submission id, or list_submissions returns one for this product. 1. Fetch its current state with get_submission before changing anything, so you’re editing what the partner sees rather than what you remember. 2. Don’t call submit_url. It always creates a new listing, so calling it here leaves the partner with two. 3. Work through what is still empty or weak, rather than rewriting fields the partner already settled. 4. Check the images before you call it done. A listing with no hero and no gallery will not pass review, and images are what a half-built listing is usually missing. Make the ones that aren’t there yet, following the brief’s Media section, and put them up yourself with upload_image or request_image_upload. 5. Check redemption with get_fulfillment. Its warnings list is what will stall approval; a licensing deal that was never validated is the usual gap. See "Finish redemption" below. 6. Preview it with preview_listing before you show the partner. 7. Give the partner the link to the draft and ask them to read it. See "Show the partner their draft" below for the URL and what to say with it. ### Changing a listing that is already live **When:** list_submissions shows the listing as approved and not editable, or the partner is asking you to change a product that is already on sale. 1. Do not call submit_url. The listing exists; a second one is a duplicate, not an edit. 2. Find the listing with list_listings. It gives you both ids you need, and they are not interchangeable: deal_id addresses the live listing (get_listing_content, the reviews and questions, analytics), and latest_approved_submission_id is the submission id to hand create_submission_version. Any version of the listing would do — the newest approved one is what gets forked either way — so that field is simply the one already in front of you. 3. Read what is live with get_listing_content(deal_id), so you are editing the published page rather than an old draft. 4. Call create_submission_version with that submission id. An approved listing cannot be edited in place, and update_submission refuses it. You get back a fresh draft that inherits the live content, images and codes. 5. If it answers version_in_progress, a version is already open: edit the submission id it names instead of forcing a new one. Only one may be open per listing. 6. Edit that draft exactly as you would any other, then preview it and hand the partner the link before you submit. The live listing stays untouched and on sale until staff approve the new version. 7. Codes cannot be changed this way. request_codes_upload and delete_codes_file both refuse a revision; the partner asks AppSumo support. 8. Leave set_licensing_urls alone unless the URLs are actually changing. Every call invalidates the configuration, unchanged URLs included, so re-saving them to "confirm" them takes a product that is currently selling to not-validated until test_licensing passes again. If you did change them, test before you submit. 9. Run get_fulfillment before you submit either way, the same as on a first listing. Its warnings are what will hold the revision in review. ## Finish redemption Every listing needs a way to fulfil a purchase before it can be approved. Which way depends on the pricing model the brief had you choose: Codes or Licensing. get_fulfillment tells you where a submission stands and lists the warnings that would stall approval. ### Codes 1. Set the redemption URL (where buyers go to redeem a code), the support email and the buyer-facing redemption instructions (the steps a buyer follows after purchase) with update_submission. 2. Get the codes CSV from the partner. You cannot generate it — the codes have to work against their system. request_codes_upload states the required count range and the file limits, so ask for the file with those numbers in hand. 3. Upload it with request_codes_upload, then run the curl command it returns against the file. Do not print that command or its ticket into the conversation. Check it landed with get_fulfillment. If the partner would rather do it themselves, the editor’s Redemption step takes the same file. 4. Uploading replaces every codes file already on the draft; delete_codes_file removes one on its own. Neither works once the listing is live or a revision is open, because AppSumo staff change codes after that. 5. Expect submit_for_review to refuse a codes deal with no file; it says so in its checklist. ### Licensing 1. Set product_type to "licensing", the plans, the support email and the buyer-facing redemption instructions with update_submission first. set_licensing_urls and test_licensing refuse a deal that is not a licensing deal. 2. Call set_licensing_urls with the partner’s webhook URL (we POST license events there: purchase, activate, upgrade, deactivate) and OAuth redirect URL (where buyers land after granting the app access to their license). Both must be public https. The result includes the private key the partner’s server needs to verify our calls. Put it in their server configuration and nowhere else; never paste it back into chat, and remember it now sits in this transcript wherever your client keeps transcripts. Every set_licensing_urls call, changed URLs or not, invalidates the configuration until the next passing test_licensing — so do not call it again just to see the key; if it is lost, one more call returns it and then you test again. Rotation is not available through the tools; the partner asks AppSumo support. 3. Build or fix the partner’s endpoints per https://docs.licensing.appsumo.com/ — a webhook handler that accepts JSON and answers 2xx, and the OAuth redirect. 4. Call test_licensing. It sends a real synthetic event to the live webhook URL and GETs the redirect URL, then records the result as the listing’s licensing validity. Read the request and response it returns, fix the endpoint, and call it again until is_valid is true. No tool marks licensing valid any other way (the partner’s editor runs the same kind of tests). 5. A plan change does not clear the validity flag, but it changes which event is tested — a multi-plan deal is exercised with an upgrade, a single plan with an activation — so a pass recorded before the change no longer covers what the deal now sells. Test again after adding or removing plans. A licensing deal submitted before validation reaches review but cannot be approved; submit_for_review tells you with a licensing_not_validated warning, and test_licensing still works on a pending submission so you can fix it. ## Look after a live listing Once a listing is approved the same connection keeps working. list_listings finds it, get_listing_analytics reports how it is selling, and the review and question tools are how the partner answers their customers. 1. Find the listing with list_listings and use the deal_id it returns; the submission ids from drafting are a different thing. 2. Read before you write: list_listing_reviews and list_listing_questions return the threads newest first, each with any reply the partner already posted. "answered" means their team replied, so a busy thread with no reply from them still needs one. 3. Draft the reply, show it to the partner, and only send it once they agree. reply_to_review and reply_to_question publish IMMEDIATELY as the company’s official public response, with no staff review, and the customer is notified. There is no edit and no delete. 4. One reply per thread. A second is refused with already_answered unless you pass allow_follow_up, which you should only do when the partner asked for a follow-up. 5. Answer the question that was asked, in the partner’s voice, and never argue with a bad review in public. If a reply needs a refund, an account change, or anything you cannot promise on their behalf, hand it back to the partner instead of writing it. 6. get_listing_analytics covers sales, revenue and traffic for a date window of up to 366 days, and defaults to the last 30 days. It is an expensive read: fetch once and work from the answer rather than calling it per question. ## Show the partner their draft Whenever you finish a draft or a round of edits, end your reply with the link to the listing. The partner cannot find it from a submission id, so the link is the only way they reach what you wrote. Substitute the submission_id the tools returned: ``` https://partners.appsumo.com/self-submission/{submission_id}/build?from=agent ``` - Post the URL as its own line so it stays clickable, not buried mid-paragraph. - If the partner already has the listing open, your changes should appear there within a few seconds on their own; a section they are typing in at that moment catches up once they pause. If they still do not see the change after a short wait, ask them to reload the page. - Say in a line or two what you filled in and what is still empty. Name every image you made, say where the files are, and flag any you could not upload yourself so the partner can put them in the editor. - Give them the preview_url from preview_listing as well, on its own line. It shows the page as a buyer will see it; the draft link shows the editor. - Wait for the partner to look at it and approve before you call submit_for_review. Their sign-off is the point of showing them the link. - Stop handing out that URL once you have submitted. The editor only opens a listing that is still editable, so after submit_for_review it bounces the partner to an error page. Swap /build for /review to point them at a listing you have already sent in.