npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bn-telegram-mcp-server

v0.0.6

Published

Stateless MCP Server for Telegram via TDLib

Readme

Telegram MCP Server Tools


Quick Reference Table

| Tool | Description | Key Input | Key Output | |------|-------------|-----------|------------| | getMe | Current user info | none | {id, name, status} | | getChat | Get/list chats | chat?, limit? | {id, title, type} or {chats[], summary} | | getMessages | Get messages (history/specific/search) | chat?, mode, query? | {messages[], total_count} | | getMessageContext | Get surrounding messages for context | chat, mode, message_id?, query? | {contexts[], summary} | | sendMessage | Send/forward messages | chat, action, text? | {id, content, date} | | getUser | User profile | user (name/ID) | {id, name, status} | | getContacts | List/search contacts | query?, limit? | {contacts[], total_count} | | getFile | Get file metadata | file_id | {id, size, remote_id} | | getGroup | Group info (basic/super) | group, type? | {id, name, member_count} | | getChatMembers | Chat members with filters | chat, filter? | {members[], total_count} |


1. getMe

Description: Get information about the current Telegram user (the authenticated user). Returns name, username, phone, status, and profile info.

Input Schema

{
  "type": "object",
  "properties": {}
}

No parameters required.

Output Schema

{
  id: number;           // User's numeric ID
  name: string;         // Full name (e.g., "John Doe")
  username?: string;    // @username if set
  phone?: string;       // Phone number if visible
  status: string;       // Online status (e.g., "online", "last seen 2 hours ago")
  is_contact: boolean;
  is_premium: boolean;
  is_verified: boolean;
}

Use Cases

Use Case 1: Check authenticated user

# Input
{}

# Output
{
  "id": 111222333,
  "name": "John Doe",
  "phone": "+1234567890",
  "status": "online",
  "is_contact": false,
  "is_premium": false,
  "is_verified": false
}

Use Case 2: Verify connection status

# Call getMe to verify the Telegram session is active
# If successful, returns user info; if failed, session needs re-authentication

2. getChat

Description: Get chat information - either a specific chat or list all chats. When chat is provided, returns single chat details. When chat is omitted, returns list of all chats.

Input Schema

{
  "type": "object",
  "properties": {
    "chat": {
      "type": ["number", "string"],
      "description": "Optional: Chat identifier (name/title or numeric ID). If omitted, lists all chats."
    },
    "chat_list": {
      "type": "string",
      "enum": ["main", "archive"],
      "description": "Which chat list to retrieve (default: main)"
    },
    "limit": {
      "type": "number",
      "description": "Maximum chats when listing (default: 100, max: 4000)"
    }
  }
}

Output Schema (Single Chat)

{
  id: number;
  title: string;
  type: string;          // "private", "group", "supergroup", "channel"
  unread_count: number;
  last_message?: {
    preview: string;
    sender: string;
    date: string;
    date_relative: string;
  };
  is_pinned: boolean;
  is_muted: boolean;
}

Output Schema (List Chats)

{
  chats: Array<{
    id: number;
    title: string;
    type: string;
    unread_count: number;
    last_message?: { preview, sender, date, date_relative };
    is_pinned: boolean;
    is_muted: boolean;
  }>;
  total_count: number;
  summary: string;        // e.g., "15 chats loaded, 3 unread messages"
}

Use Cases

Use Case 1: List all chats

# Input
{"limit": 10}

# Output
{
  "chats": [
    {
      "id": 555666777,
      "title": "John Doe",
      "type": "private",
      "unread_count": 0,
      "last_message": {
        "preview": "Test message",
        "sender": "User 111222333",
        "date": "2025-12-04T08:41:54.000Z",
        "date_relative": "4 hours ago"
      }
    }
  ],
  "total_count": 15,
  "summary": "10 chats loaded, 0 unread messages"
}

Use Case 2: Get specific chat by name

# Input
{"chat": "John Doe"}

# Output
{
  "id": 555666777,
  "title": "John Doe",
  "type": "private",
  "unread_count": 0,
  "is_pinned": false,
  "is_muted": false
}

Use Case 3: Get archived chats

# Input
{"chat_list": "archive", "limit": 50}

3. getMessages

Description: Get messages from a chat using different modes: paginated history, specific message IDs, or text search. Supports both chat-specific and global search.

Input Schema

