Telegram MCP Server

by chigwell
Verified
Apache 2.0
55
  • Apple
  • Linux

local-only server

The server can only run on the client’s local machine because it depends on local resources.

Integrations

  • Enables interaction with Telegram chats, allowing users to retrieve lists of chats, fetch message history, and send messages directly through the Telegram platform.

텔레그램 MCP 서버


🤖 MCP 작동 중

다음은 Claude에서 Telegram MCP 기능을 보여주는 데모입니다.

기본 사용 예:

  1. 예: Claude에게 채팅 기록을 분석하고 응답을 보내달라고 요청합니다.

  1. 그룹에 메시지를 성공적으로 보냈습니다:

보시다시피, AI는 귀하의 Telegram 계정과 원활하게 상호 작용하여 자연스러운 방식으로 귀하의 채팅, 메시지 및 기타 데이터를 검색하여 표시합니다.


TelethonMCP(Model Context Protocol) 를 기반으로 Claude, Cursor 및 모든 MCP 호환 클라이언트를 위한 모든 기능을 갖춘 Telegram 통합 솔루션입니다. 이 프로젝트를 통해 Telegram 계정과 프로그래밍 방식으로 상호작용하여 메시징부터 그룹 관리까지 모든 것을 자동화할 수 있습니다.


🚀 기능 및 도구

이 MCP 서버는 방대한 Telegram 도구 모음을 제공합니다. 모든 주요 Telegram/Telethon 기능을 도구로 사용할 수 있습니다!

채팅 및 그룹 관리

  • get_chats(page, page_size) : 페이지별로 정리된 채팅 목록
  • list_chats(chat_type, limit) : 메타데이터와 필터링을 사용하여 채팅을 나열합니다.
  • get_chat(chat_id) : 채팅에 대한 자세한 정보
  • create_group(title, user_ids) : 새로운 그룹을 생성합니다.
  • create_channel(제목, 정보, 메가그룹) : 채널 또는 슈퍼그룹을 생성합니다.
  • edit_chat_title(chat_id, title) : 채팅/그룹/채널 제목 변경
  • edit_chat_photo(chat_id, file_path) : 채팅/그룹/채널 사진 설정
  • delete_chat_photo(chat_id) : 채팅/그룹/채널 사진 삭제
  • leave_chat(chat_id) : 그룹이나 채널에서 나가기
  • get_participants(chat_id) : 모든 참가자 나열
  • get_admins(chat_id) : 모든 관리자 나열
  • get_banned_users(chat_id) : 모든 차단된 사용자 나열
  • promote_admin(chat_id, user_id) : 사용자를 관리자로 승격합니다.
  • demote_admin(chat_id, user_id) : 관리자를 사용자로 강등합니다.
  • ban_user(chat_id, user_id) : 사용자 차단
  • unban_user(chat_id, user_id) : 사용자 차단 해제
  • get_invite_link(chat_id) : 초대 링크 받기
  • export_chat_invite(chat_id) : 초대 링크 내보내기
  • import_chat_invite(hash) : 초대 해시로 채팅에 참여
  • join_chat_by_link(링크) : 초대 링크로 채팅에 참여합니다.

메시징

  • get_messages(chat_id, page, page_size) : 페이지가 매겨진 메시지
  • list_messages(chat_id, limit, search_query, from_date, to_date) : 필터링된 메시지
  • send_message(chat_id, message) : 메시지를 보냅니다.
  • reply_to_message(chat_id, message_id, text) : 메시지에 답장
  • edit_message(chat_id, message_id, new_text) : 메시지를 편집합니다
  • delete_message(chat_id, message_id) : 메시지 삭제
  • forward_message(from_chat_id, message_id, to_chat_id) : 메시지 전달
  • pin_message(chat_id, message_id) : 메시지 고정
  • unpin_message(chat_id, message_id) : 메시지 고정 해제
  • mark_as_read(chat_id) : 모두 읽음으로 표시
  • get_message_context(chat_id, message_id, context_size) : 메시지 주변의 컨텍스트
  • get_history(chat_id, limit) : 전체 채팅 기록
  • get_pinned_messages(chat_id) : 고정된 메시지 목록

