Skip to content

Add streamable HTTP transport, document shared-container setup#147

Open
paskal wants to merge 1 commit into
chigwell:mainfrom
paskal:feat/streamable-http-transport
Open

Add streamable HTTP transport, document shared-container setup#147
paskal wants to merge 1 commit into
chigwell:mainfrom
paskal:feat/streamable-http-transport

Conversation

@paskal

@paskal paskal commented Jul 3, 2026

Copy link
Copy Markdown

Hi there! Thanks a lot for your work on this project, and for merging the SSE transport in #146 — this builds directly on it.

Previously, MCP_TRANSPORT supported only stdio and the legacy SSE transport, and the Docker guidance in the README had every MCP client spawn its own container (docker run -i --rm ...). With several clients this multiplies Telethon sessions, which Telegram throttles and may flag; a client that exits uncleanly also leaves its container running, since the server keeps serving after the stdio peer is gone. On one of my machines this quietly accumulated 92 running containers for 29 live clients before I noticed.

After this change, MCP_TRANSPORT=http serves streamable HTTP on MCP_HOST:MCP_PORT at /mcp. Streamable HTTP is the current MCP transport, and it is what Claude Code (claude mcp add --transport http) and Codex (codex mcp add --url) speak natively — Codex has no legacy SSE support, so SSE alone was not enough for a shared server there.

Changes:

  • telegram_mcp/runner.py: transport selection extracted into _serve(); http runs run_streamable_http_async(), sse and stdio behave as before, unknown values still fall back to stdio.
  • tests/test_runner.py: tests for transport selection, host/port binding, and defaults.
  • README.md: a Transports section (transport table, client registration commands, mcp-remote bridge for stdio-only clients) and a rewritten Docker section recommending one long-lived shared container, with a note that the endpoint is unauthenticated and must stay on localhost.
  • docker-compose.yml: runs the shared HTTP server on 127.0.0.1:8765 instead of an idle stdio container (stdin_open/tty are no longer needed).
  • requirements.txt: mcp[cli] raised to >=1.8.0 (first release with streamable HTTP), matching the existing pin in pyproject.toml.

Tested: full pytest suite passes (136 passed); built the Docker image and verified the initialize/tools/list flow over /mcp with curl, plus real tool calls end-to-end from both Claude Code and Codex against a single shared container; docker compose config validates; black --check and the flake8 CI selectors are clean on the touched files.

Previously, MCP_TRANSPORT supported only stdio and the legacy SSE
transport, and the README's docker guidance had every MCP client spawn
its own container. With several clients (or coding agents spawning
subagent sessions) this multiplies Telethon sessions, which Telegram
throttles, and a client that exits uncleanly leaves its container
running: on one machine this accumulated 92 running containers for 29
live clients.

After this change, MCP_TRANSPORT=http serves streamable HTTP on
MCP_HOST:MCP_PORT at /mcp, which Claude Code (--transport http) and
Codex (--url) speak natively. The transport selection is extracted into
_serve() with tests, docker-compose.yml runs the shared HTTP server on
localhost, and the README documents the shared-container setup and
client registration. The mcp pin in requirements.txt is raised to
>=1.8.0 (first release with streamable HTTP), matching pyproject.toml.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant