0.3.1npm · @discourse/mcp · latest release
Observed 2026-08-25T08:21:41.539Z using mcpSecurity-inventory. Protocol 2025-06-18.
| Tool | Category | Risk |
|---|---|---|
discourse_filter_topicsDiscover topics through a filtered, top, or hot view. Filtered uses Discourse TopicsFilter syntax; top uses Discourse's authoritative top score and defaults to weekly; hot is defined exactly as daily top (not sentiment, controversy, or real-time velocity). Returns a uniform rich topic projection and truthful pagination metadata.Input schema{
"type": "object",
"properties": {
"filter": {
"type": "string",
"description": "TopicsFilter query (required for the filtered view)"
},
"view": {
"type": "string",
"enum": [
"filtered",
"top",
"hot"
],
"default": "filtered"
},
"top_period": {
"type": "string",
"enum": [
"daily",
"weekly",
"monthly",
"quarterly",
"yearly",
"all"
],
"description": "Top period (top view only; defaults to weekly)"
},
"page": {
"type": "integer",
"minimum": 0,
"description": "Page number (0-based, default: 0)"
},
"per_page": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Items per page (default 20, max 50)"
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_get_chat_messagesGet messages from a chat channel. Returns JSON object with channel_id, messages array (id, username, created_at, message, edited, thread_id, in_reply_to_id), and meta.Input schema{
"type": "object",
"properties": {
"channel_id": {
"type": "integer",
"exclusiveMinimum": 0,
"description": "The chat channel ID"
},
"page_size": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Number of messages to return (default: 50, max: 50)"
},
"target_message_id": {
"type": "integer",
"exclusiveMinimum": 0,
"description": "Message ID to query around or paginate from"
},
"direction": {
"type": "string",
"enum": [
"past",
"future"
],
"description": "Pagination direction: 'past' for older messages, 'future' for newer"
},
"target_date": {
"type": "string",
"description": "ISO 8601 date string to query messages around"
}
},
"required": [
"channel_id"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_get_draftRetrieve a specific draft by key. Returns JSON with draft_key, sequence, and parsed data (title, reply, categoryId, tags, action).Input schema{
"type": "object",
"properties": {
"draft_key": {
"type": "string",
"minLength": 1,
"maxLength": 40,
"description": "Draft key (e.g., \"new_topic\", \"topic_123\", \"new_private_message\")"
},
"sequence": {
"type": "integer",
"minimum": 0,
"description": "Expected sequence number (optional)"
}
},
"required": [
"draft_key"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_get_queryGet full details of a Data Explorer query including SQL and parameters. Requires admin API key.Input schema{
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0,
"description": "Query ID"
}
},
"required": [
"id"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_get_userGet user info. Returns JSON with id, username, name, trust_level, created_at, bio, admin, and moderator.Input schema{
"type": "object",
"properties": {
"username": {
"type": "string",
"minLength": 1
}
},
"required": [
"username"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_list_private_messagesList authenticated personal or group private-message mailboxes. Returns normalized JSON messages and pagination metadata.Input schema{
"type": "object",
"properties": {
"username": {
"type": "string"
},
"mailbox": {
"type": "string",
"enum": [
"inbox",
"sent",
"archive",
"unread",
"new"
]
},
"group_name": {
"type": "string"
},
"page": {
"type": "integer",
"minimum": 0
},
"per_page": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_list_user_postsGet paginated list of user posts/replies. Returns JSON object with posts array (id, topic_id, post_number, slug, title, created_at, excerpt, category_id) and meta (page, limit, has_more).Input schema{
"type": "object",
"properties": {
"username": {
"type": "string",
"minLength": 1
},
"page": {
"type": "integer",
"minimum": 0
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Posts per page (max 50, default 30)"
}
},
"required": [
"username"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_list_usersList users via admin API. Requires admin API key. Returns ~100 users per page (Discourse's fixed page size). Returns JSON with users array and pagination meta.Input schema{
"type": "object",
"properties": {
"query": {
"type": "string",
"enum": [
"active",
"new",
"staff",
"suspended",
"silenced",
"pending",
"staged"
],
"default": "active",
"description": "User query type"
},
"filter": {
"type": "string",
"description": "Search by username, email, or IP address"
},
"order": {
"type": "string",
"enum": [
"created",
"last_emailed",
"seen",
"username",
"trust_level",
"days_visited",
"posts"
],
"description": "Sort order field"
},
"asc": {
"type": "boolean",
"default": false,
"description": "Sort ascending (default: false/descending)"
},
"page": {
"type": "integer",
"minimum": 0,
"description": "Page number (0-indexed)"
}
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_read_postRead a specific post. Returns JSON with id, topic_id, post_number, username, created_at, and raw content.Input schema{
"type": "object",
"properties": {
"post_id": {
"type": "integer",
"exclusiveMinimum": 0
}
},
"required": [
"post_id"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_read_private_messageRead an authenticated private message, its posts, and direct allowed-user and allowed-group records. Rejects public topics.Input schema{
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"exclusiveMinimum": 0
},
"post_limit": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Max posts to return (default 5, max 50)"
},
"start_post_number": {
"type": "integer",
"minimum": 1,
"description": "Start from this post number (1-based)"
}
},
"required": [
"topic_id"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_read_topicRead topic metadata and posts. Large post limits can require multiple upstream requests. For moderation queues, prefer reviewable list/detail evidence instead of fanning this tool out across flagged topics.Input schema{
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"exclusiveMinimum": 0
},
"post_limit": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Max posts to return (default 5, max 50)"
},
"start_post_number": {
"type": "integer",
"minimum": 1,
"description": "Start from this post number (1-based)"
}
},
"required": [
"topic_id"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_read_topic_postsRead exact, earliest, latest, around-post, or username-filtered topic evidence. Selection is bounded to 50 posts and reports the visible stream size without claiming the entire topic was loaded.Input schema{
"type": "object",
"properties": {
"topic_id": {
"type": "integer",
"exclusiveMinimum": 0
},
"selection_mode": {
"type": "string",
"enum": [
"latest",
"earliest",
"post_ids",
"around_post",
"usernames"
]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 50
},
"post_ids": {
"type": "array",
"items": {
"type": "integer",
"exclusiveMinimum": 0
},
"minItems": 1,
"maxItems": 50
},
"post_number": {
"type": "integer",
"exclusiveMinimum": 0
},
"usernames": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1,
"maxItems": 50
},
"replies_only": {
"type": "boolean"
}
},
"required": [
"topic_id",
"selection_mode"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_run_queryExecute a Data Explorer query with parameters. Returns columns, rows, result_count, duration_ms. Queries run in read-only transactions with 10-second timeout. Requires admin API key.Input schema{
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Query ID to run"
},
"params": {
"type": "object",
"additionalProperties": {},
"description": "Query parameters as key-value pairs"
},
"limit": {
"anyOf": [
{
"type": "integer",
"exclusiveMinimum": 0
},
{
"type": "string",
"const": "ALL"
}
],
"description": "Maximum number of rows to return (default: query default, use 'ALL' for unlimited)"
},
"explain": {
"type": "boolean",
"description": "Include query execution plan in response"
}
},
"required": [
"id"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_searchSearch site content. Returns JSON object with results array of matching topics (id, slug, title) and meta (total, has_more).Input schema{
"type": "object",
"properties": {
"query": {
"type": "string",
"minLength": 1,
"description": "Search query"
},
"max_results": {
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"required": [
"query"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_search_postsSearch post-level evidence with Discourse query syntax. Unlike discourse_search, this preserves matched posts, highlighted blurbs, authors, topics, categories, and truthful bounded continuation. This is keyword search, not Discourse AI semantic search.Input schema{
"type": "object",
"properties": {
"query": {
"type": "string",
"minLength": 1
},
"page": {
"type": "integer",
"minimum": 1,
"maximum": 10
}
},
"required": [
"query"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}Annotations{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
} | — | — |
discourse_select_siteValidate and select a Discourse site. Returns JSON with site URL and title.Input schema{
"type": "object",
"properties": {
"site": {
"type": "string",
"format": "uri",
"description": "Base URL of the Discourse site"
}
},
"required": [
"site"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
} | — | — |
List all public chat channels with id, title, slug, status, members_count, and description.
{
"resource_key": "discourse://chat/channels",
"uri": "discourse://chat/channels",
"name": "chat_channels",
"description": "List all public chat channels with id, title, slug, status, members_count, and description.",
"mime_type": null,
"annotations": null,
"metadata_hash": "e4cd795940d7a03bf655ac8c8787cd1eebc4793daa4effa96c4a35b614178ceb"
}Saved Data Explorer queries (30/page, by last used). Shows id, name, description. Use explorer_queries_page for other pages.
{
"resource_key": "discourse://explorer/queries",
"uri": "discourse://explorer/queries",
"name": "explorer_queries",
"description": "Saved Data Explorer queries (30/page, by last used). Shows id, name, description. Use explorer_queries_page for other pages.",
"mime_type": null,
"annotations": null,
"metadata_hash": "8dd63224d283c6570511546cbd26b6b843d2963211c15afe3aedf1e04583c4e3"
}Database schema (core tables). Format: col, col:int, col:ts, col*, col>fk_table. No type = text. Use explorer_schema_tables for all/specific tables.
{
"resource_key": "discourse://explorer/schema",
"uri": "discourse://explorer/schema",
"name": "explorer_schema",
"description": "Database schema (core tables). Format: col, col:int, col:ts, col*, col>fk_table. No type = text. Use explorer_schema_tables for all/specific tables.",
"mime_type": null,
"annotations": null,
"metadata_hash": "40e4e716935e0d2af7be555e10ea999e0bd72f74a67829d08355f73747a93377"
}DEPRECATED compatibility resource. Use discourse_list_categories (opt-in administration toolset) for the canonical structured directory. Lists categories with hierarchy (parent_category_id; legacy pid), optional permissions (perms), counts, and truthful completeness metadata.
{
"resource_key": "discourse://site/categories",
"uri": "discourse://site/categories",
"name": "site_categories",
"description": "DEPRECATED compatibility resource. Use discourse_list_categories (opt-in administration toolset) for the canonical structured directory. Lists categories with hierarchy (parent_category_id; legacy pid), optional permissions (perms), counts, and truthful completeness metadata.",
"mime_type": null,
"annotations": null,
"metadata_hash": "4d160853bcea0b221c854dc80c520bc32682b16215a7dae95390c1b0d117ca8e"
}DEPRECATED compatibility resource. Use discourse_list_groups (opt-in groups toolset) for the canonical structured directory. Lists all visible groups with visibility and interaction levels plus truthful completeness metadata.
{
"resource_key": "discourse://site/groups",
"uri": "discourse://site/groups",
"name": "site_groups",
"description": "DEPRECATED compatibility resource. Use discourse_list_groups (opt-in groups toolset) for the canonical structured directory. Lists all visible groups with visibility and interaction levels plus truthful completeness metadata.",
"mime_type": null,
"annotations": null,
"metadata_hash": "ac7c2cb1bd602c47020a1c8c3e86672e4767d1934e96a570f34eede881576cd1"
}List all tags with usage counts. Returns empty if tags are disabled.
{
"resource_key": "discourse://site/tags",
"uri": "discourse://site/tags",
"name": "site_tags",
"description": "List all tags with usage counts. Returns empty if tags are disabled.",
"mime_type": null,
"annotations": null,
"metadata_hash": "affddef0a795928c40e77bc8202da2b8d2108c1a3ae02289e16d257cb119674a"
}List user's chat channels (public + DMs) with unread/mention counts. Requires authentication.
{
"resource_key": "discourse://user/chat-channels",
"uri": "discourse://user/chat-channels",
"name": "user_chat_channels",
"description": "List user's chat channels (public + DMs) with unread/mention counts. Requires authentication.",
"mime_type": null,
"annotations": null,
"metadata_hash": "656420a0471a9a006100ae382e05091646cfdf9171a9acbfa0be0180f3f9b707"
}List user's drafts with draft_key, sequence, title, category_id, created_at, and reply_preview. Requires authentication.
{
"resource_key": "discourse://user/drafts",
"uri": "discourse://user/drafts",
"name": "user_drafts",
"description": "List user's drafts with draft_key, sequence, title, category_id, created_at, and reply_preview. Requires authentication.",
"mime_type": null,
"annotations": null,
"metadata_hash": "e643ea184b81747c0c16c94fa8788a38c190aebfd72de029dd27aae2ffd067dd"
}Saved Data Explorer queries - specific page number.
{
"template_key": "discourse://explorer/queries/{page}",
"uri_template": "discourse://explorer/queries/{page}",
"name": "explorer_queries_page",
"description": "Saved Data Explorer queries - specific page number.",
"mime_type": null,
"annotations": null,
"metadata_hash": "fee98c97e8151eed73aae1d139ff017498e377e326dc102504384c5ac8b219d9"
}Database schema for specific tables. Use 'all' for all tables, or comma-separated names (e.g., 'users,topics,posts').
{
"template_key": "discourse://explorer/schema/{tables}",
"uri_template": "discourse://explorer/schema/{tables}",
"name": "explorer_schema_tables",
"description": "Database schema for specific tables. Use 'all' for all tables, or comma-separated names (e.g., 'users,topics,posts').",
"mime_type": null,
"annotations": null,
"metadata_hash": "b20353d2342b46403cf15d58d11b54b5c0bea9b8fe4d6d75a013118c7ab96470"
}Guided workflow for database queries: discover schema, write SQL, run queries via Data Explorer
{
"prompt_key": "sql_query",
"name": "sql_query",
"description": "Guided workflow for database queries: discover schema, write SQL, run queries via Data Explorer",
"arguments": [
{
"name": "goal",
"description": "What you want to learn from the data",
"required": false
}
],
"metadata_hash": "243d0d5dd263bd69da70a579c4f1cd6673f85327c64b9d19690aa3b857e97e36"
}No completed comparison is available.
| Risk | Change | Subject |
|---|---|---|
| No material changes recorded. | ||
| Severity | Finding | Advisory |
|---|---|---|
| high | Ssrf in @discourse/mcp (tool discourse_filter_topics, argument filter) | MCPSEC-1021CC946DF3BE0F |
| high | Ssrf in @discourse/mcp (tool discourse_get_chat_messages, argument target_date) | MCPSEC-50E8F2A734EB8445 |
| high | Ssrf in @discourse/mcp (tool discourse_get_draft, argument draft_key) | MCPSEC-B968D454060B0E54 |
| high | Ssrf in @discourse/mcp (tool discourse_get_user, argument username) | MCPSEC-E1AED05CF366E300 |
| high | Ssrf in @discourse/mcp (tool discourse_list_user_posts, argument username) | MCPSEC-AD7C8E28F12A8494 |
| high | Ssrf in @discourse/mcp (tool discourse_search, argument query) | MCPSEC-6EE1E652F228B813 |
| high | Ssrf in @discourse/mcp (tool discourse_select_site, argument site) | MCPSEC-308AFFABF88E6DB1 |
Artifact SHA-256: 91e6df1d0bd07e4f443bb368a5230718f89ce4319010b009af5d024dfd24704e
Scanner: mcp-proof-engine 0.1.0.