It started as a very domestic problem: I wanted to ask ChatGPT what a particular person had written to me on Telegram, and get an answer.
Not copy the conversation by hand.
Not export the messages.
Not open a second client next to it.
Just type:
What was the last thing Lena wrote to me on Telegram?
And have the model actually go into my Telegram and look.
Turns out there is still a fairly large technical gap between those two actions.
That’s how telegram-business-mcp came about.
I didn’t want a Telegram bot
Telegram integrates with bots very well.
But a bot is a separate interlocutor.
I wanted something else.
I already have ChatGPT. I have Claude. That’s where the model lives, along with the context of the current conversation, the tools and everything else.
I didn’t want to move the AI into Telegram.
I wanted the opposite:
bring Telegram into the interface where I already talk to the AI.
So that I could ask:
— what did Pasha and I talk about a week ago;
— find the message where we discussed monitoring;
— show me the latest messages from Lena;
— what was sent to me yesterday;
— reply to this person with this text.
All of it straight from ChatGPT Web or Claude Web.
At some point that distinction started to feel important.
This isn’t one more AI bot inside a messenger.
The messenger itself becomes a data source and a tool for the model.
The obvious route didn’t appeal to me
To work with a personal Telegram account you’d normally reach for MTProto and authorise as a user.
Technically that’s the powerful option. You get the account’s history and work almost like a full client.
But it comes with a user session.
And that’s where the design stopped making me happy.
A session file is effectively access to the account. If it ends up somewhere it shouldn’t, the problem is no longer confined to some local message archive.
So I looked the other way — at Telegram Business.
Telegram has an official mechanism for connecting a Business bot to a personal account.
The bot receives messages from the connected conversations and can reply on behalf of the account owner.
So instead of:
LLM → MTProto → my Telegram account
you can assemble:
LLM → MCP → Telegram Business Bot API
No user session.
Just a regular bot token, revocable through BotFather.
The trade-off is real too: Telegram doesn’t hand a Business bot any correspondence retroactively.
Connect it today, and the history starts accumulating today.
A year of old messages won’t magically appear.
And I actually like that as an engineering constraint: the system doesn’t pretend to be a full Telegram client where it isn’t one.
Then came the archive
If you simply proxy Telegram’s current updates into the model, you get something fairly useless.
The interesting part begins once messages accumulate.
So SQLite appeared between Telegram and MCP.
The scheme became this:
Telegram → collector → SQLite → MCP → ChatGPT / Claude
The collector keeps picking up new messages and storing them locally.
The MCP server no longer works with Telegram directly, but with that archive.
Several useful things fell out of this at once.
You can get the latest messages.
You can open a specific conversation.
You can search the whole accumulated history.
You can even search voice transcripts, if local transcription is switched on.
And most importantly — the history lives on my own server and grows by itself.
I connected Telegram once and after that mostly stopped thinking about how the data gets there.
The client side turned out to be a single link
This is probably my favourite part of the whole thing.
Nothing needs to be installed on the machine running ChatGPT.
No browser extension.
No local proxy.
No separate stdio process sitting next to the browser.
MCP works remotely over HTTPS.
So on the client side the entire integration comes down to roughly one URL.
In ChatGPT Web you add a remote MCP.
In Claude Web — the same server as a custom connector.
After that two completely different AI interfaces get an identical set of Telegram tools.
That’s when I realised I was no longer building an integration between “Telegram and ChatGPT”.
ChatGPT stopped being a required part of the architecture at all.
What came out was:
any MCP client → one interface → my Telegram
Today that’s ChatGPT and Claude.
Tomorrow it could be some other client that speaks MCP.
The model got more than memory
I built reading first.
That’s the safe, comprehensible part.
The model can do:
telegram_list_chats
telegram_recent_messages
telegram_get_messages
telegram_search_messages
telegram_find_chat
You can say:
“Find Pasha’s latest messages.”
And get actual messages.
You can ask:
“What did we discuss about n8n monitoring?”
And the model searches the archive itself.
But then an entirely logical next question came up.
If the model already understands who I want to reply to and what the conversation is about, why should I then open Telegram and send the message by hand?
That’s how telegram_send_message appeared.
And here the system shifted meaning slightly.
I can sit in ChatGPT, discuss the correspondence with the model, work out a reply and — after confirmation — send it from the same place.
The recipient sees a message from me.
Not from a separate Telegram bot.
So the chain now looks roughly like this:
person → Telegram → archive → LLM → decision → Telegram → person
The AI didn’t end up next to the messenger.
It ended up on top of it.
I deliberately turned writing off by default
Reading the archive and sending a message are two completely different levels of risk.
So a fresh install runs read-only.
Sending has to be enabled separately.
There are a few more constraints.
You can’t invent a random chat_id and make the server write to a stranger. Sending is allowed only into conversations that already exist in the archive.
Every sent message is logged and comes back into the archive.
The MCP tool itself is marked as state-changing.
But the main safeguard is still the model’s: before sending, it has to confirm the recipient and the text.
That’s not a perfect hard gate.
If I ever want a stricter mode, the obvious architecture here is two-phase:
prepare_send → confirm_send
For now I’ve deliberately not done it.
I wanted a tool that replies for me after confirmation, not a separate message approval system.
The strangest part happened after it all worked
For several days I thought I was writing a Telegram connector.
Then I started using it.
And the wording stopped adding up.
Because Telegram in this system is no longer the interface.
ChatGPT became the interface.
Or Claude.
Telegram remained the transport, the history of the correspondence and the place where other people are.
It used to go roughly like this:
remember → open Telegram → find the chat → find the message → read → think → write
Now it sometimes goes:
ask
The whole middle is done by tools.
The most telling moment was completely idiotic.
I asked ChatGPT what a person had written to me.
It found the conversation.
We worked out a reply.
I said send it.
The message appeared in Telegram.
No special magic happened on screen.
And that’s exactly why the effect was strange.
The line between “talking to a model about my life” and “letting a model look into a real system” suddenly got very thin.
MCP mattered more here than the specific model
I could have written a separate integration for ChatGPT.
Then a separate one for Claude.
Then one more for the next interface.
But then Telegram would be integrated with products.
MCP lets you integrate it with a class of products.
One server describes the tools.
The client decides how to use them.
That’s why the same backend now works from ChatGPT Web and Claude Web.
And that’s probably the main conclusion of the whole experiment.
I’m less and less interested in writing “an AI feature for product X”.
It’s far more interesting to make a data source or an action available to models through a common protocol — and then see what interfaces show up around it.
What isn’t ideal here
There’s no history from before the connection.
If the collector is down for a long time, Telegram won’t hold the updates forever either.
So the sane setup is a server that runs continuously.
Remote MCP requires a reachable HTTPS endpoint.
With sending enabled, the MCP secret becomes far more valuable than in read-only mode.
SQLite is a fine choice for a personal archive, but I wouldn’t automatically turn this architecture into a corporate multi-tenant product.
And the Telegram Business API imposes its own limits anyway.
This isn’t a new Telegram client.
It’s a specific bridge with specific boundaries.
But that very narrowness is what let me build a system simple enough to actually use myself.
I put it all in open source
Usually things like this stay alive somewhere on a server in a state of:
“it works — don’t touch it”.
This time I decided otherwise.
I brought the project into a state where it can be stood up separately, wrote a README, SETUP, Docker configuration, systemd units, environment variables, and published the code.
The repository is called:
OlegNickeshin/telegram-business-mcp
Licence — Apache 2.0.
You can run it on your own server.
And I think that’s a small change for me too.
For a long time I built integrations as finished solutions for a specific task.
Here it came out as a piece of infrastructure rather than a finished system.
It doesn’t do anything particularly interesting by itself.
It just gives the AI access to a place it previously couldn’t comfortably reach.
And then the interesting part starts above it.
I think I finally understand what I built
Not a Telegram bot.
Not a message archive.
Not a plugin for ChatGPT.
And not quite an MCP server either.
More like a thin layer between my communication and the models.
Telegram underneath.
Any AI that speaks MCP on top.
A few rather boring tools in between: find, read, look at a photo, send a message.
But sometimes it’s precisely the boring tools that change the interface most.
Because after them you can write to the model:
“See what was there, and reply.”
And not go anywhere else.