Vexa
Meeting bot and transcripts for Google Meet, Teams and Zoom. Live or after, speakers labelled.
作者による説明(英語の原文)
MCP server for the Discord REST API: 5 read tools always on, 7 write tools env-gated, default off.
この3つを1つのスコアにまとめることはしません。意見、測定、人気はそれぞれ別のものだからです。
このサーバーのやさしい解説はまだ書いていません。以下はレジストリから読み取った事実です。
使っているAIアプリを選んで、設定をコピーしてください。
必要なもの
どのアプリを使っていますか?
上でアプリを選んでください。選んだアプリを覚えておくので、次からはボタンに「…にインストール」と表示されます。
Claude Desktop → Settings → Developer → Edit Config を開き、claude_desktop_config.json にこれを貼り付けます
{
"mcpServers": {
"discord": {
"command": "uvx",
"args": [
"jaimenbell-discord-mcp"
]
}
}
}ターミナルでこれを実行します
claude mcp add discord -- uvx jaimenbell-discord-mcpプロジェクトの .cursor/mcp.json、または ~/.cursor/mcp.json に貼り付けます
{
"mcpServers": {
"discord": {
"command": "uvx",
"args": [
"jaimenbell-discord-mcp"
]
}
}
}ブラウザがアプリを開いてよいか確認し、そのあとアプリが設定を表示して確認を求めます。キーの値は空欄のままなので、自分で入力してください。
プロジェクトの .vscode/mcp.json に貼り付けます
{
"servers": {
"discord": {
"type": "stdio",
"command": "uvx",
"args": [
"jaimenbell-discord-mcp"
]
}
}
}ブラウザがアプリを開いてよいか確認し、そのあとアプリが設定を表示して確認を求めます。キーの値は空欄のままなので、自分で入力してください。
これはパソコンで動くサーバーですが、ChatGPTがつなげるのはインターネット上のサーバーだけです。ほかのアプリを選んでください。
選んだアプリは、この端末のCookieに保存されます。アカウントは不要です。
この設定は、作者のレジストリ登録情報から作成しています。READMEと違う場合は、READMEに従ってください。
パソコンで動くサーバーです。インストールすると、ツール一覧がAIアプリに表示されます。
誰でも見られる情報をチェックしており、コードは読んでいません。当てはまらない項目は数に入れていません。 · 2026年11月9日にチェック
レジストリ名は、リポジトリを所有するGitHubアカウント jaimenbell で確認済みです
このリポジトリはまだGitHubから読み取っていません
このリポジトリはまだGitHubから読み取っていません
これはパソコンで動くため、インターネット上のエンドポイントはありません
パソコンで動き、代わりにローカルの設定を使います
パソコンで動くサーバーです。ツール一覧を読み取れるのは、インターネット上のエンドポイントがある場合だけです
レジストリでこのカテゴリにある有効なすべてのサーバーと比較しています。スターは、公開者がリポジトリの所有者である場合だけ数えます。
当てはまる基本チェック1項目のうち1項目に合格しました。コードは読んでいません。キーやトークンを追加する前に、サーバーがどんなアクセスを求めているかを確認し、必要な権限だけを持つキーを使ってください。
レジストリには必須のキーは載っていません。ただし、最初に使うときにサインインを求めるサーバーもあります。
あなたのパソコンで動きます。必要なときにAIアプリが起動し、データは作者のサーバーを通りません(サーバー自体がオンラインサービスを呼び出す場合を除きます)。
GitHubリポジトリの最終更新は–、最新バージョン(0.1.1)がレジストリに届いたのは3 か月前です。
Claude Desktop、Claude Code、Cursor、VS CodeなどのMCP対応アプリで使えます。パソコンにPython (uv)も必要です。
同じカテゴリには:Vexa, emailmd, MCP WhatsApp Cloud
同じカテゴリで、ほかの作者が作ったサーバー。スターの多い順。
カードの見方:↓ 週あたりのダウンロードi★ GitHubスターi3つの柱:レビュー · チェック · 利用状況i更新=最新バージョンをレジストリに公開した日i
Meeting bot and transcripts for Google Meet, Teams and Zoom. Live or after, speakers labelled.
Render markdown into email-safe HTML, lint drafts for deliverability problems, and preview emails.
MCP server for WhatsApp Cloud API (Meta) — messages, media, and templates via Graph API
作者のリポジトリから書かれたとおりにコピーしたものです。PopNx MCPは内容を確認・推奨していません。HTML、画像、スクリプトは取り除いています。リンクはこのサイトの外へ移動します。
An MCP server over the real Discord REST API -- so a Claude agent calls list_channels(guild_id="...") instead of hand-rolling an authenticated httpx request. Built to the github-mcp/bus-mcp standard in this portfolio (own pyproject, fastmcp server, typed errors, real test suite, honest README) -- fifth flagship, first over Discord.
5 read-only tools, always on + 7 write tools, gated OFF by default behind DISCORD_MCP_ENABLE_WRITE=1 -- see "Write tools" below.
python -m venv .venv
.venv/Scripts/python.exe -m pip install -e ".[test]"
Add to your Claude Desktop/Code MCP config:
{
"mcpServers": { "discord-mcp": { "command": "python", "args": ["C:/path/to/discord-mcp/run_server.py"], "env": { "DISCORD_BOT_TOKEN": "your-bot-token-here" } } } }
Without DISCORD_BOT_TOKEN set, every tool call still returns a clean structured error (Discord's own 401) instead of crashing -- see "Typed errors" below. Write tools also need DISCORD_MCP_ENABLE_WRITE=1 in the same env block, or they refuse locally with policy_refusal -- see "Write tools" below.
This is a reference portfolio implementation demonstrating an MCP server over a real external SaaS API (Discord) -- it is NOT an official Discord MCP server, and it is not affiliated with Discord Inc. It started from an earlier, separate sibling project's HttpDiscordClient, a stdlib-urllib Discord transport built and verified against a real live guild for that project's own server-provisioning tooling. This repo hand-adapts that client's request-building, header construction (including its deliberately descriptive User-Agent -- see below), and error handling onto httpx (matching this fleet's other MCP servers) as its own standalone client with no dependency on that sibling project. discord-mcp does not import from or depend on that other package at all.
Started as 5 read-only tools with no write capability at all; now ships a 7-tool write group, off by default, mirroring the *_MCP_ENABLE_WRITE-style gate already shipped in github-mcp/bus-mcp/desktop-mcp in this same portfolio -- see "Write tools" below.
| Tool | Discord endpoint | Purpose |
|---|---|---|
list_channels | GET /guilds/{guild_id}/channels | All channels (every type) in a guild |
list_roles | GET /guilds/{guild_id}/roles | All roles in a guild |
list_categories | GET /guilds/{guild_id}/channels (filtered) | Category channels only (Discord type 4) -- Discord has no dedicated categories-only endpoint, so this filters the same channels payload client-side |
get_channel_permission_overwrites | GET /channels/{channel_id} (permission_overwrites field) | Role/member allow+deny bitfields set on one channel |
get_member_roles | GET /guilds/{guild_id}/members/{member_id} (roles field) | Role ids currently assigned to one guild member |
DISCORD_MCP_ENABLE_WRITE=1, default OFF)| Tool | Discord endpoint | Purpose |
|---|---|---|
create_channel | POST /guilds/{guild_id}/channels | Create a text/voice/category channel |
edit_channel | PATCH /channels/{channel_id} | Rename/re-topic/re-parent/reorder an existing channel |
create_role | POST /guilds/{guild_id}/roles | Create a role |
edit_role | PATCH /guilds/{guild_id}/roles/{role_id} | Edit an existing role |
edit_guild | PATCH /guilds/{guild_id} | Update guild-level identity (name/icon/banner/description) |
delete_channel | DELETE /channels/{channel_id} | Destructive. Delete a channel |
create_message | POST /channels/{channel_id}/messages | Post a message to a text channel (content: non-empty, <= 2000 chars) |
Seven write tools were added on top of the original 5 read-only tools, mirroring the exact write-gate pattern already shipped in this portfolio (github-mcp's GITHUB_MCP_ENABLE_WRITE, desktop-mcp's DESKTOP_MCP_ENABLE_*, and most closely bus-mcp's BUS_MCP_ENABLE_WRITE + gated_write decorator, copied as the reference template). create_message was added a night later than the other 6, once it became clear that none of create_channel/edit_channel/create_role/edit_role/edit_guild/delete_channel can actually post content to a channel -- it reuses the exact same gate and the post() helper create_channel/create_role already added to client.py, no new HTTP plumbing.
DISCORD_MCP_ENABLE_WRITE=1 (or true/yes/on) in the server's environment to enable the write group. Unset (or any other value) means every write tool call refuses locally, with zero Discord API calls attempted, returning a structured policy_refusal error: {"ok": false, "error": {"type": "policy_refusal", "message": "Tool group 'write' is disabled. Set DISCORD_MCP_ENABLE_WRITE=1 in the server's environment to enable it.", "group": "write", "tool": "create_channel", "required_env": "DISCORD_MCP_ENABLE_WRITE"}}
@config.gated_write decorator wraps each write function directly in discord_mcp/routes.py (not merely the @mcp.tool wrapper in server.py), so the gate is unit-testable without spinning up fastmcp or a real transport, and can't be bypassed by any alternate calling path into routes.py.DISCORD_MCP_ENABLE_WRITE env var as the other write tools -- confirmed by dedicated tests in test_routes.py (setting plausible-but-wrong var names like DISCORD_MCP_ENABLE_DELETE does not arm it)._headers()/pooled httpx.AsyncClient construction in client.py as every read tool -- there is only one auth code path in this repo.content must be a non-empty string of at most 2000 characters (Discord's real message-length limit) -- checked by client.validate_message_content before any request is built, same "never even attempt the call" discipline as the snowflake-id checks. A violation returns validation_error, not a raw Discord 400.icon_base64/banner_base64 on edit_guild -- a flagged assumptionDiscord's docs describe PATCH /guilds/{id}'s icon/banner fields as an "image data" string -- a full data URI (data:image/png;base64, ), not a bare base64 payload. edit_guild accepts either:
data:...;base64,... URI, passed through unchanged, ordata:image/png;base64, .This PNG assumption is not verified against a real Discord response -- this repo has not confirmed whether Discord accepts, rejects, or silently mis-renders a non-PNG image (JPEG, animated GIF for boosted-server icons, etc.) sent under an image/png label. If you have a non-PNG image, pass a full data:image/...;base64,... URI yourself rather than relying on the default. Flagged here rather than guessed silently.
Every tool returns {"ok": true, ...} on success or {"ok": false, "error": {...}} on failure -- never an unhandled exception or stack trace.
{"message": "Missing Access", "code": 50001}) -- the bot lacks the permission/scope for this call, or isn't in the guild.User-Agent; without one, a client's default UA is a well-known bot fingerprint that Discord's Cloudflare edge can reject with a bare 403 *before* the request ever reaches route-level permission checks. This is otherwise indistinguishable from a real permission_error 403 -- Discord's real permission-denied responses always carry a JSON body, so absence of a JSON body on a 403 is the signal this type is built on. This is a best-effort heuristic, not a certainty: a proxy, load balancer, or future Discord change that strips the body on a *different* kind of 403 would also land here. discord-mcp sends the same descriptive User-Agent this heuristic exists to explain (see client.py's _headers()), so in practice this type should rarely fire from this server's own calls -- see "Honest limitations" below.retry_after_s, parsed straight from Discord's own JSON body (retry_after, in seconds). This server does not auto-retry -- it surfaces the limit as a structured error immediately and leaves any backoff/retry decision to the caller.create_message only) -- content was empty or exceeded Discord's real 2000-character message limit, caught before any request was built.Internally, discord_mcp/client.py raises typed DiscordUnreachable / DiscordApiError (with a DiscordDecodeError subclass for the 2xx-non-JSON case) exceptions; discord_mcp/routes.py catches both and normalizes to the dict shape above before a tool ever returns. Tests exercise both layers for every error type, across every HTTP verb (GET/POST/PATCH/DELETE).
cloudflare_blocked vs. permission_error split is a heuristic (JSON-body-present-or-not), not something Discord documents or guarantees. It is accurate for the specific failure mode it was written to explain (an edge reject due to a missing/generic User-Agent) but a 403 with a stripped body from an unrelated cause (e.g. a misbehaving proxy in between) would also be classified as cloudflare_blocked.get_channel_permission_overwrites and get_member_roles were not exercised against every possible real-world edge case (e.g. a member with zero roles, a channel with zero overwrites) via the live smoke test -- only via respx-mocked unit tests. The live smoke test only calls list_channels/list_roles; it does not exercise any write tool.list_channels/list_roles are single-request, unpaginated Discord endpoints (Discord doesn't paginate either of these), so this is a non-issue for the tools in scope -- but a guild large enough to need member-list pagination is out of scope entirely (there is no list_members tool here).icon_base64/`banne冒頭だけを表示しています。続きはリポジトリで読めます