# create_article (/docs/build/mcp-reference/create_article)

{/* GENERATED by scripts/generate-mcp-reference.mjs from the MCP server tools/list. Do not edit. */}

| Group | Access | MCP name |
| --- | --- | --- |
| Articles | Writes data | `create_article` |

## Description [#description]

The description the MCP server sends to the model, word for word. Its rules apply to every call.

> Create a WriteStack article draft. BEFORE calling, call list_article_newsletters and ASK the user which newsletter this article belongs to, then pass that publicationId. Only enabled newsletters are accepted — never guess or pick a default. Also pass title or topic, optional subtitle, markdown body, imageUrl (remote images fetched to S3 and inserted), and an optional plannedForDate target date (omit for an undated draft). Images in bodyMarkdown are also fetched to S3. GitHub-flavored Markdown body. Supported and synced to Substack: headings #–######, **bold**, *italic*, ~~strikethrough~~, `inline code`, [links](https://...), images !\[alt](url), bullet and numbered lists, &gt; blockquotes, :::pullquote ... :::, :::callout ... :::, and a paid-only split with a standalone :::paywall::: line (content after it is behind the Substack paywall). Voice and video embeds are not supported.

## Arguments [#arguments]

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `bodyMarkdown` | `string` | No | GitHub-flavored Markdown body. Supported and synced to Substack: headings #–######, **bold**, *italic*, ~~strikethrough~~, `inline code`, [links](https://...), images !\[alt](url), bullet and numbered lists, &gt; blockquotes, :::pullquote ... :::, :::callout ... :::, and a paid-only split with a standalone :::paywall::: line (content after it is behind the Substack paywall). Voice and video embeds are not supported. |
| `imageUrl` | `string[]` | No | Optional image URLs to insert into the article. WriteStack fetches each URL, stores the image on S3, and appends it to the markdown body. For an image that has no public URL (a local file, a private Google Drive file), call create_article_image_upload first, upload the file, and pass the imageUrl it returned. Markdown/HTML images already in bodyMarkdown are ingested the same way. Max 20. Pass full https:// URLs. Invalid or unreachable URLs are skipped. Images are uploaded to Substack when the article is opened or saved with the Chrome extension, and again when pushing the draft. Max items 20. |
| `plannedForDate` | `string` | No | Optional ISO target date to place the article on the calendar. Omit for an undated draft. |
| `publicationId` | `number` | No | Enabled newsletter publicationId. BEFORE creating or pushing an article, call list_article_newsletters and ASK the user which newsletter to use. Never guess or pick a default. Only IDs returned by that tool are accepted — newsletters the user hid from Articles are rejected. |
| `subtitle` | `string` | No |  |
| `title` | `string` | No |  |
| `topic` | `string` | No |  |

## Example call [#example-call]

The smallest valid request: required arguments only, with placeholder values.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_article",
    "arguments": {}
  }
}
```

## Result [#result]

The result has `structuredContent` that matches this schema. The same data is also in `content` as JSON text.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `articleId` | `string` | Yes |  |
| `contentVersion` | `number` | No |  |
| `images` | `object[]` | No |  |
| `images[].s3Url` | `string` | Yes |  |
| `images[].sourceUrl` | `string` | No |  |
| `message` | `string` | Yes |  |
| `status` | `string` | Yes |  |

## Annotations [#annotations]

| Hint | Value |
| --- | --- |
| `readOnlyHint` | `false` |
| `destructiveHint` | `false` |
| `openWorldHint` | `true` |

The full input and output JSON Schemas for every tool are in [/mcp-tools.json](/mcp-tools.json).
