talk-to-claude-code
This server lets you drive local Claude Code sessions from any MCP client or voice assistant: you can list, inspect, message, poll, rename, and read the history of sessions, and have tools relay the work back for hands-free use.
List sessions – see which Claude Code sessions are available, with optional detailed info like cwd, status, and ids.
Check session status – get the current state of one session by name, id, or pid.
Read transcripts – view recent conversation turns, including work done from other clients.
Send messages – queue a prompt into a running session as if typed, returning a cursor for follow-up.
Poll for replies – repeatedly fetch new output since a cursor to follow long-running tasks and know when the session finishes.
Ask and wait – send a prompt and wait for the answer in one call for short questions.
Rename sessions – change a session's displayed name.
Voice/Shortcuts support – plain-text HTTP endpoints let Siri Shortcuts ask questions and read replies aloud.
Observation mode – can be restricted to read-only, or limited to specific sessions, for safe remote monitoring.
Enables OpenAI's ChatGPT to drive local Claude Code sessions via a tunnel or HTTP endpoint, allowing it to queue prompts, monitor progress, and retrieve results.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@talk-to-claude-codeAsk my Claude Code session to run the tests and list any failures"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
talk-to-claude-code
Drive your Claude Code sessions by voice, hands-free, from any MCP client.
Ask Grok — or Claude, or your own script — to give a task to a Claude Code session running on your machine, hear what it is doing while it works, and get the answer read back. It was built to work from a car: Grok's voice mode on CarPlay reaches custom MCP connectors, so the whole loop runs without touching a keyboard.
It works by injecting messages into the target session's prompt queue as if they had been typed, through the cross-session messaging inbox the CLI already uses to talk to its peers. Because the prompt lands in the normal queue, a Remote Control client — your phone, or claude.ai/code — can watch and drive the same session at the same time. There is no proxy, no patched binary, and no interception of the Remote Control connection.
you (voice) ──> Grok ──> MCP ──> talk-to-claude-code ──> Claude Code session
▲ │
└────── "Running Read… 4 steps so far" ─────────┘The hard part is not the transport, it is keeping a remote model in the loop for the five to ten minutes a real coding task takes. Most of the design exists for that: short polls that always return a cursor, an elapsed counter so no two polls look alike, progress notifications, and result text written to tell the client what to do next. See Driving a session.
This lets whatever you connect it to run code on your machine. It queues prompts into
Claude Code sessions, and those sessions edit files and run shell commands. Anything that can
reach this server — including a model that has been prompt-injected — inherits that reach.
Do not expose it to the internet without a secret, and prefer narrowing it to one session with
CLAUDE_REMOTE_MCP_ALLOW, or CLAUDE_REMOTE_MCP_READONLY=1 when you only want observation.
Unofficial, and not affiliated with or endorsed by Anthropic. It talks to aninternal,
undocumented interface of the Claude Code CLI, reconstructed by inspection (see
Protocol notes). It works against the versions listed under Requirements and
may break on any update. scripts/probe.mjs is there to tell you quickly when it does.
Why this channel
Claude Code has three separate remote surfaces. Only one of them is a good foundation:
Channel | Transport | Redirectable? |
Device bridge |
| Yes, via |
Remote Control |
| No — |
Cross-session inbox | Unix domain socket, NDJSON | n/a — it is local by construction |
Redirecting the device bridge only buys you device_bash, and routes your OAuth token through
a proxy. Redirecting Remote Control needs a binary patch or TLS interception, and breaks on
every CLI update.
The cross-session inbox is orthogonal to Remote Control: the phone talks to the session over the bridge, this server talks to it over the socket, and both stay in sync because both end up in the same transcript.
Related MCP server: claudecode-mcp
Requirements
Node 22+
Claude Code 2.1.229 or newer to send to a session. The cross-session inbox arrived in that version; older sessions register themselves but never bind a socket. Restarting one picks it up, and resuming keeps the conversation:
cd <cwd> && claude --resume <sessionId>.
Reading has no such requirement — read_transcript works on any session, whatever its version,
because transcripts are files on disk.
Install
npm install
npm run buildRegister it with Claude Code:
claude mcp add talk-to-claude-code -- node /path/to/talk-to-claude-code/dist/index.jsOr in an MCP client config:
{
"mcpServers": {
"talk-to-claude-code": {
"command": "node",
"args": ["/path/to/talk-to-claude-code/dist/index.js"]
}
}
}Connecting Grok (the voice path)
Grok is the client this was built around, because it is the one that closes the loop end to end: its voice mode reaches custom MCP connectors, it ships on CarPlay, and it polls patiently instead of giving up after one call.
Grok calls your server from its own infrastructure, so it needs a public HTTPS URL. Run HTTP mode behind a tunnel of your choice — Tailscale Funnel gives a stable hostname without a domain, which matters because a connector has to be reconfigured every time the URL changes:
bash scripts/serve-tailscale.sh # READONLY=1 to expose observation only
bash scripts/serve-tailscale.sh --stopThat generates a secret on first run and reuses it afterwards, starts the server, puts it behind Funnel and prints the connector settings. The hostname is stable, so the connector is configured once and later restarts stay invisible to it — worth the setup, because reconfiguring a connector after every restart gets old fast.
Funnel only accepts ports 443, 8443 and 10000; the script defaults to 8443 and leaves any
existing mapping on 443 alone. Override with FUNNEL_PORT= and PORT=.
Without Tailscale, scripts/serve-public.sh does the same through a Cloudflare quick tunnel. It
needs no account, but the URL changes on every restart:
bash scripts/serve-public.shThen add it in the app: grok.com/connectors → New Connector → Custom. Give it the URL with
the secret in the path, and pick no authentication:
https://<your-host>:8443/mcp/<token>That matters. On the bare /mcp URL the client's first request arrives with no credentials, the
server answers 401, and clients read that as "this server wants OAuth" — Grok then asks for a
client ID, authorize and token endpoints, none of which exist here. Putting the secret in the URL
means no request is ever unauthenticated, so the OAuth prompt never appears. A token= query
parameter works too.
Over the API you can instead send a proper Authorization header:
tools: [{
"type": "mcp",
"server_label": "talk-to-claude-code",
"server_url": "https://<your-host>/mcp",
"authorization": "<your token>",
"allowed_tools": ["list_sessions", "read_transcript"] // optional: narrow what Grok may do
}]allowed_tools is a useful second lock: it restricts Grok to a subset regardless of what the
server exposes, and composes with CLAUDE_REMOTE_MCP_ALLOW on this side.
Other clients
Any MCP client works — the server is not Grok-specific. Two things decide whether a given one is usable for the voice case, and both are worth checking before you invest time:
Does its voice mode reach custom MCP connectors? Several assistants expose connectors in text chat but not in voice, which makes them useless in a car no matter how the server is set up. Test in voice early.
Does it keep polling? A single request cannot outlive the client's deadline, so the client has to call
get_replyrepeatedly. One that stops after the firststate=workingwill never see an answer to anything that takes more than a minute.
If your client fails the first test, the /voice endpoints
below sidestep MCP entirely.
Before you expose it
This server queues prompts into local Claude Code sessions, and those sessions edit files and run shell commands. Whatever you connect — and anything that successfully prompt-injects it — inherits that reach.
A sensible posture for anything internet-facing:
CLAUDE_REMOTE_MCP_TOKEN="$(openssl rand -hex 24)" \
CLAUDE_REMOTE_MCP_ALLOW=my-scratch-session \
node dist/index.js --httpThat pins it to one throwaway session. Use CLAUDE_REMOTE_MCP_READONLY=1 when you only want the
client to observe, and prefer a tunnel that gives you a private hostname over one that publishes
a guessable URL.
Transports
Mode | Command | Use |
stdio (default) |
| Claude Code, Claude Desktop, any local MCP client |
Streamable HTTP |
| Grok and other hosted clients, behind a tunnel |
HTTP mode binds 127.0.0.1:8787/mcp by default and refuses to start without
CLAUDE_REMOTE_MCP_TOKEN unless CLAUDE_REMOTE_MCP_NO_AUTH=1 is set. Override with --host,
--port, --path or CLAUDE_REMOTE_MCP_HOST / _PORT / _PATH.
Tools
Tool | Purpose |
| Names the sessions you can drive, in one line. |
| State of one session |
| Recent turns, including work done from a phone |
| Queue a prompt, return a cursor immediately |
| Poll for output since a cursor; says whether the session finished |
| Send and wait in one call, for short questions |
| Set periodic updates on/off, interval, and confirm-before-action |
| Shortcut for the update interval alone (5–55s) |
| Change a session's display name |
Sessions are addressed by the name you gave them, the registry name, the session id (or a unique
prefix), or the pid. Results use the name you gave: the registry only carries one derived from the
working directory — tachify-33 for a session you call Tachyo — which is no help when you are
naming a session out loud. The real title lives in the transcript and is read from there.
Results are written to be read aloud: short by default, with a detailed flag when the user
actually wants identifiers and paths. A voice client speaks the entire tool result, so a verbose
listing costs the user half a minute of talking to say nothing they can act on.
Driving a session
A remote client cannot sit on one long blocking call — tunnels and tool-call budgets cut it off, and the user sees nothing meanwhile. So work is followed in short hops:
send_message -> [session=my-session state=sent cursor="2026-08-13T07:55:29.595Z"]
get_reply -> [session=my-session state=working ... cursor="…31.919Z"] # tool activity so far
get_reply -> [session=my-session state=finished ... cursor="…35.729Z"] # answerEvery result leads with a machine-readable state line, so the decision to poll
again never depends on reading prose. state=working means call get_reply
again with the returned cursor; state=finished means stop.
A third state matters more than it looks: state=needs_answer. A session that
ends its turn by asking the user something goes idle exactly like one that
finished the job, so without this it reads as done and the pending decision is
never surfaced — the user hears a report, answers out loud, and the answer goes
nowhere. On needs_answer the client must put the question to the user and send
their reply back with send_message. Detection is by wording, since nothing in
the transcript marks a question: scripts/test-asks.mjs pins the awkward cases,
including requests that end in a full stop rather than a question mark. Assistant turns
list the tools the session used, which is the progress signal during a long
task.
When the session asks a question
A session can stop and put a form up — AskUserQuestion — and it then sits idle-looking while it
waits. Results carry the question and its options verbatim, so a relayed client can read them out
instead of reporting that nothing is happening.
The answer, though, has to be given in the session itself — the Claude app over Remote Control, or the terminal. Two measurements say why:
An ordinary message queues behind the form. On a session parked on a question, it had still not been seen 93s later, with the form untouched.
A message sent with
interrupt: truejumps the queue and dismisses the prompt — but the session records it as declined, not answered, and says so: a relayed claim is not the user's decision.
This is not a gap to close. Everything through the messaging inbox is stamped as a peer by the
receiving CLI, using the connecting process's kernel-verified credentials (SO_PEERCRED) — not a
field the sender controls. There is no inbox action to submit a form answer, and no way to make a
message count as the user. The only inputs that authenticate as the user are the session's own
terminal and Remote Control (the phone). Answering a question is therefore done there; the
connector cannot, by construction.
plain_questions (default on) is what makes questions answerable by voice at all. It asks the
session, via a fenced relay note, to never use AskUserQuestion and never hold a pending
question — instead to present the question and its options as plain-text output, the way it
would present a result, and end its turn. Because there is no pending prompt, the user's spoken
reply arrives as an ordinary instruction and the session acts on it — verified end to end: a
session laid out two options, the relayed "take the second one" was accepted and executed, with
no peer-refusal. It does not decide for the user, and it does not block. interrupt still drops
a question outright when the user would rather not engage with it.
Pacing and confirmation
How a driven session keeps the user in the loop is set per conversation, ideally by asking at the start (the server instructions prompt the client to onboard):
Periodic updates. When on, a still-working
get_replytells the client to keep polling on its own and give one short update every interval, until the session finishes — no nudging. When off, it reports once and stops until asked.Interval. How often those updates come —
set_delay(seconds, 5–55) orset_preferences(interval_seconds:). A ceiling: a call returns as soon as the session settles.Confirm before acting (
confirm_before_action, or per-callconfirm). When on, before a new request the session restates what it understood and lays out its plan as output — a result to hear, not a form — then ends its turn. The user's "go" or changes arrive as an ordinary instruction it then acts on.
set_preferences({periodic_updates, interval_seconds, confirm_before_action})
records all three; they stick for the conversation. The client is asked to
collect them up front with three short questions.
Voice endpoints (Siri Shortcuts)
If your assistant cannot reach MCP connectors from its voice mode — several cannot — this route skips MCP altogether. Siri runs hands-free in CarPlay without any special entitlement, and a Shortcut can call a URL and speak the reply. These endpoints exist for that: plain text in, plain text out, short enough to be read aloud.
GET|POST /voice/ask?session=<name>&message=<text>&wait=20
GET /voice/reply?session=<name>&wait=15Auth is the same shared secret, accepted as a Bearer header, any path segment,
or a token= query parameter — Shortcuts cannot set headers easily, so the
query form is usually simplest.
/voice/reply remembers where it left off per session, so a Shortcut just keeps
asking "what's new" without tracking a cursor:
Shortcut "Ask Claude"
1. Dictate Text -> spoken prompt
2. Get contents of …/voice/ask?session=my-session&token=…&message=[Dictated Text]
3. Speak Text -> the reply, or "Working on it. Running Read."
4. Repeat 8 times:
Get contents of …/voice/reply?session=my-session&token=…
Speak Text
If it contains "Still working" -> continue, else StopRun this behind Tailscale rather than a public tunnel if you can: the phone joins the tailnet, the endpoint stays off the public internet, and it still works on cellular.
Live progress
ask and get_reply emit notifications/progress while they wait, one per
turn the session produces, each carrying a short spoken-style line (Running Read, Checking the config…). A client that surfaces them — a voice client in
particular — narrates the work as it happens instead of going quiet.
Two constraints shape this:
MCP clients abort a request after 60s (
DEFAULT_REQUEST_TIMEOUT_MSEC), andresetTimeoutOnProgressdefaults to false, so progress notifications do not extend that deadline unless the client opts in. Every call here therefore stays under 45s and returns a cursor; progress complements short calls rather than replacing them.MCP has no way to push into a conversation between calls. Continuous narration comes from the client looping on
get_reply, which is why the instructions insist on it.
Relay discipline
The server is a conduit between the user and another agent, so a client that paraphrases in either direction corrupts the channel. The expectation is stated in three places, deliberately:
the server
instructionssent at initialize,the description of the
messageparameter onsend_messageandask— the highest-leverage spot, since it sits where the client writes the value,a footer on every completed answer, where the client is about to decide how to report back.
These are instructions, not enforcement: a model can still ignore them. Client-side settings (your client's own system prompt or custom instructions) are a stronger lever and compose with these.
Two details worth knowing if you change this logic:
Finished means idle across consecutive polls with no new output. It does not require output in the current call — a turn whose text was already consumed is equally finished, and requiring output made polling never terminate.
A session stays
idlefor a moment after a prompt is queued, before it picks it up. A poll issued in that window would otherwise report "finished" before any work started, so a 12s startup grace applies while no output has appeared yet. An older cursor is past the window and settles immediately.
Permissions
Reads are always allowed. Writes are conservative by default and configurable by environment:
Variable | Effect |
| Disable every write tool |
| Only these sessions accept writes |
| These sessions never accept writes |
| Permit writing to the session hosting this server |
Writing to the host session is refused by default: the message would feed straight back into the conversation that sent it.
The recipient may also gate an incoming message itself — a session in prompting mode holds peer
messages for the user's approval. That verdict comes back as a peer_message_status receipt
(held / denied / expired / delivered) and is surfaced in the tool result.
Protocol notes
Reconstructed from the CLI binary (v2.1.229); this is an internal interface and may drift.
Discovery — ~/.claude/sessions/<pid>.json:
{ "pid": 12345, "sessionId": "bf577127-1c0a-4a1e-9c2f-0d6b7e5a8f31", "cwd": "/home/you/project",
"status": "idle", "peerProtocol": 1,
"messagingSocketPath": "/run/user/1000/cc-socks/12345.sock",
"bridgeSessionId": "session_01ABCDEF…" }A record outlives its process after an abrupt kill, so liveness is confirmed by checking the pid
and matching procStart against /proc/<pid>/stat field 22.
Auth — the token lives at ~/.claude/sessions/<pid>.<sha256 of the canonical socket path>.key
(mode 0600), containing {"peerToken":"<32 hex>","procStart":"…"}. On Linux auth is optional, but
sending it is what earns the peer role rather than being treated as an anonymous writer.
Frames — newline-delimited JSON, 1 MiB per line:
{"type":"auth","token":"<peerToken>"}
{"type":"user","message":{"role":"user","content":"hello"},"msg_id":"…","from":"uds:/path.sock"}
{"type":"control","action":"rename","name":"new-name"}
{"type":"control","action":"peer_message_status","status":"held","orig_msg_id":"…"}Receipts — a recipient only replies to an address in the same directory as its own socket
that ends in .sock, so the receipt listener binds inside the shared cc-socks directory.
Replies — read from the session's transcript at
~/.claude/projects/<cwd-slug>/<sessionId>.jsonl.
Development
node scripts/probe.mjs # discovery + auth-key derivation, sends nothing
node scripts/e2e.mjs <session> # drives a session over a real MCP stdio client
node scripts/e2e-http.mjs # Streamable HTTP: auth rejection, bearer, secret path
node scripts/e2e-poll.mjs <session> [prompt] # send_message + get_reply loopNote when spawning a test session from inside another Claude Code session: unset
CLAUDE_CODE_CHILD_SESSION, or the child is treated as nested, session persistence is disabled,
and it never registers or binds a socket.
Available Tools
7 toolsaskAsk a session and wait for its replyA
WHEN TO USE THIS: any question or instruction about the user's own projects, code, repositories, machine, builds, deployments or work in progress belongs to a session — relay it. You do not know what is on their disk, and neither does a web search. Do not answer from your own knowledge, do not search the web, and do not ask clarifying questions the session could answer better: pass it through and let the session look. Answer in your own voice only when the user asks about you, or about how this connector itself works.
Send a prompt and wait for the answer in one call. Best for short questions. If the session is still working when the wait runs out, this returns the output so far plus a cursor — continue with get_reply rather than calling ask again, which would send the prompt a second time.
| Name | Required | Description | Default |
|---|---|---|---|
| message | Yes | The prompt to deliver, copied word for word from what the user wrote, in their original language. Do not rephrase, translate, summarise, expand, or add framing of your own — the receiving agent must see the user's exact words. Only compose your own wording if the user explicitly asked you to. | |
| session | Yes | Session name, session id (or unique prefix), or pid. | |
| timeout_seconds | No | How long to wait for the answer before returning partial output and a cursor (default and max 45s; values below 40 are raised to it). Do not shorten this: an answer that arrives inside this call needs no polling at all, and polling is where answers get lost. The 60s client deadline is the only reason it is not longer. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full disclosure burden. It discloses that the call waits for a reply, may time out and return partial output plus a cursor, and that re-calling ask would duplicate the prompt. This is substantive behavioral context beyond the title.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Despite its length, the description is front-loaded with a clearly marked WHEN TO USE section and every sentence carries routing or behavior guidance. No filler; the formatting makes the high-priority instruction immediately visible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description still explains the core call/response contract, timeout behavior, cursor continuation, and when to answer directly from the agent. It is complete enough for an agent to invoke ask correctly and avoid the common duplicate-prompt mistake.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents all three parameters with detailed descriptions (100% coverage), so the baseline is 3. The description mostly reuses the 'prompt' concept and does not add syntax, format, or cross-parameter relationships beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the verb and resource explicitly: 'Send a prompt and wait for the answer in one call.' It also differentiates itself from the continuation tool by warning not to call ask again after a timeout ('continue with get_reply'), so an agent can tell it apart from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description opens with a 'WHEN TO USE THIS' block that assigns ownership of user-project questions to sessions and explicitly forbids answering from memory or web search. It gives the continuation rule ('continue with get_reply rather than calling ask again') and marks the tool as best for short questions, giving clear when-to and when-not-to guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_replyPoll a session for new outputA
Watch a session and return whatever it produced since the given cursor, along with a fresh cursor. Blocks for at most wait_seconds, then returns what it has — so call it repeatedly to follow a long task. The result says whether the session finished or is still working. If it is still working, call this again with the returned cursor. Assistant turns list the tools the session used, which is the progress signal while a task is underway.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | Cursor from a previous send_message/get_reply call. Omit to read from now on. | |
| session | Yes | Session name, session id (or unique prefix), or pid. | |
| wait_seconds | No | How long to wait for activity before returning (default 25). Values below 20 are raised to 20: short waits mean more polls for the same task, and every extra poll is another chance to lose the thread. It returns as soon as the session settles, so a longer wait costs nothing. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and delivers: it discloses blocking behavior, wait limits, return contents, finished/working status, and the cursor contract. This is a high level of transparency for an agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences with no filler. The most important behavior (blocking return with fresh cursor) is front-loaded, and each sentence adds a distinct operational detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a polling tool with no output schema, the description covers the call pattern, return semantics, termination signal, and progress signal. Nothing essential for invoking it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaningful context around wait_seconds ('short waits mean more polls... every extra poll is another chance to lose the thread') and clarifies the cursor usage pattern. That pushes it above the baseline without being redundant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Watch a session'), the resource (session output), and the key mechanism (cursor-based incremental retrieval). It clearly distinguishes itself from siblings like read_transcript or session_status by emphasizing blocking, cursors, and repeated polling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage guidance: call repeatedly to follow a long task, call again with the returned cursor if still working, and rely on assistant turns as the progress signal. It does not explicitly compare against alternatives like read_transcript or session_status, so it misses a small opportunity for routing clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sessionsList Claude Code sessionsA
Name the sessions you can drive. Returns one short line by default, because a voice client reads the whole result aloud. Ask for details only when the user wants them.
| Name | Required | Description | Default |
|---|---|---|---|
| detailed | No | Include cwd, status, version and Remote Control id for each session. Verbose — omit for voice. | |
| include_unreachable | No | Also name the sessions that cannot be messaged. They are only counted otherwise. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral transparency burden. It discloses a meaningful behavioral trait: the tool returns a single short line by default because a voice client reads results aloud. It also implies the tool is read-only and non-destructive by framing it as 'name the sessions.' It could mention edge cases like empty lists or error behavior, but the disclosed voice-optimization behavior is valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences. The first states the core purpose immediately, and the second explains the default behavior and the condition for requesting details. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple (two optional booleans, no output schema), and the description explains the default output style and when to deviate. It doesn't cover every possible edge case, such as empty session lists or exact formatting of the detailed output, but the combination of schema and description is sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents both parameters in detail. The description adds some voice-related guidance for the 'detailed' parameter ('Ask for details only when the user wants them'), but it doesn't add meaning beyond what the schema provides for 'include_unreachable.' Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Name the sessions you can drive.' This clearly distinguishes list_sessions from its siblings (session_status, read_transcript, send_message, get_reply, ask, rename_session), none of which are about enumerating sessions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use the default short output for voice clients and only include details when the user actually wants them. It doesn't explicitly contrast with sibling tools like session_status, but the intended usage pattern is communicated well enough for most cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_transcriptRead session transcriptA
Read recent conversation turns from a session, including work it did while driven from a phone or from claude.ai. Subagent sidechains and tool plumbing are omitted.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many recent turns to return (default 20). | |
| session | Yes | Session name, session id (or unique prefix), or pid. | |
| include_user | No | Include user turns as well as assistant turns. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral disclosure burden. It does well by revealing that the transcript includes work from phone and claude.ai sessions and explicitly excludes subagent sidechains and tool plumbing. This goes beyond a generic 'reads transcript' statement, though it does not mention response format or other edge behaviors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The main action is stated first, and the second sentence adds valuable exclusions/inclusions that would otherwise be unknown. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a relatively simple read operation with a small, fully described schema, the description covers the essential context: what is returned, what additional sources are included, and what is omitted. It could be slightly more explicit about return shape or the fact that it is non-mutating, but the name and verb make this largely evident.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides descriptions for all three parameters, including defaults and ranges, so schema coverage is 100%. The description adds no additional parameter-level semantics beyond calling the resource a 'session,' which aligns with the schema. Baseline of 3 is appropriate because the schema carries the parameter documentation burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('Read') and resource ('recent conversation turns from a session'). It also adds distinguishing scope, noting that phone-driven and claude.ai-driven work are included, and that subagent sidechains and tool plumbing are omitted. This makes the tool's purpose unambiguous even among siblings like list_sessions and get_reply.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies its use case: reading recent conversation history from a session. However, it does not explicitly contrast it with sibling tools or state conditions like 'use get_reply when you need a single reply' or 'use list_sessions to enumerate sessions.' Usage context is clear but not explicitly differentiated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rename_sessionRename a sessionA
Change a session's display name, as shown in its prompt box and session pickers.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The new display name. | |
| session | Yes | Session name, session id (or unique prefix), or pid. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly discloses the mutating nature ('Change') and the user-visible effect (display name shown in prompt box and session pickers). No annotations are present, so the description carries the burden, but for a simple one-field rename it adequately reveals the behavior and scope of the change.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. It states the action, the target, and the visible effect in a compact way, earning its place without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity tool with two required parameters and full schema coverage, the description is mostly adequate. However, there is no output schema and no mention of return values, errors, or side effects beyond the display name, leaving a small but real gap in the agent's ability to handle the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already explains both parameters: 'name' is the new display name and 'session' accepts a session name, id, prefix, or pid. The description adds only minor context about where the name is displayed, so it doesn't significantly expand on the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Change a session's display name' and even clarifies where the name appears ('prompt box and session pickers'). This is clearly distinct from sibling tools like list_sessions, send_message, or get_reply, so an agent can identify what this tool does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance about when to use this tool versus alternatives, no prerequisites, and no mention of when not to use it. The intended use is only implied by the verb 'Change', but the description doesn't state a usage policy or compare to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageSend a message to a sessionA
WHEN TO USE THIS: any question or instruction about the user's own projects, code, repositories, machine, builds, deployments or work in progress belongs to a session — relay it. You do not know what is on their disk, and neither does a web search. Do not answer from your own knowledge, do not search the web, and do not ask clarifying questions the session could answer better: pass it through and let the session look. Answer in your own voice only when the user asks about you, or about how this connector itself works.
Queue a prompt in a running session and return immediately with a cursor. The message enters that session as if typed, so it is also visible to any Remote Control client watching it. Follow up with get_reply, passing the cursor as since, to watch the session work. Prefer this over ask for anything long-running.
| Name | Required | Description | Default |
|---|---|---|---|
| message | Yes | The prompt to deliver, copied word for word from what the user wrote, in their original language. Do not rephrase, translate, summarise, expand, or add framing of your own — the receiving agent must see the user's exact words. Only compose your own wording if the user explicitly asked you to. | |
| session | Yes | Session name, session id (or unique prefix), or pid. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it discloses the key behaviors: the call queues a prompt and returns immediately with a cursor (asynchronous), the message appears as if typed, and it is visible to Remote Control clients. It stops short of addressing failure modes or side effects when the session acts on the prompt, but the main behavioral contract is clearly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but it is front-loaded with the most important routing rules and every section serves a purpose. The opening 'WHEN TO USE THIS' block is somewhat repetitive about not answering from knowledge or searching the web, which keeps it from being a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with no output schema and no annotations, the description covers the workflow end-to-end: when to call it, what it does, what it returns (a cursor), and how to follow up with `get_reply`. It remains slightly incomplete about what happens when the session is not running or if the prompt is rejected, but those are edge cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline applies and the schema already documents both `session` and `message` thoroughly, including the word-for-word requirement. The description reinforces the semantics behaviorally ('enters that session as if typed') but does not add new parameter meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Queue a prompt in a running session'), a concrete resource (a session), and a clear delivery mode ('as if typed'). It also differentiates the tool from its sibling `ask` by stating a preference for long-running work, so an agent can select it without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE THIS' block gives explicit selection criteria: user questions about their own projects, code, machine, etc. should be relayed to a session rather than answered from knowledge or web search. It also names the follow-up tool (`get_reply`) and states when to prefer this over `ask`, which is exactly the kind of routing guidance needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
session_statusGet session statusA
Report the current state of one session, resolved by name, session id, or pid.
| Name | Required | Description | Default |
|---|---|---|---|
| session | Yes | Session name, session id (or unique prefix), or pid. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. 'Report' and 'current state' imply a read-only snapshot, but it does not disclose error behavior, exact return shape, or what happens when the session is not found. This is adequate but not thorough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no redundant words. It conveys the core operation and resolution options clearly and efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and the parameter is fully documented, but there is no output schema and the description does not hint at what status fields are returned or how this tool relates to read_transcript. It is usable, but not fully complete for all selection and invocation needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully documents the single parameter, including the same name/id/pid resolution detail. The description adds no new parameter semantics beyond what the schema provides, so the 100% schema coverage baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'Report the current state of one session.' It also specifies the resolution methods (name, session id, or pid) and the singular 'one session' distinguishes it from list_sessions and other sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'one session' sets clear context that this tool is for a targeted single-session lookup rather than enumeration, which reasonably distinguishes it from list_sessions. However, it does not explicitly name alternatives or when-not-to-use conditions, so it misses a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.1.0- First observed
ask - First observed
get_reply - First observed
list_sessions - First observed
read_transcript - First observed
rename_session - First observed
send_message - First observed
session_status
TDQS
Scored across 7 tools
send_message and ask both relay prompts to a session, differentiated mainly by async-vs-sync behavior; the descriptions document this distinction but the overlapping purpose creates selection risk. read_transcript and get_reply also both retrieve conversation output, though they differ in full-history vs. incremental-polling. The remaining tools (list_sessions, session_status, rename_session) are clearly distinct.
Most tools follow a clean verb_noun pattern (list_sessions, read_transcript, send_message, get_reply, rename_session), but session_status breaks the pattern by omitting a verb, and ask is a bare verb with no noun. These are minor deviations that don't cause real confusion.
Seven tools is well within the ideal range for a session-driving server. Each tool has a clear job: list, status, transcript, async send, reply polling, sync ask, and rename — nothing feels redundant or missing at the count level.
The core drive-a-session workflow is fully covered: discover sessions, check status, send prompts (both sync and async), follow progress, and read history. The main gap is the lack of a stop/cancel operation for long-running work, and session creation appears out of scope since sessions come from phone or claude.ai clients.
Maintenance
Related MCP Connectors
Use AI models for chat, image, and video generation from Claude Code and other MCP hosts.
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Related MCP Servers
- AlicenseBqualityDmaintenanceMCP server for managing Claude Code conversation sessions1296 npmMIT
- AlicenseAqualityBmaintenanceLocal MCP server that wraps the headless Claude Code CLI as MCP tools, providing stateless access to Claude's coding capabilities through prompt-based interactions. It enables users to execute Claude Code commands with various prompt formats and structured outputs directly from MCP clients.3MIT
- AlicenseAqualityDmaintenanceThis MCP server enables remote control and management of Claude Code agents, allowing you to execute missions, configure agent personalities, and integrate with other MCP tools.79 npm1MIT
- FlicenseNot gradedqualityCmaintenanceExposes headless Claude Code as a remote MCP server with a voice client, enabling hands-free task execution and session management via OpenAI's Realtime API.-