VoiceOS Discord MCP Server
by CharityDEX
README.md
# VoiceOS Discord MCP Server
This is a standalone TypeScript MCP server that lets VoiceOS read and write Discord messages through Composio's `DISCORDBOT` toolkit.
VoiceOS still launches this as a local stdio MCP server, but Discord authentication and token handling are delegated to Composio.
## Features
- `connect_discord_bot`: Returns a Composio Connect Link for Discord bot/account authentication.
- `list_discord_servers`: Explains guild/server discovery for the Composio-backed bot flow.
- `list_discord_channels`: Lists channels for a known Discord guild/server ID.
- `read_discord_messages`: Fetches recent messages from a Discord channel ID.
- `send_discord_message`: Sends a message to a Discord channel ID.
- `reply_discord_message`: Replies to a specific Discord message ID.
Write actions are described clearly in the MCP tool definitions so VoiceOS can show its confirmation pill before sending anything to Discord.
## Requirements
- Node.js 20+
- Composio API key
- A stable user ID for local testing
For production VoiceOS, the user ID should be injected automatically from the logged-in VoiceOS account. Users should not manually determine or enter it.
## Install
```bash
npm install
```
## Configure Environment
Create a local `.env` file:
```bash
COMPOSIO_API_KEY=your_composio_api_key
VOICEOS_USER_ID=local-test-user
COMPOSIO_TOOLKIT=DISCORDBOT
# Recommended/required for reliable DISCORDBOT channel and message tools.
COMPOSIO_AUTH_CONFIG_ID=your_discordbot_auth_config_id
```
`COMPOSIO_AUTH_CONFIG_ID` should point to a custom Composio `DISCORDBOT` auth config that includes the Discord client ID, client secret, bot token, and permission integer. The default Composio-managed OAuth connection can show as `ACTIVE` while still lacking the bot token needed for server channel/message endpoints, which causes Discord `401 Unauthorized` responses.
Optional server IDs for channel discovery:
```bash
DISCORD_GUILD_IDS=server_id_1,server_id_2
```
`DISCORD_GUILD_IDS` is useful because the current Composio-backed MCP maps channel listing to `DISCORDBOT_LIST_GUILD_CHANNELS`, which requires a guild/server ID.
## Run Locally
```bash
npm run start
```
## Connect to VoiceOS
1. Open VoiceOS settings.
2. Go to **Custom Integrations**.
3. Click **Add**.
4. Name the integration, for example `Discord`.
5. Paste the launch command:
```bash
/Users/makslas/Desktop/Development-Repos/VoiceOS-Discord-MCP/run-discord-mcp.sh
```
6. Click **Connect**.
## Authentication Flow
After the MCP is connected in VoiceOS, ask:
```text
Connect Discord
```
VoiceOS should call `connect_discord_bot`, which opens a Composio Connect Link. If `COMPOSIO_AUTH_CONFIG_ID` is set, the link is created against that exact auth config instead of Composio's default managed OAuth config.
If the user tries any Discord action before authenticating, the MCP returns an auth-required message. Normal Discord actions intentionally do not open Composio automatically, which prevents auth retry loops.
```text
Discord Bot authentication is required before I can access Discord.
Please explicitly ask: `Connect Discord` when you want me to open the Composio connection page.
```
## Tool Details
### `connect_discord_bot`
Creates a Composio Connect Link for `DISCORDBOT`.
Use this when asking VoiceOS:
```text
Connect Discord
```
### `list_discord_servers`
If `DISCORD_GUILD_IDS` is configured, fetches details for those guilds. Otherwise, explains that Composio `DISCORDBOT` channel listing requires a guild/server ID.
### `list_discord_channels`
Lists Discord channels for a server/guild.
Parameters:
- `guild_id`: Optional Discord server/guild ID. If omitted, the tool uses `DISCORD_GUILD_IDS`.
- `text_only`: Defaults to `true`, returning only text-like channels suitable for read/send message workflows.
Use this when asking VoiceOS:
```text
What Discord channels do you have access to in server GUILD_ID?
```
### `read_discord_messages`
Reads recent messages from a channel via `DISCORDBOT_LIST_MESSAGES`.
Parameters:
- `channel_id`: Discord channel ID.
- `channel_name`: Discord channel name, such as `general`. Used when `channel_id` is omitted.
- `guild_id`: Optional Discord server/guild ID used to resolve `channel_name`. If omitted, the tool uses `DISCORD_GUILD_IDS`.
- `limit`: Number of messages to fetch, from 1 to 100. Defaults to 10.
- `before`: Optional message ID for pagination. Fetches messages before this message.
- `after`: Optional message ID for pagination. Fetches messages after this message.
- `around`: Optional message ID for pagination. Fetches messages around this message.
- `author_filter`: Optional user ID, username, or display-name filter.
### `send_discord_message`
Sends a message to a channel via `DISCORDBOT_CREATE_MESSAGE`.
Parameters:
- `channel_id`: Discord channel ID.
- `channel_name`: Discord channel name, such as `general`. Used when `channel_id` is omitted.
- `guild_id`: Optional Discord server/guild ID used to resolve `channel_name`. If omitted, the tool uses `DISCORD_GUILD_IDS`.
- `content`: Exact message content. Max 2000 characters.
- `tts`: Whether to send as text-to-speech. Defaults to `false`.
- `allowed_mentions`: Mention parsing policy. One of `none`, `users`, `users_and_roles`, or `everyone`. Defaults to `none`.
### `reply_discord_message`
Replies to a specific message via `DISCORDBOT_CREATE_MESSAGE` with `message_reference`.
Parameters:
- `channel_id`: Discord channel ID containing the original message.
- `channel_name`: Discord channel name, such as `general`. Used when `channel_id` is omitted.
- `guild_id`: Optional Discord server/guild ID used to resolve `channel_name`. If omitted, the tool uses `DISCORD_GUILD_IDS`.
- `message_id`: Discord message ID to reply to.
- `content`: Exact reply content. Max 2000 characters.
- `allowed_mentions`: Mention parsing policy. One of `none`, `users`, `users_and_roles`, or `everyone`. Defaults to `none`.
## Discord DM Limitations
Composio `DISCORDBOT` supports bot-accessible channel messaging, message reads, replies, guild channel listing, and bot-created DMs.
It does not grant broad access to a user's existing personal DMs. Group DM operations require user OAuth2 access tokens with `gdm.join` and remain constrained by Discord API limitations.
## Production VoiceOS User IDs
For production, VoiceOS should pass its internal logged-in user ID to Composio automatically. The user should never manually type a user ID.
Do not use Discord email as the primary Composio `user_id`:
- The connect link requires a user ID before Discord OAuth completes.
- Discord email may be unavailable depending on scopes.
- Email can change.
- One VoiceOS user may eventually connect multiple Discord accounts.
## Security Notes
- Do not commit `.env`.
- Do not commit `COMPOSIO_API_KEY`.
- Do not commit Discord bot tokens or connected-account credentials.
- `allowed_mentions` defaults to `none` so generated messages do not accidentally ping users, roles, `@everyone`, or `@here`.
TDQS
B3.4/5.0
Scored across 6 tools
Disambiguation4/5
Most tools have distinct purposes (connect, list channels, read, send, reply), but list_discord_servers is ambiguous as it 'explains how to list' rather than listing, potentially overlapping with list_discord_channels.
Naming Consistency5/5
All tools consistently follow verb_noun pattern (e.g., connect_discord_bot, list_discord_channels), with clear and predictable naming.
Tool Count4/5
6 tools is reasonable for a Discord bot integration covering auth, listing, reading, and writing. Slightly narrow but not excessive.
Completeness3/5
Covers core operations but list_discord_servers only explains rather than actually retrieving servers, creating a functional gap. Missing update/delete message and server management tools.
Maintenance
ActivityInactive
ResponsivenessNo issues