연락처 관리

  • list_contacts() : 모든 연락처를 나열합니다
  • search_contacts(쿼리) : 연락처 검색
  • add_contact(전화번호, 이름, 성) : 연락처 추가
  • delete_contact(user_id) : 연락처 삭제
  • block_user(user_id) : 사용자 차단
  • unblock_user(user_id) : 사용자 차단 해제
  • import_contacts(연락처) : 대량 연락처 가져오기
  • export_contacts() : 모든 연락처를 JSON으로 내보냅니다.
  • get_blocked_users() : 차단된 사용자 목록
  • get_contact_ids() : 모든 연락처 ID를 나열합니다.
  • get_direct_chat_by_contact(contact_query) : 연락처와 직접 채팅을 찾습니다.
  • get_contact_chats(contact_id) : 연락처와의 모든 채팅을 나열합니다.
  • get_last_interaction(contact_id) : 연락처와의 가장 최근 메시지

사용자 및 프로필

  • get_me() : 사용자 정보를 가져옵니다
  • update_profile(first_name, last_name, about) : 프로필을 업데이트하세요
  • set_profile_photo(file_path) : 프로필 사진을 설정합니다.
  • delete_profile_photo() : 프로필 사진 삭제
  • get_user_photos(user_id, limit) : 사용자의 프로필 사진을 가져옵니다.
  • get_user_status(user_id) : 사용자의 온라인 상태를 가져옵니다.

메디아

  • send_file(chat_id, file_path, caption) : 파일 전송
  • send_voice(chat_id, file_path) : 음성 메시지 보내기
  • download_media(chat_id, message_id, file_path) : 미디어 다운로드
  • upload_file(file_path) : Telegram 서버에 파일을 업로드합니다.
  • get_media_info(chat_id, message_id) : 메시지의 미디어에 대한 정보를 가져옵니다.

검색 및 발견

  • search_public_chats(query) : 공개 채팅/채널/봇 검색
  • search_messages(chat_id, query, limit) : 채팅에서 메시지 검색
  • resolve_username(username) : 사용자 이름을 ID로 변환합니다.

스티커, GIF, 봇

  • get_sticker_sets() : 스티커 세트 나열
  • send_sticker(chat_id, file_path) : 스티커 보내기
  • get_gif_search(query, limit) : GIF 검색
  • send_gif(chat_id, gif_id) : GIF 보내기
  • get_bot_info(bot_username) : 봇에 대한 정보를 가져옵니다.
  • set_bot_commands(bot_username, commands) : 봇 명령 설정(봇 계정만 해당)

개인정보 보호, 설정 및 기타

  • get_privacy_settings() : 개인정보 보호 설정 가져오기
  • set_privacy_settings(키, allow_users, disallow_users) : 개인정보 보호 설정을 지정합니다.
  • mute_chat(chat_id) : 알림 음소거
  • unmute_chat(chat_id) : 알림 음소거 해제
  • archive_chat(chat_id) : 채팅 보관
  • unarchive_chat(chat_id) : 채팅 보관 해제
  • get_recent_actions(chat_id) : 최근 관리자 작업 가져오기

📋 요구 사항


🔧 설치 및 설정

1. 포크 및 복제

지엑스피1

2. 가상 환경 만들기

python3 -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -r requirements.txt

3. 세션 문자열 생성

python3 session_string_generator.py

메시지에 따라 인증을 받고 .env 파일을 업데이트하세요.

4. .env 구성

.env.example .env 로 복사하고 값을 입력합니다.

TELEGRAM_API_ID=your_api_id_here TELEGRAM_API_HASH=your_api_hash_here TELEGRAM_SESSION_NAME=anon TELEGRAM_SESSION_STRING=your_session_string_here

my.telegram.org/apps 에서 API 자격 증명을 받으세요.


