⚠️ Security Notice: This project handles Discord credentials and privileged Discord operations. Treat all tokens and secrets as sensitive.
Discord MCP Server exposes Discord runtime packages through one MCP tool with a unified metadata/execution protocol.
This repository now uses the Discord runtime vNext protocol:
- MCP tool:
discord_manage - HTTP runtime: Hono (
@hono/node-server) - Read operations (
automation.read):discord.meta.packagesdiscord.meta.symbolsdiscord.meta.preflightdiscord.meta.refresh
- Write operations (
automation.write):discord.exec.invokediscord.exec.batch
discord_manage uses the contract below:
mode:botoruseridentityId: identity record (for exampledefault-bot)method: optional override (automation.readorautomation.write)operation: one ofdiscord.meta.packagesdiscord.meta.symbolsdiscord.meta.preflightdiscord.meta.refreshdiscord.exec.invokediscord.exec.batch
paramsorargs
Runtime symbol coverage:
class,function,enum,interface,type, andvariableare discovered.interface,type,namespace, andvariablecan be sourced from package declaration files (.d.ts) when missing at runtime.discord.meta.symbolscan include an operational matrix per symbol for preflight/execution readiness.- Catalog responses include
catalogFingerprint,catalogBuiltAt, andisFreshmetadata for agent-side cache control.
- Canonical branch:
new-architecture-main - Repository default branch:
new-architecture-main
- Node.js 18+
- npm
- Discord bot token
git clone https://github.com/drvova/discord-mcp.git
cd discord-mcp
npm install
npm run build# stdio mode (default)
npm start
# dev mode
npm run dev
# HTTP/SSE mode
npm run webCreate .env:
DISCORD_TOKEN=your_bot_token_here
DISCORD_GUILD_ID=your_guild_id_here
# Optional user-mode token
# DISCORD_USER_TOKEN=your_discord_user_token
# Optional encrypted identity store
# DISCORD_MCP_MASTER_KEY=your_32_byte_key_material
# DISCORD_MCP_IDENTITY_STORE_PATH=./.discord-mcp-identities.enc
# Optional risk policy override
# DISCORD_MCP_BLOCK_HIGH_RISK=true
# Optional audit log file
# DISCORD_MCP_AUDIT_LOG_PATH=./data/discord-mcp-audit.log
# Optional logging
# LOG_LEVEL=INFO
# LOG_STYLE=pretty
# LOG_COLOR=true
# ENABLE_LOGGING=true
# Optional OpenTelemetry
# OTEL_ENABLED=true
# OTEL_SERVICE_NAME=discord-mcp
# OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
# OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer token
# OTEL_PROMETHEUS_PORT=9464
# OTEL_PROMETHEUS_ENDPOINT=/metrics
# Optional OAuth (HTTP mode)
# DISCORD_CLIENT_ID=...
# DISCORD_CLIENT_SECRET=...
# DISCORD_OAUTH_REDIRECT_URI=http://localhost:1455/oauth/discord/callbackWhen MCP_HTTP_PORT (or PORT) is set:
GET /ssePOST /messageGET /healthGET /oauth/discord/startGET /oauth/discord/callback
Server logs use a shared Pino logger with compact one-line output (no ISO timestamp clutter in pretty mode).
LOG_LEVELcontrols verbosity:ERROR,WARN,INFO,DEBUG(defaultINFO)LOG_STYLEcontrols output shape:prettyorjson(when unset, auto mode usesprettyfor interactive terminals and dev scripts, otherwisejson)LOG_COLORenables/disables ANSI colors (defaulttrue)ENABLE_LOGGINGdisables all logs when set tofalse(defaulttrue)
For stdio MCP mode, logs are written to stderr so protocol output on stdout remains clean.
- Traces are exported using OTLP HTTP (
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT). - Metrics are exposed via Prometheus exporter at
http://localhost:${OTEL_PROMETHEUS_PORT:-9464}${OTEL_PROMETHEUS_ENDPOINT:-/metrics}. - Service metadata is controlled by
OTEL_SERVICE_NAME.
You can use the generated typed client from Hono route types:
import { createHttpClient } from "./src/http-client.js";
const client = createHttpClient("http://localhost:1455");
const healthResponse = await client.health.$get();
const health = await healthResponse.json();
const rpcResponse = await client.index.$post({
json: {
id: 1,
method: "tools/list"
}
});
const rpc = await rpcResponse.json();The MCP JSON-RPC contract on POST / is unchanged (initialize, tools/list, tools/call).
{
"mode": "bot",
"identityId": "default-bot",
"method": "automation.read",
"operation": "discord.meta.packages",
"params": {
"packages": ["discordjs", "discordjs_voice"]
}
}{
"mode": "bot",
"identityId": "default-bot",
"method": "automation.read",
"operation": "discord.meta.symbols",
"params": {
"packageAlias": "discordjs",
"kinds": ["class", "function", "enum", "interface", "type", "variable"],
"query": "TextChannel#send",
"includeAliases": true,
"includeKindCounts": true,
"includeOperationalMatrix": true
}
}{
"mode": "bot",
"identityId": "default-bot",
"method": "automation.read",
"operation": "discord.meta.preflight",
"params": {
"packageAlias": "discordjs",
"symbol": "TextChannel#send",
"kind": "function",
"target": "channel",
"context": {
"channelId": "123456789012345678"
},
"policyMode": "strict",
"strictContextCheck": true,
"strictArgCheck": false
}
}{
"mode": "bot",
"identityId": "default-bot",
"method": "automation.read",
"operation": "discord.meta.refresh",
"params": {
"force": true,
"includeDiff": true
}
}{
"mode": "bot",
"identityId": "default-bot",
"method": "automation.write",
"operation": "discord.exec.invoke",
"params": {
"packageAlias": "discordjs",
"symbol": "TextChannel#send",
"kind": "function",
"args": ["hello from invoke"],
"target": "channel",
"context": {
"channelId": "123456789012345678"
},
"dryRun": false,
"requirePreflightPass": true,
"allowWrite": true
}
}{
"mode": "bot",
"identityId": "default-bot",
"method": "automation.write",
"operation": "discord.exec.batch",
"params": {
"mode": "best_effort",
"haltOnPolicyBlock": false,
"maxParallelism": 4,
"dryRun": true,
"items": [
{
"packageAlias": "discordjs",
"symbol": "TextChannel#send",
"kind": "function",
"target": "channel",
"context": {
"channelId": "123456789012345678"
},
"args": ["hello from batch"]
}
]
}
}Legacy operation strings are not supported. Use only vNext operations:
discord.meta.packagesdiscord.meta.symbolsdiscord.meta.preflightdiscord.meta.refreshdiscord.exec.invokediscord.exec.batch
If you expect thousands of discovered symbols, this is by design:
- The MCP registry exposes a small, fixed operation surface.
- Package discovery is exposed through
discord.meta.packages. - Symbol discovery is exposed through
discord.meta.symbols. - Execution preflight is exposed through
discord.meta.preflight. - Catalog invalidation/refresh is exposed through
discord.meta.refresh. - Single and batch execution are exposed through
discord.exec.invokeanddiscord.exec.batch. - Runtime discovery includes
enumexports (for exampleChannelType,ActivityType). - Startup logs print loaded package aliases and versions.
- Keep tokens private and rotate regularly.
- Use minimum Discord permissions required.
- Prefer
dryRunfor risky operations. - Use
allowWriteonly when intended. - Enable audit logging in production.
npm run build- compile TypeScriptnpm run dev(orbun run dev) - build once, then runtsc -w+node --watchwith forced pretty logsnpm start- run compiled stdio servernpm run web- run compiled Hono HTTP/SSE server on port 1455
Use gh to track upstream Codex MCP interface updates and keep this server aligned:
gh api repos/openai/codexgh api repos/openai/codex/contents/codex-rs/docs/codex_mcp_interface.mdgh api "search/code?q=repo:openai/codex+mcp_tool_call.rs"