# uprank > uprank is an editorial control room for evidence-backed content: it researches, drafts, scores and publishes articles for your own site, with every claim traced to a source gathered before drafting and nothing published until it clears hard quality gates. - What it is: a multi-tenant web app that researches, drafts, scores and publishes articles for a company's own site. - Who it is for: teams that need brand-safe, cited articles on their own blog, not content volume. - Pipeline: brand profile → research into an Evidence Pack → brief → draft → claim check → scoring → revision → CMS draft. - Quality: 11 scored dimensions and 13 hard gates; an article that fails any gate cannot be published. - Publishing: Strapi, as drafts by default. Draft creation is idempotent; live publishing needs an explicit confirmation and is audited. - Agents: a remote MCP server (streamable HTTP, bearer token or OAuth) with 17 tools; a connection sees the ones its scopes allow, and live publishing needs a hand-issued credential. Guides for Claude Code, Codex, Cursor, Windsurf, VS Code (Copilot), OpenCode. - What it does not do: promise rankings, invent citations, fake first-hand expertise, or publish an article that fails a hard gate. Source: https://uprank.devino.ca/ ## How uprank scores articles uprank scores every draft from 0 to 100 on 11 quality dimensions and will not publish it unless it clears 13 hard gates: 6 minimum scores and 7 integrity checks, including no invented citations and no unsupported high-risk claims. The overall score is a weighted mean (risk counts inverted); it is shown for comparison but never overrides a failed gate. Every article is checked against these thresholds; workspaces and campaigns can’t change them. | Dimension | Weight | Gate | What it measures | | --- | --- | --- | --- | | Evidence | 18% | ≥ 85 | Claims are backed by credible, attributed sources. | | Information gain | 14% | ≥ 70 | Adds something not already covered by top results. | | Practical value | 14% | ≥ 75 | Actionable for the reader — steps, examples, specifics. | | Brand fit | 12% | ≥ 80 | Matches the brand voice, positioning, and proof points. | | Search intent | 10% | — | Answers what the searcher actually wants. | | Readability | 8% | ≥ 75 | Clear structure and prose for the target audience. | | Freshness | 6% | — | Time-sensitive facts are current and within window. | | External sources | 6% | — | Cites authoritative outside references. | | Risk | 5% | ≤ 20 | Lower is better — legal, safety, and accuracy exposure. | | Internal links | 4% | — | Links to relevant own-site content. | | Media | 3% | — | Has licensed, relevant imagery or diagrams. | Integrity gates: - **No invented citations.** Every citation must point to a source in the article’s Evidence Pack, gathered before drafting. - **No broken required links.** Every cited link is checked each time the article is scored, before it can be published. One that returns not found (404 or 410), does not resolve, refuses the connection, times out twice or points to a private address blocks the article. Pages that refuse automated checks (401, 403, 429) or return server errors are not counted as broken. - **High-risk claims are supported.** Each high-risk claim is checked against its source; any unsupported or contradicted one blocks the article. - **Time-sensitive claims are fresh.** Claims that depend on dates, prices or versions must fall inside their freshness window. - **At least one information-gain element.** For example a decision framework, worked example, checklist, comparison, template or labelled research synthesis. First-hand expertise is never faked. - **Licensed images only.** Every external image carries license metadata. - **Unique title.** No other article on the same site may use the same title (ignoring case and extra spaces), checked each time the article is scored. Archived and failed articles don’t count. Slugs are made unique automatically. ### Questions about the quality gates #### What is a quality gate for AI-written articles? A quality gate is a hard rule an article must pass before it can be published. In uprank it is either a score threshold on one dimension or a pass/fail integrity check, such as no invented citations. Failing any one gate blocks the article from being approved, pushed to your CMS or published, whatever its overall score. uprank enforces 13 gates: 6 score gates and 7 integrity checks. #### What score does an article need before uprank will publish it? uprank has no minimum overall score. An article must clear every gate instead: Evidence ≥ 85, Information gain ≥ 70, Practical value ≥ 75, Brand fit ≥ 80, Readability ≥ 75 and Risk ≤ 20, plus all 7 integrity checks. Missing any one of them blocks publishing, and the other 5 dimensions, which have no score gate, only feed the overall score. #### Can a high overall score make up for a failed gate? No. In uprank the overall score is a weighted mean shown for comparison, and it never overrides a failed gate. An article that scores 84 on Evidence, or cites a source that is not in its Evidence Pack, stays blocked however well it scores everywhere else, until that gate passes. #### How is the overall quality score calculated? uprank’s overall score is a weighted mean of the 11 dimension scores, rounded to a whole number from 0 to 100. Weights, heaviest first: Evidence 18%, Information gain 14%, Practical value 14%, Brand fit 12%, Search intent 10%, Readability 8%, Freshness 6%, External sources 6%, Risk 5%, Internal links 4%, Media 3%. Risk counts as 100 minus the risk score, so a low risk score raises the overall. #### What happens to the score when an article is edited? Saving an edit in uprank creates a new version and marks the article’s existing quality assessments stale. The new version cannot be approved, pushed to your CMS or published until it is scored again. article_revise over MCP does that in one step: it writes a revised version, extracts and verifies its claims against their sources, then scores it. A stale score never counts as a pass. #### Can the quality gate thresholds be changed? No. Every article in every uprank workspace and campaign is checked against the same thresholds: Evidence ≥ 85, Information gain ≥ 70, Practical value ≥ 75, Brand fit ≥ 80, Readability ≥ 75 and Risk ≤ 20, plus the 7 integrity checks. Neither the app nor the MCP server has a setting that tightens, relaxes or switches off a gate. #### Do AI agents have to pass the same quality gates? Yes. Agents connected to uprank over MCP face the same thresholds. article_score evaluates every gate, and publication_publish refuses a version whose current assessment has not passed. publication_create_draft only records a draft request and pushes nothing to the CMS; the Strapi draft push, made from the app, is blocked until the version passes. Source: https://uprank.devino.ca/quality-gates ## How to fact-check AI content before you publish To fact-check AI content, collect your sources before the draft is written, list every factual claim, and check each one against the exact passage of its cited source, high-risk claims first. Then check that time-sensitive claims are still current and that every citation exists and its link resolves, and hold publishing until the draft passes and a person has reviewed it. uprank automates most of this method: it gathers an Evidence Pack before drafting, checks each claim against it, and blocks publishing when any of its 13 hard gates fails. Reading the draft stays with you. Updated 2026-10-06 The method: 1. **Collect your sources before the draft is written.** Gather attributable sources first, primary or official ones where you can, and write from them. Sourcing after the fact makes it easy to bolt links onto claims they do not actually support. 2. **List every factual claim in the draft.** Pull out each statistic, date, name, quote, comparison and "best", "first" or "only" statement. Opinions can stay as opinions; anything a reader could check cannot. 3. **Check each claim against the exact passage of its source.** Open the source and find the passage. Mark the claim as supported, partly supported, contradicted or unsupported. A source that is merely on the same topic does not support the claim. 4. **Check the high-risk claims first.** Medical, financial, legal, safety and reputation claims cost the most when they are wrong. Fix or cut any of them that is unsupported or contradicted before you spend time on the rest. 5. **Check time-sensitive claims for freshness.** Prices, dates, versions and anything described as current can expire. Give each one a window, and re-check anything that is past it. 6. **Confirm every citation exists and every link resolves.** Open each link. Check the source is real and that its title, publisher and date match what the draft says. A citation to something that cannot be found counts as an invented one. 7. **Hold publishing until it passes, with a person reviewing the draft.** Save the article as a draft, have a human read it, and treat any edit as a reason to re-check. Publish only when every check above has passed. What uprank automates at each step: - **Collect your sources before the draft is written.** Research runs before drafting and produces an Evidence Pack of attributable sources. The draft is then written from that pack, with research and drafting as separate pipeline stages. - **List every factual claim in the draft.** After the draft, the pipeline extracts the checkable claims from it, each with a claim type and a risk level. - **Check each claim against the exact passage of its source.** Each claim is checked against the numbered source excerpts in the Evidence Pack and marked directly supported, partly supported, contradicted or unsupported. Contradicting sources are recorded, not dropped. The Evidence score, which weighs these results, has a minimum (≥ 85 by default). - **Check the high-risk claims first.** Medical, financial, legal, safety and reputation claims are rated at least high risk. Any high-risk claim that is unsupported or contradicted blocks the article, and the Risk score has a maximum (≤ 20 by default). Gates: High-risk claims are supported. - **Check time-sensitive claims for freshness.** A time-sensitive claim carries a freshness window in days. A claim outside its window blocks the article. Gates: Time-sensitive claims are fresh. - **Confirm every citation exists and every link resolves.** Every citation must point to a source in the Evidence Pack; one that does not is an invented citation and blocks the article. uprank also checks that each cited link resolves: one that returns not found, does not resolve or points to a private address blocks the article. Sites that refuse automated checks (401, 403, 429) or return server errors are counted as unknown, not broken, so open those yourself in review. Gates: No invented citations; No broken required links. - **Hold publishing until it passes, with a person reviewing the draft.** Drafts go to your CMS as drafts by default. Editing an article makes its earlier score stale, so it must be re-scored before it can be published. Live publishing needs an explicit confirmation and is audited, and over MCP, publication_publish refuses a version that has not passed the gates. - **Also enforced before publishing.** Beyond fact-checking: At least one information-gain element; Licensed images only; Unique title. These integrity gates apply to every article. Pre-publish checklist: - [ ] **Evidence.** Is every factual claim backed by a source you have opened and read? - [ ] **Information gain.** Does the article tell the reader something the top results for this topic do not already say? - [ ] **Practical value.** Could a reader act on it after one read, with steps, examples and specifics rather than general advice? - [ ] **Brand fit.** Does it sound like your brand and stay within your positioning and proof points? - [ ] **Readability.** Can someone in your audience follow it in a single pass, with plain words and clear headings? - [ ] **Risk.** Have you ruled out anything that could mislead readers, cause harm or damage your reputation? - [ ] **No invented citations.** Does every citation point to a source that exists and says what the draft says it does? - [ ] **No broken required links.** Does every cited link open on the page it is meant to? - [ ] **High-risk claims are supported.** Is every medical, financial, legal, safety or reputation claim supported by the passage in its source? - [ ] **Time-sensitive claims are fresh.** Is every price, date, version and "current" claim still true today? - [ ] **At least one information-gain element.** Does it include at least one element of its own, such as a framework, worked example, checklist, comparison or template? - [ ] **Licensed images only.** Does every image that is not yours come with a license you have checked? - [ ] **Unique title.** Is the title different from every other article on your site? ### Can I use AI to fact-check AI-written content? It can do the legwork, such as matching each claim to a passage in a source, but only if it checks against the actual source text rather than its own memory. A person should still review the high-risk claims. uprank’s claim check works from the numbered source excerpts in the Evidence Pack and does not bring in outside sources, and its drafts go to your CMS as drafts by default so a person reviews them. ### What counts as a high-risk claim? Claims where being wrong costs the most: medical, financial, legal, safety and reputation claims. uprank rates those at least high risk, and an unsupported or contradicted high-risk claim blocks the article from being published. ### How do I fact-check a statistic in an AI draft? Find the original source rather than a page that repeats it. Confirm that the number, what it measures, who it covers and the date all match how the draft uses it. If you cannot find the source, reword the sentence or remove it. ### Does passing a fact-check mean the article is correct? No. It means each claim matches its source. It does not prove the sources themselves are right, so prefer primary and official sources and keep a human review step. uprank checks claims against the sources it gathered; it does not independently verify those sources. Source: https://uprank.devino.ca/how-to-fact-check-ai-content ## An AI writer that doesn't hallucinate sources No AI writer can honestly promise zero hallucinations, because any language model can produce a fluent claim that is wrong. What uprank does is refuse to publish what it cannot trace: it researches into an Evidence Pack before drafting, treats any citation outside that pack as invented, checks each claim against its source, and blocks the article on an invented citation or an unsupported high-risk claim. Drafts go to your CMS as drafts by default, so a person reviews them before anything goes live. Updated 2026-10-06 Why AI writers hallucinate: - **A language model writes likely text, not looked-up facts.** It produces what sounds right given its training. Fluent and confident wording says nothing about whether the claim is true. - **Without sources in front of it, it fills gaps from memory.** Memory can be wrong, out of date or a blend of several things. A statistic, date or quote that is missing from the context tends to get a plausible-sounding replacement. - **Citations are generated text too.** If nothing checks them, a reference can look real, with a plausible title, publisher and URL, and still point to nothing. - **Links added after the draft can still be wrong.** Finding a real page that sounds related is not the same as finding a source that says what the sentence says. What uprank does instead: - **Research first.** Research runs before drafting and produces an Evidence Pack of attributable sources. The draft is written from that pack, not from the model’s memory alone. - **Citations only to the Evidence Pack.** Every citation must point to a source in the article’s Evidence Pack, gathered before drafting. A citation that points anywhere else is an invented citation, and that is a hard gate. - **Every claim is checked.** The claims in the draft are extracted and each is checked against the source excerpts, then marked directly supported, partly supported, contradicted or unsupported. A claim no gathered source supports is treated as unsupported, even if it happens to be true. - **High-risk and time-sensitive claims can block publishing.** Each high-risk claim is checked against its source; any unsupported or contradicted one blocks the article. Claims that depend on dates, prices or versions must fall inside their freshness window. - **13 hard gates before publishing.** An article that fails any of them cannot be published: 6 minimum scores and 7 integrity checks. A score never overrides a failed gate. - **Draft-first, with an audit trail.** Articles go to your CMS as drafts by default, so a person reviews them before anything is live. Live publishing needs an explicit confirmation and is audited. Claims, the sources they were checked against, scores and article versions are stored. What uprank will not do: - Promise zero hallucinations. No language model can, and the claim check is itself automated, which is why drafts go to your CMS for human review. - Invent citations, or publish an article that cites something outside its Evidence Pack. - Publish an article that fails a hard gate. - Fake first-hand expertise. - Promise rankings or traffic. - Prove its sources right. It checks claims against the sources it gathered, so a wrong source can still support a claim. Questions to ask any AI writer: 1. Are sources gathered before the draft is written, or are links added afterwards? 2. Can every citation be traced to a source the writer actually collected? 3. Is each factual claim checked against the passage in its source, and can you see the result? 4. What happens to a claim with no supporting source: flagged, cut, or published anyway? 5. Are time-sensitive claims, such as prices, dates and versions, checked for freshness? 6. Does a failed check stop publishing, or is it only advice? 7. Does the draft reach a human review step before it goes live, and is a live publish recorded? ### Can an AI writer guarantee no hallucinations? No. Any language model can write a claim that sounds right and is not. What a writer can do is limit the damage: ground the draft in sources gathered beforehand, check claims against those sources, and block publishing when a check fails. That is what uprank does, and its drafts go to your CMS for human review. ### How does uprank stop invented citations? Every citation must point to a source in the article’s Evidence Pack, which is gathered before drafting. A citation that points elsewhere is an invented citation. That is a hard gate: the article cannot be published until it is fixed. ### What happens to a claim uprank cannot support? Each claim is checked against the source excerpts and marked directly supported, partly supported, contradicted or unsupported. An unsupported or contradicted high-risk claim blocks the article. Other unsupported claims pull down the Evidence score, which has a minimum the article must meet. ### Do I still need to review articles written by uprank? Yes. The claim check is automated, and uprank cannot tell whether a source is itself wrong. Articles reach your CMS as drafts by default for that reason, and a live publish needs an explicit confirmation and is audited. Source: https://uprank.devino.ca/ai-writer-that-doesnt-hallucinate ## AI blog writer for Strapi: fact-checked drafts in your CMS uprank is an AI blog writer that sends its articles to Strapi 5 as drafts. It researches and drafts each article, checks it against 13 hard quality gates, and, when you press Create / update draft on a version that passed them, creates the entry in your own content type through Strapi’s REST API, with each article field mapped to the attribute names you choose. The push creates a draft only, so a person reviews the article in Strapi before anything is live. Updated 2026-10-10 How it works: | Stage | What uprank does | Strapi REST call | | --- | --- | --- | | Connect | A workspace owner saves your Strapi base URL and an API token. The token is encrypted at rest and sent as a Bearer token. Validate sends one authenticated request and marks the connection connected or invalid. | GET /content-type-builder/content-types | | Map | A publish target stores your content-type UID and a mapping from each article field to your own Strapi attribute name. No content type is assumed. | None. The mapping is stored in uprank. | | Write | uprank researches, drafts and scores the article in the app, or from your coding agent over MCP. | None. Nothing is sent to Strapi yet. | | Create draft | Create / update draft on the article’s Publishing tab first checks that the version’s current quality assessment passed every hard gate, then records the publication, then creates the entry with status draft. The request carries an idempotency key. | POST /api/{route}?status=draft | | Update draft | Pressing the button again on a publication that already has a documentId updates that entry instead of creating another. | PUT /api/{route}/{documentId}?status=draft | | Recover | If Strapi rejects the payload, the publication is marked FAILED and shows the error. Fix the content type in Strapi, then press Retry; the troubleshooting table below maps each error to its likely cause. | The same POST or PUT, sent again. | | Go live | Not sent by the Publishing tab, which creates and updates drafts only. You review the draft in Strapi. | None. | Connect Strapi: 1. **Create the content type in Strapi.** uprank does not create content types or fields. In Strapi, make a collection type with attributes for the title, slug and body, plus any optional fields from the mapping table below. 2. **Create a Strapi API token.** Create an API token in Strapi that is allowed to create and update entries in that content type. uprank sends it as a Bearer token, and it uses POST and PUT requests. 3. **Add the connection in uprank.** Open Connections, choose New connection, keep the type as STRAPI, and enter your Strapi base URL and the token. Only a workspace owner can add a connection. The token is encrypted at rest and never shown again. 4. **Validate the connection.** Press Validate on the connection. uprank sends one authenticated request to your Strapi and records the connection as connected or invalid, with the time it was checked. 5. **Create a publish target and map the fields.** Choose New publish target, pick the connection, and enter the content-type UID, for example api::article.article. uprank turns the UID into the REST route by pluralizing its name; to use a different route, enter the plural API route instead of the UID. The dialog starts with two example rows: replace them so the left side is a key from the mapping table below and the right side is your Strapi attribute name. 6. **Push a draft from an article.** Open the article, choose the Publishing tab, pick the target and press Create / update draft. The button is enabled once the version’s current quality assessment has passed every hard gate; until then the tab says why. The entry appears in Strapi as a draft, and the tab shows its documentId and the publication’s status history. Field mapping: | Key | What it sends | Filled by the Publishing tab | | --- | --- | --- | | title | The article title. | Yes | | slug | The article slug. | Yes | | body | The body as a Markdown string, the same as bodyMarkdown. | Yes | | bodyMarkdown | The body as a Markdown string. | Yes | | bodyHtml | The body as an HTML string. | Yes | | bodyBlocks | The body as Strapi blocks JSON, for a Blocks field. Needs the article’s structured body. | Yes | | excerpt | The version’s excerpt, or one computed from the body when it has none. | Yes | | seoTitle | The version’s SEO title, when it has one. | Yes | | seoDescription | The version’s meta description, when it has one. | Yes | | featuredImage | Accepted in a mapping, but the Publishing tab sends no value for it. | No | | author | Accepted in a mapping, but the Publishing tab sends no value for it. | No | | categories | Accepted in a mapping, but the Publishing tab sends no value for it. | No | | tags | Accepted in a mapping, but the Publishing tab sends no value for it. | No | | publicationDate | Accepted in a mapping, but the Publishing tab sends no value for it. | No | | canonicalUrl | The site’s base URL followed by the slug. | Yes | | citations | Accepted in a mapping, but the Publishing tab sends no value for it. | No | The key on the left must be one of these. A mapping with any other key, or an empty mapping, fails with a mapping error before anything is sent to Strapi. A key whose value the Publishing tab does not fill is left out of the request. Body formats: The body format follows which key you map. Map one body key, or several to different attributes. - `bodyMarkdown`: Markdown string. For a text field. body does the same. - `bodyHtml`: HTML string. For a text field that holds HTML. - `bodyBlocks`: Strapi blocks JSON. For a Blocks field. Paragraphs, headings, lists, quotes and code map directly. Tables, callouts, images and citations become paragraphs or links, so no content is dropped. Worked example: A collection type with the UID api::article.article, a title, a slug, an excerpt and a Blocks body, mapped to the matching uprank keys. The Strapi schema is yours to build in Strapi; the request below is what uprank sends for a fixed sample article. Strapi content type (api::article.article), schema.json: ```json { "kind": "collectionType", "collectionName": "articles", "info": { "singularName": "article", "pluralName": "articles", "displayName": "Article" }, "options": { "draftAndPublish": true }, "attributes": { "title": { "type": "string", "required": true }, "slug": { "type": "uid", "targetField": "title" }, "excerpt": { "type": "text" }, "body": { "type": "blocks" } } } ``` Mapping on the publish target: | uprank key | Strapi attribute | | --- | --- | | title | title | | slug | slug | | excerpt | excerpt | | bodyBlocks | body | Request for the sample article: ```http POST /api/articles?status=draft ``` ```json { "data": { "title": "Reversible decisions", "slug": "reversible-decisions", "excerpt": "How to tell a reversible decision from a one-way one.", "body": [ { "type": "heading", "level": 2, "children": [ { "type": "text", "text": "Why a two-way door is cheap" } ] }, { "type": "paragraph", "children": [ { "type": "text", "text": "A reversible decision can be undone at a small cost." } ] }, { "type": "list", "format": "unordered", "children": [ { "type": "list-item", "children": [ { "type": "text", "text": "Decide quickly" } ] }, { "type": "list-item", "children": [ { "type": "text", "text": "Review after a week" } ] } ] } ] } } ``` - The route comes from the UID: the name after the dot, pluralized, so api::article.article is /api/articles. - Only the keys in the mapping are sent. This mapping has no seoTitle, seoDescription or canonicalUrl row, so none of them is in the body. - The request also carries the token as an Authorization Bearer header, a JSON content type, and an idempotency-key header set to the publication’s request hash. - bodyBlocks became Strapi blocks JSON: the heading, the paragraph and the list are blocks in the body attribute. - The article is a fixed sample. The body above is produced by the same field builder and request builder the Publishing tab uses. uprank will not: - Push live from the Publishing tab. It creates and updates drafts, and you review them in Strapi. - Push a version that has not passed its hard quality gates. The Publishing tab refuses a version without a current, passing quality assessment, and so do approving it and, over MCP, publication_publish. - Create or change your content types or fields. The attributes you map to must already exist, or Strapi rejects the payload and the publication shows its error. - Upload images or fill the featured image, author, categories, tags, publication date or citations fields from the Publishing tab. - Retry a failed push on its own. The publication shows FAILED with the error and a Retry button. - Publish to any CMS other than Strapi. The Strapi publisher is the only one registered. Troubleshooting: | What you see | Likely cause | What to do | | --- | --- | --- | | Create / update draft is disabled, with a line under it that starts “Score this version first” or “Blocked by”. | The version has no current quality assessment, or it fails a hard gate. Nothing has been sent to Strapi. | Score the version, or fix the blockers listed on the Quality tab and score it again. | | “No publish targets configured. Add one on the Connections page first.” | The workspace has no publish target yet, so there is nothing to push to. | On the Connections page, add a publish target: a connection, the content-type UID and the field mapping. | | Validate marks the connection INVALID, with “Authentication failed: the API token was rejected.” or “Unexpected status …” in the toast. | Validate sends one GET to /content-type-builder/content-types. A 401 means Strapi rejected the token; any other status except success or 403 also marks the connection INVALID. | Check the Strapi base URL and the token, then press Validate again. | | The connection shows CONNECTED, but pushing a draft fails. | Validate only reads the Content-Type Builder, and a 403 there still counts as connected (token valid, scope limited). It does not test creating or updating entries. | Make sure the token can create and update entries in your content type, then push again; the push result is the real check. | | The publication is FAILED with “Could not reach the Strapi server.” The same text is the Validate toast when the check cannot connect. | The request threw before any response came back. uprank maps every such failure, including the request timing out, to this message. | Check the base URL on the Connections page, and that your Strapi is reachable from uprank’s server and not only from your own network. Then press Retry. | | The publication is FAILED with “Field mapping is empty; nothing to publish.” or “Field mapping references unknown canonical fields.” | The publish target’s mapping has no rows, or a key on its left side is not in the field table above. This is checked before any request is sent. | The app has no edit for a publish target (connection-actions.ts only creates them). Create a new target whose mapping keys come from the field table, and push with it from the Publishing tab. | | The publication is FAILED with Strapi’s own message, or “Strapi rejected the payload.” | Strapi answered HTTP 400: it refused the data uprank sent. Typical reasons are an attribute in the mapping that the content type does not have, a required attribute that is not mapped, or a value of the wrong type, such as bodyBlocks mapped to a text attribute. | Compare the attribute Strapi names with your mapping and with the content type, and match each key to its attribute type (the body formats above). Fix the content type in Strapi and press Retry. If the mapping is wrong, create a new publish target. | | The publication is FAILED with Strapi’s message or “Strapi request failed during createDraft.” (updateDraft when it was an update). | Any other failing status. A push does not tell a 401, a 403, a 404 or a server error apart, and the tab shows Strapi’s message, not the status code. The usual suspects are a token that is wrong or cannot create and update entries in this content type, and a route that does not exist because the UID or plural route is wrong. | In Strapi, check that the token allows create and update on this content type, and that the route exists. uprank takes it from the UID (the name after the dot, pluralized), or uses the plural API route you entered instead of the UID. Fix it, then press Retry. A server error is marked retryable but is never retried on its own. | | The publication is FAILED with “The CMS rejected the draft.” | Strapi answered with a success status, but the response had no data.documentId, so uprank cannot record a draft. The publisher expects the Strapi 5 response shape. | Check that the base URL points at a Strapi 5 server and not at a proxy or another service in front of it. | Drive it from your coding agent: A coding agent can run the same pipeline and gates over MCP. publication_create_draft records the draft publication for a target; pushing it to Strapi is done from the article’s Publishing tab, once the version passes its hard gates. - `article_score`: Score a version on the quality dimensions and hard gates. - `publication_create_draft`: Record a draft publication for a publish target in uprank; idempotent and safe to retry. Nothing is pushed to the CMS: the Strapi draft is pushed from the article’s Publishing tab, once the version passes its hard gates. - `publication_status`: Read the state of a publication. - `publication_publish`: Record a live publication request for a version with a current, passing quality assessment; needs publication:live and confirm "PUBLISH LIVE". Nothing is pushed to the CMS. Agent setup guides: /agent-setup ### Does it work with Strapi 5? It is built for Strapi 5. Entries are addressed by documentId, and draft or published is set with the status query parameter on the REST API. Strapi 4 is not targeted. ### Do I need a particular content type? No. You use your own content type and map each article field to your own attribute names, so no universal schema is assumed. The attributes you map to must exist in Strapi. ### Will it publish articles live in Strapi? Not from the Publishing tab. It creates and updates drafts, and you publish from Strapi after review. Over MCP, a live publication record needs a credential with publication:live, the literal confirmation PUBLISH LIVE and a passing quality assessment, and every live publish is audited. ### What if I press Create draft twice? You do not get two entries. uprank records the publication before it calls Strapi, keyed to the article version, the target and the mode, and sends that key as an idempotency header. The second press updates the same Strapi entry by its documentId. ### What happens when Strapi rejects the article? The publication is marked FAILED and shows the error. Nothing is retried on its own. Fix the content type in Strapi, then press Retry on the publication to send it again. The app has no edit for a publish target, so a wrong mapping is fixed by creating a new target. The Troubleshooting section of this page maps each error to its likely cause. ### Are articles checked before they reach Strapi? Each article is scored in uprank against 13 hard gates: 6 minimum scores and 7 integrity checks. The Publishing tab only pushes a version whose current assessment passed every hard gate; a version that fails one is refused and nothing is sent to Strapi. A version that passes still lands in Strapi as a draft for review. Source: https://uprank.devino.ca/strapi-ai-blog-writer ## MCP server for AI blog writing A blog-writing MCP server lets your coding agent run the steps of writing an article, such as research, briefing, drafting and scoring, as tool calls instead of in a chat window. uprank exposes 17 tools over MCP: research, briefs, drafts, scoring against 13 hard gates, revision, link suggestions and publication records for Strapi drafts. Every call runs the same pipeline and the same gates as the app, so an article your agent drafts is held to the same rules. Updated 2026-10-15 Agents compared: | Agent | Added with | Command or file | Confirm it loaded | | --- | --- | --- | --- | | Claude Code | CLI command | `claude mcp add --transport http --scope user uprank https://uprank.devino.ca/api/mcp --header 'Authorization: Bearer ${UPRANK_MCP_TOKEN}'` | Run claude mcp list: uprank shows ✔ Connected once Claude Code has reached the server. claude mcp get uprank shows that one entry, and /mcp inside a session lists it with its tool count. | | Codex | CLI command | `codex mcp add uprank --url https://uprank.devino.ca/api/mcp --bearer-token-env-var UPRANK_MCP_TOKEN` (config: `~/.codex/config.toml`) | Run codex mcp list and check that uprank is among the configured servers. Inside the Codex TUI, /mcp shows the active MCP servers. | | Cursor | Config file | `~/.cursor/mcp.json` | Open Customize in the sidebar and choose MCPs: uprank should be listed with its toggle on. Its tools also appear in the tools list at the top of the chat panel. | | Windsurf | Config file | `~/.config/devin/mcp_config.json` | Open the Actions (...) menu at the top right of the Cascade panel. Its MCPs section lists uprank with the number of tools it has enabled, and a toggle to switch it on or off. | | VS Code (Copilot) | Config file | `.vscode/mcp.json` | Run MCP: List Servers from the Command Palette and select uprank to start, stop or restart it, or to show its output. It is also listed under MCP SERVERS - INSTALLED in the Extensions view. | | OpenCode | Config file | `~/.config/opencode/opencode.json` | Run opencode mcp list: it lists every configured MCP server and its auth status, so uprank should appear there. | Tokens and scopes: - **Issuing a token.** A workspace OWNER can issue a token by hand at https://uprank.devino.ca/mcp: a name and the scopes it may use. The raw token is shown once and only its hash is stored. A token issued this way has no expiry date and works until it is revoked. - **Changing scopes.** A token issued at https://uprank.devino.ca/mcp keeps the scopes it was issued with. To change them, issue a new token and revoke the old one. An Add to Claude connection works the same way: its scopes are fixed when the owner approves it. - **Add to Claude (OAuth).** Add to Claude connects through OAuth, so there is no token to copy. Only a workspace OWNER can approve its consent screen, and only for a workspace that person owns. The owner does not pick scopes there: the connection gets the scopes the client asked for out of every scope except publication:live, or all of those scopes when the client asked for none of them. Claude is not the only client that can start the flow: any MCP client that registers itself can reach the consent screen, which treats a client whose callbacks are Claude's or ChatGPT's as verified and warns that any other client is unverified. The connection is stored as a credential, so it appears at https://uprank.devino.ca/mcp with a “connected app” badge, named like “OAuth: Claude”. - **OAuth lifetime.** An Add to Claude access token lasts 1 hour. The client renews it with a refresh token that lasts 30 days. Each refresh issues a new access token and a new refresh token on the same credential, and the old pair stops working. Once the refresh token runs out, or the owner who approved the connection is no longer an owner of the workspace, it stops renewing and has to be approved again. - **Missing scope.** A tool call without every scope the tool needs is refused with UNAUTHORIZED, naming the missing scopes. - **Never by default.** publication:live is never granted by default, and the issue dialog marks it as dangerous. An Add to Claude connection cannot hold it at all. - **Revoking.** A workspace OWNER revokes a token or an Add to Claude connection from the credentials table at https://uprank.devino.ca/mcp. That cuts off every agent using it at once: the next call is refused with a 401 (“Unknown, revoked, or expired MCP credential.”), and a revoked connection can no longer refresh. The revocation is audited. An OAuth client can also revoke its own connection through the standard revocation endpoint (RFC 7009). - **Audit.** Every successful tool call that changes something is written to the audit log, with the tool name and the scopes it required. | Scope | Tools that need it | Resources that need it | Advice | | --- | --- | --- | --- | | `brand:read` | `brand_get` | `brandSite` | In the recommended first token | | `brand:write` | `brand_ingest` | None today | | | `campaign:read` | `topic_research` | `campaign`, `topic` | In the recommended first token | | `campaign:write` | None today | None today | | | `research:run` | `pipeline_run`, `topic_research` | None today | Add to research, draft, score and revise | | `article:read` | `pipeline_status`, `publication_status`, `refresh_list`, `article_get`, `article_list` | `evidencePack`, `article`, `articleVersion`, `claims`, `quality`, `workflowRun`, `publication` | In the recommended first token | | `article:write` | `pipeline_run`, `brief_generate`, `article_generate`, `article_revise`, `links_suggest`, `media_select` | None today | Add to research, draft, score and revise | | `quality:run` | `article_score` | None today | Add to research, draft, score and revise | | `publication:draft` | `publication_create_draft` | None today | | | `publication:live` | `publication_publish` | None today | Never granted by default | | `connection:read` | None today | None today | | | `connection:write` | None today | None today | | A tool needs every scope listed for it: `pipeline_run` needs `article:write` and `research:run`; `topic_research` needs `research:run` and `campaign:read`. Troubleshooting: | What you see | Likely cause | What to do | | --- | --- | --- | | The consent screen says “Only a workspace owner can connect an app to uprank.” and has no Allow button. | Your account is not an OWNER of any workspace, and the screen lists only workspaces you own. The server checks the role again when you press Allow, and refuses with “Only an owner of that workspace can connect an app.” | Ask an owner of the workspace to connect the app, or to issue you a token at https://uprank.devino.ca/mcp. Back returns you to the app without connecting. | | The consent page says “This connection can’t continue”, with “unknown client_id” or “The redirect_uri does not match any URI this app registered.” | The request names an app uprank has no registration for, or a callback address that app did not register. uprank refuses these without sending you back to the app. | Start the connection again from the app. If it keeps failing, email support. | | The connection works, but it shows the wrong workspace, or nothing you expect. | A connection belongs to the one workspace picked on the consent screen. The screen shows a Workspace choice only when you own more than one, and it preselects your current workspace when you own it. A tool call cannot name another workspace. | To switch, an owner revokes the connection in the credentials table at https://uprank.devino.ca/mcp, then connects again and picks the other workspace. | | Every call fails with HTTP 401 and “Unknown, revoked, or expired MCP credential.” | The token is unknown, was revoked, or has expired. An Add to Claude access token lasts 1 hour and is renewed with a refresh token that lasts 30 days. A connection cannot renew once the refresh token has run out, or once the owner who approved it is no longer an owner of the workspace (uprank then revokes it). A token issued by hand has no expiry date, so it is usually revoked or mistyped. The 401 carries a WWW-Authenticate header that points OAuth clients to uprank’s authorization metadata. | For an Add to Claude connection, connect again and approve the consent screen as an owner. For a token, check it in the credentials table at https://uprank.devino.ca/mcp; if it is revoked or lost, an owner issues a new one. | | HTTP 401 with “Missing or malformed Authorization header (expected "Bearer ").” | The request carried no bearer token, or the header was not in that form. | Send the header Authorization: Bearer . For a hand-issued token, the guide for your agent shows where it reads the token from (UPRANK_MCP_TOKEN). | | A tool you expect is not in the tool list. | The server lists only the tools whose scopes the credential holds. A tool that needs a scope the credential lacks is not advertised. | The scope table above shows which scope each tool needs. A token keeps the scopes it was issued with, so an owner issues a new token with the extra scope. | | A tool call returns an error with code UNAUTHORIZED and “Missing MCP scope(s): …”. | The credential does not hold every scope the tool needs. A tool called by name is checked the same way as a listed one. The missing scopes are named in the message and in details.missing. | Use a credential that holds the named scopes. Some tools need more than one, as the line under the scope table says. | | publication_publish is not in the tool list for an Add to Claude connection. | An Add to Claude connection never holds publication:live, even if the app asks for it, so the tool is not advertised. The consent screen says “Never live publishing.” | Only if you want an agent to record live publication requests: an owner issues a token at https://uprank.devino.ca/mcp with publication:live, marked dangerous in the issue dialog, and gives it to the agent. The call also needs confirm: "PUBLISH LIVE" and a passing quality assessment. It records a live publication request in uprank and does not push to the CMS. There is no separate human approval, so grant it only to an agent you trust. | | publication_publish returns QUALITY_GATE_FAILED: “No current quality assessment exists for this version; score it before publishing.” or “The article version has not passed its hard quality gates; live publishing is blocked.” | The version has no current quality assessment, or its assessment failed a hard gate. The check runs before anything is recorded, so a refusal leaves nothing behind. | Run article_score, or revise the article until the gates pass, then publish again. The error’s suggestedAction says which. The thresholds are listed at https://uprank.devino.ca/quality-gates. | | A tool call returns VALIDATION_FAILED: “Input failed schema validation.” | The arguments do not match the tool’s input schema. details.issues lists each problem as “path: message”. The error is marked retryable: false. A request body that is not valid JSON gets HTTP 400 and the same code. | Correct the arguments that details.issues names and call again. Repeating the same call fails the same way. | | HTTP 429 with code RATE_LIMITED: “Rate limit exceeded for this MCP credential; retry after a short delay.” | Each credential has a bucket of 60 calls that refills at 1 call per second. Only tool calls and resource reads count; the handshake and the list calls do not. The error is marked retryable: true. | Wait a few seconds and call again. Over a long run, space calls out to about one per second. | | A tool returns only a workflowRunId and no result (pipeline_run, brand_ingest, topic_research, brief_generate, article_generate, article_score, article_revise, links_suggest, media_select). | These tools start a run on the server and return at once. The work carries on after the call returns. | Call pipeline_status with the workflowRunId. It returns the status (PENDING, RUNNING, SUCCEEDED, FAILED or CANCELLED), the current step and the progress from 0 to 100. | | pipeline_status returns status FAILED with an error object. | The run stopped at a step, and currentStep names it. error holds code, message, retryable and, when the code sets them, suggestedAction and step. The code marks a transient failure with retryable: true. | Read error.message and error.suggestedAction and fix what they name. When retryable is true you can start the tool again. | | An error with code MODEL_OUTPUT_INVALID. | The server uses this code for an unexpected failure that has no more specific code, and for a run whose executor threw. It is marked retryable: true. | Try the call again. If it repeats, email support with the code, the message and the workflowRunId. | | media_select finishes, but the article has no image. | No media provider is configured. The tool does not fail and never inserts a placeholder. It records a missing media asset (“No media provider configured.”) and the article completes without an image. The Media tab lists the asset with a “missing” badge. | Nothing failed, so there is nothing to retry. Without a media provider the article has no image until one is attached. | | publication_create_draft succeeds, but nothing appears in Strapi. | The tool records a draft publication in uprank. It does not push anything to the CMS. | Push the draft from the article’s Publishing tab in the app, once the version passes its hard gates. | | You want to disconnect an agent, or a token may have leaked. | A token and an Add to Claude connection are both credentials. They work until they expire or an owner revokes them. | An owner revokes it in the credentials table at https://uprank.devino.ca/mcp. The next call is refused with a 401, and a revoked connection can no longer renew. | Still stuck? Email support@devino.ca with your workspace name and, when there is one, the workflowRunId, the error code and the message. ### Which coding agents work with the uprank MCP server? Any agent that can call a streamable-HTTP MCP server with a bearer token. There are setup guides for Claude Code, Codex, Cursor, Windsurf, VS Code (Copilot), OpenCode, and the onboarding sentence on this page works in each of them. ### Can an agent publish live without review? Not unless you allow it. publication_publish needs a credential that holds publication:live, which is never granted by default, the literal confirmation confirm: "PUBLISH LIVE", and a passing, non-stale quality assessment on the article version; otherwise the call is refused with UNAUTHORIZED or QUALITY_GATE_FAILED. There is no separate human-approval check, so grant publication:live only to an agent you trust. Today the call records a live publication request in uprank and does not push anything to the CMS. Every call is audited. ### What does an MCP token allow? Only what its scopes allow. A first token is read-only: article:read, brand:read, campaign:read. Add research:run, article:write, quality:run to research, draft, score and revise, and publication:draft to record draft publications. A workspace OWNER issues the token at https://uprank.devino.ca/mcp; the raw token is shown once and stored hashed. ### Does it run the same checks as the app? Yes. The tools call the same pipeline and domain services as the app, so article_score evaluates the same 13 hard gates: 6 minimum scores and 7 integrity checks. Tenancy and scopes come from the credential, never from request input. ### Which CMS does it publish to? Strapi. A publish target holds your content type and field mapping, and publication_create_draft records a draft publication for it. The push to Strapi is made from the article’s Publishing tab, as a draft, once the version passes its hard gates. No other CMS has a publisher yet. How the connection works: https://uprank.devino.ca/strapi-ai-blog-writer. Source: https://uprank.devino.ca/agent-setup ## MCP tools Connect any MCP-capable agent to `https://uprank.devino.ca/api/mcp` with a bearer token in `UPRANK_MCP_TOKEN`, or add it to Claude as a custom connector (OAuth, no token): https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Uprank&connectorUrl=https%3A%2F%2Fuprank.devino.ca%2Fapi%2Fmcp. Setup: https://uprank.devino.ca/agent-setup. - `pipeline_run`: Run the full pipeline for a topic: research, evidence, brief, draft, claim check, scoring. - `pipeline_status`: Read a run’s status, current step and any structured error. - `brand_ingest`: Rebuild the brand profile from pages you list: at least one URL is required and at most 40 are fetched. A sitemap cannot be passed over MCP. - `brand_get`: Read the brand profile: voice, positioning, proof points. - `topic_research`: Research one seed query (required) into a single topic opportunity with an Evidence Pack, for a campaign. - `brief_generate`: Generate and critique an editorial brief for a topic. - `article_generate`: Draft an article from its brief and Evidence Pack. - `article_score`: Score a version on the quality dimensions and hard gates. - `article_revise`: Revise weak sections into a new version, within a bounded loop. - `links_suggest`: Suggest internal and external links for review. - `media_select`: Attach a licensed image, or warn visibly when none is available. - `publication_create_draft`: Record a draft publication for a publish target in uprank; idempotent and safe to retry. Nothing is pushed to the CMS: the Strapi draft is pushed from the article’s Publishing tab, once the version passes its hard gates. - `publication_publish`: Record a live publication request for a version with a current, passing quality assessment; needs publication:live and confirm "PUBLISH LIVE". Nothing is pushed to the CMS. - `publication_status`: Read the state of a publication. - `refresh_list`: List published, approved and needs-review articles; the reason is set only when a time-sensitive claim has expired or the canonical version has no current quality assessment. - `article_get`: Read an article and one of its versions. - `article_list`: List articles with site, campaign, status or search filters. ## FAQ ### What does uprank actually do? It runs a research → evidence → brief → draft → claim-check → scoring pipeline for each article, then lets you push a version to your CMS (Strapi) as a draft. Every claim is traced to a source and every quality gate is enforced before anything ships. ### How does uprank keep AI-written articles from inventing facts? Research runs before drafting and produces an Evidence Pack of attributable sources. Every citation must point to a source in that pack and each high-risk claim is checked against its source. An invented citation or an unsupported high-risk claim is a hard gate: the article cannot be published until it is fixed. The full rules are at https://uprank.devino.ca/quality-gates. ### How is uprank different from an AI blog writer? It treats publishing as a gated editorial process, not a text generator. Research comes before drafting, every draft is scored on 11 dimensions against published thresholds, and a draft that fails a hard gate is blocked instead of shipped. Drafts go to your CMS as drafts by default. ### Does uprank guarantee rankings or traffic? No. Nobody can promise rankings, and uprank does not try. It enforces what it can check before publishing: evidence for claims, information gain, practical value, brand fit, readability and risk. ### How do I connect an AI coding agent? Copy the "Onboard your agent" sentence from https://uprank.devino.ca/agent-setup and paste it into your agent. It fetches https://uprank.devino.ca/agent-setup/prompt.md and registers the MCP server itself. Per-agent guides are on the same page. ### Where do I get an MCP token? A workspace OWNER issues one at https://uprank.devino.ca/mcp. The raw token is shown once; tokens are stored hashed. Revoke and re-issue if you lose it. ### Which scopes should a first token have? Read-only: article:read, brand:read, campaign:read. Add research:run, article:write, quality:run to research, draft and score, and publication:draft to record draft publications. publication:live is never granted by default. ### Why does the MCP server return 401? The token is missing, revoked, expired, or its credential name starts with "dev:" while the server runs in production. Issue a fresh credential without a dev: prefix. ### Can an agent publish live? Only with a credential that holds publication:live, the literal confirmation confirm: "PUBLISH LIVE", and a passing, non-stale quality assessment on the article version. Today the call records a live publication request in uprank; it does not push anything to the CMS. There is no separate human-approval check, so grant publication:live only to an agent you trust. Every call is audited. ### Why did my article fail the quality gate? The Quality tab lists every blocker: a score under its minimum (evidence, information gain, practical value, brand fit, readability), risk over its maximum, or a failed integrity check such as an invented citation. Fix the flagged sections with article_revise or the in-app editor, then re-score. The thresholds are listed at https://uprank.devino.ca/quality-gates. ### What CMS can uprank publish to? Strapi only, via a validated connection on the Connections page. The Publishing tab pushes a draft to Strapi once the version has passed its hard gates; you publish from Strapi after review. Drafts are idempotent, so pushing again never creates duplicates. ### Is my workspace data isolated from other tenants? Yes. Tenancy and scopes are derived from the session or the MCP credential, never from request input. Cross-organization ids resolve to NOT_FOUND. ### How do I get support? Email support@devino.ca with your workspace name and, for pipeline issues, the workflow run id from the Trace tab. Source: https://uprank.devino.ca/faq