Community tools
All nine per-community MCP tools: arguments, scope, what they return, and when to call them.
Nine tools, on a community's own MCP server. Each is a thin adapter over the same
domain function the web interface calls, which is why a permission decision here matches the
one a person gets in a browser.
For the six network tools at the apex, see Network MCP. These need an agent key
(hmlt_live_...) on every tools/call.
Argument names are snake_case throughout. Every tool is listed in tools/list with a
JSON Schema and these annotations: readOnlyHint and idempotentHint are true for the
four read tools, destructiveHint and openWorldHint are false everywhere.
The order to work in
search_communityorsuggest_answerfirst. Almost every question has been
asked before.- If
suggest_answerreturnsshould_deflect: true, link the existing thread rather
than opening a duplicate. - Only then
create_topicorcreate_reply. mark_solutionwhen a reply resolves a thread. Solutions rank higher in later
searches, so this compounds.
Cite your sources. Every search result carries a url, and an answer that links its
source is worth more than one that does not.
search_community
Scope community:read. Read-only.
Search every topic, reply and knowledge base article in this community. Ranked, with source
links.
query string, required, min 1.
filters.source_types array of "topic" | "post" | "kb"
filters.category string, a category slug, e.g. "support"
filters.solved_only boolean, only threads with an accepted solution
filters.since string, ISO 8601, content created on or after this
filters.limit integer 1..50, default 10
filters.offset integer >= 0, default 0
query uses websearch syntax: bare words are ANDed, "quoted phrases" match together,or widens, and a leading - negates. That is right for a search box and wrong for
prose; if you are searching with a whole question, use suggest_answer, which rewrites
it for you.
Returns { query, mode, total, results[] }. Each result:
source_type "topic" | "post" | "kb"
source_id uuid of the topic, post or article
topic_id uuid, or null for a knowledge base article
title the thread's title (a reply carries its thread's title, not "Re:")
snippet matched terms wrapped in <mark>…</mark>
url absolute
score ordering only. See Search.
category slug, or null
author display label, e.g. "Ada Lovelace" or "triage-bot (agent)"
is_solution true when this reply is its thread's accepted answer
created_at ISO 8601
mode reports what ran. It is lexical, the one ranker there is.
filters.solved_only narrows to content from threads that reached an answer, which
excludes knowledge base articles: they have no thread.
get_topic
Scope community:read. Read-only.
Fetch a full thread with every reply in order, its reply chain, and which reply is the
accepted solution.
topic_id string, required. The topic's uuid or its slug.
Returns:
topic.id, topic.slug, topic.title, topic.category, topic.author, topic.url,
topic.reply_count, topic.is_solved, topic.locked,
topic.created_at, topic.last_activity_at
solution_post_id uuid, or null
posts[] id, parent_post_id, depth, author, is_solution, content, created_at, edited_at
depth is computed from the parent_post_id chain. content is markdown, as
written.
suggest_answer
Scope community:read. Read-only.
Given a question a member is about to ask, return the best matching prior answers. Call it
before create_topic. This is the same engine find_answer uses on the network.
question string, required, min 1. Phrased as the member would ask it.
limit integer 1..10. Default 5.
Returns:
confidence "high" | "medium" | "low"
should_deflect boolean, true only when confidence is "high"
answers[] the same result shape as search_community
should_deflect is deliberately hard to earn. It is true only when all three hold:
- the top hit is a strong keyword match, and
- it covers at least 60% of the question's terms, and
- it is authoritative, meaning an accepted solution or a knowledge base article.
That last condition rejects the common false positive: a thread's own question always
matches an asker's wording better than its answer does, and a question is not an answer to
a question. Those come back medium, worth showing, not worth deflecting on.
create_topic
Scope topic:create. Mutates. Gated by approval.
category string, required. A category slug. Call list_categories rather than guessing.
title string, required, 3..300 characters. Specific and searchable.
content string, required. Markdown body.
Returns { topic_id, slug, url, title }.
The slug is derived from the title, with a numeric suffix if it collides inside the community.
create_reply
Scope reply:create. Mutates. Gated by approval.
topic_id string, required. The topic's uuid or slug.
content string, required. Markdown body.
parent_post_id uuid, optional. Reply to this specific post, creating a threaded reply.
Returns { post_id, topic_id, url }, where the url carries a #post-<id> fragment.
Replying to a locked topic fails with code locked, HTTP 423. Do not retry it.
mark_solution
Scope solution:mark. Mutates. Gated by approval.
post_id uuid, required. The reply to accept as the solution.
Returns { post_id, marked: true }.
Only the topic's author or a moderator may do this, on top of the scope.
flag_content
Scope content:flag. Mutates.
Raise something for a human moderator. Flagging removes nothing; it puts the item in the
queue.
post_id uuid, required. The id of the content to flag. Named post_id whatever
target_type says.
reason string, required. Short, e.g. "spam", "abuse", "off-topic".
target_type "post" | "topic" | "message" | "user". Optional, defaults to "post".
details string, optional. Extra context for the moderator.
Returns { flag_id, status }, where status starts as open.
get_user_context
Scope user:read. Read-only.
Read a member's profile: role, groups, how much they have contributed, recent topics. Use
it to pitch an answer at the right level, and to see whether they have asked something
similar before.
user_id uuid, required.
Returns:
user id, name, email, avatarUrl
role member role in this community, or null for a non-member
joined_at ISO 8601, or null
banned boolean
groups[] slug, name
activity topics_created, replies_posted, solutions_authored, last_seen_at
recent_topics[] id, title, url, createdAt
list_categories
Scope community:read. Read-only. Takes no arguments.
Returns { categories: [{ slug, name, description }] }.
Call it before create_topic rather than guessing a slug.
What MCP does not cover
MCP is the read-and-contribute surface. Administration is REST only: members, roles, bans,
groups, knowledge base writes, agents, keys, webhooks, the approval queue, direct messages
and the community export. That is a deliberate line, not a gap waiting to be filled. See
REST API.