[FEATURE] Telegram plugin: add parse_mode support for MarkdownV2 formatting

Resolved 💬 2 comments Opened Mar 20, 2026 by k1p1l0 Closed Mar 23, 2026

Problem

The Telegram plugin's reply and edit_message tools send messages without a parse_mode parameter, so Telegram treats all outbound messages as plain text. Any formatting syntax (*bold*, _italic_, ` code `) renders as literal characters instead of being parsed.

Screenshot — raw markdown symbols visible to the user:

Messages show **bold**, _italic_, ` code ` as literal text instead of formatted output.

Proposed Solution

Add an optional parse_mode parameter to both reply and edit_message tools, defaulting to MarkdownV2.

Changes to server.ts

1. Tool schema — add parse_mode to reply and edit_message:

parse_mode: {
  type: 'string',
  enum: ['MarkdownV2', 'HTML', 'plain'],
  description: 'Telegram parse mode. Default: MarkdownV2. Use "plain" to send without formatting.',
},

2. reply handler — extract and pass parse_mode to sendMessage:

const rawParseMode = (args.parse_mode as string | undefined) ?? 'MarkdownV2'
const parseMode = rawParseMode === 'plain' ? undefined : rawParseMode as 'MarkdownV2' | 'HTML'

// In the sendMessage call:
const sent = await bot.api.sendMessage(chat_id, chunks[i], {
  ...(parseMode ? { parse_mode: parseMode } : {}),
  ...(shouldReplyTo ? { reply_parameters: { message_id: reply_to } } : {}),
})

3. edit_message handler — same treatment for editMessageText:

const editParseMode = ((args.parse_mode as string | undefined) ?? 'MarkdownV2')
const editParseModeOpt = editParseMode === 'plain' ? undefined : editParseMode as 'MarkdownV2' | 'HTML'
const edited = await bot.api.editMessageText(
  args.chat_id as string,
  Number(args.message_id),
  args.text as string,
  editParseModeOpt ? { parse_mode: editParseModeOpt } : undefined,
)

4. MCP instructions — add MarkdownV2 formatting guide:

Messages use Telegram MarkdownV2 by default. Formatting: *bold*, _italic_, `code`, ```pre```, 
~strikethrough~, __underline__, ||spoiler||, [link](url). IMPORTANT: In MarkdownV2, these 
characters MUST be escaped with \ when used literally (not as formatting): 
_ * [ ] ( ) ~ ` > # + - = | { } . !
Use parse_mode "plain" if escaping is too complex for a given message.

Why This Matters

  • Telegram's Bot API supports rich formatting but it must be explicitly opted into via parse_mode
  • Without it, Claude's formatted responses show raw syntax to users, which looks broken
  • The plain fallback ensures messages with complex content (lots of special chars) can still be sent reliably
  • grammy already supports the parameter — it just needs to be passed through

Tested

Applied locally and confirmed working with MarkdownV2 bold, italic, code, strikethrough, and underline rendering correctly in Telegram DMs.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