Skip to main content

crosstalk-mcp (Python edition)

A tiny cross-machine relay MCP server — a shared "mailbox" two coding agents connect to so they can message each other and run a back-and-forth until they're done. Unlike file- or SQLite-on-one-box approaches, this relay speaks streamable-HTTP MCP over the network, so the two agents can live on different machines (same LAN, a VPN, or a tunnel).

This is the Python (FastMCP) edition. A functionally equivalent Java edition lives on the java folder — pick whichever fits your stack.

  • MCP (for agents): streamable HTTP at POST /mcp — tools post_message, get_messages, list_channels.
  • REST mirror (for humans/tools): GET /api/channels, GET|POST /api/channels/{channel}/messages, GET /api/channels/{channel}/wait?since_id=&timeout_s= (long-poll mirror of wait_for_message), GET /api/channels/{channel}/stream?since_id= (Server-Sent Events stream).
  • Storage: SQLite file (relay.db), durable across restarts.
  • Auth: optional shared bearer token (RELAY_TOKEN) — off by default, strongly recommended whenever the relay is reachable beyond localhost.

Quick start

Option A — Docker (recommended)

docker build -t crosstalk-mcp .
docker run -d --name relay -p 8765:8765 \
  -e RELAY_TOKEN=$(openssl rand -hex 16) \
  -v relay-data:/data \
  crosstalk-mcp

Option B — Python (3.10+)

pip install -r requirements.txt          # or: pip install .
RELAY_TOKEN=your-shared-secret PORT=8765 python crosstalk_mcp.py
# (after `pip install .` you can also run the console script: crosstalk-mcp)

The host must allow inbound TCP on the port (default 8765) for other machines to connect.

Connect your agents (run on each machine)

# same machine:
claude mcp add --transport http crosstalk http://localhost:8765/mcp \
  --header "Authorization: Bearer your-shared-secret"

# another machine (use the host's reachable IP/hostname):
claude mcp add --transport http crosstalk http://<HOST>:8765/mcp \
  --header "Authorization: Bearer your-shared-secret"

(Drop the --header if you run without RELAY_TOKEN.) Allowlist the crosstalk tools on each side so polling doesn't prompt for permission every time.

Tools

Tool Args Returns
post_message channel, sender, type, body {id, channel, created_at}
get_messages channel, since_id (0 = all) messages with id > since_id
list_channels channels with counts + last activity
wait_for_message channel, since_id, timeout_s (default 30, capped 300) new messages with id > since_id, blocking until one arrives or timeout ([] on timeout)

Pick any channel name; both sides use the same one. type is a free-text label (NOTE, QUESTION, ANSWER, DONE, …) you define for your workflow.

How two agents converse

  1. Agent A: post_message(channel, "agent-a", "QUESTION", "...").
  2. Agent B polls get_messages(channel, since_id) (track the highest id seen), replies with post_message(...).
  3. Repeat until both post a DONE. Drive it turn-by-turn ("check the relay and reply") or let each side poll on a loop.

For low-latency, cost-efficient back-and-forth, skip polling altogether: an agent post_message(...) then wait_for_message(channel, <last_id_seen>) to block until the peer replies (or timeout). Loop that turn-by-turn instead. The relay still just moves messages; the agents drive who speaks when.

Security

  • The relay moves data between machines. Set RELAY_TOKEN for anything beyond localhost, and prefer HTTPS (terminate TLS at a reverse proxy / tunnel) when exposed publicly.
  • Treat a channel as a shared bus: don't post credentials, secrets, or PII.
  • The shared token is a single secret; rotate it if it leaks.

Per-participant tokens (identity binding)

The shared RELAY_TOKEN gates the relay but does not stop one participant from claiming to be another (e.g. humanX posting as humanY). For that, set RELAY_PARTICIPANTS — a map of participant id to token:

RELAY_PARTICIPANTS="humanX:tokX,humanY:tokY,agentX:tokA" PORT=8765 python crosstalk_mcp.py
  • Each request must present its participant's token (Authorization: Bearer <token>, or ?token= for browser SSE). The token is bound to its identity: it may only post as, or announce presence as, its own id — a mismatch returns 403. An unknown token returns 401.
  • RELAY_TOKEN and RELAY_PARTICIPANTS can be combined. When both are set, the shared RELAY_TOKEN still works as an unbound privileged token (no identity binding), which is handy for agents/services; humans use their own per-participant tokens.
  • In the /ui, each person sets their Participant ID and their token in the identity settings — the token must match the id it was issued for.
  • Ids and tokens must not contain , or : (the delimiters). Rotate any token that leaks.

License

MIT — see LICENSE.

Release files for crosstalk-mcp 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crosstalk-mcp 2.0.0
File Size Uploaded
crosstalk_mcp-2.0.0.tar.gz 24.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for crosstalk-mcp 2.0.0
File Interpreter ABI Platform
crosstalk_mcp-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 50.3 kB

Release files / crosstalk_mcp-2.0.0.tar.gz

Download URL crosstalk_mcp-2.0.0.tar.gz
Size 24.8 kB
Tags Source
SHA-256 checksum
How to use checksums
340556490a1cbf085f471e3a2cdf16ef2fd6e4fac4bd22fe12dd88f457d11160
BLAKE2b-256 checksum
How to use checksums
1621404d6d74719fa65fd9ea48d406c5b7bf0af5a2d91192be5d8b1a984e1b88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.

Transparency log

Release files / crosstalk_mcp-2.0.0-py3-none-any.whl

Download URL crosstalk_mcp-2.0.0-py3-none-any.whl
Size 25.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7a098095a7fb10ddf5572a54aefa7f53ea314c527c13a9b51c2cb497210729d8
BLAKE2b-256 checksum
How to use checksums
64ac2a4984a3451fc6a9d03bae25de2311122d1172ef846d1a57e7638e9870e8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page