mirror of
https://ghfast.top/https://github.com/discourse/discourse-mcp.git
synced 2026-07-16 11:47:54 +08:00
6.6 KiB
6.6 KiB
Discourse MCP — Agent Guide
What this is
- Purpose: An MCP (Model Context Protocol) stdio server that exposes Discourse forum capabilities as tools for AI agents.
- Entry point:
src/index.ts→ compiled todist/index.js(binary name:discourse-mcp). - SDK:
@modelcontextprotocol/sdk. Node ≥ 18.
How it works
- On start, the server validates CLI flags via Zod, constructs a dynamic site state, and registers tools on an MCP server named
@discourse/mcp. - Choose a target Discourse site by either:
- Calling the
discourse_select_sitetool (validates via/about.json), or - Starting with
--site <url>to tether to a single site (validates via/about.jsonand hidesdiscourse_select_site).
- Calling the
- Outputs are text-oriented; some tools embed compact JSON in fenced code blocks for structured extraction.
Authentication & permissions
- Supported auth:
- None (read-only public data)
- Per-site overrides via
--auth_pairs, e.g.[{"site":"https://example.com","api_key":"...","api_username":"system"}].
- Writes are disabled by default. Write tools (
discourse_create_post,discourse_create_topic,discourse_create_category,discourse_create_user) are only registered when all are true:--allow_writesAND not--read_onlyAND a matchingauth_pairsentry exists for the selected site.
- Secrets are never logged; config is redacted before logging.
Tools exposed (built-in)
- discourse_search
- Input:
{ query: string; with_private?: boolean; max_results?: number (1–50, default 10) } - Output: Top topics with titles and URLs; appends a JSON footer of
{ results: [{ id, url, title }] }inside a fenced block.
- Input:
- discourse_read_topic
- Input:
{ topic_id: number; post_limit?: number (1–20, default 5); start_post_number?: number } - Output: Title, category, tags, and the first N posts (raw preferred when available) up to the configured max read length per post; includes canonical topic link.
- Input:
- discourse_read_post
- Input:
{ post_id: number } - Output: Author, timestamp, content (raw preferred) truncated to the configured max read length, and a direct link.
- Input:
- discourse_list_categories
- Input:
{} - Output: Category names with topic counts.
- Input:
- discourse_list_tags
- Input:
{} - Output: Tags with usage counts (or notice if tags are disabled).
- Input:
- discourse_get_user
- Input:
{ username: string } - Output: Display name, trust level, joined date, short bio, and profile link.
- Input:
- discourse_filter_topics
- Input:
{ filter: string; page?: number; per_page?: number (1–50) } - Output: Paginated topic list with titles and URLs; appends a JSON footer
{ page, per_page, results: [{ id, url, title }], next_url? }. - Query language: key:value tokens separated by spaces; category/categories (comma = OR,
=category= without subcats,-exclude); tag/tags (comma = OR,+= AND) and tag_group; status:(open|closed|archived|listed|unlisted|public); personalin:(bookmarked|watching|tracking|muted|pinned); dates created/activity/latest-post-(before|after) asYYYY-MM-DDorNdays; numeric likes[-op]-(min|max), posts-(min|max), posters-(min|max), views-(min|max);order:with optional-asc; free text terms allowed.
- Input:
- discourse_create_post (conditionally available; see permissions)
- Input:
{ topic_id: number; raw: string (≤ 30k chars) } - Output: Link to created post/topic. Includes a simple 1 req/sec rate limit.
- Input:
- discourse_create_topic (conditionally available; see permissions)
- Input:
{ title: string; raw: string (≤ 30k chars); category_id?: number; tags?: string[] } - Output: Link to created topic. Includes a simple 1 req/sec rate limit.
- Input:
- discourse_create_category (conditionally available; see permissions)
- Input:
{ name: string; color?: hex; text_color?: hex; parent_category_id?: number; description?: string } - Output: Link to created category. Includes a simple 1 req/sec rate limit.
- Input:
- discourse_select_site (hidden when
--siteis provided)- Input:
{ site: string } - Output: Confirms selection; validates via
/about.json. Triggers remote tool discovery when enabled.
- Input:
Remote Tool Execution API (optional)
- If the target Discourse site exposes an MCP-compatible Tool Execution API:
- GET
/ai/toolsis discovered after selecting a site whentools_modeisauto(default) ortool_exec_api(or immediately at startup if--siteis provided). - Each remote tool is registered dynamically using its JSON Schema input.
- Calls POST
/ai/tools/{name}/callwith{ arguments, context: {} }. - Results may include
details.artifacts[]; links are surfaced at the end of the tool output.
- GET
- Set
--tools_mode=discourse_api_onlyto disable remote tool discovery.
CLI configuration
- Optional flags:
--auth_pairs(JSON)--read_only(default true),--allow_writes(default false)--timeout_ms <number>(default 15000)--concurrency <number>(default 4)--cache_dir <path>(currently unused; in-memory caching is built-in)--log_level <silent|error|info|debug>(default info)--tools_mode <auto|discourse_api_only|tool_exec_api>(default auto)--profile <path.json>: load partial config from JSON (flags override)--site <url>: tether to a single site (hidesdiscourse_select_site)--default-search <prefix>: unconditionally prefix every search query (e.g.,category:support tag:ai)--max-read-length <number>(default 50000): maximum number of characters returned for post content indiscourse_read_postand per-post content indiscourse_read_topic. Tools preferrawcontent via Discourse API (include_raw=true) when available.
Networking & resilience
- User-Agent:
Discourse-MCP/0.x (+https://github.com/discourse-mcp). - Retries on 429/5xx with backoff (3 attempts).
- Lightweight in-memory GET cache for selected endpoints (e.g., topics, site metadata).
Errors & rate limits
- Tool failures return
isError: truewith human-readable messages. discourse.create_postanddiscourse.create_categoryenforce ~1 request/second to avoid flooding.
Source map
- MCP server and CLI:
src/index.ts - HTTP client:
src/http/client.ts - Tool registry:
src/tools/registry.ts - Built-in tools:
src/tools/builtin/* - Remote tools:
src/tools/remote/tool_exec_api.ts - Logging/redaction:
src/util/logger.ts,src/util/redact.ts
Quick start (for human operators)
- Build:
pnpm build - Run:
node dist/index.js - Select site with
discourse_select_sitein your client