t3code-mcp
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., "@t3code-mcpcreate a thread in project acme with default harness and model, and send 'fix the failing tests'"
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.
t3code-mcp
A local MCP server that lets coding agents create and manage threads in a running T3 Code server.
Runs on Bun with selectable stdio, Streamable HTTP, or legacy HTTP/SSE for MCP clients, authenticated HTTP and WebSocket connections to T3, and no build step.
Talks to T3 the way the T3 web app does: T3's own HTTP + WebSocket interfaces and T3's own pairing tokens.
Threads show up in the normal T3 UI, with a link back to them.
Never opens or writes T3's database.
Runs locally. Stdio needs no extra port; HTTP and SSE listen on loopback by default.
Tools
Tool | What it does |
| Projects the T3 server knows, with ids and workspace roots |
| Git worktrees and local branches of one project |
| Configured harnesses and their models, with a usable flag and reason |
| Recent threads, newest first, optionally per project |
| Create a thread with an explicit project + worktree + harness + model and send the first prompt |
| Send a follow-up prompt to an existing thread (steers a running turn) |
| Status, latest turn state, and recent messages including the assistant reply |
| Block until the current turn finishes, then return the reply |
| Interrupt the running turn |
Related MCP server: codex-mcp-server
Guarantees
No silent substitution. Unknown, disabled, uninstalled, or signed-out harnesses, unknown models, projects, and worktrees fail with the list of valid options.
No duplicate launches. Pass an
idempotencyKey: thread, command, and message ids are SHA-256 of the key, and T3 dedupes on command id, so a retry after a crash cannot launch twice. A key whose command T3 rejected is burned; the error says so.Loud on drift. The response fields the wait loop depends on are checked at runtime, so a T3 upgrade that renames them fails clearly instead of reporting "done".
Requirements
Bun 1.2 or newer.
A running T3 Code server on this machine (desktop app,
t3 start, ornpx t3).A pairing code from that T3.
Install and pair
git clone https://github.com/daniel100097/t3code-mcp.git
cd t3code-mcp
bun install
# one-time: mint a pairing code in T3 (Settings → Connections, or:)
t3 auth pairing create --ttl 10m --label t3code-mcp --json # the code is the "credential" field
bun run src/cli.ts pair <code-or-pairing-url>
bun run src/cli.ts statuspair exchanges the one-time code for a 30-day bearer token and stores it in ~/.t3code-mcp/credentials.json (mode 0600). Run pair again when it expires; revoke it any time in T3 → Settings → Connections (or t3 auth session revoke). Credentials from earlier installations are still recognized.
Headless alternative: set T3_ACCESS_TOKEN to a token from t3 auth session issue --token-only.
Configure your MCP client
Select a transport
All three modes expose the same MCP tools and use the same T3 pairing credentials. Stdio is the default.
Transport | Start command | Client connection |
Stdio |
| Client launches the process and uses stdin/stdout |
Streamable HTTP |
|
|
Legacy HTTP/SSE |
|
|
Select the transport directly and set a different address or port:
bun run src/cli.ts serve --transport http --host 127.0.0.1 --port 8080
bun run src/cli.ts serve --transport sse --port 8080
bun run src/cli.ts serve --transport stdio
# Or use environment variables (flags take precedence):
T3CODE_MCP_TRANSPORT=http T3CODE_MCP_PORT=8080 bun startStop the running server before switching HTTP and SSE on the same port. --port 0 selects a free port; the server prints its endpoint to stderr. serve can be omitted when passing transport flags.
Stdio
Use the absolute path to your checkout in your MCP client's stdio configuration. For clients using mcpServers:
{
"mcpServers": {
"t3code-mcp": {
"command": "bun",
"args": ["/path/to/t3code-mcp/src/cli.ts", "serve", "--transport", "stdio"]
}
}
}Streamable HTTP
Start bun run start:http, then configure your client with the /mcp URL. For clients using mcpServers and a transport type:
{
"mcpServers": {
"t3code-mcp": {
"type": "http",
"url": "http://127.0.0.1:3001/mcp"
}
}
}Legacy HTTP/SSE
Start bun run start:sse, then configure the /sse URL:
{
"mcpServers": {
"t3code-mcp": {
"type": "sse",
"url": "http://127.0.0.1:3001/sse"
}
}
}The SSE stream advertises /messages?sessionId=... as its POST endpoint; the client handles this automatically. Client configuration formats vary, so use the matching transport and URL in your client's schema. Prefer Streamable HTTP when your client supports it.
Docker
GitHub Actions builds ghcr.io/daniel100097/t3code-mcp for linux/amd64 and linux/arm64. The image runs as the non-root bun user, contains only production dependencies, and defaults to stdio. All CLI commands and transport flags work in the container.
docker pull ghcr.io/daniel100097/t3code-mcp:latest
# Or build and check the image locally:
docker build -t t3code-mcp:local .
bun run test:docker t3code-mcp:localSet T3_SERVER_URL explicitly in containers: host runtime-file discovery cannot reliably check host process IDs from a container. Set T3_ACCESS_TOKEN in your shell to a token from t3 auth session issue --token-only; the examples forward it at runtime. The image does not contain credentials or need access to your project files.
Connect to T3 on a Linux host
Use host networking to reach T3 even when it listens only on 127.0.0.1. Replace 3773 with your T3 server's actual port:
# Streamable HTTP at http://127.0.0.1:3001/mcp
docker run --rm --network host \
-e T3_SERVER_URL=http://127.0.0.1:3773 \
-e T3_ACCESS_TOKEN \
-e T3CODE_MCP_HOST=127.0.0.1 \
ghcr.io/daniel100097/t3code-mcp:latest serve --transport http
# Stdio: keep stdin open with -i; do not allocate a TTY with -t.
docker run --rm -i --network host \
-e T3_SERVER_URL=http://127.0.0.1:3773 \
-e T3_ACCESS_TOKEN \
ghcr.io/daniel100097/t3code-mcp:latest serve --transport stdioFor legacy SSE, change --transport http to --transport sse and connect to http://127.0.0.1:3001/sse.
Connect to T3 on Docker Desktop
Use Docker Desktop's host alias and publish the MCP port on loopback:
docker run --rm -p 127.0.0.1:3001:3001 \
-e T3_SERVER_URL=http://host.docker.internal:3773 \
-e T3_ACCESS_TOKEN \
ghcr.io/daniel100097/t3code-mcp:latest serve --transport httpThe image defaults T3CODE_MCP_HOST to 0.0.0.0 inside the container so published ports work. With Linux host networking, explicitly use T3CODE_MCP_HOST=127.0.0.1 as shown above to keep the MCP listener local.
Persist pairing credentials
To use pairing instead of T3_ACCESS_TOKEN, mount a named volume at /data for both the pairing command and the server. For a Linux host:
docker volume create t3code-mcp-data
docker run --rm --network host \
-e T3_SERVER_URL=http://127.0.0.1:3773 \
-v t3code-mcp-data:/data \
ghcr.io/daniel100097/t3code-mcp:latest pair <pairing-code>
docker run --rm --network host \
-e T3_SERVER_URL=http://127.0.0.1:3773 \
-e T3CODE_MCP_HOST=127.0.0.1 \
-v t3code-mcp-data:/data \
ghcr.io/daniel100097/t3code-mcp:latest serve --transport httpThe token is stored in /data/credentials.json. Use the same T3 URL for pairing and serving. On Docker Desktop, apply the host alias and port mapping from the previous example.
GitHub builds
The Docker workflow runs formatting, linting, type checks, and tests before building. It then checks MCP initialization and tool discovery against the production image. Pull requests build both architectures without publishing; pushes to main, version tags, and manual workflow runs publish to GHCR using the repository's GITHUB_TOKEN.
Image tag | Published from |
| Successful builds of |
| Each published commit |
| A version tag such as |
The Bun image and GitHub Actions are pinned; update the Bun version in both Dockerfile and the workflow together.
Typical agent flow
t3_list_projects → pick a project id
t3_list_worktrees {project} → pick a worktreePath (or use the project root)
t3_list_harnesses → pick harnessId + model slug
t3_create_thread {project, worktreePath, harness, model, title, prompt,
idempotencyKey, wait: true} → reply text + thread url
t3_send_message {threadId, prompt, wait: true} → next reply
t3_get_thread {threadId} → status + recent messages
t3_cancel_turn {threadId} → stop a running turnEvery thread result includes url (opens the thread in the T3 web UI) and turn.state (running, completed, interrupted, error).
Environment variables
Variable | Meaning |
| MCP transport: |
| HTTP/SSE bind address. Default |
| HTTP/SSE port. Default |
| Skip discovery and use this origin, e.g. |
| T3 data directory to search for |
| Bearer token to use instead of the stored one |
| Path of the credentials file. Default |
CLI commands: serve (default), pair <url-or-code>, status, help. Run serve --help for transport options.
How it works
MCP transports. Stdio uses the SDK's stdio server. Streamable HTTP uses its stateless HTTP handler, supporting both current and older MCP protocol versions. Legacy SSE uses one event stream and a separate message endpoint per client. Network modes support multiple clients and close connections on shutdown.
Discovery. Reads
<T3 home>/userdata/server-runtime.json(thendev/), checks the pid is alive, and probes/.well-known/t3/environment. The server connects lazily on the first tool call, so the MCP server starts even while T3 is still booting.Auth. Bearer token from T3's pairing flow (
POST /oauth/tokentoken exchange), sent on HTTP requests and on the WebSocket upgrade.Reads.
GET /api/orchestration/shellandGET /api/orchestration/threads/:id?turnLimit=.Commands.
orchestration.dispatchCommandover T3's WebSocket RPC:thread.turn.startwithbootstrap.createThread(and optionalprepareWorktree), andthread.turn.interrupt.RPC client.
server.getConfigandvcs.listRefsare socket-only, sosrc/t3/transport/rpc-client.tsspeaks the RPC JSON envelope on Bun's built-in WebSocket:Request,Chunk+Ackback-pressure,Exit,Ping/Pong,Interrupt.Waiting. One
orchestration.subscribeThreadstream stays open per wait; on settle events the HTTP snapshot is re-read a few times. After a dispatch only the turn carrying your own message id counts.
Wire contracts target T3 Code server 0.0.43-nightly.20260918.
Development
bun test # unit tests and MCP transport integration tests; no T3 needed
bun run typecheck
bun run lint # strict, type-aware linting
bun run lint:fix # apply safe lint fixes
bun run format # format the project
bun run check # formatting, lint, types, and unit tests
bun run test:docker t3code-mcp:local # MCP smoke test against a built Docker image
bun run test:live # read-only checks against your running T3
bun run test:live --create <projectIdOrRoot> <harness> <model> # also launches ONE real threadOxlint checks correctness, suspicious code, performance, and TypeScript safety with warnings treated as failures. Narrow overrides allow sequential discovery, paging, and stream operations, plus awaited test assertions that Bun currently types as returning void. Oxfmt formats the source, tests, scripts, configuration, and documentation.
Layout:
src/
cli.ts entry point: serve | pair | status
mcp/
register-tools.ts assemble the tool registry
serve-options.ts transport flags and environment settings
http-server.ts Bun HTTP listener, request validation, and routing
sse-transport.ts legacy SSE event streams and message handling
register-tool.ts JSON responses, error handling, and annotations
schemas.ts shared MCP input schemas
presenters.ts thread summaries, replies, and message formatting
tools/ project, harness, thread, and turn handlers
t3/
client.ts typed T3 operations and their options
connection.ts assemble authenticated HTTP and RPC clients
session.ts lazy connection lifetime
server-discovery.ts find the running T3 server
credentials.ts pairing exchange and token store
selection.ts strict project, harness, model, and worktree lookup
command-ids.ts idempotency key → deterministic ids
thread-snapshot.ts read snapshots and check contract drift
turn-waiter.ts wait for the caller's turn to settle
contracts/ orchestration, command, provider, and VCS wire shapes
transport/ HTTP and WebSocket RPC clients, shared error formatting
test/ tests grouped to match the source modules
scripts/smoke-live.ts opt-in checks against a running T3 server
scripts/smoke-docker.ts MCP smoke test against a production Docker image
Dockerfile production container with all MCP transports
.github/workflows/docker.yml checks, image smoke test, and multi-platform GHCR publicationT3 wire contracts live in src/t3/contracts/; client options and transport types stay beside the code that owns them. MCP schemas reuse the contract's mode values, and inferred schema types describe validated inputs. The T3 client has no dependency on the MCP layer.
Security
The stored token carries T3's standard client scopes (
orchestration:read/operate,terminal:operate,review:write,relay:read). Treat the credentials file like a password.Anything reachable through your T3 (its projects, its harness credentials) is reachable through this server. Only expose it to MCP clients you trust.
HTTP/SSE bind to
127.0.0.1by default and validate Host and Origin headers. The MCP listener has no client authentication; T3 pairing authenticates the connection from this server to T3. Use an authenticated proxy if you expose the listener beyond your machine. Wildcard bind addresses accept Host headers for the machine's local interface addresses; a proxy should forward a matching Host header.
License
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP Server for an Agent Task Marketplace
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
Create guides as MCP servers to instruct coding agents to use your software (library, API, etc).
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients to spawn and control Codex CLI and Claude Code sessions on the host machine, with session management and filesystem access.4MIT
- AlicenseCqualityDmaintenanceBridges MCP clients with local Codex CLI to execute autonomous coding tasks, manage threads, and inspect history via SQLite state.13836 npm4Apache 2.0
- FlicenseAqualityCmaintenanceMCP server for interacting with a running T3 Code instance. Enables viewing agent threads, sending messages, and approving permission requests from Claude Code or voice-controlled models.19-
- AlicenseAqualityAmaintenanceEnables MCP clients to create, read, message, wait for, interrupt, and settle persistent peer threads through an existing T3 Code server, keeping them visible across its clients. It supports project-scoped coordination with source attribution and retry-safe commands.71MIT