Skip to main content
Glama
LLMTooling

Discord Webhook MCP

by LLMTooling
README.md
<div align="center">
  <h1>Discord Webhook MCP</h1>
  <p>Model Context Protocol server for Discord Webhooks</p>
</div>

<p align="center">
  <img src="https://img.shields.io/badge/Node.js-18%2B-green?style=for-the-badge&logo=node.js&logoColor=white">
  <img src="https://img.shields.io/badge/TypeScript-5.x-blue?style=for-the-badge&logo=typescript&logoColor=white">
  <img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge">
  <img src="https://img.shields.io/badge/MCP-1.0-purple?style=for-the-badge">
</p>

<div align="center">
  <h2>Overview</h2>
</div>

<div align="center">

Enables LLMs to send messages and rich embeds to Discord via webhooks. Built with TypeScript and the official MCP SDK, it provides a simple, type-safe interface for sending plain text messages, formatted embeds with images and fields, and customizing webhook appearance. Perfect for AI-powered Discord notifications, monitoring, and integrations.

</div>

<div align="center">
  <h2>Core Features</h2>
</div>

<div align="center">
<table>
  <tr>
    <th>Feature</th>
    <th>Description</th>
    <th>Use Case</th>
  </tr>
  <tr>
    <td>Simple Messages</td>
    <td>Send plain text messages up to 2000 characters</td>
    <td>Quick notifications, status updates</td>
  </tr>
  <tr>
    <td>Rich Embeds</td>
    <td>Beautiful formatted messages with titles, descriptions, colors, images</td>
    <td>Structured data, announcements, alerts</td>
  </tr>
  <tr>
    <td>Custom Fields</td>
    <td>Add up to 25 name-value pairs with inline or block layout</td>
    <td>Data tables, metrics, lists</td>
  </tr>
  <tr>
    <td>Images & Thumbnails</td>
    <td>Attach images and thumbnails to embeds</td>
    <td>Visual content, branding</td>
  </tr>
  <tr>
    <td>Timestamps</td>
    <td>Automatic or custom timestamps on embeds</td>
    <td>Event tracking, logs</td>
  </tr>
  <tr>
    <td>Customization</td>
    <td>Override webhook username and avatar per message</td>
    <td>Multi-bot appearance, personalization</td>
  </tr>
  <tr>
    <td>Validation</td>
    <td>Comprehensive input validation and error handling</td>
    <td>Reliability, debugging</td>
  </tr>
</table>
</div>

<div align="center">
  <h2>MCP Tools</h2>
</div>

<div align="center">

The server exposes three tools through the Model Context Protocol interface.

</div>

<div align="center">
<table>
  <tr>
    <th>Tool</th>
    <th>Description</th>
    <th>Required Parameters</th>
  </tr>
  <tr>
    <td><code>send_message</code></td>
    <td>Send a simple text message to Discord</td>
    <td>content</td>
  </tr>
  <tr>
    <td><code>send_embed</code></td>
    <td>Send a rich embed with title, description, colors, images, and more</td>
    <td>None (at least one embed field required)</td>
  </tr>
  <tr>
    <td><code>send_embed_with_fields</code></td>
    <td>Send an embed with custom fields for structured data display</td>
    <td>fields</td>
  </tr>
</table>
</div>

<div align="center">
  <h2>Tool Parameters</h2>
</div>

<div align="center">

**send_message**

</div>

<div align="center">
<table>
  <tr>
    <th>Parameter</th>
    <th>Type</th>
    <th>Required</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>content</td>
    <td>string</td>
    <td>Yes</td>
    <td>Message content (max 2000 characters)</td>
  </tr>
  <tr>
    <td>username</td>
    <td>string</td>
    <td>No</td>
    <td>Override webhook username</td>
  </tr>
  <tr>
    <td>avatar_url</td>
    <td>string</td>
    <td>No</td>
    <td>Override webhook avatar URL</td>
  </tr>
</table>
</div>

<div align="center">

**send_embed**

</div>