{
  "type": "object",
  "properties": {
    "chat": {
      "type": ["number", "string"],
      "description": "Chat identifier. Required for 'history'/'specific' modes, optional for 'search'"
    },
    "mode": {
      "type": "string",
      "enum": ["history", "specific", "search"],
      "description": "Mode: 'history' (default), 'specific', or 'search'"
    },
    "from_message_id": {
      "type": "number",
      "description": "(history/chat search mode) Start from this message ID (0 for latest)"
    },
    "offset": {
      "type": "number",
      "description": "(history mode) Numeric pagination offset"
    },
    "limit": {
      "type": "number",
      "description": "Max messages to return (default: 50, max: 100)"
    },
    "only_local": {
      "type": "boolean",
      "description": "(history mode) Only return cached messages"
    },
    "message_ids": {
      "type": "array",
      "items": { "type": "number" },
      "description": "(specific mode) Array of message IDs to retrieve"
    },
    "query": {
      "type": "string",
      "description": "(search mode) Search query text"
    },
    "next_offset": {
      "type": "string",
      "description": "(search mode) Cursor for pagination - pass the next_offset from previous response"
    }
  }
}

Output Schema (History/Search)

{
  messages: Array<{
    id: number;
    chat_id: number;
    sender: string;
    sender_id: number;
    content: string;
    content_type: string;    // "Text", "Photo", "Video", etc.
    date: string;
    date_relative: string;
    is_outgoing: boolean;
    is_pinned: boolean;
    file_id?: number;
  }>;
  total_count: number;
  chat_title?: string;       // (history mode)
  search_query?: string;     // (search mode)
  next_offset?: string;      // (search mode) For pagination
}

Use Cases

Use Case 1: Get chat history

# Input
{"chat": "John Doe", "mode": "history", "limit": 5}

# Output
{
  "messages": [
    {
      "id": 14680064,
      "chat_id": 555666777,
      "sender": "User 111222333",
      "content": "Test message from script",
      "content_type": "Text",
      "date": "2025-12-04T08:41:54.000Z",
      "date_relative": "4 hours ago",
      "is_outgoing": true
    }
  ],
  "total_count": 1,
  "chat_title": "John Doe"
}

Use Case 2: Get specific messages by IDs

# Input
{"chat": "John Doe", "mode": "specific", "message_ids": [9437184, 9437185]}

# Output
{
  "messages": [...],
  "count": 2,
  "chat_title": "John Doe"
}

Use Case 3: Search messages globally

# Input
{"mode": "search", "query": "meeting", "limit": 10}

# Output
{
  "messages": [...],
  "total_count": 5,
  "search_query": "meeting"
}

Use Case 4: Search in specific chat

# Input
{"chat": "Project Team", "mode": "search", "query": "deadline"}

Use Case 5: Search with pagination

# First request
{"mode": "search", "query": "meeting", "limit": 10}

# Response includes next_offset
{
  "messages": [...],
  "total_count": 50,
  "next_offset": "abc123xyz",
  "search_query": "meeting"
}

# Next page - pass the next_offset from previous response
{"mode": "search", "query": "meeting", "limit": 10, "next_offset": "abc123xyz"}

4. getMessageContext

Description: Get surrounding messages for context around a specific message or search results. Returns messages before and after the target to understand the full conversation flow. Useful when you need to understand the context of a particular message.

Input Schema

{
  "type": "object",
  "properties": {
    "chat": {
      "type": ["number", "string"],
      "description": "Chat identifier. Required for 'message_id' mode, optional for 'search' mode (global search if omitted)"
    },
    "mode": {
      "type": "string",
      "enum": ["message_id", "search"],
      "description": "Mode: 'message_id' (default) or 'search'"
    },
    "message_id": {
      "type": "number",
      "description": "(message_id mode) The message ID to get context around"
    },
    "query": {
      "type": "string",
      "description": "(search mode) Search query to find messages"
    },
    "search_limit": {
      "type": "number",
      "description": "(search mode) Max search results to get context for (default: 5, max: 20)"
    },
    "context_count": {
      "type": "number",
      "description": "Messages to fetch before AND after target (default: 5, max: 50)"
    }
  }
}

Output Schema