⚙️ Claude 및 Cursor 구성

MCP 구성

Claude 데스크톱 구성(예: ~/Library/Application Support/Claude/claude_desktop_config.json ) 또는 커서 구성( ~/.cursor/mcp.json )을 편집하세요.

{ "mcpServers": { "telegram-mcp": { "command": "uv", "args": [ "--directory", "/full/path/to/telegram-mcp-server", "run", "main.py" ] } } }

📝 코드 및 출력을 포함한 도구 예제

다음은 가장 일반적으로 사용되는 도구의 예와 구현 예, 그리고 샘플 출력입니다.

채팅 받기

@mcp.tool() async def get_chats(page: int = 1, page_size: int = 20) -> str: """ Get a paginated list of chats. Args: page: Page number (1-indexed). page_size: Number of chats per page. """ try: dialogs = await client.get_dialogs() start = (page - 1) * page_size end = start + page_size if start >= len(dialogs): return "Page out of range." chats = dialogs[start:end] lines = [] for dialog in chats: entity = dialog.entity chat_id = entity.id title = getattr(entity, "title", None) or getattr(entity, "first_name", "Unknown") lines.append(f"Chat ID: {chat_id}, Title: {title}") return "\n".join(lines) except Exception as e: logger.exception(f"get_chats failed (page={page}, page_size={page_size})") return "An error occurred (code: GETCHATS-ERR-001). Check mcp_errors.log for details."

출력 예:

Chat ID: 123456789, Title: John Doe Chat ID: -100987654321, Title: My Project Group Chat ID: 111223344, Title: Jane Smith Chat ID: -200123456789, Title: News Channel

메시지 보내기

@mcp.tool() async def send_message(chat_id: int, message: str) -> str: """ Send a message to a specific chat. Args: chat_id: The ID of the chat. message: The message content to send. """ try: entity = await client.get_entity(chat_id) await client.send_message(entity, message) return "Message sent successfully." except Exception as e: logger.exception(f"send_message failed (chat_id={chat_id})") return "An error occurred (code: SENDMSG-ERR-001). Check mcp_errors.log for details."

출력 예:

Message sent successfully.

채팅 초대 링크 받기

get_invite_link 함수는 특히 여러 대체 방법을 사용할 수 있는 강력한 함수입니다.

@mcp.tool() async def get_invite_link(chat_id: int) -> str: """ Get the invite link for a group or channel. """ try: entity = await client.get_entity(chat_id) # Try using ExportChatInviteRequest first try: from telethon.tl import functions result = await client(functions.messages.ExportChatInviteRequest( peer=entity )) return result.link except AttributeError: # If the function doesn't exist in the current Telethon version logger.warning("ExportChatInviteRequest not available, using alternative method") except Exception as e1: # If that fails, log and try alternative approach logger.warning(f"ExportChatInviteRequest failed: {e1}") # Alternative approach using client.export_chat_invite_link try: invite_link = await client.export_chat_invite_link(entity) return invite_link except Exception as e2: logger.warning(f"export_chat_invite_link failed: {e2}") # Last resort: Try directly fetching chat info try: if isinstance(entity, (Chat, Channel)): full_chat = await client(functions.messages.GetFullChatRequest( chat_id=entity.id )) if hasattr(full_chat, 'full_chat') and hasattr(full_chat.full_chat, 'invite_link'): return full_chat.full_chat.invite_link or "No invite link available." except Exception as e3: logger.warning(f"GetFullChatRequest failed: {e3}") return "Could not retrieve invite link for this chat." except Exception as e: logger.exception(f"get_invite_link failed (chat_id={chat_id})") return f"Error getting invite link: {e}"

출력 예:

https://t.me/+AbCdEfGhIjKlMnOp

초대 링크를 통해 채팅에 참여하기

