Skip to content

About

A multi-server Discord control plane that exposes Discord operations as MCP tools, resources, and prompts for AI clients, with a built-in conversational AI agent.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

Discord MCP Platform

A multi-server Discord control plane that exposes Discord operations as MCP tools, resources, and prompts for AI clients. Includes a built-in conversational AI agent that responds to Discord @mentions.

What It Does

Users connect their Discord identity via OAuth2, install the platform bot into their servers, and then interact through MCP-compatible AI clients or by @mentioning the bot directly in Discord.

The platform translates natural language requests into safe, authorized Discord operations:

  • "List my servers and channels"
  • "Summarize the last 100 messages in #general"
  • "Create a support channel and set permissions"
  • "Create an automation that answers FAQs in #support"
  • "Draft a moderation warning for this message"

What This Is Not

This is not a self-bot. It does not use user tokens, control personal Discord accounts, scrape DMs, or bypass Discord permissions/rate limits. All operations execute through authorized bot accounts using official Discord APIs.

Architecture

graph TD
    subgraph "Clients"
        AI["AI Client / MCP Client"]
        DU["Discord User"]
    end

    subgraph "Platform"
        MCPS["MCP Server<br/>66 tools"]
        GW["Discord Gateway<br/>WebSocket"]
        PE["Policy Engine"]
        AGENT["Agent Service<br/>~60 tools"]
        SVC["Discord Service Layer<br/>107 async REST methods"]
    end

    AI -->|MCP call| MCPS
    DU -->|"@mention"| GW
    MCPS --> PE
    GW --> AGENT
    AGENT --> PE
    PE --> SVC
    SVC -->|API v10| DISC["Discord API"]
Loading
graph LR
    subgraph "Authorization Flow"
        direction TB
        A1["1. MCP client auth"] --> A2["2. Workspace membership"]
        A2 --> A3["3. Guild installation check"]
        A3 --> A4["4. Platform role/permission"]
        A4 --> A5["5. Channel policy check"]
        A5 --> A6["6. Discord bot permission"]
        A6 --> A7["7. Rate-limit check"]
        A7 --> A8["8. Execute & audit"]
    end
Loading

Features

MCP Server (66 tools)

graph LR
    subgraph "MCP Tools by Domain"
        G["Guild<br/>4 tools"]
        CH["Channel<br/>7 tools"]
        MSG["Message<br/>7 tools"]
        MOD["Moderation<br/>2 tools"]
        THR["Thread<br/>1 tool"]
        ROLE["Role<br/>7 tools"]
        MEM["Member<br/>6 tools"]
        WH["Webhook<br/>6 tools"]
        INV["Invite<br/>8 tools"]
        AUTO["Automation<br/>1 tool"]
        AUD["Audit<br/>1 tool"]
        REA["Reaction<br/>4 tools"]
        EVT["Event<br/>6 tools"]
        AMOD["Automod<br/>5 tools"]
    end
Loading
Domain Tools
Guild list, get, modify, incident_actions (lockdown)
Channel list, get, create, edit, delete, edit_permissions, delete_permissions
Message list_recent, send, get, edit, send_embed, delete, bulk_delete
Moderation delete, bulk_delete
Thread create
Role list, create, modify, delete, reorder, assign, remove
Member get, list, kick, ban, timeout, unban
Webhook create, list, get, modify, delete, execute
Invite create, list, get, delete, target.add, target.remove, target.bulk_add, target.bulk_remove
Automation draft
Audit list
Reaction add, remove, list, remove_user
Event list, get, create, update, delete, list_users
Automod list, get, create, update, delete
Pins pin.list, pin.add, pin.remove

All state-changing tools support dry-run (default on). Risky operations require explicit confirmation. Every write is audited.

Conversational Agent

sequenceDiagram
    participant U as Discord User
    participant GW as Gateway
    participant AG as Agent Service
    participant LLM as LLM API
    participant BOT as Discord Bot

    U->>GW: @mention bot
    GW->>AG: MESSAGE_CREATE event
    AG->>AG: Check guild + channel allowlist
    AG->>AG: Load channel conversation history
    AG->>LLM: Send history + 60 tool definitions
    loop Tool-use loop (max 10 iterations)
        LLM-->>AG: Tool call or text response
        AG->>BOT: Execute tool call
        BOT-->>AG: Tool result
        AG->>LLM: Send tool result
    end
    AG->>BOT: Send final response to channel
    BOT-->>U: Bot reply
Loading
  • ~60 agent tools covering the full Discord API surface
  • Per-channel conversation history
  • Per-user cooldown
  • Admin-controlled via /allow-chat and /disallow-chat slash commands

Data Model

