API Reference

Technical reference for integrating with Discord Agent MCP. Covers the MCP protocol, request/response formats, error handling, and schemas.


Overview

Discord Agent MCP implements the Model Context Protocol (MCP), a standardized interface for AI assistants to interact with external tools and resources.

Protocol Details


Endpoints

Health Check

GET /health

Response:

{
  "status": "healthy",
  "discord": "connected"
}

MCP Endpoint

POST /mcp
Content-Type: application/json
Accept: application/json, text/event-stream

All MCP operations go through this endpoint using JSON-RPC 2.0 format.


MCP Methods

tools/list

List all available tools.

Request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "send_message",
        "description": "Send a text message to a channel",
        "inputSchema": {
          "type": "object",
          "properties": {
            "channelId": { "type": "string" },
            "content": { "type": "string", "maxLength": 2000 }
          },
          "required": ["channelId", "content"]
        }
      }
      // ... 70 more tools
    ]
  }
}

tools/call

Execute a tool.

Request:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "send_message",
    "arguments": {
      "channelId": "123456789012345678",
      "content": "Hello from MCP!"
    }
  }
}

Response (Success):

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Message sent successfully to channel 123456789012345678"
      }
    ],
    "structuredContent": {
      "messageId": "987654321098765432",
      "channelId": "123456789012345678",
      "timestamp": "2024-01-15T10:30:00.000Z"
    },
    "isError": false
  }
}

Response (Error):

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Error: Missing permission SEND_MESSAGES in channel 123456789012345678"
      }
    ],
    "isError": true
  }
}

resources/list

List available resources.

Request:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "resources/list"
}

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resources": [
      {
        "uri": "discord://guilds",
        "name": "Guild List",
        "description": "List of all guilds the bot is connected to",
        "mimeType": "application/json"
      }
    ]
  }
}

resources/read

Read a resource.

Request:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "resources/read",
  "params": {
    "uri": "discord://guilds"
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "contents": [
      {
        "uri": "discord://guilds",
        "mimeType": "application/json",
        "text": "[{\"id\":\"123456789\",\"name\":\"My Server\",\"memberCount\":150}]"
      }
    ]
  }
}

prompts/list

List available prompts.

Request:

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "prompts/list"
}

Response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "prompts": [
      {
        "name": "moderate-channel",
        "description": "Interactive channel moderation assistant",
        "arguments": [
          { "name": "guildId", "required": true },
          { "name": "channelId", "required": true },
          { "name": "moderationLevel", "required": false }
        ]
      }
      // ... more prompts
    ]
  }
}

prompts/get

Get a prompt with arguments.

Request:

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "prompts/get",
  "params": {
    "name": "setup-server",
    "arguments": {
      "guildId": "123456789012345678",
      "serverPurpose": "gaming"
    }
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "messages": [
      {
        "role": "user",
        "content": {
          "type": "text",
          "text": "Help me set up a gaming server structure..."
        }
      }
    ]
  }
}

Data Types

Snowflake IDs

Discord uses “snowflake” IDs - 17-19 digit numeric strings.

// Valid snowflake
"123456789012345678"

// Pattern: 17-19 digits
/^\d{17,19}$/

Timestamps

ISO 8601 format in UTC:

2024-01-15T10:30:00.000Z

Colors

Hex color as integer (0-16777215):

// Blue: 0x5865F2 = 5793266
// Red: 0xFF0000 = 16711680
// Green: 0x00FF00 = 65280

Input Schemas

Embed Object

interface Embed {
  title?: string;        // max 256 chars
  description?: string;  // max 4096 chars
  url?: string;
  timestamp?: string;    // ISO 8601
  color?: number;        // 0-16777215
  footer?: {
    text: string;        // max 2048 chars
    icon_url?: string;
  };
  image?: {
    url: string;
  };
  thumbnail?: {
    url: string;
  };
  author?: {
    name: string;        // max 256 chars
    url?: string;
    icon_url?: string;
  };
  fields?: Array<{
    name: string;        // max 256 chars
    value: string;       // max 1024 chars
    inline?: boolean;
  }>;                    // max 25 fields
}

Permission Names

Valid permission strings for role/channel operations:

Administrator
ViewChannel
ManageChannels
ManageRoles
ManageGuild
CreateInstantInvite
KickMembers
BanMembers
ManageNicknames
ChangeNickname
ManageWebhooks
ManageEmojisAndStickers
ManageEvents
ModerateMembers

