Skip to main content
Glama

claude-intercom

An MCP server that lets Claude Code sessions talk to each other.

Run many Claude Code sessions at once (e.g. with agent-deck, tmux, or just several terminals) and let them:

  • list_sessions — discover recent sessions and see which are live right now

  • whoami — find out which session you are

  • send_message — drop an async message into another session's inbox

  • read_messages — pick up messages other sessions sent you

  • reply — answer a message you received

  • ask — ask a live session a question and get its answer back synchronously

No daemon, no database. Messages are plain JSON files under ~/.claude-intercom/, and sessions are discovered from Claude Code's own transcripts (~/.claude/projects/).


How it works

  • Discovery. Every Claude Code session writes a transcript to ~/.claude/projects/<project>/<session-id>.jsonl. list_sessions reads those for the session id, project, first prompt (as a title), and last-active time.

  • Liveness. A session is "live" if its claude process is running inside a tmux pane. The server correlates tmux panes → processes → the session id each one has open.

  • Self-identity. The server walks up from its own process to the parent claude process and uses lsof to find which transcript that process has open — that's you. (Override with CLAUDE_INTERCOM_SESSION if detection ever fails.)

  • Live delivery / ask. For a live target, the message is typed into its tmux pane with tmux send-keys. For ask, the server then tails the target's transcript and returns the assistant text that appears in response.

Heads up: live delivery and ask interrupt whatever the target session is doing, exactly as if you typed into its terminal. Async send_message (the default) does not — the recipient sees it when it next calls read_messages.

Related MCP server: claude-session-bridge

Requirements

  • Node.js ≥ 18

  • tmux, ps, and lsof on PATH (standard on macOS/Linux) — only needed for liveness, live delivery, and ask. Async messaging works without them.

Install

git clone https://github.com/AriOliv/claude-intercom
cd claude-intercom
npm install
npm run build

Then register it with Claude Code (user scope = available in every session):

claude mcp add intercom -s user -- node "$(pwd)/dist/index.js"

If you run several Claude Code config dirs, register it in each:

CLAUDE_CONFIG_DIR=~/.claude     claude mcp add intercom -s user -- node "$(pwd)/dist/index.js"
CLAUDE_CONFIG_DIR=~/.claude-ari claude mcp add intercom -s user -- node "$(pwd)/dist/index.js"

Via npx (once published to npm)

claude mcp add intercom -s user -- npx -y claude-intercom

Or add it to your MCP config manually:

{
  "mcpServers": {
    "intercom": {
      "command": "node",
      "args": ["/absolute/path/to/claude-intercom/dist/index.js"]
    }
  }
}

Usage

In any Claude Code session:

"List the other sessions I have open."

"Ask the litellm session whether the model-selection refactor is merged yet."

"Tell the BRLA session I'm done with the migration — it can rebase."

"Check my intercom inbox."

Configuration

Env var

Default

Purpose

CLAUDE_CONFIG_DIR

~/.claude

Where Claude Code stores projects/ transcripts

CLAUDE_INTERCOM_DIR

~/.claude-intercom

Where messages are stored

CLAUDE_INTERCOM_SESSION

(auto)

Force this server's session identity (a session id)

CLAUDE_INTERCOM_RESUME_FLAGS

(empty)

Extra flags passed to claude -p --resume when ask reaches an idle session (e.g. --dangerously-skip-permissions). Empty = safe default.

Reaching idle sessions

ask works whether the target is live or idle. A live session (running in a tmux pane) gets the question typed into its terminal. An idle session — one whose transcript exists but isn't currently running — is resumed headlessly with claude -p --resume <id> in its own cwd, so you can still reach it; the thread continues in the same transcript. Set CLAUDE_INTERCOM_RESUME_FLAGS if those headless resumes need extra flags.

Hands-off pickup (optional Stop hook)

hooks/pickup-stop.mjs is a Claude Code Stop hook: when a session finishes a turn, it pulls any unread messages addressed to that session and feeds them back so the session handles them (and replies) without anyone calling read_messages. Register it in settings.json:

{ "hooks": { "Stop": [ { "hooks": [
  { "type": "command", "command": "node /absolute/path/to/claude-intercom/hooks/pickup-stop.mjs" }
] } ] } }

Development

npm install
npm run build      # compile to dist/
npm run dev        # run from source with tsx

Limitations

  • Liveness, live delivery, and ask assume sessions run inside tmux. Plain-terminal sessions still work for list_sessions and async send_message/read_messages.

  • ask reads the answer by tailing the target's transcript; it returns the assistant text produced after the question, capped at ~4k chars. It's pragmatic, not a structured RPC.

  • A session only checks its inbox when something calls read_messages (or you tell it to). Pair it with a hook or a polling loop if you want hands-off pickup.

License

MIT

Available Tools

6 tools
askA

Ask a LIVE session a question and wait for its answer. Injects the question into the target's running terminal, then reads the answer back from its transcript. Only works on sessions marked live in list_sessions. Note: this interrupts what the target is currently doing.

Inputs: to (required), question (required), wait_seconds.

list_sessionsA

List Claude Code sessions discovered on this machine — recent ones and which are currently live (running in a tmux pane). Use scope='live' to see only sessions you can reach right now, or pass a project filter.

Inputs: scope, project, limit.

read_messagesA

Read intercom messages other sessions have sent to you. Call this at the start of a turn (or when prompted) to pick up cross-session messages. Marks them read.

Inputs: unread_only.

replyA

Reply to a message in your inbox. Looks up the original sender by message id and delivers your reply to their inbox (and live, if they're running).

Inputs: message_id (required), text (required), deliver_live.

send_messageA

Send an async message to another Claude Code session. It lands in that session's intercom inbox; the recipient reads it with read_messages on its next turn. Set deliver_live=true to also inject it immediately into the recipient's live tmux pane (this interrupts whatever it's doing).

Inputs: to (required), text (required), deliver_live.

whoamiA

Identify which Claude Code session this is (its id, project, and cwd). Useful so other sessions can message you back.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 6 tools

    Disambiguation5/5

    Each tool targets a distinct action: listing sessions, asking live sessions, reading messages, replying, sending async messages, and identifying the current session. Even though 'send_message' with deliver_live=true overlaps with 'ask' in interrupting a session, the synchronous vs async distinction is clear.

    Naming Consistency4/5

    Most tools use a verb_noun pattern (list_sessions, read_messages, send_message) but two are single verbs (ask, reply) and whoami is a fixed phrase. The naming is clear and follows imperative verbs, but the pattern isn't perfectly uniform.

    Tool Count5/5

    6 tools is a well-scoped set for intercom functionality across Claude Code sessions. Each tool serves a necessary role without redundancy or excessive specialization.

    Completeness4/5

    The set covers core operations: discover sessions, communicate (ask, send, reply, read), and identify self. Missing a 'peek' or 'list messages' without marking read, but this is a minor gap for the domain.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers