Back to MCP Servers

Discourse

Official Discourse MCP server for forum integration. Search topics, read posts, manage categories and tags, discover users, and interact with Discourse communities.

communicationgo
By discourse
7039Updated 4 days agoTypeScriptMIT

Installation

npx -y discourse-mcp

Configuration

{
  "mcpServers": {
    "discourse-mcp": {
      "command": "npx",
      "args": ["-y", "discourse-mcp"]
    }
  }
}

How to use

  1. Run the installation command above (if needed)
  2. Open your Claude Code settings file (~/.claude/settings.json)
  3. Add the configuration to the mcpServers section
  4. Restart Claude Code to apply changes

Discourse MCP

A Model Context Protocol (MCP) stdio server that exposes Discourse forum capabilities as tools and resources for AI agents.

  • Entry point: src/index.ts → compiled to dist/index.js (binary name: discourse-mcp)
  • SDK: @modelcontextprotocol/sdk
  • Node: >= 24
  • Version: 0.3.0 (adds operator-selectable toolsets, structured directory output, and expanded opt-in administration capabilities; 0.2.x introduced breaking changes from 0.1.x, including JSON-only tool output; category/group resources remain deprecated compatibility surfaces alongside canonical list tools)

Quick start (release)

  • Run (read‑only, recommended to start)
npx -y @discourse/mcp@latest

Then, in your MCP client, either:

  • Call the discourse_select_site tool with { "site": "https://try.discourse.org" } to choose a site, or

  • Start the server tethered to a site using --site https://try.discourse.org (in which case discourse_select_site is hidden).

  • Enable writes (opt‑in, safe‑guarded)

npx -y @discourse/mcp@latest --allow_writes --read_only=false --auth_pairs '[{"site":"https://try.discourse.org","api_key":"'$DISCOURSE_API_KEY'","api_username":"system"}]'
  • Run with only Data Explorer built-in tools
npx -y @discourse/mcp@latest --toolsets data_explorer --tools_mode discourse_api_only

This exposes discourse_select_site plus the read-only Data Explorer tools. Add --site, authentication, and the write flags as needed; see Built-in toolsets.

  • Use in an MCP client (example: Claude Desktop) — via npx
{
  "mcpServers": {
    "discourse": {
      "command": "npx",
      "args": ["-y", "@discourse/mcp@latest"],
      "env": {}
    }
  }
}

Alternative: if you prefer a global binary after install, the package exposes discourse-mcp.

{
  "mcpServers": {
    "discourse": { "command": "discourse-mcp", "args": [] }
  }
}

Configuration

The server registers tools under the MCP server name @discourse/mcp. Choose a target Discourse site either by:

  • Using the discourse_select_site tool at runtime (validates via /about.json), or

  • Supplying --site <url> to tether the server to a single site at startup (validates via /about.json and hides discourse_select_site).

  • Auth

    • None by default.
    • Admin API Keys (require admin permissions): --auth_pairs '[{"site":"https://example.com","api_key":"...","api_username":"system"}]'
    • User API Keys (any user can generate): --auth_pairs '[{"site":"https://example.com","user_api_key":"...","user_api_client_id":"..."}]'
    • HTTP Basic Auth (for sites behind a reverse proxy): Add http_basic_user and http_basic_pass to any auth_pairs entry. This is useful for Discourse sites protected by HTTP Basic Authentication at the reverse proxy level.
    • You can include multiple entries in auth_pairs; the matching entry is used for the selected site. If both user_api_key and api_key are provided for the same site, user_api_key takes precedence.
  • Write safety

    • Writes are disabled by default.
    • Built-in write tools are only registered when --allow_writes is enabled and --read_only=false. This includes post, topic, private-message, category, user, upload, draft, and saved Data Explorer query mutations.
    • Private-message listing and reading also require a matching authenticated site because PM data is never public.
    • Toolset selection does not bypass write safety. A selected write tool remains absent unless writes are enabled.
    • Write tools require a matching auth_pairs entry for the selected site; otherwise they return an error.
    • A ~1 req/sec rate limit is enforced for write actions.
  • Flags & defaults

    • --help, -h, or positional help: print current CLI help and exit successfully before loading profiles or starting a transport.

    • --version, -v, or positional version: print one package-version line and exit successfully. -v means version; logging verbosity uses --log_level.

    • --read_only (default: true)

    • --allow_writes (default: false)

    • --timeout_ms <number> (default: 15000)

    • --concurrency <number> (default: 4)

    • --log_level <silent|error|info|debug> (default: info)

      • debug: Shows HTTP request URLs, statuses, and detailed network/retry information (response bodies are never logged because admin APIs may echo sensitive content)
      • info: Shows retry attempts and general operational messages
      • error: Shows only errors
      • silent: No logging output
    • --show_emails (default: false). includes emails in user tools. Requires admin access

    • --tools_mode <auto|discourse_api_only|tool_exec_api> (default: auto)

    • --toolsets <name[,name...]>: Expose selected built-in domains. Omit for the compact default catalog (all non-opt-in domains); use --toolsets all to include opt-in category/group/tag-group, moderation, workflow, and AI administration domains. See Built-in toolsets.

    • --site <url>: Tether MCP to a single site and hide discourse_select_site.

    • --default-search <prefix>: Unconditionally prefix every search query (e.g., tag:ai order:latest).

    • --max-read-length <number>: Maximum characters returned for post content (default 50000). Applies to discourse_read_post and per-post content in discourse_read_topic and discourse_read_private_message. The tools prefer raw content by requesting include_raw=true.

    • --allowed_upload_paths <paths>: Comma-separated list or JSON array of directories allowed for local file uploads. Required to enable local file uploads in discourse_upload_file. Example: --allowed_upload_paths "/home/user/images,/tmp/uploads" or --allowed_upload_paths '["/home/user/images"]'. These security-sensitive paths do not receive ~ expansion.

    • --transport <stdio|http> (default: stdio): Use standard input/output by default, or loopback-only Streamable HTTP with JSON responses. HTTP explicitly supports one stateful MCP client/session per process. Every post-initialize request must carry the returned Mcp-Session-Id; a second initialize is rejected. After session DELETE/close, restart the process before connecting another client. /health returns 503 restart_required in that closed state. Request bodies are bounded to 4 MiB.

    • --port <number> (default: 3000): Port to listen on when using HTTP transport.

    • --cache_dir <path> (reserved)

    • --profile <path.json> (see below)

  • Profile file (keep secrets off the command line)