SendMessages
SendMessagesInThreads
CreatePublicThreads
CreatePrivateThreads
EmbedLinks
AttachFiles
AddReactions
UseExternalEmojis
MentionEveryone
ManageMessages
ManageThreads
ReadMessageHistory

Connect
Speak
Stream
MuteMembers
DeafenMembers
MoveMembers
UseVAD
PrioritySpeaker
RequestToSpeak

Error Handling

Error Response Format

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Error: [ErrorType] - Description\n\nResolution: How to fix this"
      }
    ],
    "isError": true
  }
}

Error Types

Error Description Resolution
DiscordNotConnectedError Bot not logged in Check token, wait for connection
PermissionDeniedError Missing permission Grant permission in Discord
ChannelNotFoundError Channel doesn’t exist Verify channel ID
GuildNotFoundError Server not found Verify guild ID, check membership
MessageNotFoundError Message deleted/invalid Verify message ID
RateLimitError API rate limited Wait and retry
InvalidInputError Invalid parameter Check input format

Rate Limiting

Discord API has rate limits. The server handles these automatically, but excessive requests may fail with RateLimitError.

Rate Limit Response:

{
  "isError": true,
  "content": [{
    "type": "text",
    "text": "Error: Rate limit exceeded. Retry after 5000ms"
  }]
}

Client Integration

Node.js / TypeScript

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { HttpClientTransport } from "@modelcontextprotocol/sdk/client/http.js";

const client = new Client({
  name: "my-discord-client",
  version: "1.0.0"
});

// Connect via HTTP
const transport = new HttpClientTransport({
  url: "http://localhost:3000/mcp"
});
await client.connect(transport);

// List tools
const { tools } = await client.listTools();
console.log(`Found ${tools.length} tools`);

// Call a tool
const result = await client.callTool({
  name: "send_message",
  arguments: {
    channelId: "123456789012345678",
    content: "Hello from MCP client!"
  }
});

console.log(result.content[0].text);

Python

import httpx
import json

class MCPClient:
    def __init__(self, url: str):
        self.url = url
        self.request_id = 0

    def _request(self, method: str, params: dict = None) -> dict:
        self.request_id += 1
        payload = {
            "jsonrpc": "2.0",
            "id": self.request_id,
            "method": method
        }
        if params:
            payload["params"] = params

        response = httpx.post(
            f"{self.url}/mcp",
            json=payload,
            headers={"Content-Type": "application/json"}
        )
        return response.json()["result"]

    def list_tools(self) -> list:
        result = self._request("tools/list")
        return result["tools"]

    def call_tool(self, name: str, arguments: dict) -> dict:
        return self._request("tools/call", {
            "name": name,
            "arguments": arguments
        })

# Usage
client = MCPClient("http://localhost:3000")
tools = client.list_tools()
print(f"Found {len(tools)} tools")

result = client.call_tool("send_message", {
    "channelId": "123456789012345678",
    "content": "Hello from Python!"
})
print(result["content"][0]["text"])

cURL

# List tools
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# Call tool
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc":"2.0",
    "id":2,
    "method":"tools/call",
    "params":{
      "name":"send_message",
      "arguments":{
        "channelId":"123456789012345678",
        "content":"Hello from cURL!"
      }
    }
  }'

Stdio Transport

For local process integration, use stdio transport:

Configuration

TRANSPORT_MODE=stdio npm start

Usage

The server reads JSON-RPC requests from stdin and writes responses to stdout. Each message is newline-delimited.

Input (stdin):

{"jsonrpc":"2.0","id":1,"method":"tools/list"}

Output (stdout):

{"jsonrpc":"2.0","id":1,"result":{"tools":[...]}}

Claude Code Stdio Config

{
  "mcpServers": {
    "discord-agent": {
      "type": "stdio",
      "command": "node",
      "args": ["dist/server/index.js"],
      "cwd": "/path/to/discord-agent-mcp",
      "env": {
        "DISCORD_TOKEN": "your_token",
        "TRANSPORT_MODE": "stdio"
      }
    }
  }
}

Logging

Log Format (JSON)

{
  "level": "info",
  "message": "Tool executed",
  "tool": "send_message",
  "guildId": "123456789",
  "channelId": "987654321",
  "duration": 150,
  "success": true,
  "timestamp": "2024-01-15T10:30:00.000Z"
}

Log Levels

Level Description
error Errors only
warn Warnings and errors
info General info (default)
debug Verbose debugging

Resources