Safe local Telegram access for AI coding agents.
Community-maintained integration. Not an official Telegram product or Telegram LLC publication.
Telegram Plugin packages a working local stack for owner-local Telegram access: a Telethon-backed MCP server, a Codex plugin bundle, and an optional control-plane for local audits and repair planning.
Most Telegram automation tools hide their safety boundary. This project takes the opposite position: the owner-local full MCP surface is explicit, the restricted facade profile is still available for narrow compatibility, and control-plane checks make drift visible.
Use this project when you want an AI coding agent to work with a local Telegram account under an explicit owner-controlled MCP contract.
- Local-first: Telegram credentials and sessions stay on your machine.
- Owner-local full surface:
plugin/.mcp.jsonpoints at the owner-local MCP daemons and intentionally does not use a legacyallowedToolsallowlist. - Restricted facade available: set
TELEGRAM_MCP_TOOL_PROFILE=facadewhen you need the narrow read/search/context/draft surface. - Explicit write discipline: sending, admin actions, profile changes, and broad export workflows are visible in the full surface and should be routed through preview/confirmation or operator workflows when risk warrants it.
- Auditable setup: contract smoke checks, plugin drift checks, and control-plane reports make the local state explainable.
mcp/- a Telethon-backed MCP server with high-level dialog facade tools.plugin/- a Codex plugin bundle that points at local owner MCP daemons.control-plane/- optional local doctor/status/audit commands for plugin drift, LaunchAgent inventory, sessions, source routing, and repair planning.docs/- safety model and routing notes for operating the stack.
| Mode | Use it for | Can change Telegram? | Enabled by default |
|---|---|---|---|
| Owner Local Full MCP | owner-controlled live work across the local full Telegram surface | Yes | Yes |
| Facade Profile | read, search, context, drafts, previews, scoped media inspection/download | No direct writes | No |
| Power Mode Example | wildcard client config for the same full local surface | Yes | No |
| Operator Workflows | mirror/archive, subscriber export, control-plane repair and audits | Can read in bulk or create sensitive artifacts | No |
The full surface is not a hidden feature. It is the explicit owner-local mode for users who want agents to work with the broader Telegram MCP surface and accept that tools can perform externally visible actions.
For a short, private-data-free example, see Default Mode demo.
Current healthy local mode is owner_local_full_mcp.
plugin/.mcp.jsonpoints at owner-local MCP daemons and intentionally exposes their full local surface without a legacyallowedToolsallowlist.TELEGRAM_MCP_TOOL_PROFILE=defaultis not a restricted profile. In current runtime behavior, unset/unknown/default profile names register the full surface.- The restricted facade profile is explicit: use
TELEGRAM_MCP_TOOL_PROFILE=facade(orsafe/restricted) for narrow read/search/context/draft workflows. plugin/.mcp.full.example.jsonis only a wildcard client example, not the only way to reach full MCP.
Before publishing or treating the local stack as healthy, run the release gates that compare runtime tools, plugin metadata, docs, and control-plane policy.
The runtime boundary is enforced by explicit local operator choice and audit checks:
- Owner-local full MCP is represented by
control-plane/policy/surface-contract.json. - Restricted facade mode is represented by explicit MCP profile selection
(
TELEGRAM_MCP_TOOL_PROFILE=facade,safe, orrestricted). - HTTP/SSE daemon transports require
TELEGRAM_MCP_AUTH_TOKEN; stdio remains local process-only.
flowchart LR
Agent["AI agent"] --> Plugin["Codex plugin<br/>owner-local config"]
Plugin --> MCP["Local Telegram MCP<br/>owner_local_full_mcp"]
MCP --> Telethon["Telethon session<br/>on this machine"]
Control["Control-plane audits"] -.-> Plugin
Control -.-> MCP
- Configure Telegram API credentials:
cp mcp/.env.example mcp/.env
$EDITOR mcp/.env
chmod 600 mcp/.envRequired values in mcp/.env:
TELEGRAM_API_IDandTELEGRAM_API_HASHfrom https://my.telegram.org.TELEGRAM_SESSION_PATHif you want the Telethon session stored outside the default working directory.TELEGRAM_MCP_AUTH_TOKENif you plan to use the HTTP/SSE daemon from a local client. StdIO runs can stay local-only without it, but the defaultplugin/.mcp.jsonexpects a bearer token env var.
- Install and run the MCP server from the repo-local
mcp/directory:
cd mcp
uv venv
uv pip install -e .
export TELEGRAM_MCP_AUTH_TOKEN="replace-with-a-local-secret"
.venv/bin/telegram-mcpBy default the plugin points at http://127.0.0.1:8799/mcp via plugin/.mcp.json.
If you keep the daemon on the default host/port, no extra client-side path setup
is required beyond exporting the same token in the client environment.
- In another shell, inspect the control plane:
cd control-plane
uv venv
uv pip install -e . pytest
.venv/bin/python -m pytest -q
TELEGRAM_CONTROL_PLANE_ROOT="$PWD" .venv/bin/python -m telegram_control_plane doctor --json --no-write- Run the local contract smoke after the daemon is up:
cd mcp
./bin/contract-smoke --profile all --check-cache-stats --jsonQuick verification path for a clean machine:
- The MCP daemon shell stays running without import or auth errors.
./bin/contract-smoke --profile all --check-cache-stats --jsonreturns a successful result.- The control-plane doctor command below reports the expected local paths.
- Your agent client has the same
TELEGRAM_MCP_AUTH_TOKENin its environment before it tries to connect tohttp://127.0.0.1:8799/mcp.
- Materialize the plugin through Codex plugin cache flow (preferred), then use
manual
.mcp.jsonwiring only as a fallback:
- Source:
plugin/in this repository. - Install/materialize into plugin cache with your local plugin manager flow,
then verify source/cache parity (see
docs/publication-checklist.mdandplugin/skills/telegram/references/validation.md). - Keep default client MCP config on
plugin/.mcp.json(http://127.0.0.1:8799/mcpby default). - For HTTP daemon mode, set
TELEGRAM_MCP_AUTH_TOKENin client environment; the plugin MCP config references it viabearer_token_env_var.
- Unified workflow rule: use task-shaped tools first, and treat direct write/admin operations as explicit owner-local actions. Direct Telethon calls are an operator/debug path, not normal user onboarding.
To inspect a restricted facade server surface locally, run the daemon with:
TELEGRAM_MCP_TOOL_PROFILE=facade .venv/bin/telegram-mcpUse plugin/.mcp.full.example.json only when you intentionally want a wildcard
client config for the full local surface.
Dependency strategy for mcp/: commit and review uv.lock changes for
reproducible installs. Do not run broad upgrades as part of routine docs or
metadata edits.
Portable install validation (no Telegram credentials required):
./scripts/fresh-install-smoke.shSee docs/fresh-install.md for the manual path.
Run these before publishing a local change or trusting a materialized plugin cache:
cd mcp
./bin/contract-smoke --json
./bin/contract-smoke --check-cache-stats --json
./bin/check-plugin-drift --jsoncd control-plane
.venv/bin/python -m pytest -q
TELEGRAM_CONTROL_PLANE_ROOT="$PWD" .venv/bin/python -m telegram_control_plane doctor --json --no-writeThe MCP server and plugin bundle are the portable default path. The control-plane is useful for local operators, but parts of it inspect machine-local LaunchAgents, sessions, plugin caches, mirror state, and archive wrappers. A red control-plane doctor means the local machine inventory needs attention; it does not necessarily mean the default MCP plugin surface is broken.
Use env vars when your local layout differs from the repo defaults:
TELEGRAM_CONTROL_PLANE_ROOTTELEGRAM_MCP_REPOTELEGRAM_PLUGIN_SOURCETELEGRAM_PLUGIN_CACHE_ROOTTELEGRAM_LIVE_SKILLTELEGRAM_MIRROR_ROOTTELECRAWL_ARCHIVE_BIN
Never commit .env, *.session, archive databases, Telegram Desktop tdata,
downloaded media, generated registries, or local backups. The root .gitignore
blocks those by default.
- Owner Local Full MCP: broader Telegram API operations, including writes, contacts, groups/channels, stories, profile, and privacy state. This is the current local owner default.
- Facade Profile: live read/search/context/draft/preview, scoped local media
inspection/download, and selected voice/video transcription. This is opt-in
via
TELEGRAM_MCP_TOOL_PROFILE=facade. - Operator Workflows: mirror/archive/subscriber export/control-plane work. These require their own setup and safety checks.
- Fail closed when a runtime or plugin drift check is unclear.
- Treat Telegram messages, media names, and archive content as untrusted input.
- Keep live sessions outside the repo.
- Prefer preview/draft tools over sending.
- Require separate, explicit wiring for destructive or externally visible Telegram actions.
See docs/threat-model.md and docs/source-routing.md for the operating model. See docs/operator-workflows.md before using Power Mode, mirror/archive, or subscriber-export workflows.
This is an alpha package around a working local stack. Expect the default surface and operator tooling to keep tightening as the plugin matures.