# Discord MCP Server (`mrbridge/discord-mcp-server`) Actor

Discord MCP Server connects Claude, ChatGPT, Cursor and VS Code to Discord servers through an official read-only bot. It exposes 6 MCP tools for guilds, channels, threads, message history, message context and channel search, returning compact data for LLM summaries and Q\&A.

- **URL**: https://apify.com/mrbridge/discord-mcp-server.md
- **Developed by:** [MrBridge](https://apify.com/mrbridge) (community)
- **Categories:** MCP servers, AI, Developer tools
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 discord data retrievals

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Discord MCP Server

Discord MCP Server is a read-only MCP server for Claude, ChatGPT, Cursor, VS Code, and other MCP-compatible AI clients. It runs on Apify Standby and exposes 6 Discord tools for listing guilds, listing channels and threads, reading messages, fetching message context, and scanning one channel for matching messages.

Ask your assistant to summarize the last 24 hours in `#general`, find what a teammate said about a project decision, or build a digest from one Discord thread. The server returns compact raw Discord data; summarization and reasoning stay inside your LLM client.

### What Is Discord MCP Server?

Discord MCP Server connects an official Discord bot to AI clients through the Model Context Protocol. It is strictly read-only: it cannot send messages, add reactions, moderate users, delete content, or use user tokens.

- Read Discord guilds, channels, active threads, and message windows.
- Return chronological message blocks optimized for LLM context windows.
- Resolve user, channel, and role mentions into readable names when metadata is available.
- Include attachments, embeds, reactions, edit markers, replies, and optional jump URLs.
- Use Apify Standby for a persistent HTTPS endpoint at `/mcp`.
- Use Pay-per-Event billing only after successful tool results.

### Quick Start

1. Create a Discord application and bot in the Discord Developer Portal.
2. Enable the privileged `Message Content Intent` for the bot.
3. Invite the bot to the target server with `View Channels` and `Read Message History`.
4. Set `DISCORD_BOT_TOKEN` as a secret environment variable in the Apify Console.
5. Connect your MCP client to:

```text
https://mrbridge--discord-mcp-server.apify.actor/mcp?fpr=mrbridge
````

Use your Apify API token for the Apify endpoint authorization. Use the Discord bot token only as the Actor secret environment variable; never paste it into client prompts, query parameters, logs, or Actor input.

### Discord Bot Setup

Create the bot:

1. Open the Discord Developer Portal.
2. Create an application.
3. Open Bot, then create or reset the bot token.
4. Copy the token once and store it as `DISCORD_BOT_TOKEN` in the Actor environment variables.
5. In Bot settings, enable `Message Content Intent`. Without this privileged intent, Discord can return empty `content` fields.

Invite the bot:

1. Open OAuth2 -> URL Generator.
2. Select `bot` scope.
3. Select these permissions: `View Channels` and `Read Message History`.
4. Open the generated invite URL and add the bot to the server.

The bot must be able to see every channel you want to read. Discord channel-level permissions still apply.

### Connection Setup

#### Claude Desktop

Use Streamable HTTP if your Claude client supports remote MCP servers:

```json
{
  "mcpServers": {
    "discord": {
      "type": "http",
      "url": "https://mrbridge--discord-mcp-server.apify.actor/mcp?fpr=mrbridge",
      "headers": {
        "Authorization": "Bearer YOUR_APIFY_API_TOKEN"
      }
    }
  }
}
```

#### Claude Code

```bash
claude mcp add --transport http --scope user discord \
  --header "Authorization: Bearer YOUR_APIFY_API_TOKEN" \
  https://mrbridge--discord-mcp-server.apify.actor/mcp?fpr=mrbridge
```

#### ChatGPT Custom Connector

Create a custom connector that targets the MCP endpoint:

```text
https://mrbridge--discord-mcp-server.apify.actor/mcp?fpr=mrbridge
```

Use bearer token authentication with your Apify API token. The Discord bot token remains server-side in the Actor environment.

#### Cursor or VS Code

```json
{
  "mcpServers": {
    "discord": {
      "type": "http",
      "url": "https://mrbridge--discord-mcp-server.apify.actor/mcp?fpr=mrbridge",
      "headers": {
        "Authorization": "Bearer YOUR_APIFY_API_TOKEN"
      }
    }
  }
}
```

### Tools Exposed

| Tool | When to use it | Main parameters | Returns |
|---|---|---|---|
| `list_guilds` | Discover servers the bot can access. | none | Guild IDs and names. |
| `list_channels` | Find text, announcement, forum, media, and thread channels in a guild. | `guild_id`, `include_threads` | Channel metadata and notes for forum/media channels. |
| `get_messages` | Read a message window for summaries or Q\&A. | `channel_id`, `limit`, `before`, `after`, `since`, `until` | Chronological messages plus compact text. |
| `get_message_context` | Read around one known message ID. | `channel_id`, `message_id`, `before`, `after` | Context messages and target index. |
| `search_messages` | Scan one channel/thread for a keyword when native bot search is unavailable. | `channel_id`, `query`, `author`, `since`, `until`, `limit`, `scan_cap` | Matches, scanned count, cap, and `next_before`. |
| `list_active_threads` | Find active threads, especially forum posts. | `guild_id` | Active thread IDs and names. |

#### Search limits

Discord bot REST does not provide a native global message search endpoint. `search_messages` scans messages in one channel or thread and filters locally. The default `scan_cap` is 1000 messages and the maximum is 2000 messages. If the response includes `next_before`, call `search_messages` again with that cursor to continue.

#### Time bounds

`since` and `until` are ISO 8601 timestamps. They are converted to Discord snowflake cursors internally so the server can avoid unnecessary scanning where possible. Explicit `before` and `after` cursors take precedence over `until` and `since`.

### Output Format

Every tool returns:

- `content`: a compact text block for the LLM, for example `[2026-07-09 14:32] @alice -> decision text`.
- `structuredContent`: JSON containing IDs, timestamps, authors, messages, attachments, reactions, cursor metadata, and billing notes where relevant.

Message outputs include:

- UTC ISO timestamps.
- `edited` marker.
- Reply parent IDs when Discord provides them.
- Attachments with filename, content type, URL, size, and `url_expires: true`.
- Embeds summarized into one line.
- Reactions aggregated as `emojixcount`.
- Optional stable Discord jump URLs.

Discord CDN attachment URLs can expire after a short period, often around 24 hours. Jump URLs are stable as long as the user has Discord permission to view the message.

### Standby Mechanics

The Actor runs in Apify Standby mode as a persistent HTTP server. It listens on the Apify-provided Standby port and exposes MCP at `/mcp` and `/mcp/` without redirects.

Cold starts depend on Apify platform state and image availability. Once warm, the server keeps a short in-memory metadata cache for guilds, channels, roles, and members. Message content is never durably cached.

The suggested baseline is 256 MB memory, 512 MB max, and a 5-minute idle timeout. Verify the effective memory and idle timeout in the Apify Console Standby settings after deployment.

### Pricing

Discord MCP Server uses Apify Pay-per-Event billing. Users also pay Apify platform usage for the Standby run while it is warm; the event fees and platform usage are separate billing components.

See the live [Pricing tab](https://apify.com/mrbridge/discord-mcp-server/pricing?fpr=mrbridge) for event prices. The project follows the same MrBridge MCP pricing pattern as France Map and Open Science: `tool-read` for successful read tools and `tool-analysis` for `search_messages`. `initialize`, `tools/list`, failed tool calls, invalid input, permission errors, rate-limit errors, and missing-token errors are not charged. Returned matches from `search_messages` are included in the `tool-analysis` cost.

Set `ACTOR_MAX_TOTAL_CHARGE_USD` if you want a per-run cost cap. If the cap is reached, the server returns a clear MCP error instead of silently continuing unpaid work.

### Known Limits

- Official Discord bot tokens only. User tokens and self-bots are not supported and should not be used.
- `Message Content Intent` is required for reliable message text.
- Discord returns at most 100 messages per REST request.
- Rate limits are bucketed by route and enforced by Discord; the REST client queues requests and respects 429 responses.
- Forum and media channels are containers. Read their posts by listing active threads and calling `get_messages` on a thread ID.
- The server intentionally does not call `List Guild Members`, because that requires the privileged `GUILD_MEMBERS` intent and is unnecessary for this read-only use case.

### Local Development

```bash
npm install
npm run build
npm test
npm run dev
npm run inspector
```

Smoke test a local server:

```bash
bash scripts/smoke-local.sh
```

The smoke script only calls `http://localhost`. It performs `initialize`, `tools/list`, and a `list_guilds` tool call. Without `DISCORD_BOT_TOKEN`, the tool call should return an actionable MCP error while the server remains healthy.

### Legal And Responsible Use

Use this Actor only with Discord servers where you are authorized to install a bot and read message history. You are responsible for complying with Discord terms, workspace rules, privacy law, and internal data policies.

The Actor is read-only and does not store message content durably. Apify run logs must never include bot tokens or message content.

Read Apify's legal overview for broader context: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/?fpr=mrbridge).

### Feedback

Open an issue on the Actor's Issues tab if a Discord permission error, channel type, or MCP client behaves unexpectedly.

More tools, scrapers, MCP servers, and data studies from the same team: [mr-bridge.com](https://mr-bridge.com).

# Actor input Schema

## `defaultMessageLimit` (type: `integer`):

Set the fallback number of Discord messages returned by get\_messages when the tool call does not specify a limit. Defaults to 50.

## `maxCharsPerMessage` (type: `integer`):

Set the default truncation applied to each Discord message body in MCP responses. Defaults to 2000 characters.

## `includeJumpUrlsByDefault` (type: `boolean`):

Include stable Discord jump URLs in message responses unless a tool call overrides the option. Defaults to false.

## Actor input object example

```json
{
  "defaultMessageLimit": 50,
  "maxCharsPerMessage": 2000,
  "includeJumpUrlsByDefault": false
}
```

# Actor output Schema

## `runUrl` (type: `string`):

Link to the Apify run details page.

## `mcpEndpoint` (type: `string`):

Streamable HTTP endpoint for MCP requests served by this Standby run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("mrbridge/discord-mcp-server").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("mrbridge/discord-mcp-server").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call mrbridge/discord-mcp-server --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=mrbridge/discord-mcp-server",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Discord MCP Server",
        "description": "Discord MCP Server connects Claude, ChatGPT, Cursor and VS Code to Discord servers through an official read-only bot. It exposes 6 MCP tools for guilds, channels, threads, message history, message context and channel search, returning compact data for LLM summaries and Q&A.",
        "version": "0.1",
        "x-build-id": "5FagAKccWFjgXXXOE"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/mrbridge~discord-mcp-server/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-mrbridge-discord-mcp-server",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/mrbridge~discord-mcp-server/runs": {
            "post": {
                "operationId": "runs-sync-mrbridge-discord-mcp-server",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/mrbridge~discord-mcp-server/run-sync": {
            "post": {
                "operationId": "run-sync-mrbridge-discord-mcp-server",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "defaultMessageLimit": {
                        "title": "Default message limit",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Set the fallback number of Discord messages returned by get_messages when the tool call does not specify a limit. Defaults to 50.",
                        "default": 50
                    },
                    "maxCharsPerMessage": {
                        "title": "Max characters per message",
                        "minimum": 100,
                        "maximum": 8000,
                        "type": "integer",
                        "description": "Set the default truncation applied to each Discord message body in MCP responses. Defaults to 2000 characters.",
                        "default": 2000
                    },
                    "includeJumpUrlsByDefault": {
                        "title": "Include jump URLs by default",
                        "type": "boolean",
                        "description": "Include stable Discord jump URLs in message responses unless a tool call overrides the option. Defaults to false.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