erDiagram
    User ||--o{ WorkspaceMembership : "belongs to"
    User ||--o{ OAuthAccount : "has"
    Workspace ||--o{ WorkspaceMembership : "contains"
    Workspace ||--o{ GuildInstallation : "owns"
    Workspace ||--o{ MCPClient : "issues"
    GuildInstallation ||--o{ BotConfig : "has"
    GuildInstallation ||--o{ GuildPolicy : "enforces"
    GuildInstallation ||--o{ ChannelPolicy : "enforces"
    GuildInstallation ||--o{ Automation : "runs"
    GuildInstallation ||--o{ AllowedChatChannel : "allows"
    AuditEvent }o--|| Workspace : "records in"
Loading

Infrastructure

  • Discord Gateway WebSocket with auto-reconnect
  • Discord REST client with rate limit tracking and automatic retry
  • Scope-based permission engine with guild/channel allowlists
  • Audit logging with PII redaction
  • 14 database models (PostgreSQL)
  • Redis for caching and rate-limit coordination

Quick Start

cp .env.example .env
# Edit .env with your Discord bot token and other settings
docker compose up --build

Health check:

curl http://localhost:8000/health

Development

make install    # install dependencies
make dev        # run dev server with reload
make test       # run tests (no real Discord token needed)
make lint       # ruff check
make format     # ruff format
make typecheck  # mypy
make version    # print the current version
make up         # docker compose up --build (dev: source mounted, auto-reload)
make down       # docker compose down

docker compose up automatically merges docker-compose.override.yml, which mounts the source tree and enables --reload. For a production-like run without dev conveniences: docker compose -f docker-compose.yml up --build.

Spec Coverage

The official Discord OpenAPI spec is vendored at specs/openapi.json and treated as the source of truth for endpoint coverage.

  • specs/COVERAGE.md — generated report comparing spec endpoints with the REST client and MCP tools (regenerate with python3 scripts/coverage_report.py).
  • scripts/fetch-discord-spec.sh — refreshes the vendored spec; a scheduled agent (Hermes cron, Saturdays 06:00 America/Sao_Paulo) opens a sync PR whenever Discord publishes spec changes.
  • python3 scripts/coverage_report.py --check — regression guard: fails if the number of in-scope implemented endpoints drops below the baseline in specs/.coverage-baseline.

Releases & Versioning

The version lives in exactly one place: src/discord_mcp_platform/_version.py. pyproject.toml declares dynamic = ["version"] and hatchling reads it from there; the FastAPI app and /health report the same value.

To cut a release:

# 1. Bump the version and refresh the committed lockfile
$EDITOR src/discord_mcp_platform/_version.py   # __version__ = "0.2.0"
uv lock
make release-check                             # tests + lint + mypy

# 2. Commit and tag
git add src/discord_mcp_platform/_version.py uv.lock
git commit -m "chore(release): v0.2.0"
git tag v0.2.0
git push origin main --tags

Pushing a v* tag triggers .github/workflows/release.yml, which:

  1. runs the test suite, ruff and mypy;
  2. fails if the tag does not match __version__ (or the lockfile is stale);
  3. builds and pushes ghcr.io/rastrian/discord-mcp-platform with tags <version>, <major>.<minor> and latest — pre-release tags (e.g. v1.2.0-rc1) only get the full version tag, never the rolling ones;
  4. creates a GitHub Release with auto-generated notes.

The recommended way to deploy (e.g. the k3s cluster) is to pin the versioned image:

ghcr.io/rastrian/discord-mcp-platform:0.2.0   # exact pin
ghcr.io/rastrian/discord-mcp-platform:0.2     # track patch releases

The image is multi-stage, runs as a non-root user, and serves /health for probes. Currently linux/amd64 only (arm64 is a follow-up).

Environment Variables

Key variables (see .env.example for full list):

Variable Description
DISCORD_BOT_TOKEN Discord bot token
DISCORD_CLIENT_ID Discord OAuth client ID
DISCORD_CLIENT_SECRET Discord OAuth client secret
DATABASE_URL PostgreSQL connection string
REDIS_URL Redis connection string
ALLOWED_GUILD_IDS Comma-separated guild allowlist (empty = all)
MCP_TRANSPORT http or stdio
ENABLE_GATEWAY Enable Discord Gateway WebSocket
AGENT_ENABLED Enable conversational AI agent
AGENT_API_KEY LLM API key for the agent

MCP Client Configuration

Local STDIO mode:

{
  "mcpServers": {
    "discord": {
      "command": "uv",
      "args": ["run", "python", "-m", "discord_mcp_platform.mcp.server"],
      "env": {
        "DISCORD_BOT_TOKEN": "your-bot-token"
      }
    }
  }
}

HTTP mode: the MCP server is available at http://localhost:8000/mcp when MCP_TRANSPORT=http.

Acknowledgements

Discord API types and endpoint coverage are based on the official Discord OpenAPI specification.

Tech Stack

Python 3.12+ | FastAPI | MCP Python SDK | pydantic v2 | httpx | SQLAlchemy 2.x | PostgreSQL | Redis | Docker | pytest

License

This project is licensed under the Apache License 2.0. See LICENSE for details.

Copyright 2026 Luis Gustavo Vaz me@rastrian.dev

About

A multi-server Discord control plane that exposes Discord operations as MCP tools, resources, and prompts for AI clients, with a built-in conversational AI agent.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages