mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-29 14:02:19 +00:00
Add Telegram MCP tools and server components for enhanced functionality
- Introduced core components for Telegram MCP integration, including server management, API helpers, and tool action parsers. - Implemented various tools for user and chat management, such as adding contacts, archiving chats, and sending messages. - Created utility functions for handling Telegram-specific actions and responses, improving interaction with the Telegram API. - Defined types and context for better type safety and clarity in tool implementations. These changes establish a comprehensive framework for Telegram MCP interactions, enhancing the application's capabilities in managing Telegram functionalities.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Telegram MCP Server
|
||||
* Main entry point for Telegram MCP integration
|
||||
*/
|
||||
|
||||
import type { Socket } from 'socket.io-client';
|
||||
import { TelegramMCPServer } from './server';
|
||||
|
||||
let telegramMCPInstance: TelegramMCPServer | undefined;
|
||||
|
||||
export function initTelegramMCPServer(socket: Socket | null | undefined): TelegramMCPServer {
|
||||
telegramMCPInstance = new TelegramMCPServer(socket);
|
||||
console.log('[MCP] Telegram MCP server initialized');
|
||||
return telegramMCPInstance;
|
||||
}
|
||||
|
||||
export function getTelegramMCPServer(): TelegramMCPServer | undefined {
|
||||
return telegramMCPInstance;
|
||||
}
|
||||
|
||||
export function updateTelegramMCPServerSocket(socket: Socket | null | undefined): void {
|
||||
if (telegramMCPInstance) {
|
||||
telegramMCPInstance.updateSocket(socket);
|
||||
console.log('[MCP] Telegram MCP server socket updated');
|
||||
}
|
||||
}
|
||||
|
||||
export { toHumanReadableAction } from './toolActionParser';
|
||||
export type { TelegramMCPServer } from './server';
|
||||
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* Telegram MCP Server
|
||||
* Provides tools for interacting with Telegram via MCP protocol
|
||||
*/
|
||||
|
||||
import type { Socket } from "socket.io-client";
|
||||
import type { TelegramState } from "../../../store/telegram/types";
|
||||
import type {
|
||||
MCPServerConfig,
|
||||
MCPTool,
|
||||
MCPToolCall,
|
||||
MCPToolResult,
|
||||
} from "../types";
|
||||
|
||||
import { store } from "../../../store";
|
||||
import { ErrorCategory, logAndFormatError } from "../errorHandler";
|
||||
import { ValidationError } from "../validation";
|
||||
import { SocketIOMCPTransportImpl } from "../transport";
|
||||
import { mcpLog } from "../logger";
|
||||
import type { TelegramMCPToolHandler } from "./types";
|
||||
import * as tools from "./tools";
|
||||
|
||||
export class TelegramMCPServer {
|
||||
private transport: SocketIOMCPTransportImpl;
|
||||
private config: MCPServerConfig;
|
||||
|
||||
constructor(socket: Socket | null | undefined) {
|
||||
this.transport = new SocketIOMCPTransportImpl(socket ?? undefined);
|
||||
this.config = { name: "telegram-mcp", version: "1.0.0" };
|
||||
this.setupHandlers();
|
||||
}
|
||||
|
||||
updateSocket(socket: Socket | null | undefined): void {
|
||||
this.transport.updateSocket(socket ?? undefined);
|
||||
}
|
||||
|
||||
private setupHandlers(): void {
|
||||
this.transport.on(
|
||||
"toolCall",
|
||||
(data: { requestId: string; toolCall: MCPToolCall }) => {
|
||||
void this.handleToolCallRequest(data);
|
||||
},
|
||||
);
|
||||
|
||||
this.transport.on("listTools", (data: { requestId: string }) => {
|
||||
const { requestId } = data;
|
||||
try {
|
||||
const toolsList = this.listTools();
|
||||
this.transport.emit("listToolsResponse", {
|
||||
requestId,
|
||||
tools: toolsList,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[MCP] Failed to list tools", error);
|
||||
this.transport.emit("listToolsResponse", { requestId, tools: [] });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async handleToolCallRequest(data: {
|
||||
requestId: string;
|
||||
toolCall: MCPToolCall;
|
||||
}): Promise<void> {
|
||||
const { requestId, toolCall } = data;
|
||||
try {
|
||||
const result = await this.handleToolCall(toolCall);
|
||||
this.transport.emit("toolResult", { requestId, result });
|
||||
} catch (error) {
|
||||
const errorResult = logAndFormatError(
|
||||
"handleToolCall",
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
);
|
||||
this.transport.emit("toolResult", { requestId, result: errorResult });
|
||||
}
|
||||
}
|
||||
|
||||
private listTools(): MCPTool[] {
|
||||
return Object.values(tools).filter((t): t is MCPTool => {
|
||||
return (
|
||||
t !== undefined &&
|
||||
typeof t === "object" &&
|
||||
"name" in t &&
|
||||
"description" in t &&
|
||||
"inputSchema" in t &&
|
||||
typeof (t as MCPTool).name === "string" &&
|
||||
typeof (t as MCPTool).description === "string"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private async handleToolCall(toolCall: MCPToolCall): Promise<MCPToolResult> {
|
||||
const { name, arguments: args } = toolCall;
|
||||
mcpLog(`Executing tool: ${name}`, args);
|
||||
|
||||
const toolHandler = this.findToolHandler(name);
|
||||
if (!toolHandler) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Tool '${name}' not found` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
const telegramState: TelegramState = store.getState().telegram;
|
||||
|
||||
try {
|
||||
return await toolHandler(args, {
|
||||
telegramState,
|
||||
transport: this.transport,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof ValidationError) {
|
||||
return logAndFormatError(name, error, ErrorCategory.VALIDATION);
|
||||
}
|
||||
return logAndFormatError(
|
||||
name,
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private findToolHandler(name: string): TelegramMCPToolHandler | undefined {
|
||||
const toolMap: Record<string, TelegramMCPToolHandler> = {
|
||||
get_chats: tools.getChats,
|
||||
list_chats: tools.listChats,
|
||||
get_chat: tools.getChat,
|
||||
create_group: tools.createGroup,
|
||||
invite_to_group: tools.inviteToGroup,
|
||||
create_channel: tools.createChannel,
|
||||
edit_chat_title: tools.editChatTitle,
|
||||
delete_chat_photo: tools.deleteChatPhoto,
|
||||
leave_chat: tools.leaveChat,
|
||||
get_participants: tools.getParticipants,
|
||||
get_admins: tools.getAdmins,
|
||||
get_banned_users: tools.getBannedUsers,
|
||||
promote_admin: tools.promoteAdmin,
|
||||
demote_admin: tools.demoteAdmin,
|
||||
ban_user: tools.banUser,
|
||||
unban_user: tools.unbanUser,
|
||||
get_invite_link: tools.getInviteLink,
|
||||
export_chat_invite: tools.exportChatInvite,
|
||||
import_chat_invite: tools.importChatInvite,
|
||||
join_chat_by_link: tools.joinChatByLink,
|
||||
subscribe_public_channel: tools.subscribePublicChannel,
|
||||
get_messages: tools.getMessages,
|
||||
list_messages: tools.listMessages,
|
||||
list_topics: tools.listTopics,
|
||||
send_message: tools.sendMessage,
|
||||
reply_to_message: tools.replyToMessage,
|
||||
edit_message: tools.editMessage,
|
||||
delete_message: tools.deleteMessage,
|
||||
forward_message: tools.forwardMessage,
|
||||
pin_message: tools.pinMessage,
|
||||
unpin_message: tools.unpinMessage,
|
||||
mark_as_read: tools.markAsRead,
|
||||
get_message_context: tools.getMessageContext,
|
||||
get_history: tools.getHistory,
|
||||
get_pinned_messages: tools.getPinnedMessages,
|
||||
send_reaction: tools.sendReaction,
|
||||
remove_reaction: tools.removeReaction,
|
||||
get_message_reactions: tools.getMessageReactions,
|
||||
list_contacts: tools.listContacts,
|
||||
search_contacts: tools.searchContacts,
|
||||
add_contact: tools.addContact,
|
||||
delete_contact: tools.deleteContact,
|
||||
block_user: tools.blockUser,
|
||||
unblock_user: tools.unblockUser,
|
||||
get_blocked_users: tools.getBlockedUsers,
|
||||
get_me: tools.getMe,
|
||||
update_profile: tools.updateProfile,
|
||||
get_user_photos: tools.getUserPhotos,
|
||||
get_user_status: tools.getUserStatus,
|
||||
mute_chat: tools.muteChat,
|
||||
unmute_chat: tools.unmuteChat,
|
||||
archive_chat: tools.archiveChat,
|
||||
unarchive_chat: tools.unarchiveChat,
|
||||
get_privacy_settings: tools.getPrivacySettings,
|
||||
set_privacy_settings: tools.setPrivacySettings,
|
||||
list_inline_buttons: tools.listInlineButtons,
|
||||
press_inline_button: tools.pressInlineButton,
|
||||
save_draft: tools.saveDraft,
|
||||
get_drafts: tools.getDrafts,
|
||||
clear_draft: tools.clearDraft,
|
||||
search_public_chats: tools.searchPublicChats,
|
||||
search_messages: tools.searchMessages,
|
||||
resolve_username: tools.resolveUsername,
|
||||
get_media_info: tools.getMediaInfo,
|
||||
get_recent_actions: tools.getRecentActions,
|
||||
create_poll: tools.createPoll,
|
||||
get_bot_info: tools.getBotInfo,
|
||||
set_bot_commands: tools.setBotCommands,
|
||||
set_profile_photo: tools.setProfilePhoto,
|
||||
delete_profile_photo: tools.deleteProfilePhoto,
|
||||
edit_chat_photo: tools.editChatPhoto,
|
||||
get_sticker_sets: tools.getStickerSets,
|
||||
get_gif_search: tools.getGifSearch,
|
||||
get_contact_ids: tools.getContactIds,
|
||||
import_contacts: tools.importContacts,
|
||||
export_contacts: tools.exportContacts,
|
||||
get_direct_chat_by_contact: tools.getDirectChatByContact,
|
||||
get_contact_chats: tools.getContactChats,
|
||||
get_last_interaction: tools.getLastInteraction,
|
||||
};
|
||||
return toolMap[name];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Telegram API helpers for MCP tools
|
||||
* Uses mtprotoService + Redux telegram state (alphahuman)
|
||||
*/
|
||||
|
||||
import { store } from '../../../store';
|
||||
import { mtprotoService } from '../../../services/mtprotoService';
|
||||
import {
|
||||
selectOrderedChats,
|
||||
selectChatMessages,
|
||||
selectCurrentUser,
|
||||
} from '../../../store/telegramSelectors';
|
||||
import type { TelegramChat, TelegramUser, TelegramMessage } from '../../../store/telegram/types';
|
||||
|
||||
export interface FormattedEntity {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
username?: string;
|
||||
phone?: string;
|
||||
}
|
||||
|
||||
export interface FormattedMessage {
|
||||
id: number | string;
|
||||
date: string;
|
||||
text: string;
|
||||
from_id?: string;
|
||||
has_media?: boolean;
|
||||
media_type?: string;
|
||||
}
|
||||
|
||||
function getTelegramState() {
|
||||
return store.getState().telegram;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get chat by ID or username
|
||||
*/
|
||||
export function getChatById(chatId: string | number): TelegramChat | undefined {
|
||||
const state = getTelegramState();
|
||||
const idStr = String(chatId);
|
||||
|
||||
const chat = state.chats[idStr];
|
||||
if (chat) return chat;
|
||||
|
||||
if (typeof chatId === 'string' && (chatId.startsWith('@') || /^[a-zA-Z0-9_]+$/.test(chatId))) {
|
||||
const username = chatId.startsWith('@') ? chatId : `@${chatId}`;
|
||||
return Object.values(state.chats).find(
|
||||
(c) => c.username && (c.username === username || c.username === username.slice(1)),
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user by ID (current user only for now; no full user cache)
|
||||
*/
|
||||
export function getUserById(userId: string | number): TelegramUser | undefined {
|
||||
const state = getTelegramState();
|
||||
const current = state.currentUser;
|
||||
if (!current) return undefined;
|
||||
if (String(current.id) === String(userId)) return current;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messages from a chat (from store cache)
|
||||
* @param offset - numeric offset for pagination (default 0)
|
||||
*/
|
||||
export async function getMessages(
|
||||
chatId: string | number,
|
||||
limit = 20,
|
||||
offset = 0,
|
||||
): Promise<TelegramMessage[] | undefined> {
|
||||
const chat = getChatById(chatId);
|
||||
if (!chat) return undefined;
|
||||
|
||||
const state = getTelegramState();
|
||||
const order = state.messagesOrder[chat.id] ?? [];
|
||||
const byId = state.messages[chat.id] ?? {};
|
||||
const all = order.map((id) => byId[id]).filter(Boolean);
|
||||
const list = all.slice(offset, offset + limit);
|
||||
|
||||
return list.length ? list : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a chat
|
||||
*/
|
||||
export async function sendMessage(
|
||||
chatId: string | number,
|
||||
message: string,
|
||||
replyToMessageId?: number,
|
||||
): Promise<{ id: string } | undefined> {
|
||||
const chat = getChatById(chatId);
|
||||
if (!chat) return undefined;
|
||||
|
||||
const entity = chat.username ? `@${chat.username.replace('@', '')}` : chat.id;
|
||||
|
||||
if (replyToMessageId !== undefined) {
|
||||
const client = mtprotoService.getClient();
|
||||
await mtprotoService.withFloodWaitHandling(async () => {
|
||||
await client.sendMessage(entity, {
|
||||
message,
|
||||
replyTo: replyToMessageId,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
await mtprotoService.sendMessage(entity, message);
|
||||
}
|
||||
|
||||
return { id: String(Date.now()) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of chats (from store)
|
||||
*/
|
||||
export async function getChats(limit = 20): Promise<TelegramChat[]> {
|
||||
const state = store.getState();
|
||||
const ordered = selectOrderedChats(state);
|
||||
return ordered.slice(0, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search chats by query (filter by title/username from store)
|
||||
*/
|
||||
export async function searchChats(query: string): Promise<TelegramChat[]> {
|
||||
const state = store.getState();
|
||||
const ordered = selectOrderedChats(state);
|
||||
const q = query.toLowerCase();
|
||||
return ordered.filter((c) => {
|
||||
const title = (c.title ?? '').toLowerCase();
|
||||
const un = (c.username ?? '').toLowerCase();
|
||||
return title.includes(q) || un.includes(q);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user info
|
||||
*/
|
||||
export function getCurrentUser(): TelegramUser | undefined {
|
||||
const state = store.getState();
|
||||
return selectCurrentUser(state) ?? undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format entity (chat or user) for display
|
||||
*/
|
||||
export function formatEntity(entity: TelegramChat | TelegramUser): FormattedEntity {
|
||||
if ('title' in entity) {
|
||||
const chat = entity as TelegramChat;
|
||||
const type = chat.type === 'channel' ? 'channel' : chat.type === 'supergroup' ? 'group' : chat.type;
|
||||
return {
|
||||
id: chat.id,
|
||||
name: chat.title ?? 'Unknown',
|
||||
type,
|
||||
username: chat.username,
|
||||
};
|
||||
}
|
||||
const user = entity as TelegramUser;
|
||||
const name = [user.firstName, user.lastName].filter(Boolean).join(' ') || 'Unknown';
|
||||
return {
|
||||
id: user.id,
|
||||
name,
|
||||
type: 'user',
|
||||
username: user.username,
|
||||
phone: user.phoneNumber,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format message for display
|
||||
*/
|
||||
export function formatMessage(message: TelegramMessage): FormattedMessage {
|
||||
const result: FormattedMessage = {
|
||||
id: message.id,
|
||||
date: new Date(message.date * 1000).toISOString(),
|
||||
text: message.message ?? '',
|
||||
};
|
||||
if (message.fromId) result.from_id = message.fromId;
|
||||
if (message.media?.type) {
|
||||
result.has_media = true;
|
||||
result.media_type = message.media.type;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
/**
|
||||
* Tool Action Parser - Converts tool inputs to human-readable descriptions
|
||||
*/
|
||||
|
||||
type ToolArguments = Record<string, unknown>;
|
||||
|
||||
function formatId(id: string | number | undefined, prefix = ''): string {
|
||||
if (!id) return '';
|
||||
const str = String(id);
|
||||
return prefix ? `${prefix} ${str}` : str;
|
||||
}
|
||||
|
||||
function truncateText(text: string, maxLength = 50): string {
|
||||
if (text.length <= maxLength) return text;
|
||||
return `${text.substring(0, maxLength)}...`;
|
||||
}
|
||||
|
||||
export function toHumanReadableAction(toolName: string, args: ToolArguments): string {
|
||||
const parser = toolParsers[toolName];
|
||||
if (parser) return parser(args);
|
||||
return `Executing ${toolName} with provided parameters`;
|
||||
}
|
||||
|
||||
const toolParsers: Record<string, (args: ToolArguments) => string> = {
|
||||
send_message: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const message = truncateText((args.message as string) || '', 100);
|
||||
return `Send message to ${chatId}: "${message}"`;
|
||||
},
|
||||
reply_to_message: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
const text = truncateText((args.text as string) || '', 100);
|
||||
return `Reply to message ${messageId} in ${chatId}: "${text}"`;
|
||||
},
|
||||
edit_message: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
const newText = truncateText((args.new_text as string) || '', 100);
|
||||
return `Edit message ${messageId} in ${chatId} to: "${newText}"`;
|
||||
},
|
||||
delete_message: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
return `Delete message ${messageId} from ${chatId}`;
|
||||
},
|
||||
forward_message: (args) => {
|
||||
const fromChat = formatId(args.from_chat_id as string | number, 'chat');
|
||||
const toChat = formatId(args.to_chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
return `Forward message ${messageId} from ${fromChat} to ${toChat}`;
|
||||
},
|
||||
pin_message: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
return `Pin message ${messageId} in ${chatId}`;
|
||||
},
|
||||
unpin_message: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
return `Unpin message ${messageId} in ${chatId}`;
|
||||
},
|
||||
mark_as_read: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Mark messages as read in ${chatId}`;
|
||||
},
|
||||
send_reaction: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
const reaction = (args.reaction as string) || '👍';
|
||||
return `Add reaction ${reaction} to message ${messageId} in ${chatId}`;
|
||||
},
|
||||
remove_reaction: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
const reaction = (args.reaction as string) || '';
|
||||
return `Remove reaction ${reaction} from message ${messageId} in ${chatId}`;
|
||||
},
|
||||
save_draft: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const text = truncateText((args.text as string) || '', 50);
|
||||
return `Save draft in ${chatId}: "${text}"`;
|
||||
},
|
||||
clear_draft: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Clear draft in ${chatId}`;
|
||||
},
|
||||
list_chats: (args) => {
|
||||
const chatType = (args.chat_type as string) || 'all';
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `List ${limit} ${chatType} chats`;
|
||||
},
|
||||
get_chat: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Get information for ${chatId}`;
|
||||
},
|
||||
create_group: (args) => {
|
||||
const title = (args.title as string) || 'Untitled Group';
|
||||
const userCount = Array.isArray(args.user_ids) ? args.user_ids.length : 0;
|
||||
return `Create group "${title}" with ${userCount} member${userCount !== 1 ? 's' : ''}`;
|
||||
},
|
||||
create_channel: (args) => {
|
||||
const title = (args.title as string) || 'Untitled Channel';
|
||||
const description = args.description
|
||||
? `: ${truncateText((args.description as string) || '', 50)}`
|
||||
: '';
|
||||
return `Create channel "${title}"${description}`;
|
||||
},
|
||||
edit_chat_title: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const newTitle = (args.new_title as string) || '';
|
||||
return `Change title of ${chatId} to "${newTitle}"`;
|
||||
},
|
||||
delete_chat_photo: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Remove photo from ${chatId}`;
|
||||
},
|
||||
edit_chat_photo: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Update photo for ${chatId}`;
|
||||
},
|
||||
leave_chat: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Leave ${chatId}`;
|
||||
},
|
||||
mute_chat: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const muteFor = args.mute_for ? ` for ${args.mute_for} seconds` : '';
|
||||
return `Mute ${chatId}${muteFor}`;
|
||||
},
|
||||
unmute_chat: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Unmute ${chatId}`;
|
||||
},
|
||||
archive_chat: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Archive ${chatId}`;
|
||||
},
|
||||
unarchive_chat: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Unarchive ${chatId}`;
|
||||
},
|
||||
invite_to_group: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const userCount = Array.isArray(args.user_ids) ? args.user_ids.length : 0;
|
||||
return `Invite ${userCount} user${userCount !== 1 ? 's' : ''} to ${chatId}`;
|
||||
},
|
||||
ban_user: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Ban ${userId} from ${chatId}`;
|
||||
},
|
||||
unban_user: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Unban ${userId} from ${chatId}`;
|
||||
},
|
||||
promote_admin: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Promote ${userId} to admin in ${chatId}`;
|
||||
},
|
||||
demote_admin: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Demote ${userId} from admin in ${chatId}`;
|
||||
},
|
||||
block_user: (args) => {
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Block ${userId}`;
|
||||
},
|
||||
unblock_user: (args) => {
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Unblock ${userId}`;
|
||||
},
|
||||
add_contact: (args) => {
|
||||
const firstName = (args.first_name as string) || '';
|
||||
const lastName = (args.last_name as string) || '';
|
||||
const phone = (args.phone_number as string) || '';
|
||||
const name = [firstName, lastName].filter(Boolean).join(' ') || phone;
|
||||
return `Add contact: ${name}`;
|
||||
},
|
||||
delete_contact: (args) => {
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Delete contact ${userId}`;
|
||||
},
|
||||
list_contacts: (args) => {
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `List ${limit} contacts`;
|
||||
},
|
||||
search_contacts: (args) => {
|
||||
const query = truncateText((args.query as string) || '', 30);
|
||||
return `Search contacts for "${query}"`;
|
||||
},
|
||||
search_messages: (args) => {
|
||||
const chatId = args.chat_id ? formatId(args.chat_id as string | number, 'chat') : 'all chats';
|
||||
const query = truncateText((args.query as string) || '', 30);
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `Search for "${query}" in ${chatId} (limit: ${limit})`;
|
||||
},
|
||||
search_public_chats: (args) => {
|
||||
const query = truncateText((args.query as string) || '', 30);
|
||||
return `Search public chats for "${query}"`;
|
||||
},
|
||||
resolve_username: (args) => {
|
||||
const username = (args.username as string) || '';
|
||||
return `Resolve username @${username.replace('@', '')}`;
|
||||
},
|
||||
get_messages: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `Get ${limit} messages from ${chatId}`;
|
||||
},
|
||||
list_messages: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `List ${limit} messages from ${chatId}`;
|
||||
},
|
||||
get_history: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `Get message history from ${chatId} (${limit} messages)`;
|
||||
},
|
||||
get_pinned_messages: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Get pinned messages from ${chatId}`;
|
||||
},
|
||||
get_message_context: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
const limit = (args.limit as number) || 5;
|
||||
return `Get context around message ${messageId} in ${chatId} (±${limit} messages)`;
|
||||
},
|
||||
list_topics: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `List topics in ${chatId}`;
|
||||
},
|
||||
get_participants: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const limit = (args.limit as number) || 100;
|
||||
return `Get ${limit} participants from ${chatId}`;
|
||||
},
|
||||
get_admins: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Get administrators of ${chatId}`;
|
||||
},
|
||||
get_banned_users: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Get banned users from ${chatId}`;
|
||||
},
|
||||
get_blocked_users: () => 'Get list of blocked users',
|
||||
get_invite_link: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Get invite link for ${chatId}`;
|
||||
},
|
||||
export_chat_invite: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Create invite link for ${chatId}`;
|
||||
},
|
||||
import_chat_invite: (args) => {
|
||||
const inviteHash = args.invite_hash ? truncateText((args.invite_hash as string) || '', 20) : '';
|
||||
return `Join chat via invite link: ${inviteHash}`;
|
||||
},
|
||||
join_chat_by_link: (args) => {
|
||||
const inviteLink = args.invite_link ? truncateText((args.invite_link as string) || '', 30) : '';
|
||||
return `Join chat via link: ${inviteLink}`;
|
||||
},
|
||||
subscribe_public_channel: (args) => {
|
||||
const username = (args.username as string) || '';
|
||||
return `Subscribe to public channel @${username.replace('@', '')}`;
|
||||
},
|
||||
update_profile: (args) => {
|
||||
const updates: string[] = [];
|
||||
if (args.first_name) updates.push(`first name: "${args.first_name as string}"`);
|
||||
if (args.last_name) updates.push(`last name: "${args.last_name as string}"`);
|
||||
if (args.bio) updates.push(`bio: "${truncateText((args.bio as string) || '', 30)}"`);
|
||||
return `Update profile (${updates.join(', ')})`;
|
||||
},
|
||||
set_profile_photo: () => 'Set profile photo',
|
||||
delete_profile_photo: () => 'Delete profile photo',
|
||||
get_user_photos: (args) => {
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `Get ${limit} photos from ${userId}`;
|
||||
},
|
||||
get_user_status: (args) => {
|
||||
const userId = formatId(args.user_id as string | number, 'user');
|
||||
return `Get status of ${userId}`;
|
||||
},
|
||||
get_me: () => 'Get current user information',
|
||||
list_inline_buttons: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
return `Get inline buttons from message ${messageId} in ${chatId}`;
|
||||
},
|
||||
press_inline_button: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
const buttonText = args.button_text ? ` "${truncateText((args.button_text as string) || '', 30)}"` : '';
|
||||
return `Press inline button${buttonText} on message ${messageId} in ${chatId}`;
|
||||
},
|
||||
create_poll: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const question = truncateText((args.question as string) || '', 50);
|
||||
const optionCount = Array.isArray(args.options) ? args.options.length : 0;
|
||||
return `Create poll in ${chatId}: "${question}" with ${optionCount} options`;
|
||||
},
|
||||
get_bot_info: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
return `Get bot information from ${chatId}`;
|
||||
},
|
||||
set_bot_commands: (args) => {
|
||||
const chatId = args.chat_id ? formatId(args.chat_id as string | number, 'chat') : 'all chats';
|
||||
const commandCount = Array.isArray(args.commands) ? args.commands.length : 0;
|
||||
return `Set ${commandCount} bot commands for ${chatId}`;
|
||||
},
|
||||
get_privacy_settings: () => 'Get privacy settings',
|
||||
set_privacy_settings: (args) => {
|
||||
const setting = (args.setting as string) || 'unknown';
|
||||
const value = (args.value as string) || '';
|
||||
return `Set privacy setting "${setting}" to ${value}`;
|
||||
},
|
||||
get_media_info: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const messageId = args.message_id;
|
||||
return `Get media information from message ${messageId} in ${chatId}`;
|
||||
},
|
||||
get_recent_actions: (args) => {
|
||||
const chatId = formatId(args.chat_id as string | number, 'chat');
|
||||
const limit = (args.limit as number) || 20;
|
||||
return `Get ${limit} recent admin actions from ${chatId}`;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'add_contact',
|
||||
description: 'Add a contact',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
first_name: { type: 'string', description: 'First name' },
|
||||
last_name: { type: 'string', description: 'Last name' },
|
||||
phone_number: { type: 'string', description: 'Phone number' },
|
||||
},
|
||||
required: ['phone_number'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function addContact(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('add_contact');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'archive_chat',
|
||||
description: 'Archive a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function archiveChat(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('archive_chat');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'ban_user',
|
||||
description: 'Ban user from chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
user_id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
required: ['chat_id', 'user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function banUser(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('ban_user');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'block_user',
|
||||
description: 'Block a user',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function blockUser(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('block_user');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'clear_draft',
|
||||
description: 'Clear draft in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function clearDraft(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('clear_draft');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'create_channel',
|
||||
description: 'Create a channel',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: { type: 'string', description: 'Channel title' },
|
||||
description: { type: 'string', description: 'Channel description' },
|
||||
},
|
||||
required: ['title'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function createChannel(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('create_channel');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'create_group',
|
||||
description: 'Create a group',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: { type: 'string', description: 'Group title' },
|
||||
user_ids: { type: 'array', description: 'User IDs to add' },
|
||||
},
|
||||
required: ['title'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function createGroup(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('create_group');
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'create_poll',
|
||||
description: 'Create a poll in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
question: { type: 'string', description: 'Poll question' },
|
||||
options: { type: 'array', description: 'Poll options' },
|
||||
},
|
||||
required: ['chat_id', 'question', 'options'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function createPoll(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('create_poll');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'delete_chat_photo',
|
||||
description: 'Delete chat photo',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function deleteChatPhoto(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('delete_chat_photo');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'delete_contact',
|
||||
description: 'Delete a contact',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function deleteContact(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('delete_contact');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'delete_message',
|
||||
description: 'Delete a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function deleteMessage(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('delete_message');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'delete_profile_photo',
|
||||
description: 'Delete profile photo',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function deleteProfilePhoto(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('delete_profile_photo');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'demote_admin',
|
||||
description: 'Demote admin',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
user_id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
required: ['chat_id', 'user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function demoteAdmin(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('demote_admin');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'edit_chat_photo',
|
||||
description: 'Edit chat photo',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function editChatPhoto(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('edit_chat_photo');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'edit_chat_title',
|
||||
description: 'Edit chat title',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
new_title: { type: 'string', description: 'New title' },
|
||||
},
|
||||
required: ['chat_id', 'new_title'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function editChatTitle(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('edit_chat_title');
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'edit_message',
|
||||
description: 'Edit an existing message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
new_text: { type: 'string', description: 'New message text' },
|
||||
},
|
||||
required: ['chat_id', 'message_id', 'new_text'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function editMessage(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('edit_message');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'export_chat_invite',
|
||||
description: 'Create invite link for a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function exportChatInvite(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('export_chat_invite');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'export_contacts',
|
||||
description: 'Export contacts',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function exportContacts(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('export_contacts');
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'forward_message',
|
||||
description: 'Forward a message to another chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from_chat_id: { type: 'string', description: 'Source chat ID' },
|
||||
to_chat_id: { type: 'string', description: 'Target chat ID' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['from_chat_id', 'to_chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function forwardMessage(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('forward_message');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_admins',
|
||||
description: 'Get admins of a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getAdmins(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_admins');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_banned_users',
|
||||
description: 'Get banned users in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getBannedUsers(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_banned_users');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_blocked_users',
|
||||
description: 'Get list of blocked users',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function getBlockedUsers(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_blocked_users');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_bot_info',
|
||||
description: 'Get bot information in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getBotInfo(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_bot_info');
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Get Chat tool - Get detailed information about a specific chat
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatEntity, getChatById } from '../telegramApi';
|
||||
import { validateId } from '../../validation';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_chat',
|
||||
description: 'Get detailed information about a specific chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: {
|
||||
type: 'string',
|
||||
description: 'The ID or username of the chat',
|
||||
},
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getChat(
|
||||
args: { chat_id: string | number },
|
||||
context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chatId = validateId(args.chat_id, 'chat_id');
|
||||
const chat = getChatById(chatId);
|
||||
|
||||
if (!chat) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Chat not found: ${chatId}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
const entity = formatEntity(chat);
|
||||
const result: string[] = [];
|
||||
|
||||
result.push(`ID: ${entity.id}`);
|
||||
result.push(`Title: ${entity.name}`);
|
||||
result.push(`Type: ${entity.type}`);
|
||||
if (entity.username) result.push(`Username: @${entity.username}`);
|
||||
if ('participantsCount' in chat && chat.participantsCount) {
|
||||
result.push(`Participants: ${chat.participantsCount}`);
|
||||
}
|
||||
if ('unreadCount' in chat) {
|
||||
result.push(`Unread Messages: ${chat.unreadCount ?? 0}`);
|
||||
}
|
||||
|
||||
const lastMsg = chat.lastMessage;
|
||||
if (lastMsg) {
|
||||
const from = lastMsg.fromName ?? lastMsg.fromId ?? 'Unknown';
|
||||
const date = new Date(lastMsg.date * 1000).toISOString();
|
||||
result.push(`Last Message: From ${from} at ${date}`);
|
||||
result.push(`Message: ${lastMsg.message || '[Media/No text]'}`);
|
||||
}
|
||||
|
||||
return {
|
||||
content: [{ type: 'text', text: result.join('\n') }],
|
||||
};
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'get_chat',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.CHAT,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Get Chats tool - Get a paginated list of chats
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatEntity, getChats as getChatsApi } from '../telegramApi';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_chats',
|
||||
description: 'Get a paginated list of chats',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
page: { type: 'number', description: 'Page number (1-indexed)', default: 1 },
|
||||
page_size: { type: 'number', description: 'Number of chats per page', default: 20 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export async function getChats(
|
||||
args: { page?: number; page_size?: number },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const page = args.page ?? 1;
|
||||
const pageSize = args.page_size ?? 20;
|
||||
const start = (page - 1) * pageSize;
|
||||
|
||||
const chats = await getChatsApi(pageSize + start);
|
||||
const paginatedChats = chats.slice(start, start + pageSize);
|
||||
|
||||
if (paginatedChats.length === 0) {
|
||||
return { content: [{ type: 'text', text: 'Page out of range.' }] };
|
||||
}
|
||||
|
||||
const lines = paginatedChats.map((chat) => {
|
||||
const entity = formatEntity(chat);
|
||||
return `Chat ID: ${entity.id}, Title: ${entity.name}`;
|
||||
});
|
||||
|
||||
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'get_chats',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.CHAT,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_contact_chats',
|
||||
description: 'Get chats with a contact',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getContactChats(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_contact_chats');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_contact_ids',
|
||||
description: 'Get contact IDs',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function getContactIds(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_contact_ids');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_direct_chat_by_contact',
|
||||
description: 'Get direct chat by contact',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getDirectChatByContact(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_direct_chat_by_contact');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_drafts',
|
||||
description: 'Get all drafts',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function getDrafts(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_drafts');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_gif_search',
|
||||
description: 'Search GIFs',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { query: { type: 'string', description: 'Search query' } },
|
||||
required: ['query'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getGifSearch(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_gif_search');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_history',
|
||||
description: 'Get message history from a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
limit: { type: 'number', description: 'Number of messages', default: 20 },
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getHistory(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_history');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_invite_link',
|
||||
description: 'Get invite link for a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getInviteLink(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_invite_link');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_last_interaction',
|
||||
description: 'Get last interaction with a user',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getLastInteraction(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_last_interaction');
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Get Me tool - Get your own user information
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatEntity, getCurrentUser } from '../telegramApi';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_me',
|
||||
description: 'Get your own user information',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
};
|
||||
|
||||
export async function getMe(
|
||||
_args: Record<string, never>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const user = getCurrentUser();
|
||||
if (!user) {
|
||||
return {
|
||||
content: [{ type: 'text', text: 'User information not available' }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
const entity = formatEntity(user);
|
||||
const result = {
|
||||
id: entity.id,
|
||||
name: entity.name,
|
||||
type: entity.type,
|
||||
...(entity.username && { username: entity.username }),
|
||||
...(entity.phone && { phone: entity.phone }),
|
||||
};
|
||||
return {
|
||||
content: [{ type: 'text', text: JSON.stringify(result, undefined, 2) }],
|
||||
};
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'get_me',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.PROFILE,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_media_info',
|
||||
description: 'Get media info from a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getMediaInfo(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_media_info');
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_message_context',
|
||||
description: 'Get context around a specific message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
limit: { type: 'number', description: 'Number of messages before/after', default: 5 },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getMessageContext(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_message_context');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_message_reactions',
|
||||
description: 'Get reactions on a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getMessageReactions(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_message_reactions');
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Get Messages tool - Get paginated messages from a specific chat
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatMessage, getChatById, getMessages as getMessagesApi } from '../telegramApi';
|
||||
import { validateId } from '../../validation';
|
||||
import type { TelegramMessage } from '../../../store/telegram/types';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_messages',
|
||||
description: 'Get paginated messages from a specific chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'The ID or username of the chat' },
|
||||
page: { type: 'number', description: 'Page number (1-indexed)', default: 1 },
|
||||
page_size: { type: 'number', description: 'Number of messages per page', default: 20 },
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
function senderDisplay(msg: TelegramMessage): string {
|
||||
return msg.fromName ?? msg.fromId ?? 'Unknown';
|
||||
}
|
||||
|
||||
export async function getMessages(
|
||||
args: { chat_id: string | number; page?: number; page_size?: number },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chatId = validateId(args.chat_id, 'chat_id');
|
||||
const page = args.page ?? 1;
|
||||
const pageSize = args.page_size ?? 20;
|
||||
const offset = (page - 1) * pageSize;
|
||||
|
||||
const chat = getChatById(chatId);
|
||||
if (!chat) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Chat not found: ${chatId}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
const messages = await getMessagesApi(chatId, pageSize, offset);
|
||||
if (!messages || messages.length === 0) {
|
||||
return { content: [{ type: 'text', text: 'No messages found for this page.' }] };
|
||||
}
|
||||
|
||||
const lines = messages.map((msg) => {
|
||||
const formatted = formatMessage(msg);
|
||||
const replyStr = msg.replyToMessageId ? ` | reply to ${msg.replyToMessageId}` : '';
|
||||
const msgText = formatted.text || '[Media/No text]';
|
||||
return `ID: ${formatted.id} | ${senderDisplay(msg)} | Date: ${formatted.date}${replyStr} | Message: ${msgText}`;
|
||||
});
|
||||
|
||||
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'get_messages',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.MSG,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_participants',
|
||||
description: 'Get participants in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
limit: { type: 'number', description: 'Max participants', default: 100 },
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getParticipants(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_participants');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_pinned_messages',
|
||||
description: 'Get pinned messages from a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getPinnedMessages(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_pinned_messages');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_privacy_settings',
|
||||
description: 'Get privacy settings',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function getPrivacySettings(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_privacy_settings');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_recent_actions',
|
||||
description: 'Get recent admin actions in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
limit: { type: 'number', description: 'Max actions', default: 20 },
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getRecentActions(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_recent_actions');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_sticker_sets',
|
||||
description: 'Get sticker sets',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function getStickerSets(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_sticker_sets');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_user_photos',
|
||||
description: 'Get photos of a user',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
user_id: { type: 'string', description: 'User ID' },
|
||||
limit: { type: 'number', description: 'Max photos', default: 20 },
|
||||
},
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getUserPhotos(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_user_photos');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'get_user_status',
|
||||
description: 'Get online status of a user',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function getUserStatus(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('get_user_status');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'import_chat_invite',
|
||||
description: 'Join chat via invite hash',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { invite_hash: { type: 'string', description: 'Invite hash' } },
|
||||
required: ['invite_hash'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function importChatInvite(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('import_chat_invite');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'import_contacts',
|
||||
description: 'Import contacts',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { contacts: { type: 'array', description: 'Contacts to import' } },
|
||||
required: ['contacts'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function importContacts(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('import_contacts');
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* MCP Tools for Telegram
|
||||
* Each tool exports a 'tool' definition and a handler function
|
||||
*/
|
||||
|
||||
export { getChats, tool as getChatsTool } from './getChats';
|
||||
export { listChats, tool as listChatsTool } from './listChats';
|
||||
export { getChat, tool as getChatTool } from './getChat';
|
||||
export { createGroup, tool as createGroupTool } from './createGroup';
|
||||
export { inviteToGroup, tool as inviteToGroupTool } from './inviteToGroup';
|
||||
export { createChannel, tool as createChannelTool } from './createChannel';
|
||||
export { editChatTitle, tool as editChatTitleTool } from './editChatTitle';
|
||||
export { deleteChatPhoto, tool as deleteChatPhotoTool } from './deleteChatPhoto';
|
||||
export { leaveChat, tool as leaveChatTool } from './leaveChat';
|
||||
export { getParticipants, tool as getParticipantsTool } from './getParticipants';
|
||||
export { getAdmins, tool as getAdminsTool } from './getAdmins';
|
||||
export { getBannedUsers, tool as getBannedUsersTool } from './getBannedUsers';
|
||||
export { promoteAdmin, tool as promoteAdminTool } from './promoteAdmin';
|
||||
export { demoteAdmin, tool as demoteAdminTool } from './demoteAdmin';
|
||||
export { banUser, tool as banUserTool } from './banUser';
|
||||
export { unbanUser, tool as unbanUserTool } from './unbanUser';
|
||||
export { getInviteLink, tool as getInviteLinkTool } from './getInviteLink';
|
||||
export { exportChatInvite, tool as exportChatInviteTool } from './exportChatInvite';
|
||||
export { importChatInvite, tool as importChatInviteTool } from './importChatInvite';
|
||||
export { joinChatByLink, tool as joinChatByLinkTool } from './joinChatByLink';
|
||||
export { subscribePublicChannel, tool as subscribePublicChannelTool } from './subscribePublicChannel';
|
||||
export { muteChat, tool as muteChatTool } from './muteChat';
|
||||
export { unmuteChat, tool as unmuteChatTool } from './unmuteChat';
|
||||
export { archiveChat, tool as archiveChatTool } from './archiveChat';
|
||||
export { unarchiveChat, tool as unarchiveChatTool } from './unarchiveChat';
|
||||
|
||||
export { getMessages, tool as getMessagesTool } from './getMessages';
|
||||
export { listMessages, tool as listMessagesTool } from './listMessages';
|
||||
export { listTopics, tool as listTopicsTool } from './listTopics';
|
||||
export { sendMessage, tool as sendMessageTool } from './sendMessage';
|
||||
export { replyToMessage, tool as replyToMessageTool } from './replyToMessage';
|
||||
export { editMessage, tool as editMessageTool } from './editMessage';
|
||||
export { deleteMessage, tool as deleteMessageTool } from './deleteMessage';
|
||||
export { forwardMessage, tool as forwardMessageTool } from './forwardMessage';
|
||||
export { pinMessage, tool as pinMessageTool } from './pinMessage';
|
||||
export { unpinMessage, tool as unpinMessageTool } from './unpinMessage';
|
||||
export { markAsRead, tool as markAsReadTool } from './markAsRead';
|
||||
export { getMessageContext, tool as getMessageContextTool } from './getMessageContext';
|
||||
export { getHistory, tool as getHistoryTool } from './getHistory';
|
||||
export { getPinnedMessages, tool as getPinnedMessagesTool } from './getPinnedMessages';
|
||||
export { sendReaction, tool as sendReactionTool } from './sendReaction';
|
||||
export { removeReaction, tool as removeReactionTool } from './removeReaction';
|
||||
export { getMessageReactions, tool as getMessageReactionsTool } from './getMessageReactions';
|
||||
export { listInlineButtons, tool as listInlineButtonsTool } from './listInlineButtons';
|
||||
export { pressInlineButton, tool as pressInlineButtonTool } from './pressInlineButton';
|
||||
export { saveDraft, tool as saveDraftTool } from './saveDraft';
|
||||
export { getDrafts, tool as getDraftsTool } from './getDrafts';
|
||||
export { clearDraft, tool as clearDraftTool } from './clearDraft';
|
||||
|
||||
export { listContacts, tool as listContactsTool } from './listContacts';
|
||||
export { searchContacts, tool as searchContactsTool } from './searchContacts';
|
||||
export { addContact, tool as addContactTool } from './addContact';
|
||||
export { deleteContact, tool as deleteContactTool } from './deleteContact';
|
||||
export { blockUser, tool as blockUserTool } from './blockUser';
|
||||
export { unblockUser, tool as unblockUserTool } from './unblockUser';
|
||||
export { getBlockedUsers, tool as getBlockedUsersTool } from './getBlockedUsers';
|
||||
|
||||
export { getMe, tool as getMeTool } from './getMe';
|
||||
export { updateProfile, tool as updateProfileTool } from './updateProfile';
|
||||
export { getUserPhotos, tool as getUserPhotosTool } from './getUserPhotos';
|
||||
export { getUserStatus, tool as getUserStatusTool } from './getUserStatus';
|
||||
|
||||
export { searchPublicChats, tool as searchPublicChatsTool } from './searchPublicChats';
|
||||
export { searchMessages, tool as searchMessagesTool } from './searchMessages';
|
||||
export { resolveUsername, tool as resolveUsernameTool } from './resolveUsername';
|
||||
|
||||
export { getMediaInfo, tool as getMediaInfoTool } from './getMediaInfo';
|
||||
export { getRecentActions, tool as getRecentActionsTool } from './getRecentActions';
|
||||
export { createPoll, tool as createPollTool } from './createPoll';
|
||||
export { getBotInfo, tool as getBotInfoTool } from './getBotInfo';
|
||||
export { setBotCommands, tool as setBotCommandsTool } from './setBotCommands';
|
||||
|
||||
export { getPrivacySettings, tool as getPrivacySettingsTool } from './getPrivacySettings';
|
||||
export { setPrivacySettings, tool as setPrivacySettingsTool } from './setPrivacySettings';
|
||||
|
||||
export { setProfilePhoto, tool as setProfilePhotoTool } from './setProfilePhoto';
|
||||
export { deleteProfilePhoto, tool as deleteProfilePhotoTool } from './deleteProfilePhoto';
|
||||
export { editChatPhoto, tool as editChatPhotoTool } from './editChatPhoto';
|
||||
|
||||
export { getStickerSets, tool as getStickerSetsTool } from './getStickerSets';
|
||||
export { getGifSearch, tool as getGifSearchTool } from './getGifSearch';
|
||||
|
||||
export { getContactIds, tool as getContactIdsTool } from './getContactIds';
|
||||
export { importContacts, tool as importContactsTool } from './importContacts';
|
||||
export { exportContacts, tool as exportContactsTool } from './exportContacts';
|
||||
export { getDirectChatByContact, tool as getDirectChatByContactTool } from './getDirectChatByContact';
|
||||
export { getContactChats, tool as getContactChatsTool } from './getContactChats';
|
||||
export { getLastInteraction, tool as getLastInteractionTool } from './getLastInteraction';
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'invite_to_group',
|
||||
description: 'Invite users to a group',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
user_ids: { type: 'array', description: 'User IDs to invite' },
|
||||
},
|
||||
required: ['chat_id', 'user_ids'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function inviteToGroup(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('invite_to_group');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'join_chat_by_link',
|
||||
description: 'Join chat via invite link',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { invite_link: { type: 'string', description: 'Invite link URL' } },
|
||||
required: ['invite_link'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function joinChatByLink(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('join_chat_by_link');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'leave_chat',
|
||||
description: 'Leave a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function leaveChat(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('leave_chat');
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* List Chats tool - List available chats with metadata
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatEntity, getChats as getChatsApi } from '../telegramApi';
|
||||
import { toHumanReadableAction } from '../toolActionParser';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'list_chats',
|
||||
description: 'List available chats with metadata',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_type: {
|
||||
type: 'string',
|
||||
enum: ['user', 'group', 'channel'],
|
||||
description: "Filter by chat type ('user', 'group', 'channel', or omit for all)",
|
||||
},
|
||||
limit: { type: 'number', description: 'Maximum number of chats to retrieve', default: 20 },
|
||||
},
|
||||
},
|
||||
toHumanReadableAction: (args) => toHumanReadableAction('list_chats', args),
|
||||
};
|
||||
|
||||
export async function listChats(
|
||||
args: { chat_type?: string; limit?: number },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const limit = args.limit ?? 20;
|
||||
const chatType = args.chat_type?.toLowerCase();
|
||||
|
||||
const chats = await getChatsApi(limit);
|
||||
const contentItems: Array<{ type: 'text'; text: string }> = [];
|
||||
|
||||
for (const chat of chats) {
|
||||
const entity = formatEntity(chat);
|
||||
if (chatType && entity.type !== chatType) continue;
|
||||
|
||||
let chatInfo = `Chat ID: ${entity.id}, Title: ${entity.name}, Type: ${entity.type}`;
|
||||
if (entity.username) chatInfo += `, Username: @${entity.username}`;
|
||||
chatInfo +=
|
||||
'unreadCount' in chat && chat.unreadCount
|
||||
? `, Unread: ${chat.unreadCount}`
|
||||
: ', No unread messages';
|
||||
|
||||
contentItems.push({ type: 'text', text: chatInfo });
|
||||
}
|
||||
|
||||
if (contentItems.length === 0) {
|
||||
return { content: [{ type: 'text', text: 'No chats found matching the criteria.' }] };
|
||||
}
|
||||
|
||||
return { content: contentItems };
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'list_chats',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.CHAT,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'list_contacts',
|
||||
description: 'List all contacts in your Telegram account',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function listContacts(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('list_contacts');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'list_inline_buttons',
|
||||
description: 'List inline buttons on a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function listInlineButtons(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('list_inline_buttons');
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* List Messages tool - Retrieve messages with optional filters
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatMessage, getChatById, getMessages as getMessagesApi } from '../telegramApi';
|
||||
import { validateId } from '../../validation';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'list_messages',
|
||||
description: 'Retrieve messages with optional filters',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'The ID or username of the chat to get messages from' },
|
||||
limit: { type: 'number', description: 'Maximum number of messages to retrieve', default: 20 },
|
||||
search_query: { type: 'string', description: 'Filter messages containing this text' },
|
||||
from_date: { type: 'string', description: 'Filter messages from this date (YYYY-MM-DD)' },
|
||||
to_date: { type: 'string', description: 'Filter messages until this date (YYYY-MM-DD)' },
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function listMessages(
|
||||
args: {
|
||||
chat_id: string | number;
|
||||
limit?: number;
|
||||
search_query?: string;
|
||||
from_date?: string;
|
||||
to_date?: string;
|
||||
},
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chatId = validateId(args.chat_id, 'chat_id');
|
||||
const limit = args.limit ?? 20;
|
||||
|
||||
const chat = getChatById(chatId);
|
||||
if (!chat) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Chat not found: ${chatId}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
let messages = await getMessagesApi(chatId, limit * 2, 0);
|
||||
if (!messages || messages.length === 0) {
|
||||
return { content: [{ type: 'text', text: 'No messages found matching the criteria.' }] };
|
||||
}
|
||||
|
||||
if (args.search_query) {
|
||||
const q = args.search_query.toLowerCase();
|
||||
messages = messages.filter((m) => (m.message ?? '').toLowerCase().includes(q));
|
||||
}
|
||||
|
||||
if (args.from_date || args.to_date) {
|
||||
messages = messages.filter((m) => {
|
||||
const d = new Date(m.date * 1000);
|
||||
if (args.from_date && d < new Date(args.from_date)) return false;
|
||||
if (args.to_date) {
|
||||
const to = new Date(args.to_date);
|
||||
to.setHours(23, 59, 59, 999);
|
||||
if (d > to) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
const sliced = messages.slice(0, limit);
|
||||
const contentItems = sliced.map((msg) => {
|
||||
const formatted = formatMessage(msg);
|
||||
const from = msg.fromName ?? msg.fromId ?? 'Unknown';
|
||||
const replyStr = msg.replyToMessageId ? ` | reply to ${msg.replyToMessageId}` : '';
|
||||
const text = `ID: ${formatted.id} | ${from} | Date: ${formatted.date}${replyStr} | Message: ${formatted.text || '[Media/No text]'}`;
|
||||
return { type: 'text' as const, text };
|
||||
});
|
||||
|
||||
return { content: contentItems };
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'list_messages',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.MSG,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'list_topics',
|
||||
description: 'List topics in a forum chat',
|
||||
inputSchema: { type: 'object', properties: { chat_id: { type: 'string', description: 'Chat ID or username' } }, required: ['chat_id'] },
|
||||
};
|
||||
|
||||
export async function listTopics(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('list_topics');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'mark_as_read',
|
||||
description: 'Mark messages as read in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function markAsRead(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('mark_as_read');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'mute_chat',
|
||||
description: 'Mute a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
mute_for: { type: 'number', description: 'Mute duration in seconds' },
|
||||
},
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function muteChat(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('mute_chat');
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { MCPToolResult } from '../../types';
|
||||
|
||||
export function notImplemented(name: string): MCPToolResult {
|
||||
return {
|
||||
content: [{ type: 'text', text: `${name} is not implemented yet.` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'pin_message',
|
||||
description: 'Pin a message in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function pinMessage(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('pin_message');
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'press_inline_button',
|
||||
description: 'Press an inline button on a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
button_text: { type: 'string', description: 'Button text or data' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function pressInlineButton(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('press_inline_button');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'promote_admin',
|
||||
description: 'Promote user to admin',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
user_id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
required: ['chat_id', 'user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function promoteAdmin(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('promote_admin');
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'remove_reaction',
|
||||
description: 'Remove a reaction from a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
reaction: { type: 'string', description: 'Reaction to remove' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function removeReaction(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('remove_reaction');
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Reply To Message tool - Reply to a specific message in a chat
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from "../../types";
|
||||
import type { TelegramMCPContext } from "../types";
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from "../../errorHandler";
|
||||
import { getChatById, sendMessage } from "../telegramApi";
|
||||
import { toHumanReadableAction } from "../toolActionParser";
|
||||
import { validateId } from "../../validation";
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: "reply_to_message",
|
||||
description: "Reply to a specific message in a chat",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
chat_id: {
|
||||
type: "string",
|
||||
description: "The ID or username of the chat",
|
||||
},
|
||||
message_id: { type: "number", description: "The message ID to reply to" },
|
||||
text: { type: "string", description: "The reply message text" },
|
||||
},
|
||||
required: ["chat_id", "message_id", "text"],
|
||||
},
|
||||
toHumanReadableAction: (args) =>
|
||||
toHumanReadableAction("reply_to_message", args),
|
||||
};
|
||||
|
||||
export async function replyToMessage(
|
||||
args: { chat_id: string | number; message_id: number; text: string },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chatId = validateId(args.chat_id, "chat_id");
|
||||
const { message_id, text } = args;
|
||||
|
||||
const chat = getChatById(chatId);
|
||||
if (!chat) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Chat not found: ${chatId}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
const result = await sendMessage(chatId, text, message_id);
|
||||
if (!result) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Failed to reply to message ${message_id} in chat ${chatId}.`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Replied to message ${message_id} in chat ${chatId}.`,
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
"reply_to_message",
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.MSG,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Resolve Username tool - Resolve a username to a user or chat ID
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatEntity, getChatById } from '../telegramApi';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'resolve_username',
|
||||
description: 'Resolve a username to a user or chat ID',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
username: { type: 'string', description: 'Username to resolve (without @)' },
|
||||
},
|
||||
required: ['username'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function resolveUsername(
|
||||
args: { username: string },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const raw = args.username;
|
||||
const username = raw.startsWith('@') ? raw : `@${raw}`;
|
||||
const chat = getChatById(username);
|
||||
if (!chat) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Username ${username} not found` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
const entity = formatEntity(chat);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: JSON.stringify({ id: entity.id, name: entity.name, type: entity.type, username: entity.username }, undefined, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'resolve_username',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.SEARCH,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'save_draft',
|
||||
description: 'Save a draft in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
text: { type: 'string', description: 'Draft text' },
|
||||
},
|
||||
required: ['chat_id', 'text'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function saveDraft(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('save_draft');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'search_contacts',
|
||||
description: 'Search contacts by name or phone',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { query: { type: 'string', description: 'Search query' } },
|
||||
required: ['query'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function searchContacts(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('search_contacts');
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Search Messages tool - Search for messages in a chat by text
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatMessage, getChatById, getMessages } from '../telegramApi';
|
||||
import { validateId } from '../../validation';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'search_messages',
|
||||
description: 'Search for messages in a chat by text',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'The chat ID or username' },
|
||||
query: { type: 'string', description: 'Search query' },
|
||||
limit: { type: 'number', description: 'Maximum number of messages to return', default: 20 },
|
||||
},
|
||||
required: ['chat_id', 'query'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function searchMessages(
|
||||
args: { chat_id: string | number; query: string; limit?: number },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chatId = validateId(args.chat_id, 'chat_id');
|
||||
const { query, limit = 20 } = args;
|
||||
|
||||
const chat = getChatById(chatId);
|
||||
if (!chat) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Chat ${chatId} not found` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
const messages = await getMessages(chatId, Math.min(limit * 3, 100), 0);
|
||||
if (!messages || messages.length === 0) {
|
||||
return { content: [{ type: 'text', text: 'No messages found.' }] };
|
||||
}
|
||||
|
||||
const q = query.toLowerCase();
|
||||
const filtered = messages.filter((m) => (m.message ?? '').toLowerCase().includes(q)).slice(0, limit);
|
||||
|
||||
const lines = filtered.map((m) => {
|
||||
const f = formatMessage(m);
|
||||
return `ID: ${f.id} | ${m.fromName ?? m.fromId ?? 'Unknown'} | ${f.date} | ${f.text || '[Media]'}`;
|
||||
});
|
||||
|
||||
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'search_messages',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.SEARCH,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Search Public Chats tool - Search for public chats, channels, or bots
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { formatEntity, searchChats } from '../telegramApi';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'search_public_chats',
|
||||
description: 'Search for public chats, channels, or bots by username or title',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: { type: 'string', description: 'Search query' },
|
||||
},
|
||||
required: ['query'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function searchPublicChats(
|
||||
args: { query: string },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chats = await searchChats(args.query);
|
||||
const results = chats.map(formatEntity);
|
||||
return {
|
||||
content: [{ type: 'text', text: JSON.stringify(results, undefined, 2) }],
|
||||
};
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'search_public_chats',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.SEARCH,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Send Message tool - Send a message to a specific chat
|
||||
*/
|
||||
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
|
||||
import { ErrorCategory, logAndFormatError } from '../../errorHandler';
|
||||
import { sendMessage as sendMessageApi } from '../telegramApi';
|
||||
import { toHumanReadableAction } from '../toolActionParser';
|
||||
import { validateId } from '../../validation';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'send_message',
|
||||
description: 'Send a message to a specific chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'The ID or username of the chat' },
|
||||
message: { type: 'string', description: 'The message content to send' },
|
||||
},
|
||||
required: ['chat_id', 'message'],
|
||||
},
|
||||
toHumanReadableAction: (args) => toHumanReadableAction('send_message', args),
|
||||
};
|
||||
|
||||
export async function sendMessage(
|
||||
args: { chat_id: string | number; message: string },
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
try {
|
||||
const chatId = validateId(args.chat_id, 'chat_id');
|
||||
const { message } = args;
|
||||
if (!message || typeof message !== 'string') {
|
||||
return {
|
||||
content: [{ type: 'text', text: 'Message content is required' }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
const result = await sendMessageApi(chatId, message);
|
||||
if (!result) {
|
||||
return {
|
||||
content: [{ type: 'text', text: `Failed to send message to chat ${chatId}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
return { content: [{ type: 'text', text: 'Message sent successfully.' }] };
|
||||
} catch (error) {
|
||||
return logAndFormatError(
|
||||
'send_message',
|
||||
error instanceof Error ? error : new Error(String(error)),
|
||||
ErrorCategory.MSG,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'send_reaction',
|
||||
description: 'Send a reaction to a message',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
reaction: { type: 'string', description: 'Reaction emoji' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function sendReaction(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('send_reaction');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'set_bot_commands',
|
||||
description: 'Set bot commands',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
commands: { type: 'array', description: 'List of commands' },
|
||||
},
|
||||
required: ['commands'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function setBotCommands(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('set_bot_commands');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'set_privacy_settings',
|
||||
description: 'Set privacy settings',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
setting: { type: 'string', description: 'Setting name' },
|
||||
value: { type: 'string', description: 'Value' },
|
||||
},
|
||||
required: ['setting', 'value'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function setPrivacySettings(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('set_privacy_settings');
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'set_profile_photo',
|
||||
description: 'Set profile photo',
|
||||
inputSchema: { type: 'object', properties: {} },
|
||||
};
|
||||
|
||||
export async function setProfilePhoto(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('set_profile_photo');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'subscribe_public_channel',
|
||||
description: 'Subscribe to public channel by username',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { username: { type: 'string', description: 'Channel username' } },
|
||||
required: ['username'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function subscribePublicChannel(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('subscribe_public_channel');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'unarchive_chat',
|
||||
description: 'Unarchive a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function unarchiveChat(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('unarchive_chat');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'unban_user',
|
||||
description: 'Unban user from chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
user_id: { type: 'string', description: 'User ID' },
|
||||
},
|
||||
required: ['chat_id', 'user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function unbanUser(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('unban_user');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'unblock_user',
|
||||
description: 'Unblock a user',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { user_id: { type: 'string', description: 'User ID' } },
|
||||
required: ['user_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function unblockUser(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('unblock_user');
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'unmute_chat',
|
||||
description: 'Unmute a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: { chat_id: { type: 'string', description: 'Chat ID or username' } },
|
||||
required: ['chat_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function unmuteChat(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('unmute_chat');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'unpin_message',
|
||||
description: 'Unpin a message in a chat',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chat_id: { type: 'string', description: 'Chat ID or username' },
|
||||
message_id: { type: 'number', description: 'Message ID' },
|
||||
},
|
||||
required: ['chat_id', 'message_id'],
|
||||
},
|
||||
};
|
||||
|
||||
export async function unpinMessage(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('unpin_message');
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { MCPTool, MCPToolResult } from '../../types';
|
||||
import type { TelegramMCPContext } from '../types';
|
||||
import { notImplemented } from './notImplemented';
|
||||
|
||||
export const tool: MCPTool = {
|
||||
name: 'update_profile',
|
||||
description: 'Update your profile',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
first_name: { type: 'string', description: 'First name' },
|
||||
last_name: { type: 'string', description: 'Last name' },
|
||||
bio: { type: 'string', description: 'Bio' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export async function updateProfile(
|
||||
_args: Record<string, unknown>,
|
||||
_context: TelegramMCPContext,
|
||||
): Promise<MCPToolResult> {
|
||||
return notImplemented('update_profile');
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Telegram MCP server types
|
||||
*/
|
||||
|
||||
import type { SocketIOMCPTransportImpl } from '../transport';
|
||||
import type { MCPToolResult } from '../../mcp/types';
|
||||
import type { TelegramState } from '../../../store/telegram/types';
|
||||
|
||||
export interface TelegramMCPContext {
|
||||
telegramState: TelegramState;
|
||||
transport: SocketIOMCPTransportImpl;
|
||||
}
|
||||
|
||||
export type TelegramMCPToolHandler = (
|
||||
args: Record<string, unknown>,
|
||||
context: TelegramMCPContext,
|
||||
) => Promise<MCPToolResult>;
|
||||
Reference in New Issue
Block a user