t3code-mcp
# t3code-mcp
MCP server for a running [T3 Code](https://t3.codes) instance. See which agent threads exist and what they need, read their history, send them messages, approve their permission requests — from Claude Code, Claude Desktop, or (the end goal) a voice-controlled model like Hermes while away from a screen.
See `SPEC.md` for the design and `PLAN.md` for the phased build.
## Setup
```bash
pnpm install && pnpm build
```
1. Make sure T3 Code is running (desktop app or `npx t3@latest`).
2. Mint a bearer token for the local T3 server and put it in `.env` (or export it):
```bash
npx t3@latest auth session issue --token-only --label t3code-mcp --ttl 365d
echo "T3_TOKEN=<the token>" > .env
```
3. Sanity check against the live server (read-only):
```bash
pnpm smoke
```
## Connect from Claude Code
```bash
claude mcp add --scope user t3code -- node /Users/thomascrundwell/Documents/projects/t3code-mcp/dist/index.js
```
(Token is picked up from `.env` in this directory; alternatively pass `--env T3_TOKEN=...`.)
## Tools
**Visibility** — `t3_status`, `list_projects`, `list_threads` (filter by project / attention state), `get_thread`, `search_threads`
**Messaging & control** — `send_message`, `create_thread`, `wait_for_turn` (send-and-wait round trip), `interrupt_thread`, `stop_thread`, `archive_thread`, `unarchive_thread`, `set_thread_title`
**Hands-free interaction** — `pending_actions` (cross-thread "what needs me?" inbox), `respond_to_approval`, `respond_to_user_input`
**Voice layer** — `thread_digest` and `workspace_digest` (TTS-friendly `spoken` summaries), `wait_for_change` (long-poll until anything needs attention)
Every thread carries a single `attention` state: `needs-approval | needs-input | plan-ready | working | error | done | idle`.
## Remote / voice clients (HTTP mode)
For a remote voice agent (e.g. Hermes over Tailscale), run the streamable-HTTP transport with its own bearer token:
```bash
MCP_HTTP_TOKEN=<secret> node dist/index.js --http --port 3774 --host 0.0.0.0
```
Clients connect to `http://<machine>:3774/` with `Authorization: Bearer <secret>`. Binds to 127.0.0.1 unless `--host` is given; T3 Code itself stays localhost-only.
## Testing
- `pnpm smoke` — read-only pass over every query tool against the live server.
- `node scripts/smoke.mjs --mutate <projectId>` — additionally runs the full write loop (create disposable thread → agent replies → follow-up message → rename → stop → archive). Use a scratch project; "t3code-mcp scratch" (`/tmp/t3code-mcp-scratch`) exists for this.
## Notes / limitations
- Uses T3's HTTP JSON API only (`/api/orchestration/*`). Live push, git-worktree bootstrap, and turn diffs are WebSocket-RPC-only in T3, so: updates are polled, and `create_thread` runs threads directly in the project workspace (start worktree threads from the T3 UI).
- Image attachments not yet supported on `send_message`.
- Revoke access anytime: `npx t3@latest auth session list` / `... revoke`.
TDQS
Scored across 19 tools
Most tools target a distinct resource and action (threads, projects, approvals), but a few could be confused: interrupt_thread vs. stop_thread both halt work, and wait_for_turn vs. wait_for_change both block on state changes. The descriptions clarify these enough to avoid real misselection.
All names use snake_case, but the pattern is mixed: most are verb_noun (list_threads, send_message, get_thread), yet several are noun-only (pending_actions, thread_digest, workspace_digest) or use a prefix (t3_status). This inconsistency makes predicting tool names harder than a uniform verb_noun convention.
At 19 tools, the set is at the heavy end of the typical range. Each tool appears to have a genuine purpose, but some can feel redundant (two wait tools, two digest tools), making the surface larger than strictly necessary.
The tool surface covers the full thread lifecycle well: create, list, read, message, interrupt, stop, archive, unarchive, and title threads, plus approval handling and status monitoring. Minor gaps include no permanent thread deletion and limited project management, but these are not core to the server's apparent purpose.