6 minute read


I use Claude Desktop for brainstorming: exploring ideas, thinking through architecture, working out strategy. I use Claude Code for implementation: planning in the codebase, writing and testing code, running builds. Different modes of thinking, different tools. Like wanting a whiteboard for one task and a terminal for another.

The problem is they can’t see each other.

A brainstorming session on Desktop might surface a design idea that I want the Code session to act on. Or a design question on Desktop needs to know how something was actually implemented but the answer lives in the Code session’s context. The information flows both ways: Desktop pushes ideas down, and needs to pull implementation details up.

But there’s no way to do either. I copy-paste fragments, re-explain things, re-establish context that already exists in another window. Two AI agents, both with deep context on my project, completely unaware of each other.

Anthropic recently introduced Remote Control, a way to access your local CC session from the web or mobile. It solves a real problem: your laptop’s session, reachable from your phone. But it’s the same you, driving the same session, from a different screen. One agent, two windows.

What I want is different. I want the Desktop conversation (a separate agent, with its own context) to reach into a running Code session, see what’s there, and send it a message. Not multi-device single-user. Multi-agent. That axis isn’t covered.

cc-tap hero

So I mapped the session protocol that Claude Code’s web UI uses, and built an experimental MCP server that lets Claude Desktop read and interact with running Code sessions. It uses undocumented APIs that could change at any time, but it works today and the protocol itself is the interesting part.

The API is already there

Both Remote Control and Claude Code on the web use the same session protocol under the hood. I captured the browser traffic with HAR exports and mapped the endpoints. The protocol has three layers:

HTTP REST for session management. List sessions, read event history, send messages. Uses your existing OAuth token against api.anthropic.com. This is the workhorse: straightforward REST, well-structured responses, and it works from any HTTP client.

WebSocket for real-time streaming and tool approval. The web UI at claude.ai/code uses a WebSocket to receive events as they happen and to relay tool approvals back to the session. This is behind Cloudflare’s bot protection: TLS fingerprinting, JS challenges, browser verification. A non-browser client gets a 403.

Polling as a fallback. Without WebSocket access, an external client can poll the event history endpoint every 1-2 seconds. You get ~1.5s latency instead of real-time, but it works with just an OAuth token.

The session model already supports multiple clients connecting to the same session. That’s not an accident. It’s how the web UI works.

%%{init: {'theme': 'dark', 'themeVariables': {'edgeLabelBackground': 'transparent'}}}%% graph LR CD["🖥️ Claude
Desktop"] --- TAP["⚙️ cc-tap
MCP Server"] CC2["🖥️ Claude
Code B"] --- TAP TAP -->|"HTTP REST
OAuth"| API["☁️ api.anthropic.com"] TAP -.-x|"WebSocket
🚫 Cloudflare"| WS["☁️ claude.ai"] API -->|"events/messages"| CC1["🖥️ Claude
Code A"] WS -->|"streaming +
tool approval"| CC1 style CD fill:#2d1b69,stroke:#b794f4,stroke-width:2px,color:#fff style CC2 fill:#2d1b69,stroke:#b794f4,stroke-width:2px,color:#fff style TAP fill:#4a1942,stroke:#f687b3,stroke-width:2px,color:#fff style API fill:#1a365d,stroke:#63b3ed,stroke-width:2px,color:#fff style WS fill:#1a365d,stroke:#63b3ed,stroke-width:2px,color:#fff style CC1 fill:#2d1b69,stroke:#b794f4,stroke-width:2px,color:#fff

The full protocol is documented in PROTOCOL.md in the repo.

The build

cc-tap is an MCP server that exposes Claude Code sessions as tools. Install it in Claude Desktop or another Claude Code session, and you can see into and interact with running CC sessions.

pip install cc-tap
claude mcp add cc-tap -- cc_tap

Requires claude /login and Remote Control enabled.

Six tools:

Tool What it does
list_sessions List CC sessions, filter by status
get_session_info Session details: title, status, working directory
read_session Read recent conversation from a session
get_session_events Raw event stream, filterable by type
send_message Send a message to a CC session (fire and forget)
send_and_wait Send a message and wait for the full response

With this, a Claude Desktop session can ask “what are my running Code sessions?” and get a list. It can read what a Code session has been working on. It can send a message to a Code session (“run the test suite,” “what’s the status of the refactor?”) and get back the response. A second Code session can coordinate with a first one.

It uses the same OAuth credentials you already have from claude /login. No additional auth, no API keys. cc-tap reads them from your macOS Keychain (or ~/.claude/.credentials.json on Linux) and talks to the same API the web UI does.

Where it stops working

It mostly works. But there’s one place where it doesn’t, and that’s the most interesting part.

When a Claude Code session needs to run a tool (read a file, execute a command, make an edit) it asks for permission. In the terminal, you approve it by pressing Enter. In the web UI, you click a button. That approval travels to the session runtime via WebSocket.

cc-tap can see these pending tool requests through polling. But it can’t approve them.

The reason isn’t just that the WebSocket at claude.ai is behind Cloudflare’s bot protection (though it is — a non-browser client gets a 403). The deeper issue is architectural: control responses sent via HTTP POST are stored in event history but never relayed to the session worker. The worker only picks them up from an active WebSocket connection. So even if you got past Cloudflare, the HTTP path wouldn’t work for approvals. The control channel is WebSocket-shaped by design.

There are WebSocket endpoints on api.anthropic.com too, but they appear to require a session-scoped ingress token issued through a worker registration flow. I tested three different endpoint/auth combinations, all returned 403. The details are in the Open Questions section of the protocol doc.

The practical effect: the read path (listing sessions, reading events, sending messages) works over plain HTTP with OAuth. The control path (approving tool use) is WebSocket-only, and those endpoints aren’t reachable from external clients.

What this is — and isn’t

This is an exploration, not a production tool. The API is undocumented and could change tomorrow. Polling adds ~1.5 seconds of latency. Tool approval requires the CC terminal or the web UI. The protocol documentation is reverse-engineered from one person’s traffic captures — there’s almost certainly more surface area I haven’t found.

Things worth exploring further:

  • Real-time streaming. The WebSocket endpoints exist for real-time event delivery. Getting access from a non-browser client would eliminate the polling latency.
  • Structured coordination patterns. Right now cc-tap is a bridge: read and write. But the primitives are there for higher-level patterns: one session delegating subtasks to another, a Desktop session acting as a supervisor for multiple Code sessions, or an orchestrator that routes work based on session state.
  • Tool approval relay. The biggest limitation. If the WebSocket becomes accessible, or if Anthropic exposes a REST endpoint for control responses, cc-tap could go from observer to full participant.

The value right now is the proof that it works and the protocol documentation. Both show that multi-client session access isn’t hypothetical. It’s implemented, just not exposed as a platform primitive.

Closing thought

Anthropic built MCP, an open protocol so that any agent can talk to any tool. They also built multi-client session infrastructure so that their web UI, mobile app, and CLI can all attach to the same running session.

What they haven’t done is connect these two things. There’s no MCP surface for session-level operations. No way for one Claude instance to discover or interact with another through the protocol Anthropic designed for exactly that kind of interoperability.

cc-tap bridges the gap from the outside, using the same session API the web UI uses, exposed as MCP tools. It works because the pieces are already there. The session model supports multiple clients. The event stream is readable over HTTP. Messages can be injected by any authenticated client. The architecture is ready. It just hasn’t been unbundled.

If anyone at Anthropic is thinking about exposing CC sessions through MCP, the tool list in cc-tap is one shape that surface could take.


Updated: