From a718a2262d744868dd27879cceb90256e2621de1 Mon Sep 17 00:00:00 2001 From: Daniil Svetlov Date: Thu, 19 Mar 2026 02:20:47 +0300 Subject: [PATCH 1/3] feat: add unread_only, unmuted_only filters and mute status to list_chats Add filtering capabilities to the list_chats tool: - unread_only: filter to show only chats with unread messages - unmuted_only: filter to show only unmuted chats - Display mute status in chat info output Co-Authored-By: Claude Opus 4.6 (1M context) --- main.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 2785951..f1d663d 100644 --- a/main.py +++ b/main.py @@ -1248,13 +1248,15 @@ async def list_topics( @mcp.tool(annotations=ToolAnnotations(title="List Chats", openWorldHint=True, readOnlyHint=True)) -async def list_chats(chat_type: str = None, limit: int = 20) -> str: +async def list_chats(chat_type: str = None, limit: int = 20, unread_only: bool = False, unmuted_only: bool = False) -> str: """ List available chats with metadata. Args: chat_type: Filter by chat type ('user', 'group', 'channel', or None for all) - limit: Maximum number of chats to retrieve. + limit: Maximum number of chats to retrieve from Telegram API (applied before filtering, so fewer results may be returned when filters are active). + unread_only: If True, only return chats with unread messages. + unmuted_only: If True, only return unmuted chats. """ try: dialogs = await client.get_dialogs(limit=limit) @@ -1293,6 +1295,24 @@ async def list_chats(chat_type: str = None, limit: int = 20) -> str: bool(getattr(inner_dialog, "unread_mark", False)) if inner_dialog else False ) + # Extract mute status from notify_settings + notify_settings = getattr(inner_dialog, "notify_settings", None) + mute_until = getattr(notify_settings, "mute_until", None) + if mute_until is None: + is_muted = False + elif isinstance(mute_until, datetime): + is_muted = mute_until.timestamp() > time.time() + else: + is_muted = mute_until > time.time() + + # Filter by mute status if requested + if unmuted_only and is_muted: + continue + + # Filter by unread status if requested + if unread_only and unread_count == 0 and not unread_mark: + continue + if unread_count > 0: chat_info += f", Unread: {unread_count}" elif unread_mark: @@ -1300,6 +1320,8 @@ async def list_chats(chat_type: str = None, limit: int = 20) -> str: else: chat_info += ", No unread messages" + chat_info += f", Muted: {'yes' if is_muted else 'no'}" + results.append(chat_info) if not results: @@ -1307,7 +1329,7 @@ async def list_chats(chat_type: str = None, limit: int = 20) -> str: return "\n".join(results) except Exception as e: - return log_and_format_error("list_chats", e, chat_type=chat_type, limit=limit) + return log_and_format_error("list_chats", e, chat_type=chat_type, limit=limit, unread_only=unread_only, unmuted_only=unmuted_only) @mcp.tool(annotations=ToolAnnotations(title="Get Chat", openWorldHint=True, readOnlyHint=True)) From 3502aa9ec6e467af0980e206ead67ef50d024611 Mon Sep 17 00:00:00 2001 From: Eugene Evstafev <36392751+chigwell@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:00:36 +0000 Subject: [PATCH 2/3] docs: add Contributors section to README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 3aa2393..d64d18c 100644 --- a/README.md +++ b/README.md @@ -712,3 +712,9 @@ This project is licensed under the [Apache 2.0 License](LICENSE). ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=chigwell/telegram-mcp&type=Date)](https://www.star-history.com/#chigwell/telegram-mcp&Date) + +## Contributors + + + + From 73c45f910688fd5af492a3ffa8f6e542ff2ccfe9 Mon Sep 17 00:00:00 2001 From: Daniil Svetlov Date: Tue, 31 Mar 2026 18:23:00 +0300 Subject: [PATCH 3/3] style: format list_chats with black Co-Authored-By: Claude Opus 4.6 (1M context) --- main.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index f1d663d..31d738f 100644 --- a/main.py +++ b/main.py @@ -1248,7 +1248,9 @@ async def list_topics( @mcp.tool(annotations=ToolAnnotations(title="List Chats", openWorldHint=True, readOnlyHint=True)) -async def list_chats(chat_type: str = None, limit: int = 20, unread_only: bool = False, unmuted_only: bool = False) -> str: +async def list_chats( + chat_type: str = None, limit: int = 20, unread_only: bool = False, unmuted_only: bool = False +) -> str: """ List available chats with metadata. @@ -1329,7 +1331,14 @@ async def list_chats(chat_type: str = None, limit: int = 20, unread_only: bool = return "\n".join(results) except Exception as e: - return log_and_format_error("list_chats", e, chat_type=chat_type, limit=limit, unread_only=unread_only, unmuted_only=unmuted_only) + return log_and_format_error( + "list_chats", + e, + chat_type=chat_type, + limit=limit, + unread_only=unread_only, + unmuted_only=unmuted_only, + ) @mcp.tool(annotations=ToolAnnotations(title="Get Chat", openWorldHint=True, readOnlyHint=True))