Repository navigation
t3 auth session issue --access: mint an MCP client token with a runtime-mode ceiling, headless
#33080
freezscholte
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Problem
A headless control plane that dispatches coding work to T3 boxes over
/mcpcan't get a credential that lets those threads run tools without a human present.t3 auth session issueis documented as "Issue a scoped bearer access token for headless or remote clients", and/mcpaccepts its token when issued with--subject mcp-client. But the session it creates has no runtime-mode ceiling, and/mcptreats a missing ceiling asapproval-required. On 0.1.7:t3_thread_launchwithruntimeMode: "auto","auto-accept-edits"or"full-access"fails withruntime_mode_escalation_denied("Child runtime mode full-access is broader than parent mode approval-required").approval-requiredthat needs a tool stops on a permission request, andt3_pending_request"cannot approve a permission request". The run waits until someone opens the UI.So the token works for orchestration but can't run real work.
What already exists
The ceiling primitive is there; the CLI just doesn't expose it.
EnvironmentAuth.issueMcpClientSession({ access })setsruntimeModeCeilingfrom anAuthMcpClientAccesslevel.t3 thread startalready uses it in-process, withaccess: "full-access", revoked at exit (apps/server/src/cli/thread.ts).t3 auth session issuegoes throughissueSession, which never sets a ceiling.The workaround we use today drives the OAuth flow from a script on the box:
t3 auth pairing createPOST /oauth/mcp/registerPOST /oauth/mcp/decisionwith{ _tag: "pairing-code", access: "full-access", code }and PKCEPOST /oauth/mcp/tokenIt works: the 30-day token launches
autoandfull-accessthreads that run tools with no prompt. But it is four HTTP contracts, PKCE and a redirect to scrape, all to reach a primitive the CLI already holds.Proposal
Add an access level to the headless issue command:
--access <read-only|approval-required|auto-accept-edits|auto|full-access>maps toissueMcpClientSession({ access }), so scopes come frommcpClientScopes(access)and the ceiling fromaccess. That is exactly what the OAuth approval page produces.--accessimplies--subject mcp-client, or is rejected without it, so a ceiling never lands on a non-MCP session.--ttland--label. Running the CLI already requires local access as the server's user, which is the same trust thatt3 thread startrelies on.A separate
t3 auth mcp-client issue --access …subcommand would work just as well, if keepingsession issuegeneric is preferred.Use case
We run one T3 box per developer, on a VM, and a separate control plane dispatches tasks to those boxes: it launches a thread with
clientRequestIdfor idempotency, waits on it, reads it back and interrupts it when needed. Each box mints the dispatcher's credential when it is provisioned, the control plane stores it, and a scheduled job rotates it before the 30 days run out. With--access, provisioning and rotation are a single CLI call on the box, with no OAuth dance and no human approval. We'd default dispatches toauto, so Claude's classifier still screens risky actions, and allowfull-accessper task.Related
--accessmakes scripted renewal a single CLI call.t3 auth session issue): the same command, used headless.All reactions