@mcp.tool() async def join_chat_by_link(link: str) -> str: """ Join a chat by invite link. """ try: # Extract the hash from the invite link if '/' in link: hash_part = link.split('/')[-1] if hash_part.startswith('+'): hash_part = hash_part[1:] # Remove the '+' if present else: hash_part = link # Try checking the invite before joining try: # Try to check invite info first (will often fail if not a member) invite_info = await client(functions.messages.CheckChatInviteRequest(hash=hash_part)) if hasattr(invite_info, 'chat') and invite_info.chat: # If we got chat info, we're already a member chat_title = getattr(invite_info.chat, 'title', 'Unknown Chat') return f"You are already a member of this chat: {chat_title}" except Exception: # This often fails if not a member - just continue pass # Join the chat using the hash result = await client(functions.messages.ImportChatInviteRequest(hash=hash_part)) if result and hasattr(result, 'chats') and result.chats: chat_title = getattr(result.chats[0], 'title', 'Unknown Chat') return f"Successfully joined chat: {chat_title}" return f"Joined chat via invite hash." except Exception as e: err_str = str(e).lower() if "expired" in err_str: return "The invite hash has expired and is no longer valid." elif "invalid" in err_str: return "The invite hash is invalid or malformed." elif "already" in err_str and "participant" in err_str: return "You are already a member of this chat." logger.exception(f"join_chat_by_link failed (link={link})") return f"Error joining chat: {e}"

출력 예:

Successfully joined chat: Developer Community

공개 채팅 검색

@mcp.tool() async def search_public_chats(query: str) -> str: """ Search for public chats, channels, or bots by username or title. """ try: result = await client(functions.contacts.SearchRequest(q=query, limit=20)) return json.dumps([format_entity(u) for u in result.users], indent=2) except Exception as e: return f"Error searching public chats: {e}"

출력 예:

[ { "id": 123456789, "name": "TelegramBot", "type": "user", "username": "telegram_bot" }, { "id": 987654321, "name": "Telegram News", "type": "user", "username": "telegram_news" } ]

연락처와 직접 채팅하기

@mcp.tool() async def get_direct_chat_by_contact(contact_query: str) -> str: """ Find a direct chat with a specific contact by name, username, or phone. Args: contact_query: Name, username, or phone number to search for. """ try: # Fetch all contacts using the correct Telethon method result = await client(functions.contacts.GetContactsRequest(hash=0)) contacts = result.users found_contacts = [] for contact in contacts: if not contact: continue name = f"{getattr(contact, 'first_name', '')} {getattr(contact, 'last_name', '')}".strip() username = getattr(contact, 'username', '') phone = getattr(contact, 'phone', '') if (contact_query.lower() in name.lower() or (username and contact_query.lower() in username.lower()) or (phone and contact_query in phone)): found_contacts.append(contact) if not found_contacts: return f"No contacts found matching '{contact_query}'." # If we found contacts, look for direct chats with them results = [] dialogs = await client.get_dialogs() for contact in found_contacts: contact_name = f"{getattr(contact, 'first_name', '')} {getattr(contact, 'last_name', '')}".strip() for dialog in dialogs: if isinstance(dialog.entity, User) and dialog.entity.id == contact.id: chat_info = f"Chat ID: {dialog.entity.id}, Contact: {contact_name}" if getattr(contact, 'username', ''): chat_info += f", Username: @{contact.username}" if dialog.unread_count: chat_info += f", Unread: {dialog.unread_count}" results.append(chat_info) break if not results: return f"Found contacts matching '{contact_query}', but no direct chats with them." return "\n".join(results) except Exception as e: return f"Error searching for direct chat: {e}"

출력 예:

Chat ID: 123456789, Contact: John Smith, Username: @johnsmith, Unread: 3

