telegram: make MCP config portable across machines
- .mcp.json: switch telegram-* args to relative path (scripts/telegram-mcp.sh) so the committed config no longer pins a single user's home directory - telegram-mcp.sh / regen_telegram_session.sh: drop hardcoded fallbacks for TELEGRAM_MCP_BIN / TELEGRAM_MCP_DIR; require them from .env with explicit error messages naming the missing variable - .env.example: document per-machine path variables and per-account session strings, with a warning not to copy sessions between devices (Telegram revokes the auth key when one session is used from two IPs) - CLAUDE.md: add a Bootstrap-on-a-new-machine section with the setup steps, the portability rationale, and a troubleshooting table for the common MCP / session failure modes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
80c918d282
commit
f4b75ebb7d
20
.env.example
20
.env.example
|
|
@ -1,5 +1,25 @@
|
|||
# Copy this file to .env and fill in the values on each machine.
|
||||
# .env is gitignored — secrets and per-machine paths never leave the device.
|
||||
|
||||
# --- Trello (shared across machines) ---
|
||||
TRELLO_API_KEY=your_trello_api_key_here
|
||||
TRELLO_TOKEN=your_trello_token_here
|
||||
|
||||
# --- Telegram API credentials (shared across machines: one app registration) ---
|
||||
TELEGRAM_API_ID=
|
||||
TELEGRAM_API_HASH=
|
||||
|
||||
# --- Per-machine: absolute paths to the telegram-mcp install on THIS machine ---
|
||||
# TELEGRAM_MCP_DIR — root of the telegram-mcp checkout (used by the session generator)
|
||||
# TELEGRAM_MCP_BIN — the telegram-mcp executable inside that checkout's .venv
|
||||
TELEGRAM_MCP_DIR=/absolute/path/to/telegram
|
||||
TELEGRAM_MCP_BIN=/absolute/path/to/telegram/.venv/bin/telegram-mcp
|
||||
|
||||
# --- Per-machine Telegram session strings ---
|
||||
# DO NOT copy these between machines. Each device/IP must have its own session,
|
||||
# or Telegram will permanently revoke the auth key.
|
||||
# Generate on THIS machine with:
|
||||
# pnpm tg:session:usulsu -> writes TELEGRAM_SESSION_STRING
|
||||
# pnpm tg:session:helper -> writes TELEGRAM_SESSION_STRING_HELPER
|
||||
TELEGRAM_SESSION_STRING=
|
||||
TELEGRAM_SESSION_STRING_HELPER=
|
||||
|
|
|
|||
10
.mcp.json
10
.mcp.json
|
|
@ -18,17 +18,11 @@
|
|||
},
|
||||
"telegram-usulpro": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"/home/usul/workspace/projects/cv-2026/scripts/telegram-mcp.sh",
|
||||
"usulsu"
|
||||
]
|
||||
"args": ["scripts/telegram-mcp.sh", "usulsu"]
|
||||
},
|
||||
"telegram-helper": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"/home/usul/workspace/projects/cv-2026/scripts/telegram-mcp.sh",
|
||||
"helper"
|
||||
]
|
||||
"args": ["scripts/telegram-mcp.sh", "helper"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
51
CLAUDE.md
51
CLAUDE.md
|
|
@ -136,6 +136,57 @@ After a run, triage `telegram_inbox.json` and promote promising postings to [`tr
|
|||
|
||||
---
|
||||
|
||||
## Bootstrap on a new machine
|
||||
|
||||
This project runs on multiple machines (VPS, laptops) with different filesystem paths. The committed config is fully portable; everything machine-specific lives in `.env` and `.secrets/` (both gitignored). When Oleg sets up a new device, or when something Telegram-related breaks ("MCP not connecting", "session revoked", "TELEGRAM_MCP_BIN not set", etc.), walk through this.
|
||||
|
||||
### One-time setup on a fresh checkout
|
||||
|
||||
1. **`.env`** — copy from the template, then fill in:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
Required keys:
|
||||
- `TRELLO_API_KEY`, `TRELLO_TOKEN` — same across machines (copy from another device's `.env`).
|
||||
- `TELEGRAM_API_ID`, `TELEGRAM_API_HASH` — same across machines (one app registration).
|
||||
- `TELEGRAM_MCP_DIR` — **per-machine** absolute path to the `telegram-mcp` checkout on THIS machine.
|
||||
- `TELEGRAM_MCP_BIN` — **per-machine** absolute path to the `telegram-mcp` executable, typically `$TELEGRAM_MCP_DIR/.venv/bin/telegram-mcp`.
|
||||
- `TELEGRAM_SESSION_STRING`, `TELEGRAM_SESSION_STRING_HELPER` — leave empty; generated in step 3.
|
||||
|
||||
2. **Node deps**:
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
3. **Generate Telegram sessions on THIS machine** (one per account):
|
||||
```bash
|
||||
pnpm tg:session:usulsu # QR-login as @usulpro (main)
|
||||
pnpm tg:session:helper # QR-login as @samuishka (helper)
|
||||
```
|
||||
Each command opens a QR code in the terminal. Scan it from the corresponding Telegram account on Oleg's phone. The script writes the session string into `.env` and a copy into `.secrets/session_<account>.txt`.
|
||||
|
||||
**Critical rule — sessions are per-device:** never copy `TELEGRAM_SESSION_STRING*` between machines. A Telegram auth key used from two IPs gets permanently revoked, and **both** devices lose access until re-authorized. Always run the regen script on each new machine.
|
||||
|
||||
4. **Reconnect MCP servers** in Claude Code (`/mcp` → reconnect both `telegram-usulpro` and `telegram-helper`), or restart Claude Code.
|
||||
|
||||
### How paths stay portable
|
||||
|
||||
- `.mcp.json` uses a relative path (`scripts/telegram-mcp.sh`) — Claude Code launches project-scoped MCP servers with the project root as CWD, so this resolves correctly on any machine.
|
||||
- `scripts/telegram-mcp.sh` and `scripts/regen_telegram_session.sh` read `TELEGRAM_MCP_BIN` / `TELEGRAM_MCP_DIR` from `.env`. They fail with an explicit error message if the variable is missing or points at a non-existent path — never guess a default.
|
||||
|
||||
### Troubleshooting cheat sheet
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
|---|---|---|
|
||||
| MCP server `telegram-usulpro` / `telegram-helper` won't start | `.env` missing, or `TELEGRAM_MCP_BIN` not set / not executable on this machine | Check the server's stderr in Claude Code logs; the script prints exactly what's missing. Fill in `.env`. |
|
||||
| `session string for 'usulsu' is empty in .env` | Sessions weren't generated on this machine yet | `pnpm tg:session:usulsu` (and/or `:helper`) |
|
||||
| `generator not found at .../.venv/bin/python` | `TELEGRAM_MCP_DIR` points at the wrong place, or `.venv` not created in the telegram-mcp checkout | Fix the path in `.env`; in the telegram-mcp checkout run its venv setup |
|
||||
| Telegram suddenly logs us out / revokes the key | A session string got reused across two machines/IPs | Regen on each affected machine separately with `pnpm tg:session:<account>`; never copy session strings |
|
||||
| `scripts/telegram-mcp.sh: No such file or directory` from Claude Code | `.mcp.json` got hardcoded back to an absolute path | Restore relative form: `"args": ["scripts/telegram-mcp.sh", "usulsu"]` |
|
||||
| `list_telegram_channels.py` / `fetch_telegram_jobs.py` fail to auth | `TELEGRAM_SESSION_STRING` in `.env` doesn't match the usulsu account (these direct Telethon scripts always use usulsu) | Regen with `pnpm tg:session:usulsu` |
|
||||
|
||||
---
|
||||
|
||||
## Folder layout
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -27,20 +27,27 @@ case "$ACCOUNT" in
|
|||
esac
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
TELEGRAM_DIR="${TELEGRAM_MCP_DIR:-/home/usul/workspace/projects/my-utils/telegram}"
|
||||
ENV_FILE="$PROJECT_ROOT/.env"
|
||||
SECRETS_DIR="$PROJECT_ROOT/.secrets"
|
||||
OUT_FILE="$SECRETS_DIR/session_${ACCOUNT}.txt"
|
||||
|
||||
[ -f "$ENV_FILE" ] || { echo "missing $ENV_FILE" >&2; exit 1; }
|
||||
[ -f "$ENV_FILE" ] || { echo "missing $ENV_FILE (copy .env.example and fill it in)" >&2; exit 1; }
|
||||
set -a; . "$ENV_FILE"; set +a
|
||||
if [ -z "${TELEGRAM_API_ID:-}" ] || [ -z "${TELEGRAM_API_HASH:-}" ]; then
|
||||
echo "TELEGRAM_API_ID / TELEGRAM_API_HASH missing in $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TELEGRAM_DIR="${TELEGRAM_MCP_DIR:-}"
|
||||
if [ -z "$TELEGRAM_DIR" ]; then
|
||||
echo "TELEGRAM_MCP_DIR not set in $ENV_FILE" >&2
|
||||
echo "point it at the telegram-mcp checkout on THIS machine, e.g.:" >&2
|
||||
echo " TELEGRAM_MCP_DIR=/path/to/telegram" >&2
|
||||
exit 1
|
||||
fi
|
||||
[ -x "$TELEGRAM_DIR/.venv/bin/python" ] || {
|
||||
echo "generator not found at $TELEGRAM_DIR/.venv/bin/python" >&2
|
||||
echo "set TELEGRAM_MCP_DIR to your telegram-mcp checkout" >&2; exit 1; }
|
||||
echo "check TELEGRAM_MCP_DIR in $ENV_FILE and that its .venv is created" >&2; exit 1; }
|
||||
|
||||
mkdir -p "$SECRETS_DIR"
|
||||
tmp="$(mktemp)"; trap 'rm -f "$tmp"' EXIT
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
#!/usr/bin/env bash
|
||||
# Launch the telegram-mcp server for one account, reading API creds and the
|
||||
# session string from the project .env. Used by .mcp.json so that NO secrets
|
||||
# are hardcoded in the committed config.
|
||||
# and NO machine-specific paths are hardcoded in the committed config.
|
||||
#
|
||||
# Usage (from .mcp.json):
|
||||
# bash scripts/telegram-mcp.sh usulsu # main account -> TELEGRAM_SESSION_STRING
|
||||
# bash scripts/telegram-mcp.sh helper # samuishechka -> TELEGRAM_SESSION_STRING_HELPER
|
||||
#
|
||||
# The telegram-mcp binary path can be overridden with TELEGRAM_MCP_BIN.
|
||||
# Per-machine config (must live in .env, not committed):
|
||||
# TELEGRAM_MCP_BIN absolute path to the telegram-mcp executable on THIS machine
|
||||
set -euo pipefail
|
||||
|
||||
ACCOUNT="${1:?usage: telegram-mcp.sh <usulsu|helper>}"
|
||||
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
BIN="${TELEGRAM_MCP_BIN:-/home/usul/workspace/projects/my-utils/telegram/.venv/bin/telegram-mcp}"
|
||||
|
||||
[ -f "$PROJECT_ROOT/.env" ] || { echo "missing $PROJECT_ROOT/.env" >&2; exit 1; }
|
||||
[ -f "$PROJECT_ROOT/.env" ] || { echo "missing $PROJECT_ROOT/.env (copy .env.example and fill it in)" >&2; exit 1; }
|
||||
set -a; . "$PROJECT_ROOT/.env"; set +a
|
||||
|
||||
case "$ACCOUNT" in
|
||||
|
|
@ -28,9 +28,19 @@ if [ -z "${TELEGRAM_API_ID:-}" ] || [ -z "${TELEGRAM_API_HASH:-}" ]; then
|
|||
exit 1
|
||||
fi
|
||||
if [ -z "${TELEGRAM_SESSION_STRING:-}" ]; then
|
||||
echo "session string for '$ACCOUNT' is empty in .env — regenerate it with:" >&2
|
||||
echo "session string for '$ACCOUNT' is empty in .env — regenerate it on THIS machine with:" >&2
|
||||
echo " pnpm tg:session:$ACCOUNT" >&2
|
||||
echo "(do not copy session strings between machines — Telegram revokes the key)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BIN="${TELEGRAM_MCP_BIN:-}"
|
||||
if [ -z "$BIN" ]; then
|
||||
echo "TELEGRAM_MCP_BIN not set in $PROJECT_ROOT/.env" >&2
|
||||
echo "point it at the telegram-mcp executable on THIS machine, e.g.:" >&2
|
||||
echo " TELEGRAM_MCP_BIN=/path/to/telegram/.venv/bin/telegram-mcp" >&2
|
||||
exit 1
|
||||
fi
|
||||
[ -x "$BIN" ] || { echo "TELEGRAM_MCP_BIN=$BIN is not executable on THIS machine" >&2; exit 1; }
|
||||
|
||||
exec "$BIN"
|
||||
|
|
|
|||
Loading…
Reference in New Issue