GuildBridge
A remote MCP server deployed on Cloudflare Workers that provides AI agents with authenticated, permission-aware access to Discord servers. It enables agents to read, search, and post messages while maintaining secure Role-Based Access Control via OAuth2.
README
<h1> <p align="center"> GuildBridge </h1> <p align="center"> A remote MCP server for Discord, deployed on Cloudflare Workers. <br /> <a href="#about">About</a> · <a href="#tools">Tools</a> · <a href="#access-control">Access Control</a> · <a href="#token-usage">Token Usage</a> · <a href="CONTRIBUTING.md">Contributing</a> </p> </p>
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
identifyandguildsare 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 as a redirect URI in the Discord Developer Portal.
Connect an MCP Client
Point any MCP-compatible client at the server URL:
https://<your-worker>.workers.dev/mcp
Or locally:
http://localhost:8788/mcp
To test with the MCP Inspector:
npx @modelcontextprotocol/inspector@latest
Enter the URL above, complete the Discord OAuth flow, and the tools will become available.
Tools
| Tool | Description |
|---|---|
list_guilds |
List servers the bot is in |
list_channels |
List channels in a server (optionally filtered by type) |
get_channel_info |
Get channel details (topic, type, etc.) |
read_messages |
Read messages from a channel (with pagination) |
search_messages |
Search messages in a server (by content, channel, author) |
send_message |
Send a message to a channel |
reply_to_message |
Reply to a specific message |
Access Control
Every tool call goes through a layered access check before touching the Discord API. Guild membership is verified via the user's OAuth token, and channel visibility is enforced by computing Discord's permission algorithm from the bot's perspective.
flowchart TD
A[Tool call] --> B{Channel or guild scoped?}
B -->|Guild scoped| C[assertGuildAccess]
B -->|Channel scoped| D[assertChannelAccess]
C --> E[Fetch user guilds via OAuth token]
E --> F{User is member?}
F -->|No| G[Access denied]
D --> H[Fetch channel info via bot token]
H --> I{Channel in a guild?}
I -->|No| G
I -->|Yes| C
F -->|Yes| J[getGuildPermContext]
J --> K[Fetch guild roles + member roles + guild info]
K --> L{User is guild owner?}
L -->|Yes| M[Access granted]
L -->|No| N[computePermissions]
N --> O[Base: @everyone role perms]
O --> P[OR in member role perms]
P --> Q{ADMINISTRATOR set?}
Q -->|Yes| M
Q -->|No| R[Apply @everyone channel overwrite]
R --> S[Apply matching role channel overwrites]
S --> T[Apply member-specific channel overwrite]
T --> U{VIEW_CHANNEL set?}
U -->|Yes| M
U -->|No| G
For list_channels and search_messages, the same permission computation is applied as a post-filter — channels the user can't see are stripped from results.
Token Usage
GuildBridge uses two distinct Discord tokens with intentionally separate roles:
| Token | Stored in | Used for |
|---|---|---|
| Bot token | Server-side env var (DISCORD_BOT_TOKEN) |
All Discord API calls — reading messages, sending messages, fetching channels, roles, and members |
| User OAuth token | Encrypted inside the MCP access token | Guild membership verification only (/users/@me/guilds) |
The bot token never leaves the server. The user's Discord OAuth token is obtained during the OAuth2 login flow, embedded into an encrypted MCP access token, and returned to the MCP client. GuildBridge does not store the user's token server-side — the MCP client holds the encrypted token and sends it with each request, where it is decrypted to extract the OAuth token for guild membership checks.
sequenceDiagram
participant Client as MCP Client
participant Server as GuildBridge
participant Discord as Discord API
note over Client,Discord: OAuth Flow (one-time setup)
Client->>Server: Connect to /mcp
Server-->>Client: 401 — authenticate via OAuth
Client->>Server: /authorize
Server->>Discord: Redirect to Discord OAuth
Discord-->>Server: /callback with auth code
Server->>Discord: Exchange code for user OAuth token
Discord-->>Server: User OAuth token
Server-->>Client: Encrypted MCP token (contains user OAuth token)
note over Client,Discord: Tool Calls (ongoing)
Client->>Server: Tool call + MCP token (Bearer)
Server->>Server: Decrypt MCP token → extract user OAuth token
Server->>Discord: Verify guild membership (Bearer user OAuth token)
Discord-->>Server: User's guild list
Server->>Discord: Execute tool action (Bot token from env)
Discord-->>Server: API response
Server-->>Client: Tool result
During the OAuth flow, short-lived session state is managed via:
- CSRF token — HTTP-only cookie, validates the approval form submission (600s TTL)
- State token — stored in Cloudflare KV, binds the OAuth request across redirects (600s TTL)
- Approved clients cookie — HMAC-signed, lets returning users skip the approval dialog (30 days)
Contributing
See CONTRIBUTING.md for setup instructions, code style guidelines, and how to submit changes. Please also review the AI Usage Policy before contributing.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.