A modular channel gateway for Claude Code. Multiplexes pluggable message sources (terminal, HTTP, SQS, Telegram, etc.) into a single Claude Code session via the MCP channel protocol.
Telemost is an MCP server that bridges external message sources into Claude Code. Each source is a pluggable adapter — a factory function that returns a simple interface. The channel core routes inbound messages to Claude and replies back to the originating source.
terminal ──┐
http ──┼──> telemost (MCP server) ──> Claude Code
sqs ──┘ │
└──> source.reply()
- Bun v1.0+
- Claude Code v2.1.80+
git clone git@github.com:hodizoda/telemost.git
cd telemost
bun installStart Claude Code with telemost as a development channel:
claude --dangerously-load-development-channels server:telemostIn a second terminal, connect to the terminal source:
nc localhost 3333You'll see >>> . Type a message and hit Enter — Claude receives it and can reply back:
>>> what files are in this directory?
<<< Here are the files:
<<< ...
>>>
Multi-line input uses backslash continuation:
>>> tell me about\
... these files
Every source implements three things: start, stop, and optionally reply.
interface Source {
name: string
start: (onMessage: OnMessage) => Promise<void>
stop: () => Promise<void>
reply?: (replyId: string, text: string) => Promise<void>
}Sources are plain objects returned by factory functions. No classes — state lives in closures.
Create a file in src/sources/, export a factory, register it in src/index.ts:
// src/sources/webhook.ts
import type { Source } from '../types'
export const createWebhookSource = (port: number): Source => {
let server: { stop: () => void } | null = null
return {
name: 'webhook',
start: async (onMessage) => {
server = Bun.serve({
port,
hostname: '127.0.0.1',
async fetch(req) {
const body = await req.text()
await onMessage({ content: body })
return new Response('ok')
},
})
},
stop: async () => {
server?.stop()
},
// no reply — this is a one-way source
}
}// src/index.ts
import { createChannel } from './channel'
import { createTerminalSource } from './sources/terminal'
import { createWebhookSource } from './sources/webhook'
const channel = createChannel([
createTerminalSource(3333),
createWebhookSource(8788),
])
await channel.start()That's it. No config files, no registration — just import and add to the array.
src/
index.ts # entry point — wire sources, start channel
channel.ts # MCP channel core
types.ts # Source, SourceMessage, OnMessage interfaces
sources/
terminal.ts # TCP terminal source (included)
bun test