Hi Anton!
Migrating from Mattermost to Discourse is certainly doable, but will require building a custom import script, as there isn’t a pre-made script available yet (see available import scripts here). You can study the existing scripts for reference, but please double check their last update dates and adapt accordingly, as some could have outdated references to Discourse’s tables.
A pull request with a Mattermost import script would be very welcome by the community!
Channel and Data Mapping
You can import everything as chat channels but you can also map them as other types:
- Channels as Categories: Import each Mattermost channel as a Discourse category. Threads within channels can become topics, with each message as a post. Alternatively, individual posts can be the OP of topics.
 - Channels as Topics: Another approach is to make each Mattermost channel a single topic, with messages as replies, threads will be displayed in sequence in this case.
 - DMs: They can be imported as private messages too. It’s a good idea for discussions that needs archiving.
 
Think carefully about which approach best fits your community and content volume.
Topic titles
When mapping a chat to topics and posts you have to create the titles for each topic. One amazing way of doing it is using Discourse AI to generate the titles with actual context for the topic.
Generating topic titles using AI
TL;DR use this method:
def gen_title(llm, system_prompt, topic)
  begin
  content = topic.posts.map(&:cooked).join("\n").slice(0..10_000)
  message = [{type: :user, content: content}]
  prompt = DiscourseAi::Completions::Prompt.new(system_prompt, messages: message)
  title = llm.generate(
      prompt,
      user: Discourse.system_user,
      temperature: 0.3,
      feature_name: "ai_helper"
  )
  topic.title = title
  topic.save!
  puts "Topic: #{topic.id}, changed sucessfully."
  rescue ActiveRecord::RecordInvalid
    puts "validation error"
  end
end
It needs an LLM and a master prompt
llm = DiscourseAi::Completions::Llm.proxy(SiteSetting.ai_helper_model)
system_prompt = <<-PROMPT
  I want you to act as a title generator for written pieces. I will provide you with a text,\nand you will generate a title. Please keep the title concise and under 20 words,\nand ensure that the meaning is maintained. The title will utilize the language type of the topic.\nI want you to only reply the proposed title and nothing else, do not write explanations.\nNever ever use colons in the title. Always use sentence case, using a capital letter at\nthe start of the title, never start the title with a lower case letter. Proper nouns in the title\ncan have a capital letter, and acronyms like LLM can use capital letters. Format some titles\nas questions, some as statements. Make sure to use question marks if the title is a question."
PROMPT
Then you can loop to a list of topics as you prefer:
# gen everything
Topic
  .joins(:_custom_fields)
  .where('topic_custom_fields.name = ?', 'import_id')
  .find_each { |topic| gen_title(llm, system_prompt, topic) }
# filter PMs
Topic
  .joins(:_custom_fields)
  .where('topic_custom_fields.name = ?', 'import_id')
  .where.not(archetype: "private_message")
  .find_each { |topic| gen_title(llm, system_prompt, topic) }
Important Considerations
- Reactions: Mattermost supports multiple reactions per post. If importing as Discourse posts, you’ll need to limit to one, unless you’re mapping into Discourse Chat (which supports multiple reactions natively).
 - Custom Emoji: You can bring over custom emoji, see the Discourse Reactions plugin documentation.
 - Teams & Permissions: Mattermost “teams” don’t map directly to Discourse, but you can set up categories/channels with appropriate group based access controls.
 - Attachments: Mattermost attachments (images and documents) are not embedded in the content like in Discourse. When importing, you’ll need to append attachment links (Markdown) or embed them in the post bodies.
 
Reference Materials
- Pre-launch checklist for Discourse migrations
 - Why Your Community Needs a Home, Not Just a Group Chat
 - Building communities that think (Discourse blog)
 - Understanding Uploads, Images, and Attachments.
 
We have experience with chat platform migrations, if you’d like help from our team, see our Discourse migration services page.
If you have specific questions during the script development or mapping decisions, feel free to ask on Meta for guidance!