Skip to content

Build a rich announcement

This workflow posts a structured announcement with a header thumbnail and image gallery. Each builder returns { component }; unwrap that field before passing the node to the next builder.

  1. Build a section with its required accessory.

    text is an array of one to three Markdown strings. Component type identifiers are numeric.

    {
    "name": "components_v2_build_section",
    "arguments": {
    "text": [
    "# discord-mcp release",
    "A typed Discord toolset for MCP clients."
    ],
    "accessory": {
    "type": 11,
    "media": { "url": "https://example.com/hero.png" },
    "description": "Release artwork"
    }
    }
    }
  2. Build the media gallery.

    Builder inputs use a top-level url. The builder converts it to Discord’s nested media.url output shape.

    {
    "name": "components_v2_build_media_gallery",
    "arguments": {
    "items": [
    { "url": "https://example.com/tool-catalog.png", "description": "Tool catalog" },
    { "url": "https://example.com/telemetry.png", "description": "Telemetry view" }
    ]
    }
    }
  3. Wrap both returned components in a container.

    Pass sectionResult.component and galleryResult.component, not the wrapper objects.

    {
    "name": "components_v2_build_container",
    "arguments": {
    "components": [
    {
    "type": 9,
    "components": [
    { "type": 10, "content": "# discord-mcp release" },
    { "type": 10, "content": "A typed Discord toolset for MCP clients." }
    ],
    "accessory": {
    "type": 11,
    "media": { "url": "https://example.com/hero.png" },
    "description": "Release artwork"
    }
    },
    {
    "type": 12,
    "items": [
    { "media": { "url": "https://example.com/tool-catalog.png" }, "description": "Tool catalog" },
    { "media": { "url": "https://example.com/telemetry.png" }, "description": "Telemetry view" }
    ]
    }
    ],
    "accent_color": 5793266
    }
    }

    The result is { "component": { "type": 17, ... } }.

  4. Validate the final top-level array.

    {
    "name": "components_v2_validate",
    "arguments": {
    "components": [
    {
    "type": 17,
    "components": [
    {
    "type": 9,
    "components": [
    { "type": 10, "content": "# discord-mcp release" },
    { "type": 10, "content": "A typed Discord toolset for MCP clients." }
    ],
    "accessory": {
    "type": 11,
    "media": { "url": "https://example.com/hero.png" },
    "description": "Release artwork"
    }
    },
    {
    "type": 12,
    "items": [
    { "media": { "url": "https://example.com/tool-catalog.png" }, "description": "Tool catalog" },
    { "media": { "url": "https://example.com/telemetry.png" }, "description": "Telemetry view" }
    ]
    }
    ],
    "accent_color": 5793266
    }
    ]
    }
    }

    Success is exactly { "valid": true, "issues": [] }. There is no component_count in the validator result.

  5. Send the same validated array.

    Use the exact components array from validation and add the target channel ID:

    {
    "name": "components_v2_send",
    "arguments": {
    "channel_id": "222233334444555566",
    "components": [
    {
    "type": 17,
    "components": [
    {
    "type": 9,
    "components": [
    { "type": 10, "content": "# discord-mcp release" },
    { "type": 10, "content": "A typed Discord toolset for MCP clients." }
    ],
    "accessory": {
    "type": 11,
    "media": { "url": "https://example.com/hero.png" },
    "description": "Release artwork"
    }
    },
    {
    "type": 12,
    "items": [
    { "media": { "url": "https://example.com/tool-catalog.png" }, "description": "Tool catalog" },
    { "media": { "url": "https://example.com/telemetry.png" }, "description": "Telemetry view" }
    ]
    }
    ],
    "accent_color": 5793266
    }
    ]
    }
    }

    The result contains message_id, channel_id, jump_url, and component_count: 1 because there is one top-level container.

  • Each builder is read-only and can be rerun safely.
  • Wrapper objects are never valid component nodes; always pass their component value.
  • Offline validation returns precise issue paths without consuming a Discord request.
  • The final send automatically sets the Components V2 message flag.

See the exact components_v2 tool category, the components_v2_send reference, or the Components V2 architecture.