{
  contexts: Array<{
    messages: Array<{            // Single chronological array (easier for LLMs)
      id: number;
      chat_id: number;
      sender: string;
      content: string;
      content_type: string;
      date: string;
      date_relative: string;
      is_target: boolean;        // true for the target message
    }>;
    target_message_id: number;   // ID of the target message
    context_count: number;
    chat_id: number;
    chat_title?: string;
  }>;
  total_matches: number;
  search_query?: string;         // Only present in search mode
  summary: string;               // Human-readable summary
}

Use Cases

Use Case 1: Get context around a specific message

# Input
{"chat": "Project Team", "mode": "message_id", "message_id": 12345, "context_count": 3}

# Output - Single chronological array with is_target flag
{
  "contexts": [
    {
      "messages": [
        {"id": 12342, "content": "Good morning everyone", "is_target": false, ...},
        {"id": 12343, "content": "Hi team", "is_target": false, ...},
        {"id": 12344, "content": "Ready for the standup?", "is_target": false, ...},
        {"id": 12345, "content": "Let's discuss the deadline", "is_target": true, ...},
        {"id": 12346, "content": "Sure, what about Friday?", "is_target": false, ...},
        {"id": 12347, "content": "Friday works for me", "is_target": false, ...},
        {"id": 12348, "content": "Let's set it for 3pm", "is_target": false, ...}
      ],
      "target_message_id": 12345,
      "context_count": 3,
      "chat_title": "Project Team"
    }
  ],
  "total_matches": 1,
  "summary": "Showing context for 1 message(s) (7 total messages)"
}

Use Case 2: Search and get context for each match

# Input
{"chat": "Project Team", "mode": "search", "query": "deadline", "search_limit": 3, "context_count": 2}

# Output
{
  "contexts": [
    {
      "messages": [
        {"id": 12343, "content": "Hi team", "is_target": false, ...},
        {"id": 12344, "content": "Ready for the standup?", "is_target": false, ...},
        {"id": 12345, "content": "Let's discuss the deadline", "is_target": true, ...},
        {"id": 12346, "content": "Sure, what about Friday?", "is_target": false, ...},
        {"id": 12347, "content": "Friday works for me", "is_target": false, ...}
      ],
      "target_message_id": 12345,
      "chat_title": "Project Team"
    },
    {
      "messages": [
        {"id": 9874, "content": "Any updates?", "is_target": false, ...},
        {"id": 9875, "content": "Yes, checking now", "is_target": false, ...},
        {"id": 9876, "content": "The deadline is next week", "is_target": true, ...},
        {"id": 9877, "content": "Got it, thanks", "is_target": false, ...},
        {"id": 9878, "content": "I'll prepare the report", "is_target": false, ...}
      ],
      "target_message_id": 9876,
      "chat_title": "Project Team"
    }
  ],
  "total_matches": 5,
  "search_query": "deadline",
  "summary": "Found 5 match(es) for \"deadline\", showing context for 2 result(s) (10 total messages)"
}

Use Case 3: Global search with context

# Input - search across all chats
{"mode": "search", "query": "urgent", "search_limit": 5, "context_count": 3}

# Output - results may come from different chats
{
  "contexts": [
    {
      "messages": [
        {"id": 553, "content": "Please review", "is_target": false, ...},
        {"id": 554, "content": "Will do", "is_target": false, ...},
        {"id": 555, "content": "This is urgent!", "is_target": true, ...},
        {"id": 556, "content": "On it now", "is_target": false, ...}
      ],
      "target_message_id": 555,
      "chat_id": 1111111,
      "chat_title": "Work Group"
    },
    {
      "messages": [
        {"id": 775, "content": "Schedule update", "is_target": false, ...},
        {"id": 776, "content": "What time?", "is_target": false, ...},
        {"id": 777, "content": "Urgent meeting tomorrow", "is_target": true, ...},
        {"id": 778, "content": "I'll be there", "is_target": false, ...}
      ],
      "target_message_id": 777,
      "chat_id": 2222222,
      "chat_title": "Project Team"
    }
  ],
  "total_matches": 12,
  "search_query": "urgent",
  "summary": "Found 12 match(es) for \"urgent\", showing context for 2 result(s) (8 total messages)"
}

5. sendMessage

Description: Send or forward messages to a chat. Use action="send" to compose new messages, or action="forward" to forward existing messages from another chat.

Input Schema