{
  "auth_pairs": [
    {
      "site": "https://try.discourse.org",
      "api_key": "<redacted>",
      "api_username": "system"
    },
    {
      "site": "https://example.com",
      "user_api_key": "<user_api_key>",
      "user_api_client_id": "<client_id>"
    },
    {
      "site": "https://protected.example.com",
      "api_key": "<redacted>",
      "api_username": "system",
      "http_basic_user": "username",
      "http_basic_pass": "password"
    }
  ],
  "read_only": false,
  "allow_writes": true,
  "show_emails": true,
  "log_level": "info",
  "tools_mode": "auto",
  "site": "https://try.discourse.org",
  "default_search": "tag:ai order:latest",
  "max_read_length": 50000,
  "transport": "stdio",
  "port": 3000,
  "allowed_upload_paths": ["/home/user/images", "/tmp/uploads"]
}

Run with:

node dist/index.js --profile /absolute/path/to/profile.json
# Current-user home expansion is also supported:
node dist/index.js --profile ~/discourse-mcp-profile.json

Flags still override values from the profile. A leading current-user ~, ~/, or ~\ in the profile path expands to the current home directory; ~otheruser, shell-style expansion elsewhere, and upload-allowlist expansion are intentionally unsupported.

Built-in toolsets

Toolsets let an operator expose only the built-in domains needed by an MCP client. They are optional: when --toolsets and the profile field are both omitted, the server registers the default catalog (including search, discourse_search, and discourse_filter_topics). Administrative and specialized domains marked (opt-in) below—including themes—must be selected explicitly. Use --toolsets all only when every built-in domain is deliberately required.

Pass one name or a comma-separated union:

# Data Explorer reads, plus the site-selection bootstrap tool
npx -y @discourse/mcp@latest \
  --toolsets data_explorer \
  --tools_mode discourse_api_only

# Search and topic tools, retaining canonical registration order
npx -y @discourse/mcp@latest \
  --toolsets search,topics \
  --tools_mode discourse_api_only

# Every built-in domain, including opt-in workflows
npx -y @discourse/mcp@latest \
  --toolsets all \
  --tools_mode discourse_api_only

# Author, test, and run workflows (admin key required)
npx -y @discourse/mcp@latest \
  --toolsets workflows \
  --site https://forum.example.com \
  --auth_pairs '[{"site":"https://forum.example.com","api_key":"...","api_username":"system"}]' \
  --allow_writes --read_only=false \
  --tools_mode discourse_api_only

Profiles use an array (a comma-separated string is also accepted):

{
  "toolsets": ["users", "uploads"]
}

Available toolsets are:

ToolsetBuilt-in tools
sitediscourse_select_site (also retained implicitly as bootstrap for any untethered subset)
searchTopic-level search/filtering plus post-level keyword evidence
topicsCore topic/post reads, exact stream selection, post search, user-post activity, and mutations
usersUser lookup/listing, user-post activity, and user mutations
chatChat message retrieval
draftsDraft retrieval, save, and deletion
uploadsFile upload
data_explorerQuery retrieval, execution, creation, update, and deletion
private_messagesAuthenticated personal/group PM listing and reading, plus write-gated creation, replies, and participant invitations
activity (opt-in)Reply relationships, site-wide post activity, topic view history, user activity summaries and timelines, and directory/cohort metrics
administration (opt-in)Category discovery, admin-visible site settings, and explicitly confirmed user activation/approval state changes
site_settings (opt-in, admin-sensitive)Masked site-setting inspection plus write-gated, preflighted updates of ordinary non-secret settings
webhooks (opt-in, admin-sensitive)Safe webhook and delivery-history inspection plus write-gated lifecycle, ping, and single-event redelivery operations
themes (opt-in, admin-sensitive)Theme/component inspection plus write-gated local creation, editing, installation, remote synchronization, asset upload, and guarded deletion
groups (opt-in)Exhaustive empty-input group directory listing, explicit page/filter compatibility mode, complete group CRUD and membership operations, and fixed-page group-authored post evidence
tag_groups (opt-in, staff-sensitive)Public visibility-filtered search plus staff inventory/detail and write-gated, preflighted create/update/delete lifecycle
moderation (opt-in)Authenticated review queue triage, user behavioral counters, bounded post revisions, and one freshly preflighted reviewable action
workflows (opt-in)Admin-only workflow discovery, graph authoring, expression evaluation, pin-data, draft runs, step runs, executions, and version management
ai_agents (opt-in)Admin-only AI agent discovery, typed lifecycle, bot-user creation, and portable import/export
ai_custom_tools (opt-in)Admin-only database-backed scripted custom-tool guide, lifecycle, actual execution testing, and import/export
ai_features (opt-in)Admin-only AI feature discovery and exact-area, non-secret feature-

View source on GitHub