Skip to content
Conduit

mcp server

voicelog

Self-hosted Telegram voice journal with local Whisper transcription and Claude analysis via MCP

terraincognita07/voicelogcommunitylistedunreviewed

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 26, 2026

voicelog

Self-hosted Telegram voice journal with Claude analysis via MCP.

CI codecov Release License: MIT Go Version Docker Self-hosted

Send voice messages (or plain text) to your private Telegram bot. Voice is transcribed locally with whisper.cpp and stored in SQLite. Then in any Claude conversation, ask "what was I worrying about last week?" — Claude reads the corpus via an MCP server you self-host.

    you 🎙 voice ──→ | Telegram  |
                     |   bot     | — ffmpeg → whisper.cpp — text  ─┐
                                                                   │
                     | INSERT                                      │
                     └──────────→ | SQLite + FTS5    |  ←──────────┘
                                  | ./data/voicelog.db |
                                       │
                                       ▼
    Claude.ai ← MCP over HTTPS ── nginx ── | voicelog-mcp  |

Features

  • Voice + text capture — speak on the go or type when you can't; both become searchable, taggable, editable notes.
  • Local transcription — whisper.cpp on your own box, nothing leaves it.
  • Query via Claude (MCP) — search, summarize and review your corpus on demand in plain language; 15 MCP tools, with example prompts in docs/MCP.md.
  • Tags — label notes with categories that aren't in the words (#идея, #философия) and pull them back deterministically with notes_by_tag. Claude tags via MCP; you add/remove them by hand from a note's card. Shown 🏷 inline in the bot's lists.
  • Russian-aware search — Cyrillic queries are stemmed (Snowball) so searching работа also finds работе/работу; Latin terms stay exact.
  • Fix what whisper misheard — ✏️ Edit any note right in Telegram: a button menu walks you through replacing one word or rewriting the whole note (previous version archived), or have Claude retranscribe it.
  • Self-improving accuracy — Claude can spot recurring names/jargon across the corpus and add them to the whisper vocabulary via MCP (add_vocab).
  • Button-driven UI — pending queue, day-grouped lists, status filters, per-note cards (edit / tag / delete) — all inline, typed commands are a fallback.
  • Single-user, self-hosted — Telegram allow-list + bearer-token MCP; pure-Go (CGO_ENABLED=0), three small containers.

Why this exists

Most Telegram-whisper bots are stateless: send voice, get text, repeat. Some bundle in LLM summarization. None build a searchable personal corpus and let Claude analyze it on demand.

voicelog takes the opposite posture:

  • The bot has zero LLM logic — it just captures.
  • All reasoning happens externally in Claude, against your corpus, via MCP.

If you don't use Claude (or another MCP client) this isn't for you. If you do, it lets you talk to your past self.

How it differs from similar projects

ProjectPatternPersistenceSelf-hosted
whisper-telegram-mcpMCP-as-tool (Claude triggers transcription)NoYes
antirez/whisperbotTranscribe-and-replyNoYes
Voicenotes.comMCP-as-corpusYes (cloud)No, paid SaaS
voicelogMCP-as-corpusYes, local SQLite + FTS5Yes

Documentation

docs/CONFIG.mdEvery env var, defaults, rotation guidance
docs/USAGE.mdTelegram commands and inline UI
docs/MCP.mdMCP tool reference + Claude.ai web exposure (nginx / Traefik)
docs/SECURITY-MODEL.mdThreat model and what's NOT protected
docs/OPERATIONS.mdBackups, model swap, DB maintenance, debugging
docs/RUN-LOCALLY.mdLocal dev loop, project layout, Makefile targets
docs/ROADMAP.mdWhat's next / mid-term / speculative
ARCHITECTURE.mdInternal layering rules
CONTRIBUTING.mdPR setup and conventions
CHANGELOG.mdWhat shipped per release
SECURITY.mdVulnerability disclosure
CODE_OF_CONDUCT.mdCommunity ground rules

Architecture

Three containers sharing one SQLite file:

ServiceRoleImageRAM
whisperwhisper.cpp server, CPU-only inferenceghcr.io/ggml-org/whisper.cpp:main~800 MB (small model)
botTelegram poller → ffmpeg → whisper HTTP → SQLite INSERTalpine + ffmpeg~30 MB
mcpHTTP server exposing tools to Claude over MCPdistroless static~20 MB

