A remote MCP server for Discord, deployed on Cloudflare Workers.
GuildBridge
A remote MCP server for Discord, deployed on Cloudflare Workers.
About
·
Tools
·
Access Control
·
Token Usage
·
Contributing
About
There is no official Discord MCP server, yet much of the coordination with contributors in the MCP community happens on Discord. GuildBridge fills that gap for me — it gives MCP clients authenticated, permission-aware access to Discord servers so that AI agents can read, search, and post messages where the conversation is already happening. It very much came to life on the heels of a problem that I had that I solved by building my own MCP server.
[!WARNING] The actual hosted version of this MCP server is not broadly available (I have restricted it to specific accounts and servers), but you can just as easily configure and deploy it yourself on your Cloudflare account.

[!NOTE] When hosted, this MCP server authenticates users via Discord OAuth2 and makes all API calls with a bot token. Role-Based Access Control (RBAC) is implemented server-side, as Discord's own auth surface doesn't enable a clean role separation and integration with messaging APIs in its OAuth implementation.
Prerequisites
- Node.js (v18+)
- A Cloudflare account (using the free tier is sufficient)
- A Discord application with:
Discord App Setup
- Go to the Discord Developer Portal and create (or select) an application.
- Under Bot, click "Reset Token" to get your bot token. Save it.
- Under OAuth2, note the Client ID and Client Secret.
- Under OAuth2 > Redirects, add your callback URL:
- Local dev:
http://localhost:8788/callback - Production:
https://<your-worker>.workers.dev/callback(you will get this URI later when you deploy your MCP server to Cloudflare)
- Local dev:
- Under OAuth2 > Scopes, ensure `identify` and `guilds` are selected.
- Under Bot > Privileged Gateway Intents, enable **Message Content Intent** if you want full message content in search results.
- Invite the bot to your server(s) using the OAuth2 URL Generator with the
botscope and these permissions:View Channels,Read Message History,Send Messages.
Local Development
# Install dependencies
npm install
# Copy the example files and fill in your values
cp wrangler.jsonc.example wrangler.jsonc
cp .dev.vars.example .dev.vars
# Start the dev server
npm run dev
The server runs at http://localhost:8788. The MCP endpoint is at /mcp.
`.dev.vars`
[!NOTE] You will need to fill this out prior to deployment to ensure that the MCP server can actually talk to Discord's APIs.
| Variable | Description |
|---|---|
DISCORD_CLIENT_ID |
OAuth2 client ID from Discord Developer Portal |
DISCORD_CLIENT_SECRET |
OAuth2 client secret |
DISCORD_BOT_TOKEN |
Bot token (used for all Discord API calls) |
COOKIE_ENCRYPTION_KEY |
Random string for signing cookies — generate with openssl rand -hex 16 |
ALLOWED_DISCORD_USER_IDS |
Comma-separated Discord user IDs allowed to authenticate (empty = all users) |
Deploy to Cloudflare
# Create the KV namespace (https://developers.cloudflare.com/kv/)
npx wrangler kv namespace create OAUTH_KV
Copy the output id into wrangler.jsonc replacing PLACEHOLDER_KV_ID.
# Set secrets (https://developers.cloudflare.com/workers/configuration/secrets/)
npx wrangler secret bulk .dev.vars
# Deploy
npm run deploy
After deploying, Wrangler will print your worker URL (e.g. https://guildbridge.<your-subdomain>.workers.dev). Add https://<your-worker-url>/callback
Tools (3)
read_messagesRead messages from a specific Discord channel.search_messagesSearch for messages within a Discord server.post_messagePost a message to a specific Discord channel.Environment Variables
DISCORD_CLIENT_IDrequiredOAuth2 client ID from Discord Developer PortalDISCORD_CLIENT_SECRETrequiredOAuth2 client secretDISCORD_BOT_TOKENrequiredBot token used for all Discord API callsCOOKIE_ENCRYPTION_KEYrequiredRandom string for signing cookiesALLOWED_DISCORD_USER_IDSComma-separated Discord user IDs allowed to authenticateConfiguration
{"mcpServers": {"guildbridge": {"command": "npx", "args": ["-y", "@dend/guildbridge"], "env": {"DISCORD_BOT_TOKEN": "YOUR_TOKEN"}}}}