loreroom
This server gives a Claude Code Telegram bot persistent, searchable memory of past conversations (both inbound and outbound), enabling recall across sessions.
get_recent_context: Retrieve all Telegram messages from the last N hours, including timestamp, sender, role, chat ID, and content — useful for restoring context when a user references something recent ("today", "just now", etc.).search_tg_history: Full-text search across all stored Telegram history by keyword (using FTS5 trigram indexing with a LIKE fallback for short keywords) — ideal for recalling past decisions, discussions, or specific mentions (e.g., "last time we talked about the API key").
Both tools support an optional chat_id parameter to scope results to a specific conversation, and both return structured results with timestamp, sender, role, chat ID, and message text.
Captures both inbound and outbound Telegram messages from a Claude Code bot into an encrypted, searchable database.
中文版 → README.zh-TW.md
A private, encrypted room that remembers every conversation with your Claude Code Telegram bot — both sides — so it never forgets.
You chat with Claude Code from your phone through the official Telegram plugin. But every Claude Code session is amnesiac: restart it and the whole conversation is gone. LoreRoom captures both sides of that Telegram conversation into a single, whole-file-encrypted SQLite database and hands it back to Claude as searchable memory.
So you can ask your bot:
You: what did I ask you to do last night? Bot: (searches LoreRoom) You asked me to fix the crawler retry logic and send you the diff…
Local-first. No cloud, no extra API keys, it never touches your bot token.
Why LoreRoom exists (and why it's reliable)
The Claude Code Telegram plugin delivers your incoming messages to Claude through an internal channel push — not through any hook. Worse, when Claude is busy those messages queue invisibly, and if the bot never replies they're simply gone. So the obvious approaches (hooks, reading the transcript) silently lose your messages.
LoreRoom captures at the plugin's source, the instant a message arrives from Telegram:
Inbound — the moment Telegram delivers it, before any queue, regardless of whether Claude is busy, crashed, or never replies.
Outbound — whenever the bot sends a reply.
Both are written to a small spool file that an ingester drains into the encrypted database. Nothing is lost — even when your bot is unresponsive. (Messages that were stuck while the bot was busy get captured the moment it restarts and re-fetches them.)
No Claude Code hooks are used, so LoreRoom never interferes with your other Claude Code work.
You ⇄ Telegram ──(patched plugin)──> spool ──(ingester)──> encrypted SQLite (SQLCipher + FTS5)
captures in + out drained on a timer ▲
│ MCP server
get_recent_context · search_tg_history
│
Claude recalls — both sides, with time & senderRelated MCP server: cc-channel-mem
Before you start — what you need
LoreRoom adds memory to an existing Claude Code Telegram bot. So you first need that bot working. If you can already chat with your bot from Telegram, skip to Install. Otherwise, set this up once (~5 minutes):
1. Node.js 20 or newer. Check with node -v. If missing, get it from nodejs.org.
2. Claude Code — Anthropic's command-line tool. See the install guide.
3. A Telegram bot connected to Claude Code:
In Telegram, open a chat with @BotFather, send
/newbot, follow the prompts, and copy the bot token it gives you (a long string).In Claude Code, install the official Telegram plugin, then configure it with your token:
/telegram:configure <your-bot-token>.Link your account: send your bot any message in Telegram — it replies with a pairing code — then run
/telegram:access pair <code>in Claude Code.Start a bot session:
claude --channels plugin:telegram@claude-plugins-official, then send your bot "hi" in Telegram. It should reply.
Once "hi" gets a reply, your bot works. Now give it memory with LoreRoom 👇
Scope: LoreRoom only works with Claude Code + the official Telegram plugin (it is not a general Telegram bot framework). It captures by patching the plugin — one idempotent command you re-run after plugin updates. See Why patch the plugin.
Install
git clone https://github.com/fenghaochang/LoreRoom.git && cd LoreRoom
npm install
npm run build
node dist/cli.js init # creates config.json + a fresh encryption key, prints the next steps
node dist/patch-plugin.js # patches the Telegram plugin to capture in + out
# register the recall server (it also auto-drains the spool):
claude mcp add --scope user loreroom -- "$(command -v node)" "$PWD/dist/mcp-server.js"Then restart your bot session (claude --channels …) so it loads the patched plugin. Done — every Telegram message is now captured automatically.
Node version note: the encrypted-SQLite native module is ABI-bound to one Node version, and
initpins the exactnodethat ran it. If you later upgrade or remove that Node, re-runnpm install && npm run buildand re-register.
Verify
Send your bot a message on Telegram.
Ask Claude (in any session) to call
get_recent_contextwithhours: 1— you'll see your message with the correct time and sender, even if the bot never replied.Ask it to
search_tg_historyfor a keyword from that message — it comes back.
How you use it day to day
Nothing to do — that's the point. Once it's set up, just chat with your bot normally. Every message, both yours and the bot's, is saved automatically.
When you want it to remember something, just ask in plain language:
"what did we decide about the database yesterday?" "what did I send you last night?" "find where I mentioned the API key"
The bot searches its own memory and answers. You never run a command — it calls the search tools for you behind the scenes.
Two things to keep in mind:
Keep a bot session running (
claude --channels …). If it stops, restart it — messages that arrived while it was down are captured when it comes back.After you update the Telegram plugin, re-run
node dist/patch-plugin.jsonce to re-apply the patch (it's a no-op if already patched).
Why patch the plugin
There is no hook and no on-disk record for inbound Telegram messages, so the only reliable capture point is inside the plugin itself. The patch is tiny — a helper plus two one-line calls at the plugin's inbound and outbound choke points — and idempotent (running it twice is a no-op). Plugin updates overwrite it, so re-run node dist/patch-plugin.js after an update.
Self-contained
Everything LoreRoom owns lives inside this project folder:
config.json— your settings + encryption key (git-ignored,chmod 600, created byinit)data/memory.sqlite— the encrypted database (git-ignored)
The spool is a short-lived plaintext file in the plugin's own ~/.claude/channels/telegram/ state dir (mode 0700), drained continuously and deleted.
Configuration (config.json)
Key | Meaning |
| DB location. Relative paths resolve inside the project (default |
| 64-char hex (32 bytes). |
| Spool the plugin writes (default |
| Optional filters. Default |
Draining the spool
The MCP server drains on startup, every 20s, and before each query — so whenever any Claude Code session is open, capture flows into the DB automatically. For draining independent of sessions:
node dist/cli.js ingest # drain once
node dist/cli.js watch # drain continuously (good for launchd/cron)MCP tools Claude can call
get_recent_context({ hours, chat_id? })— messages from the last N hours.search_tg_history({ keyword, chat_id? })— full-text search across all history (FTS5 trigram, works for CJK; LIKE fallback for short keywords).
Both return each hit with timestamp, sender, role, chat id, and text.
Security & encryption boundary
LoreRoom never handles your Telegram bot token — that belongs to the plugin. There is no token to leak here.
The only secret is the 32-byte encryption key in
config.json(git-ignored,chmod 600) — never committed, never logged.The database is encrypted as a whole file (SQLCipher / AES-256). Copying
data/memory.sqliteto another machine is useless without the key.This is at-rest encryption of the local DB — NOT Telegram end-to-end encryption. It changes nothing about Telegram itself. Decryption happens only locally, in LoreRoom's own processes; the key is never given to Claude and never crosses a network.
Protects against: the DB file being copied off the machine / a backup leak. Does not protect against: someone who can already read your account's files on this machine (the key sits next to the DB by design). The spool is briefly plaintext until drained.
Limitations
Requires patching the official Telegram plugin (re-apply after plugin updates via
patch-plugin).Keyword + time recall only — no semantic / vector RAG yet (a future
sqlite-veclayer could add it without breaking the single-file design).Messages sent to Telegram by a separate script (not through the plugin's reply path) aren't captured.
Tested on macOS with Node 26 and the plugin running under bun; other setups may need tweaks.
License
MIT
Available Tools
2 toolsget_recent_contextA
撈回最近 N 小時的 Telegram 對話(含時間、發出方、內容;雙向都有)。當你缺乏上下文、或使用者提到『剛剛/今天/昨天/最近』時,務必優先呼叫本工具還原脈絡。
| Name | Required | Description | Default |
|---|---|---|---|
| hours | Yes | 往回幾小時 | |
| chat_id | No | 限定某對話 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided. Description discloses what is returned (time, sender, content, both directions) but not limits, pagination, or side effects. Adequate for a read tool but incomplete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: one defines function, one gives usage guidance. Zero waste, front-loaded with purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema; description partially explains return format (time, sender, content) but lacks structure details or limits. For a retrieval tool, more completeness would be beneficial.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions already cover both parameters (hours, chat_id) with 100% coverage. Description adds context on when to use them but no additional syntax or meaning beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the verb (retrieve), resource (Telegram conversations), and scope (last N hours, bidirectional). It distinguishes from sibling by implying this tool is for broad context retrieval when lacking context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use: 'when you lack context, or the user mentions just now/today/yesterday/recently'. Does not explicitly state when not to use, but presence of sibling suggests alternative for specific searches.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_tg_historyA
用關鍵字全文搜尋過去所有 Telegram 對話(雙向、含時間、發出方)。當使用者提到『之前/上次/我們討論過』等過去事件,務必優先呼叫本工具,而不要直接說不記得。
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | 搜尋關鍵字 | |
| chat_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided. Description implies read-only search behavior and includes scope (past conversations, bidirectional, with time and sender). Does not explicitly state non-destructive nature or rate limits, but adequate for a search tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, no fluff. First sentence defines action and scope, second provides clear usage directive. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given low complexity (2 params, no output schema, no annotations), description covers core purpose, usage, and behavioral context. Missing details on return format or chat_id usage, but not critical for typical search tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (keyword described, chat_id not). Description adds no information about chat_id parameter beyond schema. Only keyword is implied by context. Insufficient compensation for missing schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states full-text search of all past Telegram conversations with direction, time, and sender. Explicitly prioritizes this tool over not remembering, distinguishing it from siblings like get_recent_context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to use when users mention past events like '之前/上次/我們討論過', and not to default to saying '不記得'. Provides clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
2 tool updates
v1.0.0- First observed
get_recent_context - First observed
search_tg_history
TDQS
The two tools have clearly distinct purposes: one retrieves recent context by time, the other searches history by keywords. There is no overlap.
Both tools use consistent snake_case naming with a verb_noun pattern (get_recent_context, search_tg_history), making them predictable.
With only 2 tools, the server feels thin for its intended purpose of Telegram history retrieval, but it is borderline as it covers two essential retrieval methods.
The tool set covers time-based and keyword-based retrieval, but lacks other potentially useful operations like retrieving by user or date range, leaving notable gaps.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Private persistent memory for Claude, ChatGPT & Gemini via MCP - semantic search, zero-code setup.
- mcpOAuthai.butlerbrain
Persistent memory for AI assistants. Save once; recall from Claude, ChatGPT, or any MCP client.
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Persistent AI memory shared across Claude, ChatGPT, coding agents, and compatible MCP clients.
Related MCP Servers
- AlicenseAqualityBmaintenancePersistent memory for Claude Code. Automatically indexes every conversation and provides production-grade hybrid search (BM25 + vectors + reranker) via MCP tools. 100% local, zero config, zero API keys, zero invoice.16577MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server and background daemon that captures Discord and Telegram conversations locally to provide persistent memory for Claude Code sessions. It enables hybrid search and automatic context injection of chat history to maintain continuity across development sessions.1222MIT
- AlicenseAqualityAmaintenancePersistent local memory for Claude Code that indexes every session's JSONL file verbatim into SQLite + ChromaDB. Exposes 17 MCP tools for semantic recall, deterministic file replay, and fuzzy "do you remember when..." queries across your entire session history — no API calls, nothing leaves the machine.1713MIT
- AlicenseNot gradedqualityDmaintenanceA lightweight MCP server that gives Claude Code Channels on Telegram persistent memory by storing facts, conversation logs, and session summaries in Supabase.126MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/fenghaochang/LoreRoom'
If you have feedback or need assistance with the MCP directory API, please join our Discord server