Pure Go (modernc.org/sqlite, CGO_ENABLED=0). No native deps to audit. For full layering rules see ARCHITECTURE.md.

Quick start

Prerequisites

  • Linux server with Docker + Docker Compose v2
  • ~1 GB free RAM (for small-q5_1 model) or ~2 GB (for medium-q5_0)
  • ~2 GB disk: images (~700 MB), model (~190 MB), DB grows slowly
  • A domain with HTTPS — needed only if you want Claude.ai web to reach the MCP. Claude Code (CLI) works over an SSH tunnel without any of that.

1. Telegram setup

Talk to @BotFather in Telegram:

  1. /newbot → name your bot → save the BOT_TOKEN it gives you
  2. /setprivacy → choose your bot → Disable (without this, in group chats the bot only sees commands; for DMs it doesn't matter, but disabling is safer if you ever forward into a group)

Find your numeric user ID by messaging @userinfobot — it replies with your id (e.g. 123456789). The bot will refuse messages from any other user.

2. Clone and configure

git clone https://github.com/terraincognita07/voicelog.git
cd voicelog
cp .env.example .env

Generate a strong MCP token:

openssl rand -hex 32

Open .env and fill in:

BOT_TOKEN=8123456789:AAA...            # from BotFather
ALLOWED_USER_ID=123456789              # from @userinfobot
MCP_TOKEN=<paste output of openssl above>
TZ=Europe/Moscow                       # your timezone
HOST_UID=1000                          # `id -u` on your server
HOST_GID=1000                          # `id -g` on your server

Check your UID/GID — if not 1000, update the file:

id -u && id -g

The full env-var reference (defaults, optional knobs, rotation) is in docs/CONFIG.md.

3. Download the whisper model

chmod +x scripts/*.sh
scripts/fetch-model.sh                # ggml-small-q5_1.bin, ~190 MB

Other options:

scripts/fetch-model.sh ggml-small-q8_0.bin     # +75 MB, marginal quality bump
scripts/fetch-model.sh ggml-medium-q5_0.bin    # 314 MB, needs ~1.7 GB RAM

If you change the model, update the -m flag in docker-compose.yml:

command:
  - "whisper-server --host 0.0.0.0 --port 8080 -m /models/<your-model>.bin -t 4 -l auto"

4. Prepare host directories

The bot and mcp containers write to ./data as your UID/GID:

mkdir -p data
chown -R $(id -u):$(id -g) data

5. Build and run

docker compose build          # ~2–3 min first time
docker compose up -d
docker compose logs -f bot mcp

Version stamping (optional). The mcp container reports a version to Claude in the MCP handshake. Built as above it reports dev. To stamp the real release tag instead, prefix the build with VERSION derived from git (run on a checkout that has the tag):

VERSION=$(git describe --tags --dirty | sed 's/^v//') docker compose up -d --build

Plain docker compose up -d keeps working — dev is just the honest answer for an unstamped build.

Send a voice message to your bot in Telegram. Within a few seconds:

voicelog-bot | {"level":"INFO","msg":"transcribing", ...}

And the bot replies:

✓ Note #1 saved · 0:05 · 1 pending

Verify with /pending in Telegram, or:

docker compose exec bot ls -la /data      # voicelog.db, .db-wal, .db-shm

6. Expose the MCP server to Claude Code

The mcp container binds only to 127.0.0.1:8081. The simplest exposure — and the one with no token-in-URL tradeoff — is an SSH tunnel from your laptop:

ssh -L 8081:127.0.0.1:8081 user@your-server

Or as a permanent entry in ~/.ssh/config:

Host myserver
  HostName your-server
  User user
  LocalForward 8081 127.0.0.1:8081

Then in Claude Code MCP config (~/.claude/mcp.json or via claude mcp add):

{
  "mcpServers": {
    "voicelog": {
      "url": "http://127.0.0.1:8081/mcp",
      "headers": { "Authorization": "Bearer YOUR_MCP_TOKEN" }
    }
  }
}

Done — no public DNS, no TLS, no reverse proxy.

For Claude.ai web (needs a public HTTPS endpoint, nginx / Traefik config + token-in-URL workaround) see docs/MCP.md.

Roadmap

See docs/ROADMAP.md for the candidate list (next / mid-term / speculative / won't-do). Open a discussion before starting work on a roadmap item so we don't overlap.

License

MIT — see LICENSE.

Acknowledgements

↑↓ navigate openesc close