messages_compose
Compose and preview a complete Discord announcement locally: text, typed embeds, uploaded files, polls, and Components V2. Long text and incompatible classic/V2 layouts become ordered message parts.
When to use
Section titled “When to use”Prepare a rich announcement, tournament post, report, or survey before publishing.
Supply bounded base64 data URIs; preview returns filenames, sizes, and hashes without file bytes.
Present the draft, then call messages_publish with the same fields to obtain its target-bound approval.
MCP call example
Section titled “MCP call example”{ "name": "messages_compose", "arguments": { "content": "Hello from discord-mcp" }}| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
content |
string | no | max length: 20000 |
|
embeds |
array<object> | no | max items: 10 |
|
components |
array<unknown> | no | max items: 40 |
|
poll |
object | no | ||
files |
array<object> | no | max items: 10 |
|
allowed_mentions |
object | no | ||
tts |
boolean | no |
Complete input JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "content": { "type": "string", "maxLength": 20000 }, "embeds": { "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string", "maxLength": 256 }, "type": { "type": "string", "const": "rich" }, "description": { "type": "string", "maxLength": 4096 }, "url": { "type": "string", "format": "uri" }, "timestamp": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "color": { "type": "integer", "minimum": 0, "maximum": 16777215 }, "footer": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 2048 }, "icon_url": { "type": "string" } }, "required": [ "text" ], "additionalProperties": false }, "image": { "type": "object", "properties": { "url": { "type": "string" } }, "required": [ "url" ], "additionalProperties": false }, "thumbnail": { "type": "object", "properties": { "url": { "type": "string" } }, "required": [ "url" ], "additionalProperties": false }, "author": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 256 }, "url": { "type": "string", "format": "uri" }, "icon_url": { "type": "string" } }, "required": [ "name" ], "additionalProperties": false }, "fields": { "maxItems": 25, "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 256 }, "value": { "type": "string", "minLength": 1, "maxLength": 1024 }, "inline": { "type": "boolean" } }, "required": [ "name", "value" ], "additionalProperties": false } } }, "additionalProperties": false } }, "components": { "maxItems": 40, "type": "array", "items": {} }, "poll": { "type": "object", "properties": { "question": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 300 } }, "required": [ "text" ], "additionalProperties": false }, "answers": { "minItems": 2, "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "poll_media": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 55 }, "emoji": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^\\d{17,20}$" }, "name": { "type": "string", "minLength": 1 } }, "additionalProperties": false } }, "required": [ "text" ], "additionalProperties": false } }, "required": [ "poll_media" ], "additionalProperties": false } }, "duration": { "default": 24, "type": "integer", "minimum": 1, "maximum": 768 }, "allow_multiselect": { "type": "boolean" }, "layout_type": { "default": 1, "type": "number", "const": 1 } }, "required": [ "question", "answers" ], "additionalProperties": false }, "files": { "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "filename": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$" }, "data_uri": { "type": "string", "pattern": "^data:([A-Za-z0-9!#$&^_.+-]+\\/[A-Za-z0-9!#$&^_.+-]+);base64,([A-Za-z0-9+/]*={0,2})$" }, "description": { "type": "string", "maxLength": 1024 } }, "required": [ "filename", "data_uri" ], "additionalProperties": false } }, "allowed_mentions": { "type": "object", "properties": { "parse": { "default": [], "maxItems": 3, "type": "array", "items": { "type": "string", "enum": [ "users", "roles", "everyone" ] } }, "users": { "maxItems": 100, "type": "array", "items": { "type": "string", "pattern": "^\\d{17,20}$" } }, "roles": { "maxItems": 100, "type": "array", "items": { "type": "string", "pattern": "^\\d{17,20}$" } } }, "additionalProperties": false }, "tts": { "type": "boolean" } }}Returns
Section titled “Returns”{part_count, draft_hash, preview}. No Discord request or write.
Example structured result
Section titled “Example structured result”{ "part_count": 1, "draft_hash": "example", "preview": {}}Output schema
Section titled “Output schema”| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
part_count |
integer | yes | ||
draft_hash |
string | yes | ||
preview |
object | yes |
Complete output JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "part_count": { "type": "integer" }, "draft_hash": { "type": "string" }, "preview": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} } }, "required": [ "part_count", "draft_hash", "preview" ], "additionalProperties": false}Annotations
Section titled “Annotations”| Property | Value |
|---|---|
| Read-only | yes |
| Destructive | no |
| Idempotent | yes |
| Open-world | no |
| Confirmation required | no |
Access and common errors
Section titled “Access and common errors”- The
messagescategory must be enabled byMCP_CATEGORIESwhen an allowlist is set. - Access contract: scope=
local; this tool uses no Discord credential (local or external operation) and is scoped to the local compiler/validator only. - No named Discord permission bit is asserted by this contract.
- Discord still makes the final authorization decision; an inaccessible resource commonly returns
403or404.
Source
Section titled “Source”packages/mcp-core/src/tools/messages/compose.ts

