{"server":{"name":"autoranko","title":"Autoranko — AI SEO on autopilot","version":"1.0.0"},"instructions":"Autoranko ranks websites: analyze any URL, research keywords, write and publish SEO articles, and generate every on-page element (meta tags, Open Graph, schema.org, headings, briefs, rewrites, alt texts, robots/sitemap).\n\nGuidance:\n- Start with seo_analyze for any \"how do I rank / audit this site\" question; it returns parsed facts, a scored issue list and expert recommendations.\n- seo_write_article runs a full outline→draft pipeline (1-3 minutes, counts as 2 AI calls); seo_write_short_article is faster for 150-800 words.\n- Tools with a \"save\" argument persist results to the user's Autoranko account (Dashboard → SEO Lab) by default; pass save=false for throwaway calls.\n- create_article_job / publish_job target a connected WordPress site (see list_sites); the seo_* tools work for ANY website with no connection.\n- serp_preview and robots_sitemap are computed instantly and never consume AI allowance.","tools":[{"name":"whoami","title":"Get the current account","description":"Get the current account. Returns the account the API token belongs to: its ID, email and name, its subscription plan and how many sites it owns. Call it first to check that a token works: a `200` means the token is valid and active.","inputSchema":{"type":"object","properties":{}}},{"name":"list_sites","title":"List sites","description":"List sites. Returns every site your account owns, newest first. A site is a WordPress install connected through the Autoranko plugin; its `id` is what the articles, jobs and keyword endpoints take. The list isn't paginated.","inputSchema":{"type":"object","properties":{}}},{"name":"get_site","title":"Get a site with usage","description":"Get a site with usage. Returns one site and its usage against the plan's limits. `usage.ai_calls_used` counts every AI call the site made this calendar month (UTC), against `usage.ai_calls_limit`: each completed article job uses two (outline and draft), each keyword research request one, and the WordPress plugin's own AI features count too.","inputSchema":{"type":"object","properties":{"id":{"description":"Site ID, from `GET /sites`.","type":"integer"}},"required":["id"]}},{"name":"list_articles","title":"List synced articles","description":"List synced articles. Lists the posts the Autoranko plugin has synced from this WordPress site: your whole content library, not only the articles Autoranko wrote. Each post appears once, at its latest synced version, without the body. Fetch `GET /sites/{id}/articles/{postId}` for the full HTML.","inputSchema":{"type":"object","properties":{"id":{"description":"Site ID, from `GET /sites`.","type":"integer"},"limit":{"description":"Page size. Values outside 1–200 are clamped to that range, not rejected.","type":"integer","minimum":1,"maximum":200,"default":50},"offset":{"description":"How many posts to skip, for pagination. Negative values count as 0.","type":"integer","minimum":0,"default":0},"q":{"description":"Case-insensitive search in titles (substring match). The search covers every stored version, so a post whose title changed can match an old title; that older version is then returned.","type":"string"}},"required":["id"]}},{"name":"get_article","title":"Get an article","description":"Get an article. Returns the latest synced version of one WordPress post, including its full HTML `content`. `postId` is the WordPress post ID: `wp_post_id` in the article list, the same number WordPress shows in the post editor's URL.","inputSchema":{"type":"object","properties":{"id":{"description":"Site ID, from `GET /sites`.","type":"integer"},"postId":{"description":"WordPress post ID: `wp_post_id` from `GET /sites/{id}/articles`.","type":"integer"}},"required":["id","postId"]}},{"name":"list_article_jobs","title":"List jobs","description":"List jobs. Lists the site's generation jobs, newest first, including jobs created in the dashboard. The list leaves out the heavy fields (`outline` and `article_html`); fetch a single job with `GET /jobs/{id}` for those.","inputSchema":{"type":"object","properties":{"id":{"description":"Site ID, from `GET /sites`.","type":"integer"},"status":{"description":"Only return jobs in this status. An unknown value returns an empty list, not an error.","type":"string","enum":["pending","generating","review","publishing","published","failed"]},"limit":{"description":"How many of the newest jobs to return. Values outside 1–200 are clamped to that range.","type":"integer","minimum":1,"maximum":200,"default":50}},"required":["id"]}},{"name":"create_article_job","title":"Create a job","description":"Create a job. Starts writing a new article for the site. Autoranko builds an SEO outline for your `topic` (title, meta description, sections and FAQs, planned at about 1,800 words), then writes the full article as HTML. The call returns `201` right away with the job in `pending`; generation runs in the background and usually takes a few minutes. There's no idempotency key. If a create request times out, check `GET /sites/{id}/jobs` before retrying, or you may generate the same article twice and use up allowance for it.","inputSchema":{"type":"object","properties":{"id":{"description":"Site ID, from `GET /sites`.","type":"integer"},"topic":{"description":"What the article should be about: a working title, a question or a short brief. Surrounding whitespace is trimmed; 1–300 characters remain.","type":"string","minLength":1,"maxLength":300},"target_keyword":{"description":"The search query the article should rank for. It steers the outline, headings and on-page SEO. Omit it, or send an empty string, for none.","type":"string"},"auto_publish":{"description":"Publish to WordPress as soon as the draft is ready instead of stopping in `review`. Needs the site's WordPress connection (`wp_connected: true`); without it the job stops in `review`. Send a JSON boolean: any truthy value, even the string `\"false\"`, turns it on.","type":"boolean","default":false},"scheduled_for":{"description":"Start generating at this time instead of now: an ISO 8601 date-time such as `2026-11-02T09:00:00Z`. Include `Z` or an offset; times without one are treated as UTC. A time in the past starts the job on the scheduler's next run, within about a minute.","type":"string","format":"date-time"}},"required":["id","topic"]}},{"name":"get_article_job","title":"Get a job","description":"Get a job. Returns one job with everything generated so far. `outline` and `article_html` are `null` until the draft is finished; then they hold the structured outline and the full article HTML that will be published. Polling every 15–30 seconds per job stays far below the rate limit. With many jobs in flight, prefer webhooks.","inputSchema":{"type":"object","properties":{"id":{"description":"Job ID, from `POST /sites/{id}/jobs` or `GET /sites/{id}/jobs`.","type":"integer"}},"required":["id"]}},{"name":"publish_job","title":"Publish a job","description":"Publish a job. Approves a job that's waiting in `review` and publishes it to the site's WordPress as a live post: `article_title` becomes the post title, `article_html` the content and `meta_description` the excerpt. The call returns at once with `status` set to `publishing`; the WordPress request runs in the background. No request body is needed. Each successful publish creates a new WordPress post. A published job can't be published again (`409 invalid_state`); to publish the topic again, create a new job.","inputSchema":{"type":"object","properties":{"id":{"description":"Job ID, from `POST /sites/{id}/jobs` or `GET /sites/{id}/jobs`.","type":"integer"}},"required":["id"]}},{"name":"site_keyword_research","title":"Research keywords","description":"Research keywords. Runs AI keyword research for the site. In `ideas` mode (the default) it expands your seed keywords into related long-tail keywords, a mix of informational and commercial searches. In `metrics` mode it estimates metrics for exactly the keywords you send. Each keyword comes with estimated monthly volume, competition, difficulty and cost per click. Allow at least 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"id":{"description":"Site ID, from `GET /sites`.","type":"integer"},"keywords":{"description":"Seed keywords (`ideas`) or the exact keywords to evaluate (`metrics`), as a JSON array of strings. Empty strings are dropped and only the first 20 are used; extra items are ignored, not rejected.","type":"array","items":{"type":"string"},"maxItems":20},"mode":{"description":"`ideas` expands the seeds into related keywords; `metrics` estimates metrics for exactly the keywords sent. Any other value runs `ideas`. The legacy name `action` is accepted as an alias.","type":"string","enum":["ideas","metrics"],"default":"ideas"}},"required":["id","keywords"]}},{"name":"seo_analyze","title":"Audit a page","description":"Audit a page. Fetches any public page, from a CMS page to a hand-written HTML file, and audits it for search in four layers. `page` holds the facts parsed from the HTML: title, meta description, canonical, robots, headings, word count, images, links, Open Graph, JSON-LD and hreflang. `heuristics` is a rule-based audit scored out of 100. `serp_preview` shows how the current title and description render on Google. `expert` is a senior consultant's review, written by AI. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"url":{"description":"The page to audit. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["url"]}},{"name":"seo_keyword_research","title":"Research keywords for any site","description":"Research keywords for any site. Keyword research without a connected site. The seeds come from `keywords`, then `topic`, then the page at `url` (its title segments and headings, at most 5 phrases), up to 20 in all; `seeds_used` shows exactly which were sent. In `ideas` mode (the default) the AI expands them into related long-tail keywords, a mix of informational and commercial searches. In `metrics` mode it estimates metrics for the seeds themselves. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"topic":{"description":"What you want to rank for, as a phrase. Send at least one of `topic`, `url` and `keywords`.","type":"string","minLength":2,"maxLength":300},"url":{"description":"A page to take seed phrases from: its title segments, then its headings, skipping the brand name and generic headings such as `Contact`. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"keywords":{"description":"Seed keywords (`ideas`) or the exact keywords to evaluate (`metrics`): a JSON array of 1–20 non-empty strings, each up to 100 characters.","type":"array","items":{"type":"string"},"minItems":1,"maxItems":20},"mode":{"description":"`ideas` expands the seeds into related keywords; `metrics` estimates metrics for the seeds themselves, including the ones taken from `topic` and `url`.","type":"string","enum":["ideas","metrics"],"default":"ideas"},"language":{"description":"Language of the keywords. Defaults to the page's `lang` when `url` is sent. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"country":{"description":"The market to estimate for: a country name or code, such as `FR` or `France`.","type":"string","maxLength":60},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}}}},{"name":"seo_write_article","title":"Write a long-form article","description":"Write a long-form article. Writes a complete SEO article without a connected site, in two AI steps: an outline (title, meta description, slug, sections and FAQs), then the full HTML body written from it. Ask for 500–4,000 words (1,600 by default) in the `tone` and `language` you need. Tables are used where data helps; no images are added. Uses two AI calls (outline, then draft) from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's, so the request needs two calls left. Allow 300 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"topic":{"description":"What the article should be about: a working title, a question or a short brief.","type":"string","minLength":3,"maxLength":300},"target_keyword":{"description":"The search query the article should rank for. Without one, the outline picks it.","type":"string","maxLength":120},"word_count":{"description":"Target length in words. The result lands close to it rather than exactly on it.","type":"integer","minimum":500,"maximum":4000,"default":1600},"tone":{"description":"The voice to write in, in your own words, such as `friendly, practical` or `formal, expert`.","type":"string","maxLength":120,"default":"professional, helpful"},"language":{"description":"Language to write in. Without it, the AI usually follows the language of `topic`. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["topic"]}},{"name":"seo_write_short_article","title":"Write a short article","description":"Write a short article. Writes a short, publication-ready piece of 150–800 words (400 by default): a news post, a product blurb, an FAQ answer or a landing-page section. It answers the query in its first two sentences, then backs the answer up with one or two `<h2>` sections at most, and a list or small table where it genuinely helps. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"topic":{"description":"What the piece should answer or cover: a question, a working title or a short brief.","type":"string","minLength":3,"maxLength":300},"target_keyword":{"description":"The search query the piece should rank for.","type":"string","maxLength":120},"word_count":{"description":"Target length in words. The result lands close to it rather than exactly on it.","type":"integer","minimum":150,"maximum":800,"default":400},"tone":{"description":"The voice to write in, in your own words, such as `friendly, practical` or `formal, expert`.","type":"string","maxLength":120,"default":"clear, expert, helpful"},"language":{"description":"Language to write in. Without it, the AI usually follows the language of `topic`. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["topic"]}},{"name":"seo_meta_tags","title":"Write title and meta description variants","description":"Write title and meta description variants. Writes three title tags and three meta descriptions, plus a slug and a focus keyword, for an existing page (`url`) or a new one (`topic`). Titles put the keyword first and aim for 60 characters or less; descriptions aim for 160 or less, with the hook in the first 120. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"url":{"description":"The existing page to write tags for: its current tags and headings inform the variants, and its current title and description are measured for comparison. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"topic":{"description":"What a new page is about, when there's no `url`. With `url`, it takes precedence over the page's own heading. Send `url`, `topic` or both.","type":"string","minLength":2,"maxLength":300},"target_keyword":{"description":"The search query to put first in the titles.","type":"string","maxLength":120},"brand":{"description":"Your brand name, for titles that end with it.","type":"string","maxLength":80},"language":{"description":"Language of the tags. Defaults to the page's `lang` when `url` is sent. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}}}},{"name":"seo_open_graph","title":"Generate Open Graph and Twitter tags","description":"Generate Open Graph and Twitter tags. Generates a page's social-sharing tags: every Open Graph tag (`og:title`, `og:description`, `og:type`, `og:url`, `og:site_name`, `og:image`, `og:image:alt` and `og:locale`) and the Twitter card, plus a ready-to-paste block of `<meta>` tags. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"url":{"description":"The page to tag: its title, description, canonical and existing social tags are used. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"topic":{"description":"What a new page is about, when there's no `url`. Send `url`, `topic` or both.","type":"string","minLength":2,"maxLength":300},"brand":{"description":"Your brand name. It becomes `og:site_name`, overriding the model and the page.","type":"string","maxLength":80},"image_url":{"description":"The share image, ideally 1200×630: an absolute `http` or `https` URL, used as is (it isn't fetched). Without it, the page's existing `og:image` is kept; none is ever invented.","type":"string","maxLength":2048},"language":{"description":"Language of the tags. Defaults to the page's `lang` when `url` is sent. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}}}},{"name":"seo_schema","title":"Generate JSON-LD structured data","description":"Generate JSON-LD structured data. Generates valid schema.org JSON-LD for one of eight types: `article`, `faq`, `local_business`, `product`, `organization`, `breadcrumb`, `howto` or `website`. Pass the facts in `details`, give a `url` to read them from the page, or both. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"schema_type":{"description":"The kind of markup to generate. schema.org names work too, such as `LocalBusiness`, `FAQPage`, `BlogPosting`, `NewsArticle`, `BreadcrumbList` or `HowTo`.","type":"string","maxLength":40,"enum":["article","faq","local_business","product","organization","breadcrumb","howto","website"]},"details":{"description":"The facts to mark up, as a JSON object of up to 20,000 characters with any keys: names, URLs, address, opening hours, prices, questions and answers. Required unless `url` is sent. Only these facts and the page's are used: a missing required fact becomes a `TODO: …` string rather than an invention.","type":"object"},"url":{"description":"A page to read facts from as well: its title, description, headings, canonical, Open Graph tags and the JSON-LD types it already has. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["schema_type"]}},{"name":"seo_headings","title":"Plan the heading structure","description":"Plan the heading structure. Designs the heading structure that best serves a query: one `<h1>`, `<h2>` sections in search-intent order (the answer first, depth after), `<h3>` subsections only where a section genuinely splits, and 3–5 questions for an FAQ block. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"topic":{"description":"What a new page is about. Send `topic`, `url` or both.","type":"string","minLength":2,"maxLength":300},"url":{"description":"An existing page to restructure: its current headings are improved rather than replaced blindly. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"target_keyword":{"description":"The search query the page should rank for.","type":"string","maxLength":120},"language":{"description":"Language of the headings. Defaults to the page's `lang` when `url` is sent. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}}}},{"name":"seo_content_brief","title":"Create a content brief","description":"Create a content brief. Writes a brief a writer can work from for one keyword, the way the search results see it: the intent that wins, the angle a new page can own, the target length, the questions to answer, the entities to cover, a section structure, internal-link ideas, and a title and meta description. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"keyword":{"description":"The search query the page will target.","type":"string","minLength":2,"maxLength":150},"context":{"description":"Who the page is for, in your own words: your business, offer, audience or constraints. It shapes the angle and the internal-link ideas.","type":"string","maxLength":4000},"language":{"description":"Language of the brief. Without it, the AI usually follows the language of `keyword`. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["keyword"]}},{"name":"seo_rewrite","title":"Rewrite copy for SEO","description":"Rewrite copy for SEO. Rewrites any copy, from a paragraph to a full article, to rank for `target_keyword` and read better: tighter sentences, concrete claims, natural keyword use and a scannable structure. Facts and HTML tags are kept, and plain text stays plain text. Steer it with `instructions`. Uses one AI call from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month), not from a site's. Allow 300 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"content":{"description":"The copy to rewrite, as plain text or HTML: a paragraph, a landing-page section or a full article.","type":"string","minLength":10,"maxLength":30000},"target_keyword":{"description":"The search query the copy should rank for. It's also what `metrics` counts.","type":"string","maxLength":120},"instructions":{"description":"Extra directions, in your own words, such as a length, a tone or a term to avoid.","type":"string","maxLength":2000},"language":{"description":"Language to write in. Without it, the AI usually keeps the language of `content`. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["content"]}},{"name":"seo_alt_texts","title":"Write image alt text","description":"Write image alt text. Writes alt text for each image in `images`. Send each image's file name and the text around it, or its purpose, for the most specific results. Every alt comes with its length, lint warnings and a ready `<img>` tag; a purely decorative image gets an empty alt. Uses one AI call when `images` is sent, from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month); with `url` alone it makes none. Allow 120 seconds before your HTTP client times out.","inputSchema":{"type":"object","properties":{"images":{"description":"The images to describe: 1–30 objects with `context` (required, up to 1,000 characters: the text around the image, or what it's for) and `filename` (optional, up to 300 characters: the file name or URL, which sharpens the alt and gets you a ready `<img>` tag). Sending `images` makes one AI call. Send `images`, `url` or both.","type":"array","items":{"type":"object"}},"url":{"description":"The page the images are on, as shared context. Sent alone, it returns the page's image counts and the guidelines, with no AI call. Any public `http` or `https` URL; a bare host such as `gladiacteur.com` gets `https://` added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.","type":"string","maxLength":2048},"target_keyword":{"description":"Used only where an image genuinely shows it: keyword-stuffed alt text is a spam signal.","type":"string","maxLength":120},"language":{"description":"Language of the alt text. Defaults to the page's `lang` when `url` is sent. Send a language name or code, such as `fr`, `fr-FR` or `French`.","type":"string","minLength":2,"maxLength":40},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}}}},{"name":"robots_sitemap","title":"Generate robots.txt and a sitemap","description":"Generate robots.txt and a sitemap. Builds a robots.txt and an XML sitemap for a site from the pages you list: exact and correctly escaped for 1 URL or 500, with duplicates removed. Pages without `priority` or `changefreq` get defaults from their path. Pure computation: no AI call and nothing counted against the AI-call allowance, so only the rate limit applies.","inputSchema":{"type":"object","properties":{"site_url":{"description":"The site's home URL. Only its origin is used: every URL in the sitemap is on this host and uses its scheme. It isn't fetched.","type":"string","maxLength":2048},"pages":{"description":"The pages to list: 1–500 objects with `path` (required: a path such as `/contact/`, or an absolute URL on the same host), and optionally `priority` (a number from 0 to 1), `changefreq` (one of `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, `never`) and `lastmod` (the date the page last changed meaningfully, `YYYY-MM-DD` or an ISO 8601 date-time, not in the future). Without them, `priority` is `1.0` for the homepage, `0.8`, `0.6` or `0.5` by depth and `0.3` for legal pages; `changefreq` is `weekly` for the homepage and blog index, `yearly` for legal pages and `monthly` otherwise.","type":"array","items":{"type":"object"}},"disallow_paths":{"description":"Paths crawlers should skip, one `Disallow` rule each: up to 100, each starting with `/` or `*` and up to 500 characters. The wildcards `*` and `$` work as in Google's robots.txt. Without any, robots.txt allows everything.","type":"array","items":{"type":"string"},"maxItems":100},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["site_url","pages"]}},{"name":"serp_preview","title":"Preview a Google result","description":"Preview a Google result. Shows how a title, meta description and URL render on Google's results page. Widths are measured in pixels with Arial's metrics, the way Google truncates: about 580px for a desktop title, 920px for a description (two lines) and 680px for a description on mobile. `preview` holds the text exactly as searchers would see it, cut where Google would cut it, and the breadcrumb URL line. Pure computation: no AI call and nothing counted against the AI-call allowance, so only the rate limit applies.","inputSchema":{"type":"object","properties":{"title":{"description":"The title tag to preview.","type":"string","maxLength":300},"description":{"description":"The meta description to preview.","type":"string","maxLength":1000},"url":{"description":"The page's URL, for the breadcrumb line and the URL checks: a public `http` or `https` URL (a bare host gets `https://`). It isn't fetched.","type":"string","maxLength":2048},"keyword":{"description":"The query the page targets. With it, `keyword_placement` checks that it's early in the title and in the description's first 120 characters; without it, the check only compares the title's lead words with the description.","type":"string","maxLength":120},"save":{"description":"Save the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by `GET /seo/analyses`. Send `false` to keep nothing; `analysis_id` is then `null`. Must be a JSON boolean.","type":"boolean","default":true}},"required":["title","description","url"]}},{"name":"list_seo_analyses","title":"List saved analyses","description":"List saved analyses. Lists the account's saved toolkit results, its SEO Lab history, newest first. Each entry is a summary without the request or the result: fetch one with `GET /seo/analyses/{id}`. Dashboard → SEO Lab shows the same history. Only saved results are listed: a call made with `save: false` leaves nothing here.","inputSchema":{"type":"object","properties":{"kind":{"description":"Only return results from this endpoint. An unknown value is rejected with `400 invalid_body`.","type":"string","enum":["analyze","keywords","article","article_short","meta_tags","open_graph","schema","headings","content_brief","rewrite","alt_texts","robots_sitemap","serp_preview"]},"limit":{"description":"Page size. Values outside 1–100 are clamped to that range, not rejected.","type":"integer","minimum":1,"maximum":100,"default":50},"offset":{"description":"How many results to skip, for pagination. Out-of-range values are clamped.","type":"integer","minimum":0,"maximum":1000000,"default":0}}}},{"name":"get_seo_analysis","title":"Get a saved analysis","description":"Get a saved analysis. Returns one saved toolkit result: the validated request that produced it and the full result, as the endpoint returned it (without `analysis_id`). `id` is the `analysis_id` from the toolkit response, or an `id` from `GET /seo/analyses`.","inputSchema":{"type":"object","properties":{"id":{"description":"Analysis ID: `analysis_id` from a toolkit response, or `id` from `GET /seo/analyses`.","type":"integer"}},"required":["id"]}},{"name":"list_ai_models","title":"List AI models","description":"List AI models. Shows which AI model each step of the content pipeline uses. Each entry in `tasks` has the model in effect (`model`) and its built-in default (`default`); `kind` says whether the task runs a text model (`chat`) or an image model (`image`). `chat_models` and `image_models` list the models a task can be switched to.","inputSchema":{"type":"object","properties":{}}}]}