{
  "type": "object",
  "properties": {
    "chat": {
      "type": ["number", "string"],
      "description": "Target chat: name/title or numeric ID"
    },
    "action": {
      "type": "string",
      "enum": ["send", "forward"],
      "description": "Action type (default: 'send')"
    },
    "text": {
      "type": "string",
      "description": "(send action) Text content of the message"
    },
    "reply_to_message_id": {
      "type": "number",
      "description": "(send action) ID of message to reply to"
    },
    "from_chat": {
      "type": ["number", "string"],
      "description": "(forward action) Source chat to forward from"
    },
    "message_ids": {
      "type": "array",
      "items": { "type": "number" },
      "description": "(forward action) Message IDs to forward"
    },
    "send_copy": {
      "type": "boolean",
      "description": "(forward action) Send copies without forwarding header"
    },
    "remove_caption": {
      "type": "boolean",
      "description": "(forward action) Remove media captions"
    }
  },
  "required": ["chat"]
}

Output Schema (Send)

{
  id: number;
  chat_id: number;
  sender: string;
  content: string;
  content_type: string;
  date: string;
  date_relative: string;
  is_outgoing: true;
  is_pinned: boolean;
}

Output Schema (Forward)

{
  forwarded: Array<{
    id: number;
    chat_id: number;
    sender: string;
    content: string;
    date: string;
    is_outgoing: boolean;
  }>;
  count: number;
}

Use Cases

Use Case 1: Send a new message

# Input
{"chat": "John Doe", "text": "Hello from MCP!"}

# Output
{
  "id": 14680065,
  "chat_id": 555666777,
  "sender": "User 111222333",
  "content": "Hello from MCP!",
  "content_type": "Text",
  "date": "2025-12-04T12:45:00.000Z",
  "date_relative": "just now",
  "is_outgoing": true
}

Use Case 2: Reply to a message

# Input
{"chat": "Project Team", "text": "I agree!", "reply_to_message_id": 12345}

Use Case 3: Forward messages

# Input
{
  "chat": "John Doe",
  "action": "forward",
  "from_chat": "Project Team",
  "message_ids": [100, 101, 102]
}

# Output
{
  "forwarded": [...],
  "count": 3
}

Use Case 4: Forward as copy (no "Forwarded from" header)

# Input
{
  "chat": "John Doe",
  "action": "forward",
  "from_chat": "Project Team",
  "message_ids": [100],
  "send_copy": true
}

6. getUser

Description: Get information about a Telegram user. You can use their name, @username, or numeric user ID.

Input Schema

{
  "type": "object",
  "properties": {
    "user": {
      "type": ["number", "string"],
      "description": "User identifier: name, @username, or numeric ID"
    }
  },
  "required": ["user"]
}

Output Schema

{
  id: number;
  name: string;
  username?: string;
  phone?: string;
  status: string;        // "online", "last seen 2 hours ago", etc.
  is_contact: boolean;
  is_premium: boolean;
  is_verified: boolean;
}

Use Cases

Use Case 1: Get user by numeric ID

# Input
{"user": 555666777}

# Output
{
  "id": 555666777,
  "name": "John Doe",
  "phone": "+1234567890",
  "status": "last seen 2 hours ago",
  "is_contact": true,
  "is_premium": false,
  "is_verified": false
}

Use Case 2: Get user by username

# Input
{"user": "@johndoe"}

7. getContacts

Description: Get contacts - either list all contacts or search by name/username. When query is provided, searches contacts; otherwise returns all contacts.

Input Schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Optional: Search query to filter contacts"
    },
    "limit": {
      "type": "number",
      "description": "Max results when searching (default: 50, max: 200)"
    }
  }
}

Output Schema

{
  contacts: Array<{
    id: number;
    name: string;
    username?: string;
    phone?: string;
    status: string;
  }>;
  total_count: number;
  query?: string;         // Only present when searching
}

Use Cases

Use Case 1: List all contacts

# Input
{}

# Output
{
  "contacts": [
    {
      "id": 555666777,
      "name": "John Doe",
      "phone": "+1234567890",
      "status": "last seen 2 hours ago"
    },
    {
      "id": 123456789,
      "name": "John Doe",
      "username": "johndoe",
      "status": "online"
    }
  ],
  "total_count": 2
}

Use Case 2: Search contacts

# Input
{"query": "John", "limit": 10}

# Output
{
  "contacts": [
    {
      "id": 555666777,
      "name": "John Doe",
      "phone": "+1234567890",
      "status": "last seen 2 hours ago"
    }
  ],
  "total_count": 1,
  "query": "John"
}

8. getFile

