# com.writavo/cms (npm · @writavo/mcp-server)

Draft, edit, organise, schedule and publish a Writavo Site content from any AI assistant.

- Trust score: 74/100 (medium)
- Change this week: +4
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-15

## Components

- npm · `@writavo/mcp-server`: 74/100 (this document), [markdown](https://verifymcp.io/servers/com-writavo-cms/writavo-mcp-server.md), [page](https://verifymcp.io/servers/com-writavo-cms/writavo-mcp-server)

## Channel facts

- Registry: `npm`
- Package: `@writavo/mcp-server`
- Version: `0.1.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-15.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 30 of 96 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 48/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 7 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 84/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 5600 tokens (~136/item across 41 items; 38 tools + 3 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 23/100
  - Stability observed for 7 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 95/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 85% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add com-writavo-cms -- npx -y @writavo/mcp-server
```

### Codex

```bash
codex mcp add com-writavo-cms -- npx -y @writavo/mcp-server
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-writavo-cms": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@writavo/mcp-server"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add com-writavo-cms --command npx --arg -y --arg @writavo/mcp-server
```

### Hermes

```yaml
mcp_servers:
  com-writavo-cms:
    command: "npx"
    args: ["-y", "@writavo/mcp-server"]
```

### Other

```json
{
  "mcpServers": {
    "com-writavo-cms": {
      "command": "npx",
      "args": [
        "-y",
        "@writavo/mcp-server"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-15 (score 74, +4)

- [functional improvement] Stability: unverified → 0.23

### 2026-08-11 (score 70, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-08-08 (score 70, +31)

- [security] Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window).
- [functional improvement] Schema quality: unverified → 100
- [functional improvement] MCP protocol: unverified → pass
- [functional improvement] Tool coverage: unverified → 100
- [functional] First check of Schema quality: fail
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 85
- [functional] First check of Schema quality: excellent

### 2026-08-07 (score 39)

First indexed and scored.

## MCP tools (38)

### `verify_api_key` (~69 tokens)

Verify a key

Verify a key. The cheapest possible authenticated call. Returns the kind of key you presented and the scopes it carries. Use it to confirm credentials during setup, and as a liveness probe. It touches no content, so it is exempt from the write rate limit. Read only. Nothing is changed.

### `get_site_info` (~72 tokens)

Read Site information

Read Site information. Public facing information about the Site your key belongs to: its display name, the domain its blog is served from, its locale and its timezone. Scheduling times are interpreted against this timezone when no offset is supplied. Read only. Nothing is changed. Needs a key carrying the meta:read scope.

### `get_content_types` (~79 tokens)

List content types

List content types. The article formats available to this Site. A format is an SEO blueprint (How-To, Listicle, Versus and so on) that shapes how the generator structures an article, and that you may set on any article via `format_id`. Read only. Nothing is changed. Needs a key carrying the meta:read scope.

### `get_usage` (~90 tokens)

Read plan limits, usage and balances

Read plan limits, usage and balances. What your plan allows, what you have used in the current period, and what you can still spend. Read this before a pipeline run if you want to fail fast rather than handle a 402, and read it after a run to see the balance move. Read only. Nothing is changed. Needs a secret key (wv_sk_) carrying the meta:read scope.

### `list_articles` (~362 tokens)

List articles

List articles. Cursor paginated, newest updated first. Read only. Nothing is changed. Needs a key carrying the articles:read scope.

Input parameters:

- `author_id` (string): A UUID.
- `category_id` (string): A UUID.
- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `fields` (string): Comma separated field allow list. Any field of the Article schema may be named. Omit for the default projection, which is: `id, status, title, slug, excerpt, featured_image_url, category_id, author_i…
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.
- `order` (string)
- `slug` (string): Exact slug match. Slugs are unique within a Site, so this returns at most one article.
- `status` (array): Filter by status. Repeat the parameter to match several. A publishable key may only ask for `published`, and any other value is rejected with `403 INSUFFICIENT_SCOPE`.
- `tag_id` (string): Return only articles carrying this tag. A UUID.
- `updated_since` (string): Return only articles updated at or after this instant. This is the incremental sync parameter: store the greatest `updated_at` you have seen and pass it back next time. ISO 8601 with an offset, for e…

### `create_article` (~326 tokens)

Create an article

Create an article. Creates an article at `status: draft`. Always. There is no request field that can make it public, and supplying `status` is a validation error rather than a silent ignore, so a client written against a different CMS fails loudly instead of quietly leaving content unpublished. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `author_id` (string|null): A UUID. Send null to clear it.
- `category_id` (string|null): A UUID. Send null to clear it.
- `comparison`: Send null to clear it.
- `content` (string|null): Markdown. Send null to clear it.
- `excerpt` (string|null): Send null to clear it.
- `faqs`: Send null to clear it.
- `featured_image_url` (string|null): Send null to clear it.
- `format_id` (string|null): A UUID. Send null to clear it.
- `howto_steps`: Send null to clear it.
- `key_takeaways`: Send null to clear it.
- `seo_description` (string|null): Send null to clear it.
- `seo_keywords`: Send null to clear it.
- `seo_title` (string|null): Send null to clear it.
- `slug` (string|null): Derived from `title` when omitted. Supply it if the URL matters. Send null to clear it.
- `tag_ids` (array)
- `title` (string|null): Send null to clear it.

### `get_article` (~100 tokens)

Read one article

Read one article. Returns the full article including `content`. A publishable key may only read an article at `status: published`; anything else returns 404, for the same no disclosure reason that governs cross Site access. Read only. Nothing is changed. Needs a key carrying the articles:read scope.

Input parameters:

- `fields` (string): Comma separated field allow list. Omit to receive every readable field.
- `id` (string, required): A UUID.

### `update_article` (~377 tokens)

Update an article

Update an article. A partial update. Only the fields you send are touched. Send `null` to clear a nullable field; omit it to leave it alone. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `author_id` (string|null): A UUID. Send null to clear it.
- `category_id` (string|null): A UUID. Send null to clear it.
- `comparison`: Send null to clear it.
- `content` (string|null): Markdown. Send null to clear it.
- `excerpt` (string|null): Send null to clear it.
- `faqs`: Send null to clear it.
- `featured_image_url` (string|null): Send null to clear it.
- `format_id` (string|null): A UUID. Send null to clear it.
- `howto_steps`: Send null to clear it.
- `id` (string, required): A UUID.
- `if_match` (string): The ETag from your last read of this object. Send it and the write is refused if somebody else changed the object in the meantime, rather than silently overwriting their work.
- `key_takeaways`: Send null to clear it.
- `seo_description` (string|null): Send null to clear it.
- `seo_keywords`: Send null to clear it.
- `seo_title` (string|null): Send null to clear it.
- `slug` (string|null): Changing the slug of a published article changes its live URL and nothing is redirected for you. The old URL starts returning 404. Send null to clear it.
- `tag_ids` (array): Full replacement, not a merge. Send `[]` to clear.
- `title` (string|null): Send null to clear it.

### `delete_article` (~184 tokens)

Delete an article

Delete an article. Permanent. The row and its tag assignments are removed, and if the article was published its URL starts returning 404 on your blog once the cache is purged. PERMANENT: this deletes content from the customer's Site. There is no trash and no undo. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.
- `if_match` (string): The ETag from your last read of this object. Send it and the write is refused if somebody else changed the object in the meantime, rather than silently overwriting their work.

### `publish_article` (~124 tokens)

Publish an article

Publish an article. Makes the article public immediately, at `status: published`. PUBLIC: this makes the article publicly visible on the customer's own live site, where search engines and readers will see it. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.

### `unpublish_article` (~87 tokens)

Unpublish an article

Unpublish an article. Takes the article off the web and returns it to `status: draft`. The URL starts returning 404 on your blog once the cache is purged. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `id` (string, required): A UUID.

### `schedule_article` (~219 tokens)

Schedule an article

Schedule an article. Moves the article to `status: scheduled` and records when it should go live. A cron publishes it within a few minutes of that time, whether or not the AI pipeline is switched on for your Site. PUBLIC: this makes the article publicly visible on the customer's own live site, where search engines and readers will see it. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.
- `scheduled_publish_at` (string, required): ISO 8601. Include an offset. If you omit one it is read in the Site's timezone, which you can get from `GET /site`. ISO 8601 with an offset, for example 2026-09-01T09:00:00Z.

### `cancel_article_schedule` (~96 tokens)

Cancel a scheduled publish

Cancel a scheduled publish. Returns the article to `status: draft` and clears `scheduled_publish_at`. The content is untouched. Calling this on an article that is not scheduled is a no-op that returns the current state. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the articles:write scope.

Input parameters:

- `id` (string, required): A UUID.

### `list_categories` (~155 tokens)

List categories

List categories. Every category on the Site, alphabetically. Categories are a closed taxonomy: an article has exactly one, or none. Read only. Nothing is changed. Needs a key carrying the taxonomy:read scope.

Input parameters:

- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `fields` (string): Comma separated field allow list. Default projection: `id, name, slug, article_count`.
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.

### `create_category` (~101 tokens)

Create a category

Create a category. `slug` is unique within the Site. A collision returns `409 SLUG_CONFLICT` rather than silently appending a suffix, so your URLs are never a surprise. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the taxonomy:write scope.

Input parameters:

- `name` (string, required)
- `slug` (string): Derived from `name` when omitted.

### `get_category` (~38 tokens)

Read one category

Read one category. Read only. Nothing is changed. Needs a key carrying the taxonomy:read scope.

Input parameters:

- `id` (string, required): A UUID.

### `update_category` (~147 tokens)

Update a category

Update a category. Renaming is safe. Changing `slug` changes the category archive URL on your blog, and nothing is redirected for you, so change it only if you accept the broken link. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the taxonomy:write scope.

Input parameters:

- `id` (string, required): A UUID.
- `if_match` (string): The ETag from your last read of this object. Send it and the write is refused if somebody else changed the object in the meantime, rather than silently overwriting their work.
- `name` (string)
- `slug` (string)

### `delete_category` (~142 tokens)

Delete a category

Delete a category. Articles in this category are not deleted. Their `category_id` becomes `null`, so they stay published and simply lose their category. Removing a category never removes content. PERMANENT: this deletes content from the customer's Site. There is no trash and no undo. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the taxonomy:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.

### `list_tags` (~151 tokens)

List tags

List tags. Every tag on the Site, alphabetically. Tags are cross cutting: an article may carry many. Read only. Nothing is changed. Needs a key carrying the taxonomy:read scope.

Input parameters:

- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `fields` (string): Comma separated field allow list. Default projection: `id, name, slug, article_count`.
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.

### `create_tag` (~85 tokens)

Create a tag

Create a tag. `slug` is unique within the Site. A collision returns `409 SLUG_CONFLICT`. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the taxonomy:write scope.

Input parameters:

- `name` (string, required)
- `slug` (string): Derived from `name` when omitted.

### `get_tag` (~38 tokens)

Read one tag

Read one tag. Read only. Nothing is changed. Needs a key carrying the taxonomy:read scope.

Input parameters:

- `id` (string, required): A UUID.

### `update_tag` (~111 tokens)

Update a tag

Update a tag. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the taxonomy:write scope.

Input parameters:

- `id` (string, required): A UUID.
- `if_match` (string): The ETag from your last read of this object. Send it and the write is refused if somebody else changed the object in the meantime, rather than silently overwriting their work.
- `name` (string)
- `slug` (string)

### `delete_tag` (~124 tokens)

Delete a tag

Delete a tag. The tag is removed from every article that carried it. No article is deleted. PERMANENT: this deletes content from the customer's Site. There is no trash and no undo. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the taxonomy:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.

### `list_authors` (~150 tokens)

List authors

List authors. The byline roster for the Site. Read only. Nothing is changed. Needs a key carrying the authors:read scope.

Input parameters:

- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `fields` (string): Comma separated field allow list. Default projection: `id, name, bio, avatar_url, is_ai_generated, is_default, created_at`.
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.

### `create_author` (~152 tokens)

Create an author

Create an author. `is_ai_generated` marks a persona rather than a real person. It defaults to `true` because that is what the generation pipeline creates. Set it to `false` for a human byline, and be accurate about it: it is what your disclosure copy keys off. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the authors:write scope.

Input parameters:

- `avatar_url` (string|null): Send null to clear it.
- `bio` (string|null): Send null to clear it.
- `is_ai_generated` (boolean)
- `is_default` (boolean)
- `name` (string, required)

### `get_author` (~38 tokens)

Read one author

Read one author. Read only. Nothing is changed. Needs a key carrying the authors:read scope.

Input parameters:

- `id` (string, required): A UUID.

### `update_author` (~191 tokens)

Update an author

Update an author. Setting `is_default: true` clears the flag on whichever author held it, because a Site has at most one default byline. Setting it to `false` on the current default leaves the Site with none. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the authors:write scope.

Input parameters:

- `avatar_url` (string|null): Send null to clear it.
- `bio` (string|null): Send null to clear it.
- `id` (string, required): A UUID.
- `if_match` (string): The ETag from your last read of this object. Send it and the write is refused if somebody else changed the object in the meantime, rather than silently overwriting their work.
- `is_ai_generated` (boolean)
- `is_default` (boolean)
- `name` (string)

### `delete_author` (~135 tokens)

Delete an author

Delete an author. Articles by this author are not deleted. Their `author_id` becomes `null`, so they stay published and lose their byline. PERMANENT: this deletes content from the customer's Site. There is no trash and no undo. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the authors:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.

### `list_media` (~167 tokens)

List media assets

List media assets. The media library, newest first. Read only. Nothing is changed. Needs a secret key (wv_sk_) carrying the media:read scope.

Input parameters:

- `bucket` (string)
- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `fields` (string): Comma separated field allow list. Default projection: `id, bucket, url, file_name, mime_type, size_bytes, width, height, alt_text, created_at`.
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.

### `get_media` (~44 tokens)

Read one media asset

Read one media asset. Read only. Nothing is changed. Needs a secret key (wv_sk_) carrying the media:read scope.

Input parameters:

- `id` (string, required): A UUID.

### `update_media` (~143 tokens)

Update a media asset

Update a media asset. Only `alt_text` is editable. The bytes are immutable: to replace an image, upload a new one and repoint whatever referenced the old one. Changes content on the customer's Site. Nothing becomes public: publishing is always a separate call. Needs a secret key (wv_sk_) carrying the media:write scope.

Input parameters:

- `alt_text` (string|null): Send null to clear it.
- `id` (string, required): A UUID.
- `if_match` (string): The ETag from your last read of this object. Send it and the write is refused if somebody else changed the object in the meantime, rather than silently overwriting their work.

### `delete_media` (~118 tokens)

Delete a media asset

Delete a media asset. Removes the catalog row and the stored bytes. PERMANENT: this deletes content from the customer's Site. There is no trash and no undo. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the media:write scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `id` (string, required): A UUID.

### `list_pipeline_runs` (~158 tokens)

List pipeline runs

List pipeline runs. Recent engine activity for the Site, newest first. One row per stage invocation, so a single logical run appears as several rows as work moves through the stages. Read only. Nothing is changed. Needs a secret key (wv_sk_) carrying the pipeline:read scope.

Input parameters:

- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.
- `stage` (string)
- `status` (string)

### `trigger_pipeline_run` (~167 tokens)

Request a pipeline run

Request a pipeline run. This is the only billable operation in this API. COSTS MONEY: this spends the organisation's credit balance. It is the only billable tool here, and it is charged per unit of work the engine completes. Ask the user before calling this, and pass confirm: true only once they have agreed. Needs a secret key (wv_sk_) carrying the pipeline:run scope.

Input parameters:

- `confirm` (boolean): Set to true only after the user has explicitly agreed to this action. Calling without it returns a description of what would happen and changes nothing.
- `max_articles` (integer): An upper bound on how many articles this run may produce. Your own safety valve on top of the platform spend cap. Omit to use the Site's configured batch size.

### `get_pipeline_status` (~102 tokens)

Read one pipeline run

Read one pipeline run. The outcome of a run. `status: partial` with an `error_summary` is what you see when a run stopped early, whether because credits ran out, the spend cap was reached, or a vendor call failed. `items_succeeded` tells you what you did get. Read only. Nothing is changed. Needs a secret key (wv_sk_) carrying the pipeline:read scope.

Input parameters:

- `id` (string, required): A UUID.

### `get_pipeline_queue` (~181 tokens)

Read the content queue

Read the content queue. What the engine plans to write, highest priority first. Each item is a topic or keyword with a source: `manual` if a person added it, `content_gap` if gap analysis found it, `competitor_seed` if it came from a competitor page. Read only. Nothing is changed. Needs a secret key (wv_sk_) carrying the pipeline:read scope.

Input parameters:

- `cursor` (string): The opaque cursor from `data.next_cursor` on the previous page. Do not parse it or construct one; its encoding is not part of this contract and will change.
- `limit` (integer): Page size. Values above the maximum are clamped rather than rejected, so a client asking for a thousand rows gets a hundred and a `next_cursor`.
- `source` (string)
- `status` (string)

### `upload_media` (~276 tokens)

Upload an image

Upload an image to the Site's media library and return the asset with a usable url, which you can then set as an article's featured_image_url. Give it either a local file path or a public source_url. It drives the whole three step upload for you: reserve, transfer the bytes, register the asset. Changes content on the customer's Site. Nothing becomes public: an asset is only visible where you attach it. Needs a secret key (wv_sk_) carrying the media:write scope.

Input parameters:

- `alt_text` (string): Accessibility text. Worth sending. It is what screen readers announce and what search engines read, and there is no way to generate it for you.
- `bucket` (string): Which library the asset belongs to. Defaults to blog-images.
- `content_type` (string): The image type. Guessed from the filename when omitted. It is a hint either way: the API reads the real type from the bytes and refuses anything that is not an allowed image.
- `file_name` (string): The filename to store it under. Taken from the path or URL when omitted.
- `file_path` (string): Absolute path to an image on this machine. Give either this or source_url.
- `source_url` (string): Public https URL to fetch the image from. Give either this or file_path.

### `get_api_docs` (~123 tokens)

Read the API reference

Read the Writavo Content API reference: what the API does, how keys and scopes work, every endpoint, every error code and what to do about each one. Generated from the published OpenAPI specification, so it is exactly what the API implements. No API key required. Sections: overview, authentication, errors, meta, articles, categories, tags, authors, media, pipeline, api-keys, webhooks, tools, all.

Input parameters:

- `section` (string): Which part to read. Defaults to "overview". Use "all" for the whole reference.

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/com-writavo-cms/writavo-mcp-server#diagnostics

## Score history

- 2026-08-15: 74
- 2026-08-14: 70
- 2026-08-13: 70
- 2026-08-12: 70
- 2026-08-11: 70
- 2026-08-10: 70
- 2026-08-09: 70
- 2026-08-08: 70
- 2026-08-07: 39

## Links

- npm package: https://www.npmjs.com/package/@writavo/mcp-server
- Socket report: https://socket.dev/npm/package/@writavo/mcp-server
- Repository: https://github.com/SparkleOfficial/writavo-mcp-server
- Changelog RSS feed: https://verifymcp.io/servers/com-writavo-cms/writavo-mcp-server.xml
- Changelog JSON feed: https://verifymcp.io/servers/com-writavo-cms/writavo-mcp-server.json
- HTML version of this page: https://verifymcp.io/servers/com-writavo-cms/writavo-mcp-server