🎮 사용 예시

  • "최근 채팅 보기"
  • "채팅 123456789에 'Hello world'를 보내세요"
  • "전화번호 +1234567890, 이름 John Doe를 연락처에 추가하세요"
  • "사용자 111, 222, 333으로 '프로젝트 팀' 그룹을 만드세요"
  • "채팅 123456789의 메시지 42에서 미디어를 다운로드하세요"
  • "채팅 123456789에 대한 알림 음소거"
  • "사용자 111을 그룹 123456789의 관리자로 승격"
  • "뉴스"에 대한 공개 채널을 검색하세요
  • "초대 링크가 있는 Telegram 그룹에 가입하세요 https://t.me/+AbCdEfGhIjK "
  • "저장된 메시지에 스티커 보내기"
  • "내 스티커 세트를 모두 가져와"

Claude, Cursor 또는 MCP 호환 클라이언트에서 자연어로 이러한 도구를 사용할 수 있습니다.


🧠 오류 처리 및 견고성

이 구현에는 포괄적인 오류 처리가 포함됩니다.

  • 세션 관리 : 파일 기반 세션과 문자열 기반 세션 모두에서 작동합니다.
  • 오류 보고 : mcp_errors.log 에 자세한 오류가 기록됨
  • 우아한 저하 : 중요 기능에 대한 다양한 대체 접근 방식
  • 사용자 친화적인 메시지 : 기술적 오류 대신 명확하고 실행 가능한 오류 메시지
  • 계정 유형 감지 : 봇 계정이 필요한 기능은 사용자 계정과 함께 사용될 때 감지하고 알림을 제공합니다.
  • 초대 링크 처리 : 다양한 링크 형식 및 기존 회원 사례 처리

이 코드는 일반적인 Telegram API 문제와 제한 사항에도 견고하게 설계되었습니다.


🛠️ 기여 가이드

  1. 이 저장소를 포크하세요: chigwell/telegram-mcp
  2. 포크를 복제하세요:
    git clone https://github.com/<your-github-username>/telegram-mcp.git
  3. 새로운 지점을 만드세요:
    git checkout -b my-feature
  4. 변경 사항을 적용하고 필요한 경우 테스트/문서를 추가하세요.
  5. chigwell/telegram-mcp 에 명확한 설명과 함께 풀 리퀘스트를 푸시하고 엽니다 .
  6. 검토를 위해 PR에 @chigwell 또는 @l1v0n1을 태그하세요 .

🔒 보안 고려 사항

  • .env 또는 세션 문자열을 절대로 커밋하지 마세요.
  • 세션 문자열을 통해 Telegram 계정에 대한 전체 액세스 권한이 부여됩니다. 안전하게 보관하세요!
  • 모든 처리는 로컬에서 이루어집니다. 즉, Telegram API 외에는 어디에도 데이터가 전송되지 않습니다.
  • .env.example 템플릿으로 사용하고 실제 .env 파일은 비공개로 유지하세요.
  • 테스트 파일은 .gitignore 에서 자동으로 제외됩니다.

🛠️ 문제 해결

  • MCP 클라이언트(Claude/Cursor)와 터미널의 로그를 확인하여 오류를 확인하세요.
  • 자세한 오류 로그는 mcp_errors.log 에서 확인할 수 있습니다.
  • 인터프리터 오류가 있나요? .venv 생성되어 선택되었는지 확인하세요.
  • 데이터베이스 잠금? 파일 기반 세션이 아닌 세션 문자열 인증을 사용하세요.
  • iCloud/Dropbox 문제? 이상한 오류가 표시되면 프로젝트를 공백 없는 로컬 경로로 옮기세요.
  • Telegram 비밀번호를 변경하거나 인증 오류가 발생하는 경우 세션 문자열을 다시 생성합니다 .
  • 봇 전용 기능은 일반 사용자 계정에서 사용하면 명확한 메시지를 표시합니다.
  • 테스트 스크립트에 오류가 발생했습니까? .env 의 테스트 구성을 확인하여 유효한 테스트 계정/그룹이 있는지 확인하세요.

📄 라이센스

이 프로젝트는 Apache 2.0 라이선스 에 따라 라이선스가 부여되었습니다.


🙏 감사의 말


@chigwell@l1v0n1 이 관리합니다. PR 환영!

스타 역사

ID: oj64jpjo76