Description: Get file metadata (size, remote ID). Note: Download is not supported in stateless mode since session files are cleaned up after each request.

Input Schema

{
  "type": "object",
  "properties": {
    "file_id": {
      "type": "number",
      "description": "Identifier of the file to get metadata for"
    }
  },
  "required": ["file_id"]
}

Output Schema

{
  id: number;
  size: string;              // Human-readable (e.g., "1.5 MB")
  size_bytes: number;
  remote_id?: string;        // Remote file identifier
}

Use Cases

Use Case 1: Get file metadata

# Input
{"file_id": 33}

# Output
{
  "id": 33,
  "size": "1.00 MB",
  "size_bytes": 1024000,
  "remote_id": "AgACAgEAAxk..."
}

Use Case 2: Get file info from a message

# First, get messages to find a file_id
{"chat": "John Doe", "mode": "history", "limit": 5}
# Response includes file_id in messages with media

# Then get file metadata
{"file_id": 45}

9. getGroup

Description: Get information about a group (basic group, supergroup, or channel). Use type="auto" to detect automatically, or specify type="supergroup" or type="basic_group" explicitly.

Input Schema

{
  "type": "object",
  "properties": {
    "group": {
      "type": ["number", "string"],
      "description": "Group identifier: name or numeric ID"
    },
    "type": {
      "type": "string",
      "enum": ["auto", "supergroup", "basic_group"],
      "description": "Group type (default: 'auto')"
    }
  },
  "required": ["group"]
}

Output Schema

{
  id: number;
  name: string;
  type: "basic_group" | "supergroup" | "channel";
  member_count: number;
  is_verified?: boolean;    // supergroups only
  is_scam?: boolean;        // supergroups only
  join_date?: string;
}

Use Cases

Use Case 1: Get group with auto-detection

# Input
{"group": "Project Team"}

# Output
{
  "id": 1234567890,
  "name": "Project Team",
  "type": "supergroup",
  "member_count": 15,
  "is_verified": false,
  "is_scam": false
}

Use Case 2: Get basic group explicitly

# Input
{"group": "Family Group", "type": "basic_group"}

# Output
{
  "id": 9876543210,
  "name": "Family Group",
  "type": "basic_group",
  "member_count": 5
}

Use Case 3: Get supergroup by ID

# Input
{"group": 1234567890, "type": "supergroup"}

10. getChatMembers

Description: Get members of a chat with filtering options. Supports filtering by role (administrators, banned, bots) or searching by name.

Input Schema

{
  "type": "object",
  "properties": {
    "chat": {
      "type": ["number", "string"],
      "description": "Chat identifier: name/title or numeric ID"
    },
    "filter": {
      "type": "string",
      "enum": ["recent", "administrators", "banned", "bots", "search"],
      "description": "Filter type (default: 'recent')"
    },
    "query": {
      "type": "string",
      "description": "Search query (for 'search' and 'banned' filters)"
    },
    "offset": {
      "type": "number",
      "description": "Pagination offset"
    },
    "limit": {
      "type": "number",
      "description": "Max members to return (default: 200, max: 200)"
    }
  },
  "required": ["chat"]
}

Output Schema

{
  members: Array<{
    user_id: number;
    name: string;
    username?: string;
    status: string;
    role: string;           // "owner", "administrator", "member", etc.
    joined_date?: string;
  }>;
  total_count: number;
  chat_title?: string;
}

Use Cases

Use Case 1: Get recent members

# Input
{"chat": "Project Team", "limit": 10}

# Output
{
  "members": [
    {
      "user_id": 111222333,
      "name": "John Doe",
      "status": "member",
      "role": "creator"
    },
    {
      "user_id": 123456789,
      "name": "John Doe",
      "username": "johndoe",
      "status": "member",
      "role": "member"
    }
  ],
  "total_count": 15,
  "chat_title": "Project Team"
}

Use Case 2: Get only administrators

# Input
{"chat": "Project Team", "filter": "administrators"}

# Output
{
  "members": [
    {
      "user_id": 111222333,
      "name": "John Doe",
      "status": "administrator",
      "role": "owner"
    }
  ],
  "total_count": 1,
  "chat_title": "Project Team"
}

Use Case 3: Search members by name

# Input
{"chat": "Project Team", "filter": "search", "query": "john"}

Use Case 4: Get bot members

# Input
{"chat": "Project Team", "filter": "bots"}