Run these commands on the machine where your agent runs.{% if not new_token %} Replace kw_YOUR_AGENT_TOKEN with your saved token.{% endif %}
kw command (recommended)Works from any shell, waits out phone approvals, and scopes "this session" approvals per conversation. Install the client, store the token, set the agent up:
pipx install keywright
kw login {{ mcp_url | shellquote }} --paste # then paste the token on its own line
kw setup claude-code # or: kw setup codex
kw setup check
Agents then run kw resources, kw run <host> -r "why" -- <command>, kw put, kw get and kw tool. kw guide prints the full agent guide.
Export the token, then register Keywright:
export KEYWRIGHT_TOKEN={{ (new_token or 'kw_YOUR_AGENT_TOKEN') | shellquote }}
codex mcp add keywright \
--url {{ mcp_url | shellquote }} \
--bearer-token-env-var KEYWRIGHT_TOKEN
In ~/.codex/config.toml, set tool_timeout_sec = 180 in the Keywright section to leave time for phone approvals. The section should look like this:
[mcp_servers.keywright]
url = {{ mcp_url | tojson }}
bearer_token_env_var = "KEYWRIGHT_TOKEN"
tool_timeout_sec = 180
Start Codex from the shell where KEYWRIGHT_TOKEN is exported. Set it again in new shells, or supply it through your environment manager. For the IDE extension, the variable must be available to the IDE process. Use /mcp in Codex to check the connection.
claude mcp add --transport http keywright \
{{ mcp_url | shellquote }} \
--header {{ ('Authorization: Bearer ' ~ (new_token or 'kw_YOUR_AGENT_TOKEN')) | shellquote }}
Point the SDK or the agent at a gateway with the same token; every call names a model, and the model is what you approve. kw llm <gateway> prints these lines from a stored profile.
# {{ g.name }}: {{ (g.config.models or []) | join(', ') or 'no models listed yet' }}
export ANTHROPIC_BASE_URL={{ (public_url ~ '/llm/' ~ g.name) | shellquote }}
export ANTHROPIC_AUTH_TOKEN={{ (new_token or 'kw_YOUR_AGENT_TOKEN') | shellquote }}
export OPENAI_BASE_URL={{ (public_url ~ '/llm/' ~ g.name ~ '/v1') | shellquote }}
export OPENAI_API_KEY={{ (new_token or 'kw_YOUR_AGENT_TOKEN') | shellquote }}{% endfor %}
Unset the real ANTHROPIC_API_KEY / OPENAI_API_KEY there, and rotate them: a key that was ever on the agent's machine is spent.
Use streamable HTTP at {{ mcp_url }} with an Authorization: Bearer <agent token> header.