mcp server
readeck-toolkit
Telegram bot (multi-tenant) and MCP server for Readeck. One Go module, two binaries, one Docker image.
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 21, 2026readeck_toolkit
A Telegram bot and an MCP server for Readeck, in one Go module.
- Telegram bot — multi-tenant. Forward a URL to the bot, it saves to Readeck under the right user. Append
#tagsto set labels. - MCP server — credential-less. Exposes Readeck as tools (
readeck_save,readeck_search,readeck_find_by_url,readeck_list_recent) to any MCP client (Claude Desktop, Claude Code, Cursor, etc.). Each client passes its own Readeck token over the wire — the server stores no secrets.
readeck_search searches bookmark text. Use readeck_find_by_url to look up a saved URL exactly, including its path and query string. The URL lookup ignores fragments, host casing, and default ports.
Both share one Go module and one Docker image. The included docker-compose.yml defines both services — start whichever you need:
docker compose up -d # both
docker compose up -d mcp # only MCP server
docker compose up -d bot # only Telegram bot
docker compose stop bot # turn one off later
Each service ignores config sections it doesn't use, so you can have an MCP-only deploy without filling in [telegram] / [[tenants]], and vice versa.
Why multi-tenant on the bot?
Readeck's REST API authenticates each call with a per-user API token. The bot keeps a map of telegram_id → readeck_token in config.toml and uses the right token per incoming message. Unknown Telegram senders are silently ignored. This lets one bot instance serve a household, a team, or a friend group without anyone seeing anyone else's data.
The MCP server doesn't multi-tenant because an MCP client is, by definition, one user. Run one MCP instance per user if you need to.
Quick start
Bot
- Create a bot with @BotFather, grab the token.
cp config.example.toml config.toml, paste the bot token, setbase_url.- Add yourself to
[[tenants]]:- in Readeck → Settings → API tokens → create a token, paste as
readeck_token - run the bot once and DM it
/whoamito get yourtelegram_id
- in Readeck → Settings → API tokens → create a token, paste as
docker compose up -d bot
Adding more users later
Repeat for each new user:
- The user logs into Readeck and creates their own API token (Settings → API tokens).
- They start the bot and send
/whoami— the bot replies with their numeric Telegram id (works for non-tenants too — that's the onboarding hook). - Admin appends a new
[[tenants]]block toconfig.tomlwith the two values, thendocker compose restart bot.
Unknown senders are silently ignored, so the bot is safe to leave running while users onboard themselves.
MCP
The MCP server only needs to know the base URL of your Readeck instance. Tokens are not stored on the server — they're passed by each MCP client when connecting.
If you're already running the bot, MCP reads [readeck].base_url from the same config.toml. Otherwise set READECK_BASE_URL env.
docker compose up -d mcp
Then in your MCP client config (Claude Code / Claude Desktop / Cursor / etc.):
{
"mcpServers": {
"readeck": {
"type": "http",
"url": "https://your-mcp-host/mcp",
"headers": {
"X-API-Key": "rk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
The token is generated in Readeck → Settings → API tokens. Each user of the MCP server uses their own token; the server hands the call straight to Readeck which scopes it to that user.
Authorization: Bearer <token> is also accepted as a fallback for MCP clients that only know how to send that header.
Configuration
- Bot:
config.toml. Env overrides:TELEGRAM_TOKEN,READECK_BASE_URL. - MCP: just needs
READECK_BASE_URL(env or[readeck].base_urlin TOML). Optional:MCP_HTTP_ADDRto change the bind address from:8080.
Build from source
go build ./cmd/bot ./cmd/mcp
License
MIT.