<div align="center">
<table>
  <tr>
    <th>Parameter</th>
    <th>Type</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>content</td>
    <td>string</td>
    <td>Optional message content above the embed</td>
  </tr>
  <tr>
    <td>title</td>
    <td>string</td>
    <td>Embed title (max 256 characters)</td>
  </tr>
  <tr>
    <td>description</td>
    <td>string</td>
    <td>Embed description (max 4096 characters)</td>
  </tr>
  <tr>
    <td>url</td>
    <td>string</td>
    <td>URL that the title will link to</td>
  </tr>
  <tr>
    <td>color</td>
    <td>string</td>
    <td>Color as hex (#FF0000), named (red, blue, green, yellow, orange, purple, pink, blurple), or decimal</td>
  </tr>
  <tr>
    <td>timestamp</td>
    <td>boolean</td>
    <td>Add current timestamp to embed</td>
  </tr>
  <tr>
    <td>footer_text</td>
    <td>string</td>
    <td>Footer text (max 2048 characters)</td>
  </tr>
  <tr>
    <td>footer_icon</td>
    <td>string</td>
    <td>Footer icon URL</td>
  </tr>
  <tr>
    <td>image_url</td>
    <td>string</td>
    <td>Large image URL displayed in embed</td>
  </tr>
  <tr>
    <td>thumbnail_url</td>
    <td>string</td>
    <td>Small thumbnail URL (top right)</td>
  </tr>
  <tr>
    <td>author_name</td>
    <td>string</td>
    <td>Author name (max 256 characters)</td>
  </tr>
  <tr>
    <td>author_url</td>
    <td>string</td>
    <td>Author URL (makes name clickable)</td>
  </tr>
  <tr>
    <td>author_icon</td>
    <td>string</td>
    <td>Author icon URL</td>
  </tr>
  <tr>
    <td>username</td>
    <td>string</td>
    <td>Override webhook username</td>
  </tr>
  <tr>
    <td>avatar_url</td>
    <td>string</td>
    <td>Override webhook avatar URL</td>
  </tr>
</table>
</div>

<div align="center">

**send_embed_with_fields**

</div>

<div align="center">
<table>
  <tr>
    <th>Parameter</th>
    <th>Type</th>
    <th>Required</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>fields</td>
    <td>array</td>
    <td>Yes</td>
    <td>Array of field objects (max 25 fields)</td>
  </tr>
  <tr>
    <td colspan="4"><em>Each field object contains:</em></td>
  </tr>
  <tr>
    <td>- name</td>
    <td>string</td>
    <td>Yes</td>
    <td>Field name (max 256 characters)</td>
  </tr>
  <tr>
    <td>- value</td>
    <td>string</td>
    <td>Yes</td>
    <td>Field value (max 1024 characters)</td>
  </tr>
  <tr>
    <td>- inline</td>
    <td>boolean</td>
    <td>No</td>
    <td>Display inline (default: false)</td>
  </tr>
  <tr>
    <td colspan="4"><em>All send_embed parameters are also supported</em></td>
  </tr>
</table>
</div>

<div align="center">
  <h2>Embed Colors</h2>
</div>

<div align="center">
<table>
  <tr>
    <th>Format</th>
    <th>Example</th>
    <th>Result</th>
  </tr>
  <tr>
    <td>Hex</td>
    <td>#FF0000</td>
    <td>Red</td>
  </tr>
  <tr>
    <td>Named</td>
    <td>red, blue, green, yellow, orange, purple, pink, blurple, white, black, gray</td>
    <td>Predefined colors</td>
  </tr>
  <tr>
    <td>Decimal</td>
    <td>16711680</td>
    <td>Red</td>
  </tr>
</table>
</div>

<div align="center">
  <h2>Discord Limits</h2>
</div>

<div align="center">
<table>
  <tr>
    <th>Item</th>
    <th>Maximum</th>
  </tr>
  <tr>
    <td>Message content</td>
    <td>2000 characters</td>
  </tr>
  <tr>
    <td>Embed title</td>
    <td>256 characters</td>
  </tr>
  <tr>
    <td>Embed description</td>
    <td>4096 characters</td>
  </tr>
  <tr>
    <td>Field name</td>
    <td>256 characters</td>
  </tr>
  <tr>
    <td>Field value</td>
    <td>1024 characters</td>
  </tr>
  <tr>
    <td>Footer text</td>
    <td>2048 characters</td>
  </tr>
  <tr>
    <td>Author name</td>
    <td>256 characters</td>
  </tr>
  <tr>
    <td>Fields per embed</td>
    <td>25 fields</td>
  </tr>
  <tr>
    <td>Total embed characters</td>
    <td>6000 characters</td>
  </tr>
  <tr>
    <td>Embeds per message</td>
    <td>10 embeds</td>
  </tr>
  <tr>
    <td>Webhook rate limit</td>
    <td>30 requests/minute</td>
  </tr>
</table>
</div>

<div align="center">
  <h2>Installation</h2>
</div>

<div align="center">
<table>
  <tr>
    <th>Step</th>
    <th>Instructions</th>
  </tr>
  <tr>
    <td><strong>Prerequisites</strong></td>
    <td>
      Node.js 18.0.0 or higher<br>
      A Discord webhook URL
    </td>
  </tr>
  <tr>
    <td><strong>Getting Webhook URL</strong></td>
    <td>
      1. Open your Discord server<br>
      2. Go to Server Settings → Integrations → Webhooks<br>
      3. Click "New Webhook" or select an existing one<br>
      4. Copy the webhook URL<br>
      5. The URL format should be: <code>https://discord.com/api/webhooks/{id}/{token}</code>
    </td>
  </tr>
  <tr>
    <td><strong>Install Dependencies</strong></td>
    <td><code>npm install</code></td>
  </tr>
  <tr>
    <td><strong>Configure Environment</strong></td>
    <td>
      Create a <code>.env</code> file in the project root:<br>
      <code>DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN</code>
    </td>
  </tr>
  <tr>
    <td><strong>Build the Project</strong></td>
    <td><code>npm run build</code></td>
  </tr>
</table>
</div>

<div align="center">
  <h2>Configuration</h2>
</div>

<div align="center">

**Claude Desktop**

</div>

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "discord-webhook": {
      "command": "node",
      "args": ["/path/to/discord-webhook-mcp/dist/index.js"],
      "env": {
        "DISCORD_WEBHOOK_URL": "https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN"
      }
    }
  }
}
```

<div align="center">

**Other MCP Clients**

</div>

The server runs on stdio transport and can be used with any MCP-compatible client. Ensure the `DISCORD_WEBHOOK_URL` environment variable is set.

<div align="center">
  <h2>Development</h2>
</div>

<div align="center">

**Project Structure**

</div>

<div align="center">
<table>
  <tr>
    <th>Directory</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>src/discord/</td>
    <td>Discord API integration (webhook client, embed builder, types)</td>
  </tr>
  <tr>
    <td>src/tools/</td>
    <td>MCP tool implementations (send-message, send-embed, send-embed-fields)</td>
  </tr>
  <tr>
    <td>src/utils/</td>
    <td>Utility functions (environment validation, custom errors)</td>
  </tr>
  <tr>
    <td>src/index.ts</td>
    <td>Main MCP server entry point</td>
  </tr>
  <tr>
    <td>tests/</td>
    <td>Comprehensive test suite with 80%+ coverage</td>
  </tr>
</table>
</div>

<div align="center">

**Development Commands**

</div>

<div align="center">
<table>
  <tr>
    <th>Command</th>
    <th>Description</th>
  </tr>
  <tr>
    <td><code>npm install</code></td>
    <td>Install dependencies</td>
  </tr>
  <tr>
    <td><code>npm run dev</code></td>
    <td>Run in development mode</td>
  </tr>
  <tr>
    <td><code>npm run watch</code></td>
    <td>Watch for changes</td>
  </tr>
  <tr>
    <td><code>npm run build</code></td>
    <td>Build for production</td>
  </tr>
  <tr>
    <td><code>npm test</code></td>
    <td>Run tests</td>
  </tr>
  <tr>
    <td><code>npm run test:watch</code></td>
    <td>Run tests in watch mode</td>
  </tr>
  <tr>
    <td><code>npm run test:coverage</code></td>
    <td>Generate coverage report</td>
  </tr>
  <tr>
    <td><code>npm run typecheck</code></td>
    <td>Type check</td>
  </tr>
  <tr>
    <td><code>npm run lint</code></td>
    <td>Lint code</td>
  </tr>
  <tr>
    <td><code>npm run lint:fix</code></td>
    <td>Fix lint issues</td>
  </tr>
</table>
</div>