WebCodex exposes an MCP endpoint so ChatGPT, Claude, and other MCP clients can work with repositories through the Runner that owns them. Ordinary users only need to choose between full use and a temporary trial; protocol surfaces, scopes, and credential taxonomy are reference material, not onboarding prerequisites.
For everyday use, run a regular Server + Runner. Follow the Full Setup guide for one-time login and project registration, and use --print-mcp-config during that same webcodex login to obtain regular HTTPS MCP connection values. Public HTTPS, Cloudflare Tunnel, and OpenAI Secure MCP Tunnel are reachability choices; they do not change the capabilities of this full development path.
If you only want to try one repository temporarily, use the share path below.
If ChatGPT reports:
FORBIDDEN: This conversation does not support developer MCPs
The rejection comes from the ChatGPT host or the conversation-level Developer MCP admission and routing layer. It does not by itself mean that WebCodex permanently disabled developer access, that the Runner is offline, or that the project registration is invalid.
Check the Runner and project state independently. If they remain available and the request did not reach WebCodex, retry in a conversation where ChatGPT admits Developer MCPs. No WebCodex configuration change is required solely because this host-side error appeared.
ChatGPT Dot support is best-effort. It depends on the plugin capabilities ChatGPT exposes for that Dot, and WebCodex does not define Dot as incompatible. Accounts and Dots can differ: some call WebCodex normally, while others discover the plugin and then ask to hand the work to a local Codex or local task. This project does not have a stable public description of when a Dot may operate on local resources directly, so this page does not treat one of those behaviors as the contract.
If a Dot lists the plugin but does not dispatch calls to WebCodex, delete that Dot, create it again, and add or authorize the WebCodex plugin once more. The difference can involve plugin state, a cache, or the capabilities saved when the Dot was created, and recreation has sometimes changed the behavior. Keep the existing ChatGPT authentication and permission settings; recreation does not require a WebCodex credential or configuration change.
If the same behavior remains after recreation, add the steps to issue #955. Those steps let us judge whether WebCodex itself can improve the case.
Explicit share is supported on Linux, macOS, and Windows and owns a temporary single-project environment for that foreground run. Windows x64 can use the managed default Cloudflare Quick Tunnel; Windows ARM64 needs a trusted explicit/PATH cloudflared because the pinned Cloudflare release publishes no official ARM64 artifact. Native OpenAI Tunnel supports both Windows x64 and arm64.
For the default temporary public path, WebCodex reuses an explicit/PATH cloudflared or downloads its pinned verified managed copy automatically, then run:
npm install -g @yyjeqhc/webcodex
cd /path/to/your/repository
webcodex shareWhen the CLI says WebCodex ready:
- In ChatGPT Developer Mode, create a custom app using MCP.
- Paste the printed MCP URL.
- Choose Access token / API key (Bearer token) for the default share.
- Paste the printed temporary Credential.
- Run Scan Tools.
- Try:
Inspect this repository and summarize its structure. Do not make changes.
The command performs project setup itself. Hosted ChatGPT cannot reach a
loopback-only webcodex run, so setup, doctor, and run are not required
steps before share. ChatGPT UI labels can vary by rollout; use the CLI output
as the source of truth for URL and authentication. Developer Mode, custom MCP
apps, and write/modify actions are controlled independently by the ChatGPT plan,
workspace, and admin settings; those client-side permissions are not widened by
WebCodex scopes.
If ChatGPT itself reports FORBIDDEN: This conversation does not support developer MCPs (or says the current conversation disabled the developer MCP
server), treat that as a Host/conversation admission problem until proven
otherwise. If the Host refuses to dispatch get_runtime_status, that text is not a
WebCodex tool result. Verify the Server/Runner independently before changing
credentials or Runner configuration; see Troubleshooting.
Use the same printed /mcp URL and authentication values. In Claude, add a
custom connector and paste the MCP URL. Other MCP clients should be configured
with the same endpoint and the authentication mechanism reported by the CLI.
When a client cannot set a Bearer header, webcodex share --auth query-token
provides an explicit temporary-share fallback: paste the printed sensitive
/mcp?token=... URL and choose No authentication. The query accepts only the
current share Project Credential; it is not a general PAT/OAuth/shared-key query
auth mechanism. Treat the full URL as a secret because URL queries may be logged.
For local-only clients, webcodex share --tunnel none exposes the loopback MCP
endpoint without cloudflared.
For an OpenAI-only private transport, create/select a Secure MCP Tunnel, export
CONTROL_PLANE_TUNNEL_ID plus a Restricted CONTROL_PLANE_API_KEY with Tunnels
Read + Use, and run webcodex share --tunnel openai. ChatGPT uses Connection:
Tunnel + No authentication; the temporary WebCodex Bearer stays local and is
injected by the native Rust Tunnel client.
For a long-lived loopback-only Server reached through OpenAI Secure Tunnel,
ChatGPT host-file rewrites authenticated by the explicitly allowed local tunnel
credential can be trusted by setting
WEBCODEX_MCP_TRUST_LOOPBACK_API_TOKEN_FILE_IMPORT=true. Starting with v0.4.2,
WebCodex Desktop writes this value by default for the local loopback Server it owns; an
existing explicit value is never overwritten. The exception works only when
WEBCODEX_ADDR resolves to loopback and the authenticated credential is either a
normal user API token or the configured Server bootstrap credential used by the
Desktop regular Tunnel. The regular Tunnel derives that credential from the local
WEBCODEX_TOKEN configuration and injects it into its private native Tunnel
authorization; users should not copy or expose that credential. Independent/network-
accessible Servers remain off by default and must not use this as a substitute for
OAuth.
For a regular independent Windows Server + Runner reached through OpenAI Tunnel, or to troubleshoot a case where local MCP is healthy but ChatGPT Connector creation still fails, see the Windows + OpenAI Secure MCP Tunnel deep dive. It is advanced setup/troubleshooting material, not required reading for a first-time user.
On Stateless MCP 2026 requests advertising MCP Apps HTML support, list_jobs,
read_validation_summary and read_git_review_summary can show bounded,
read-only milestone cards. The Job card foregrounds active or attention-requiring
Jobs; validation and committed-review cards omit raw logs and diffs. These static
cards do not poll, retry or invoke tools. High-frequency observation and validation
calls retain native tool presentation. WEBCODEX_MCP_APPS_ENABLED=false removes
App metadata/resources without disabling the underlying ordinary tools.
The live Work Result card and dedicated document readers have their own explicit App read paths. Historical Host continuation experiments do not turn a milestone card into an automatic continuation controller.
present_docx(project, path) presents an authorized unchanged/untracked .docx
without Git or a Workflow Session. It pins size/SHA-256 (10 MiB maximum) and
privately reads version-fenced segments. Common styles, fit width, zoom and supported
fullscreen are available; original download requires the Host's download capability.
Word-equivalent pagination, legacy .doc, encrypted packages and editing are
unsupported. Changed content requires explicit reopening. See the
DOCX reader contract for transfer,
sanitization, expansion limits and verification.
Call present_work_result once near the first successful Project action. Its
Activity / Results / Collaboration tabs show Window activity, linked Session
evidence, current uncommitted files and sealed final changes. A workspace snapshot
can include other work; partial file lists and missing counts are labelled, and a
clean workspace is not proof of task success. Results loads diffs only on demand.
A Host may open work_result_thread_panel({}) to recover the latest successful
presentation in the same authenticated Host Window, including its explicit
business Session. Failed presentations and unrelated actions cannot retarget it.
An open card retains its exact Project/Session on refresh; Window-linked evidence
does not grant refresh authority or select a Session. Missing binding/Window
identity fails closed. Reopen to select a newer successful presentation.
Changed-file text follows fresh observations by default; Pin snapshot for review holds the inspected version, and Follow changes resumes updates. Each read remains bound to an exact working-tree snapshot. Final files use the sealed final tree even after later edits. Only advertised paths may be read, in explicit 32 KiB pages up to 256 KiB per file, with partial content/caps labelled. Deleted files have no final version. Binary, non-UTF-8, symlink and submodule content is unavailable; failed or expired reads never fall back to a live path. Every read still reauthorizes its target.
Complete .md / .markdown files can render with the bundled Markdown parser.
Raw HTML remains text, DOM nodes/attributes are allowlisted, unsafe URLs are
rejected, links stay inert and external images are not fetched. Line/selection
transfer to chat remains deferred. Automatic App refresh pauses while hidden;
presentation and private refresh do not create live Window work activity.
The card navigation,
read ownership and invalidation, and
renderer/build boundaries own UI details.
The App registry owns current resource identity;
retired URIs never alias new templates. Refresh Host schemas and reopen cached
cards after descriptor changes. Rendering entrypoints retain model/App visibility;
private bridge tools return data without ui.resourceUri, as required by the
App presentation contract.
For an existing hosted Server intentionally configured for shared-key clients, use the long-lived shared-key path with the credential supplied by its operator:
webcodex connect https://webcodex.example --key-file /private/path/shared-keyconnect starts/reuses the local Runner and prints the MCP URL and credential
source after the connection is verified. This is separate from fresh self-hosted
Docker enrollment: keep the Docker Server bootstrap administrator token on the
Server, create a short-lived pairing code there, and use webcodex login on the
repository machine. Self-hosting is documented in Deployment.
Bearer/shared-key authentication is the simplest path. When a client requires
OAuth, use share --auth oauth or connect --auth oauth with that client's exact
callback URL and follow the CLI output. Managed-user OAuth remains a separate
advanced identity flow.
One canonical ToolRuntime serves both MCP projections. Adaptive Runtime remains the default, including ChatGPT: canonical ToolDefinition rank decides the direct tools; ordinary model-visible long-tail tools are invoked through call_runtime_tool; server-owned protocol capabilities and MCP App admission may add hidden extensions for the relevant protocol request. An explicit request-local CLI surface changes discovery and presentation only, as described below. read_tool_manifest(tool_name=...) is discovery only: it never dynamically registers a new Host tool. Its exact route.primary describes the preferred callable, and a normal direct tool also exposes route.fallback through call_runtime_tool for the case where that direct callable is not present; explicit MCP App presentation tools mark that fallback as blocked while Apps are enabled. Direct versus gateway routing changes presentation only and never bypasses the target tool's authentication, Project authority, permission, Runner capability, Session, or safety checks.
When their workflow group is enabled, nine durable Agent and Goal operations have a stricter Host exposure contract: create_agent_identity, rotate_agent_continuation_endpoint, list_agent_identities, prepare_goal_workflow, get_goal, checkpoint_goal, update_goal, bootstrap_agent_conversation, and consume_agent_wake are independently exposed with their canonical input schemas, accurate effect annotations and applicable OAuth requirements. They require normal Host tool review before a new trial. If a Host does not load or rejects one of these dedicated descriptors, WebCodex does not substitute call_runtime_tool; that generic route is not a fallback for these operations. Their _wc.control forms for Goal checkpoints, Wake consumption and Goal completion are also rejected before any main or sidecar effect; use the standalone canonical tools. This bounded stage does not claim compliance for unrelated Plugin operations. This exposure policy does not grant authority or guarantee Host acceptance, and does not alter each operation's existing authentication, OAuth scopes, permissions, ownership, lifecycle, replay-safety, or effect checks. The cause of a prior Host refusal remains unknown; this contract does not claim to resolve it. Other ordinary direct tools retain their existing gateway fallback, and hidden App methods remain hidden.
Adaptive Runtime (including ChatGPT) keeps model-facing Goal, Agent continuation
and Job continuation tools opt-in. The execution-only CLI surface excludes them;
legacy CLI configuration fields remain readable but cannot reopen workflow routes. Configure the Server's WEBCODEX_MCP_TOOL_EXPOSURE as closed JSON:
{
"adaptive": {"goals": false, "agent_continuation": false, "job_continuation": false},
"cli": {"goals": false, "agent_continuation": false, "job_continuation": false},
"oauth_clients": [
{
"client_id": "YOUR_REGISTERED_CHATGPT_OAUTH_CLIENT_ID",
"adaptive": {"goals": true, "agent_continuation": true, "job_continuation": true}
}
]
}For example, place the compact JSON value in the existing Server environment
configuration. The value is read and validated once before the Server starts;
restart the Server and refresh/reconnect the Host's tool catalog after an operator
changes it. This example enables the full workflow surface only for the exact
authenticated OAuth client, so online ChatGPT needs no custom request headers.
X-WebCodex-MCP-Surface: cli still selects the CLI surface on each request.
An omitted client surface inherits its deployment surface; a supplied surface is
a complete replacement, with omitted booleans defaulting to false. Client names,
clientInfo, client windows, Sessions and previous requests never select an override.
| Setting | Model tools controlled |
|---|---|
goals |
The canonical Goal category, including preparation, reads, checkpoints, updates and present_goal_plan. |
agent_continuation |
Agent identity/setup, Endpoint rotation/detach, bootstrap/Wake consumption, wait_for_agent_events, Task Endpoint continuation and the Agent continuation card/bridge. |
job_continuation |
wait_for_job_terminal and its Job continuation card/bridge. Ordinary same-Job readiness and observation remain available. |
The switches are independent. Enable both goals and agent_continuation for
Goal-driven automatic continuation. Enabled individually reviewed operations
receive canonical standalone descriptors on Adaptive. CLI remains execution-only. Disabling a group removes its model descriptors
and optional App resources/bridge helpers. Exact manifests report unavailable
routes, generated follow-ups omit unavailable targets, and direct/gateway calls
cannot enable the omitted group. The Workbench independently retains its existing
App-only Goal read/create/update controls: those remain ui.visibility=["app"],
are not model routes and do not become gateway fallbacks. This MCP exposure policy
is not a credential scope or a global feature-disable switch for Runtime API/UI.
Configuration is limited to 16 KiB and 64 unique OAuth client entries; client ids
are non-empty, at most 256 UTF-8 bytes, without whitespace/control characters.
Unknown fields, duplicate clients, malformed JSON and wrong types fail startup;
diagnostics omit input values and client ids. Operator status reports surface
defaults and the override count. Scope filtering, canonical business schemas,
ownership, generation/revision fences, effect checks and the independent Host
review requirement still apply. WEBCODEX_MCP_COMPACT_SCHEMAS controls schema
detail, and WEBCODEX_MCP_APPS_ENABLED separately controls App admission; neither
implicitly enables workflow tools. Exposure is also separate from
WEBCODEX_GOAL_WORKFLOW preference and WEBCODEX_MCP_APP_RESUME_MODE readiness policy.
A shared Server can serve ordinary calls and Host-native orchestration without changing tools or restarting between clients. Configure these optional HTTP headers on the client connection, or inject them on a dedicated proxy route:
X-WebCodex-MCP-Profile: direct
X-WebCodex-MCP-Budget-Secs: 20X-WebCodex-MCP-Profile accepts exactly direct or host_code_mode. Omission
uses WEBCODEX_MCP_HOST_PROFILE (whose default is direct); it does not detect
client brands or prove that a particular call was programmatically orchestrated.
Send the header on each request, not just initialize or work_on_project.
There is no sticky Window, Session, credential or transport selection. For a
Server defaulting to host_code_mode, ordinary clients must explicitly select
direct; clients unable to set headers can use a configured proxy route.
The optional positive-integer budget header can only reduce the deployment's
resolved WEBCODEX_MCP_HOST_BUDGET_SECS budget. Return waits preserve the existing
five-second guard (and the existing one-second floor for tiny budgets). A Direct
request on a Server budget of 55 seconds has a 50-second synchronous/observation
ceiling. CLI defaults to that ceiling; Adaptive retains its ten-second execution
handoff; Host Code
Mode retains its five-second handoff/observation slices. wait_for_job_readiness
uses up to 45 seconds, further capped by the selected budget minus the guard,
not by the five-second handoff slice. Header omission leaves deployment behavior
unchanged. Empty, repeated or malformed headers fail before dispatch without
echoing their values; oversized numeric budgets are capped, not used to enlarge
Server limits.
This budget limits execution handoff and Job observation/readiness waiting. It
is not a universal RPC timeout or an execution lifetime: timeout_secs, Job
identity, effects, authorization, internal orchestration caps and Runner ownership
are unchanged. Explicit work_on_project.guidance_profile still selects guidance
only; it does not override transport timing. Subsequent context refreshes use the
policy of their own request. /api/tools/call, result-text compatibility,
tools/list, Apps admission and standard error semantics are unaffected.
get_runtime_status.mcp_host.profile reports the profile effective for this
request in both sparse and full responses. deployment_profile identifies the
immutable Server default, and profile_source is deployment or
request_header, including an explicit header equal to the default. Omitted
headers never inherit another client's selection. The full response's
effective_config.mcp_host remains the deployment timing snapshot; request-local
profile diagnostics do not change execution policy or that operator evidence.
Metadata/full trace records the actual selection as mcp_request_policy_selected:
selection.effective, separate profile/budget sources, parsed requested budget
and deployment cap. This distinguishes omitted headers from explicit defaults
and a clamped request; raw headers are not retained. Normal results and authority
are unchanged. See client contracts and validation.
Ordinary work stays in the current turn: finish independent work, use one bounded
wait_for_job_readiness join for blocking Jobs, then observe_jobs for needed
results. At deadline reassess work/dependencies instead of mechanically refilling
waits. Preserve pending identities when work cannot finish; never redispatch or
assume a new model turn will start. wait_for_job_terminal is optional durable
attention for an explicitly established continuation workflow, not a blocking
wait or a prerequisite for ordinary MCP.
For a CLI client connecting directly to a local or hosted Server, add
X-WebCodex-MCP-Surface: cli to every request, including discovery. Omission
(or adaptive) keeps the existing ChatGPT surface. This is independent of the
direct / host_code_mode waiting strategy and does not enable permissions,
change authentication, or remember a Project/Session between calls. Reconnect or
refresh tools after changing connection headers. Empty, unknown or repeated
preference headers fail before dispatch without echoing their values.
The CLI surface is execution-only: the local agent owns planning, repository
instructions and conversation state. It does not bootstrap a Workflow Session,
fetch guidance/Skills, deliver collaboration messages, or attach passive Job
attention. _wc sidecars are rejected, including empty envelopes and nested
gateway envelopes. Canonical audit evidence and existing history remain intact.
- With a default Project, the direct catalog has eight tools:
run_shell,observe_jobs,stop_job,read_files,edit_project_files,search_project_texts,read_tool_manifestandcall_runtime_tool. Without a default Project, it also exposeslist_projectsto select a target. Find filenames and check Git state withrun_shell, for examplegit ls-filesandgit status --short.list_project_files,list_project_tracked_filesandread_workspace_changesremain available through manifest + gateway;list_projectsuses that route too when a default is configured. - Direct schemas are selection subsets, never Server validators. The editor
shows
path,kind,edits[].old_text/new_text,content,expected_read_revisionandto_path. Exact manifests retain occurrence, range, match-count, line-edit and dry-run options. Direct observation hidesobservation_refandsummary_only; direct search shows common query fields. Canonical advanced fields still work when supplied in direct calls, through the same parser, revision guards, permissions and capabilities. Session-era fields such as workspacesession_event_limitare not advertised by CLI. Discovery budgets are 10,000 bytes with a default Project and 12,000 without, measured as the compacttools/listresult in the local-agent acceptance. run_shellis the default command entry.observe_jobscombines bounded waiting with result/log retrieval for the original Job;stop_jobrequests cancellation. Exact argv, scripts, interactive stdin, LSP navigation, build and validation remain canonical specialized tools, discovered through the manifest and called through the gateway. Process lifetime, cancellation and uncertain-effect authority remain unchanged.- Workflow Sessions, Goals, durable Agent orchestration, Skills, Memory,
communication and Apps are unavailable through discovery and dispatch.
CLI workflow exposure flags cannot reopen these routes. Manifest workflow
recipes are disabled (
include_recommended_flows=trueis rejected). - WebCodex results are text without duplicate
structuredContent, using standardisError. Source/read revisions, partial failures, unknown effects, Job identities, limits and fenced recovery remain visible. Native image/resource blocks and third-party provider passthrough retain their contracts. initialize.instructions/server/discovercontain only the execution boundary and recovery contract. Read repository instructions explicitly as files when needed; there is no automatic instruction injection.
CLI command and file behavior:
run_shellwaits up to 50 seconds by default under Direct timing. Setsync_wait_secsfor an earlier handoff; Server/Host caps can only shorten it. Pending output includes the available tail and the same Job continuation. CLI process lifetime defaults to 600 seconds (timeout_secs), subject to Runner limits; expiration terminates the process tree, independently of handoff timing.observe_jobs(items=[{job_id}], wait_secs=50)waits for terminal without a prior token.wake_ondefaults toterminal; explicitly selectchangeormeaningful_changefor update waits, which still require a baseline token. A token returns the latest incremental tail, including terminal diagnostics. Only explicitpage=trueitems read forward from the token for log recovery; generated continuations request 200 lines per page. Storage gaps/epoch changes report reset. A first observation without a token reads the current tail.- Truncated command previews keep the beginning and end. A synchronous truncated result retains its original Job under existing bounded retention and offers a log continuation. For each stream, CLI starts that page after the complete lines already shown at the beginning; a partly shown line is read again. Never rerun an effectful command to recover its output.
- A
next:line carries executable arguments and replaces separatejob_id/observation_tokenlines. Without a continuation those selectors remain. Equivalent CLI defaults such aswake_on="terminal"are omitted fromnext:. Per-stream reset flags replace the redundant aggregate reset message. - Workspace text shows
diff_status/diff_stat_statusonly for failed inspections, not an unrequested diff.??rows replace duplicateuntracked_filewarnings; other warnings remain. A refused creation through a symlink explains that the resolved path is outside the Project/allowed roots or is protected (for exampledeps -> node_modules), without exposing the resolved outside path. These presentation changes are CLI-only; Adaptive results and canonical execution contracts are unchanged. - File reads, searches, directory/filename listing, LSP paths and transactional edits accept absolute paths inside the resolved Project root. Runner path and symlink protections still apply; paths outside that root are rejected.
edit_project_fileshas one canonical flat change schema.kinddefaults toedit, and an edit'skinddefaults toreplace_exact.writeoverwrites an existing file usingcontentplusexpected_read_revision; it requires the additive Runner capabilityapply_file_write. Unique, unscopedreplace_exact/delete_exactcan omit revision: Runner checks every old-text match against the same source snapshot before committing the transaction. This checks the edited text, not whether unrelated file content changed. Supplied revisions always apply; whole-file writes/deletes/renames, insertions, occurrence/range/scope selectors and bulk replacements still require revision.- CLI rejects
session_id, andrun_shellrecording-only fieldspurpose,assertion_name,result_expectation. Calling CLIstop_jobexplicitly requests cancellation; there is no additionalconfirm=truestep. Client approval and canonical Job/Project ownership checks remain in force. - Direct execution/read/edit/search/status text uses explicit content fields; telemetry additions no longer automatically appear. Failures, uncertain effects, retained-log loss and exact follow-up arguments remain visible. Unfiltered manifests start with coding tools; exact or filtered lookup can still discover other admitted execution tools.
read_files/search_project_textsdefault to a 45,000-byte canonical result budget, preserving revision-fenced paging. CLI descriptors request Claudeanthropic/alwaysLoadandanthropic/maxResultSizeChars=70000; these are client presentation hints, not larger Server output budgets. The initialization hint asks clients to read remote AGENTS.md / CLAUDE.md; WebCodex does not inject their contents or plan the task. Client behavior should be checked with the acceptance harness.
Images already have a gateway route: discover read_project_artifact_chunk, then
call it with a Project-relative ordinary image path and as_image=true. The file
does not need to be registered as an artifact. Existing path protection, PNG/JPEG/
WebP validation and the 4 MiB image limit apply; image reads cannot be combined
with chunk offsets/lengths. CLI preserves the MCP image content block beside
text, rather than converting it into text or discarding it. A text-only consumer
must handle that block to display the image. An isolated Server/Runner probe
verified an ordinary PNG and the preserved image block; model-side visual
interpretation was not tested. The current option is manifest + gateway; a future
explicit CLI image entry could reduce discovery calls, but is not implemented.
For the optional native-tool comparison, local Claude Code 2.1.319 accepts
--tools "", leaving the MCP tools and no native executable tools (its provider
request still includes DeferredToolPlaceholder). Local Codex 0.166.0 accepts
--disable shell_tool, removing exec_command / write_stdin while retaining
apply_patch, view_image and other native tools. These are client controls,
not WebCodex authority. The acceptance harness records the actual remaining
inventory with loopback protocol fixtures, using no real model. See
local-agent acceptance and metric limits for the
three comparison arms and token accounting.
Generate connection configuration without reading a token or changing files:
webcodex mcp-config --client claude --url http://127.0.0.1:8080/mcp --project agent:dev:repo
webcodex mcp-config --client codex --url http://127.0.0.1:8080/mcp --project agent:dev:repoSet WEBCODEX_TOKEN separately, or select its name with --token-env. Output is
Claude MCP JSON (including alwaysLoad) or a Codex TOML fragment with a 65-second
client timeout and explicit approval settings for edit, shell, stop and gateway.
Codex defaults these to prompt; --approve-execution deliberately selects
approve. Claude permissions remain in its client settings. The command does
not install configuration or grant Server permissions. See the official
Claude MCP loading/result-size contract and
Codex configuration reference.
Migration from v0.5.0: this intentionally replaces the previous CLI workflow
bootstrap and _wc.ack/reply behavior. Reconnect/refresh tools/list and stop
sending CLI sidecars. Clients needing WebCodex-managed workflows or collaboration
can explicitly choose adaptive, whose workflow behavior is preserved. Shared canonical editing and log contracts
apply to both surfaces. No persisted
Session, message, credential or Job is migrated or removed.
Optionally set X-WebCodex-MCP-Project to a server-issued project_ref (for
example ~p17) or full agent:<runner>:<project> ID. A reference retains its
principal/root binding and fails closed if stale; a full ID has the same resolver
semantics as that explicit tool argument. Short names are rejected. This supplies
an omitted required project, including inside the gateway. Explicit project
values win; registration retains its own explicit source rules. Optional filters such as list_jobs.project are not filled.
The header requires the CLI surface, is bounded to 512 bytes, and is never
persisted as connection authority. Select the target deliberately; the default
is not an authorization grant.
Claude Code .mcp.json example (replace the URL with the reported endpoint):
{
"mcpServers": {
"webcodex-cli": {
"type": "http",
"alwaysLoad": true,
"url": "${WEBCODEX_MCP_URL}",
"headers": {
"Authorization": "Bearer ${WEBCODEX_MCP_TOKEN}",
"X-WebCodex-MCP-Surface": "cli",
"X-WebCodex-MCP-Profile": "direct",
"X-WebCodex-MCP-Budget-Secs": "55"
}
}
}
}Keep credentials in the environment, not the configuration file. Claude Code's HTTP headers and variable expansion provide this connection shape. For OAuth, omit the Authorization entry and use the client's normal OAuth flow.
Codex config.toml example (replace the example URL):
[mcp_servers.webcodex_cli]
url = "http://127.0.0.1:8080/mcp"
bearer_token_env_var = "WEBCODEX_MCP_TOKEN"
tool_timeout_sec = 60
http_headers = { "X-WebCodex-MCP-Surface" = "cli", "X-WebCodex-MCP-Profile" = "direct", "X-WebCodex-MCP-Budget-Secs" = "55" }The Codex MCP configuration reference
documents http_headers, bearer_token_env_var and tool_timeout_sec. The 55-second
Host budget leaves margin below this client's 60-second timeout, but is not a
universal RPC deadline. A timeout is not permission to retry a write or redispatch
a Job. These examples do not depend on either client's structured-content priority
or tool-loading strategy.
For a repository on another machine, a local CLAUDE.md / AGENTS.md note can say:
This task targets WebCodex Project agent:dev:repo on Runner dev.
Use the webcodex-cli MCP tools for that repository's files, Git and commands.
The local shell/filesystem belongs to the client machine, not necessarily that Project.
On the default Adaptive surface, machine-readable MCP tool results are returned in structuredContent; content is a concise human-readable/protocol-native fallback. Clients that need fields should consume structuredContent rather than parse text.
For standard-client command failures (isError=true, tool_failure=false, and failure_kind=command_exit_nonzero or timeout), content[0].text also includes available stdout/stderr tails so hosts that hide structured errors can still diagnose the command. Each stream reuses the command tail limit of 12,000 Unicode characters (at most 48,000 UTF-8 bytes), plus a small label; [truncated] marks either upstream or presentation truncation. Empty, untruncated streams are omitted. This text-only projection preserves the compact structured error, execution state, retry guidance and successful receipts. OpenAI structured-failure compatibility keeps its existing presentation, and text JSON compatibility emits its JSON copy without additional log sections.
Ordinary clients retain standard MCP isError behavior. For requests whose _meta["io.modelcontextprotocol/clientInfo"].name is exactly openai-mcp (any version), the MCP adapter applies an OpenAI structured-failure compatibility projection: WebCodex-owned canonical ToolResult failures use isError=false, while structuredContent.success=false remains authoritative and the complete output/error is preserved. The current OpenAI Host promotes isError=true to an exception without exposing structuredContent; this projection preserves machine-actionable failure and recovery data and can be removed when that Host behavior changes. JSON-RPC/protocol errors remain errors, and upstream third-party MCP/Plugin passthrough results retain provider semantics.
Some MCP hosts do not expose structuredContent to the model. This has been observed with Claude Custom Connector even when WebCodex successfully executes the tool and returns the complete structured result. Operators serving such a host can explicitly set WEBCODEX_MCP_TEXT_JSON_COMPAT=true. Ordinary runtime tool results then keep structuredContent canonical while also serializing that same JSON value into content[0].text. The option is off by default because the duplicate representation increases response/model-context size; protocol-native image/resource framing and the existing App-only compatibility paths remain unchanged.
Recovery fields in a result describe the next safe explicit call. They never grant authority and never trigger a hidden retry. In particular, an uncertain outcome must be reconciled before repeating an effect.
A hosted Server can expose Runner-owned local stdio MCP providers through the same /mcp endpoint. Authorized callers use the single mcp_tool entry to list, describe, and call configured providers; provider process/instance identities and schema-revision state stay internal.
Calls sharing a provider connection wait up to two seconds within the original request deadline. If provider_busy reports dispatchState=not_started, wait briefly and retry serially with the original arguments and any idempotency key, using bounded retries. Reconcile outcome_unknown before repeating an effect.
Configure local providers on the Runner under [mcp]. Access requires the explicit mcp:local permission; hosted OAuth clients opt in with webcodex connect ... --oauth-local-mcp. See Runner for provider compatibility details.
The manage_ssh_resource tool provides a narrow Runner-local onboarding path for
named SSH resources. list observes safe logical names and returns an opaque
exact-Runner/revision binding; register and remove consume that binding and
change only durable desired state. They never silently retarget a replacement
Runner or replay after an uncertain outcome. Raw SSH targets are not returned
in tool results or normal/full trace bodies. When restart_required=true,
restart the Runner and list again before selecting the resource in a Workflow
Session.
This surface requires the optional ssh:local permission. It is not part of the
ordinary hosted OAuth baseline; opt in explicitly with
webcodex connect ... --oauth-local-ssh. See
Runner for static-vs-managed and
PersistentShell details.
When OAuth is enabled, MCP clients can use the authorization-code flow instead of a static token. Register the client's exact callback URL, keep offline_access when the host requests refresh-token support, and follow the connection values produced by share --auth oauth or connect --auth oauth. Server setup is in Deployment.
For ordinary hosted connect --auth oauth, the Runner keeps its hosted credential while the MCP client receives a separate OAuth credential. Add --oauth-computer-permissions, --oauth-local-mcp, or --oauth-local-ssh only when those optional capabilities are needed. Existing clients are not silently widened; a real permission change requires reauthorization.
Shared-key OAuth delegation for Browser Use requires explicit --oauth-browser-permissions on connect --auth oauth. It adds only browser:read, browser:control, and browser:launch. The baseline excludes Browser scopes. Browser authority is independent of --oauth-computer-permissions and its consent checkboxes. Existing clients never expand automatically; narrow historical profiles gain only the explicitly selected class. Scope ceiling changes revoke old grants and require reauthorization. Reusing a Browser-enabled profile requires the flag again.
read_tool_trace requires credential-level admin authority and the Stateless MCP 2026 trace-diagnostics capability. A managed OAuth connection can acquire internal admin authority when an admin PAT authorizes its own managed-user client; tools/list, manifest discovery, direct calls and call_runtime_tool then use the same admin scope checks. admin remains absent from requestable scopes and public OAuth responses; ordinary OAuth denials do not advertise an admin scope challenge. Shared-key/project-share OAuth cannot acquire this authority. Pre-upgrade ChatGPT/NewWebCodex connections require one such reauthorization; refresh rotation then preserves authority. See Authentication.
Project-first share --auth oauth remains bound to that temporary share environment. Managed-user OAuth is a separate advanced flow (connect --auth managed-oauth). OAuth credentials are never valid on Runner transport.
For the credential and scope model, see Authentication.
Grok supports custom MCP connectors and can complete the OAuth flow required by
the MCP server. For a self-hosted WebCodex Server, first expose
https://your-domain.example/mcp over public HTTPS and enable OAuth:
WEBCODEX_OAUTH2_ENABLED=true
WEBCODEX_OAUTH2_ISSUER=https://your-domain.example
WEBCODEX_PUBLIC_URL=https://your-domain.example
For the current Grok web connector flow (verified in August 2026), register this redirect URI exactly:
https://grok.com/connectors-oauth-exchange-code/
If Grok later presents or uses a different callback, register that exact value instead. Create a dedicated OAuth client; the client secret is returned only once:
curl -fsS -X POST https://your-domain.example/api/oauth/clients/create \
-H "Authorization: Bearer $WEBCODEX_PAT" \
-H "Content-Type: application/json" \
-d '{"name":"Grok MCP","redirect_uris":["https://grok.com/connectors-oauth-exchange-code/"],"allowed_scopes":["runtime:read","project:read","project:write","job:run"]}'In Grok's Custom Connector form, use:
| Field | Value |
|---|---|
| MCP server URL | https://your-domain.example/mcp |
| Client ID | the returned wc_client_* value |
| Client Secret | the returned one-time wc_csec_* value |
| Authorization Endpoint | https://your-domain.example/oauth/authorize |
| Token Endpoint | https://your-domain.example/oauth/token |
| Scopes | runtime:read, project:read, project:write, job:run, offline_access |
| Token Auth Method | client_secret_post |
WebCodex advertises PKCE S256; Grok can use PKCE together with
client_secret_post. Do not select none (PKCE only) for a WebCodex OAuth
client that has a client secret. offline_access is a protocol-level scope for
refresh tokens and is intentionally not stored in the OAuth client's
allowed_scopes permission list. The MCP Protected Resource Metadata omits
scopes_supported because pre-registered clients can have different scope
ceilings. General-purpose MCP clients can therefore omit scope and let WebCodex
default the authorization request to that client's registered allowed_scopes.
When the WebCodex authorization page opens, sign in with a current user PAT
(wc_pat_*) for the user whose authority Grok should receive. A Runner token
(wc_agent_*) is not a user login token. The resulting OAuth access token is
bound to that user and remains constrained by the registered/requested scopes.
Common setup failures:
- Save & Connect is disabled: Grok requires a Client ID before it can start the OAuth flow.
invalid token: the PAT must authenticate against the same current WebCodex Server database. Do not use a Runner token or a stale PAT left from an older Server/database.invalid scope: every requested WebCodex permission scope must be in the OAuth client'sallowed_scopes. For normal Grok MCP use, do not requestaccount:manage;offline_accessis accepted separately as a protocol scope.- redirect mismatch: the redirect URI must match the registered value exactly, including path and trailing slash.
See xAI's Connector documentation for the current Grok Custom MCP UI and availability.
webcodex run and webcodex share bind one configured repository, start a local Server + Runner, and expose the ordinary Adaptive Runtime. The temporary or persistent Project Credential is an authentication/ProjectGrant boundary; it does not select a separate capability surface.
A typical coding flow is:
work_on_project
→ read_files / search_project_texts / semantic navigation as needed
→ edit_project_files or other canonical edit tools
→ present_work_result once when substantial work becomes materially stateful
→ run_process / run_shell / focused validation tools as needed
→ read_workspace_changes
→ finish_coding_task
work_on_project starts or resumes an explicit Workflow Session on an ordinary registered Project. If the user requests isolation and a registered Project is already known, use work_on_project(project=..., mode=worktree): the Server reauthorizes that source Project, the Runner derives its internal managed placement, and the resulting worktree is registered as another ordinary Project. The model does not reconstruct a Runner path or choose the managed destination. client_id + path + mode=worktree remains a compatibility/bootstrap form and keeps ordinary path authority checks. Without an isolation request, local share/run work directly on the Project already registered by setup.
present_work_result is a one-card presentation layer for substantial coding, not a correctness primitive. Once mounted, its App-only state reads keep current progress, workspace, validation, and review visible without model polling. A non-blocking finish_coding_task seals eligible final changes in the presentation cache at closeout; the same card then discovers that immutable snapshot and can lazily expand per-file diffs. Tiny/read-only work should skip the card; repeated presentation of the same Session should be avoided.
For intentional Go source formatting, project_format accepts adapter="go" or auto with 1–8 explicit .go paths under one nearest unambiguous go.mod recipe. It requires project:write, job:run, project_format_v1 and the additive project_format_go_v1 Runner capability. Installed gofmt reads private source bytes on stdin with no arguments and returns candidates on stdout; the Runner owns guarded writes and durable state_changed evidence. No workspace traversal, -w/rewrite/simplification flags, goimports, module loading, installs or automatic retries are introduced. go.mod is a bounded UTF-8 scope/identity witness, not parsed module semantics; native stdin fragments are accepted and formatting is not compilation. Missing tooling fails closed. Pending or uncertain work must be observed by its original Job, not redispatched. See bounded project formatting.
For ordinary bounded project validation, prefer project_validate; project-authored scripts and tests may modify files or use network. It accepts only a closed format_check / check / lint / test intent plus an optional auto / rust / go / python / node adapter hint; the Runner resolves the nearest unambiguous recipe on its own registered filesystem and then starts the existing structured validation Job. Rust maps to cargo fmt -- --check, cargo check --all-targets, cargo clippy --all-targets -- -D clippy::correctness, or cargo test; Go maps to go vet ./... or go test -json ./.... Go project validation runs in Runner-owned single-module mode with GO111MODULE=on and GOWORK=off, so ambient module mode or parent go.work selection cannot silently change the gateway's workspace semantics. Its validation target identity is domain-separated from ambient Go specialist evidence, so success under different workspace semantics cannot reconcile a gateway failure. The standalone go_test specialist keeps its existing environment behavior. Optional scope selects exactly one portable package intent: bounded packages (1..8 entries) narrows Rust check/lint/test through repeated Cargo -p selectors and Go check/test through project-relative package patterns, while all_packages=true selects the complete project unit. Rust all-packages may add exclude_packages with 1–8 exact Cargo workspace member names; unknown names and excluding every member fail before execution. Rust build and check/lint/test support exclusions, while Go/Node/Python and format_check reject them. The additive project_workspace_exclusions_v1 capability gates planning and typed Job admission. Rust all-packages maps to Cargo --workspace only when the Runner proves the effective Cargo workspace root is exactly the registered Project root and binds the in-Project Cargo manifest graph into the existing re-plan fence; Go all-packages keeps the canonical ./... single-module scope. Scoped formatting fails closed. Python uses existing configured/profile/PATH Python 3 for pytest test (python -m pytest --color=no -rA) and project-local Ruff check/format_check (explicit target-version, no fixes, cache or bytecode). Python scope and dependency policy fail closed. Node supports Runner-owned native script-based check through node --run <check|typecheck|lint> (see #995), plus a separate, opt-in native TAP test profile when package.json declares exactly node --test (or node --test --test-reporter=tap). The native test executes fixed Runner argv, parses only complete TAP v13 summaries, and requires the distinct project_validation_node_tap_v1 capability. Direct scripts.test values vitest, vitest run, and jest also support native tests through the installed local framework CLI. The Runner adds fixed official JSON reporter flags and a fresh private per-Job output file, bounded to 1 MiB. Only a complete consistent file supplies executed counts; stdout/stderr never do. Reports are removed after aggregate evidence is retained. Missing/oversized/invalid reports, timeout and cancellation cannot prove counts. JSON admission requires project_validation_node_json_v1; compound/custom scripts return structured_test_report_unavailable and remain usable through ordinary recipes. Node scope and filters remain unsupported. See Node native TAP validation. Python test planning and Job admission require project_validation_python_pytest_v1, while Ruff check/format_check require the separate project_validation_python_ruff_v1 capability. Missing selected tooling is a definite not-started failure with no automatic installation or fallback. See Python/pytest validation for environment selection, evidence and same-Job behavior. The request never carries arbitrary executable, argv, shell grammar, installation or an explicit source-mutation intent; project-authored scripts and tests can still cause effects. Existing cargo_* / go_test tools remain available for ecosystem-specific advanced options. project_validate requires the additive project_validation_v1 Runner capability; explicit packages additionally require project_validation_package_scope_v1, while all_packages=true requires project_all_packages_v1; exclusions additionally require project_workspace_exclusions_v1 at planning and Job admission. Go project-validation Job admission additionally requires project_go_single_module_v1, so a Server cannot hand a Go gateway plan to an older Runner that may inherit ambient workspace state.
An empty exclude_packages: [] is equivalent to omission, including with explicit packages, and requires no exclusion capability. Nonempty exclusions affect top-level Cargo workspace selection; an excluded member may still build as a dependency. They are not an execution-permission or dependency-graph filter.
Cargo all-packages provenance is a bounded package-selection witness, not a complete build-input snapshot. It requires a contained workspace, or a standalone package with no ancestor Cargo.toml marker; parent markers are only probed, never read outside the registered Project. External path dependencies are unavailable in this scope because their package.workspace metadata can add out-of-Project members. Relevant manifest/member/dependency aliases remain fenced, while unrelated non-manifest links are ignored. Unproven topology or exhausted bounds returns validation_scope_unavailable / build_scope_unavailable; explicit package scope and the existing specialist tools retain their contracts.
For ordinary portable Rust/Go/Python/Node builds, prefer project_build. It accepts only an exact registered project, optional project-relative cwd, an optional auto / rust / go / python / node adapter hint, optional portable scope selecting either bounded packages (1..8 entries) or all_packages=true with optional Rust-only exclude_packages (1–8 exact workspace member names), and total timeout_secs. Unknown members and excluding every workspace member fail before execution; Go/Node/Python reject exclusions. The Runner resolves the nearest unambiguous recipe and owns canonical argv: Rust maps explicit packages to repeated -p selectors and all-packages to cargo build --workspace only after proving the effective Cargo workspace root is the registered Project root; Go maps explicit package patterns directly and all-packages to go build ./.... Go project builds execute with Runner-owned GO111MODULE=on and GOWORK=off; full go.work workspace semantics are outside the v1 gateway rather than inherited implicitly from the Runner host. The request cannot provide an executable, argv, shell, script, arbitrary release/target/features flags, native workspace/exclude flags, arbitrary network policy, or arbitrary artifact-discovery contract. Portable all-packages requests require the additive project_all_packages_v1 Runner capability; Rust exclusions additionally require project_workspace_exclusions_v1 during planning and typed Job admission. Node executes the existing manifest-declared build script through detected npm/pnpm/yarn/bun, reusing packageManager/lockfile detection; missing/conflicting manager evidence and missing build scripts fail closed. Node rejects scope and dependency policy and requires project_build_node_v1. No dependencies or managers are installed; Runner overrides Corepack network/download/auto-pin settings to prevent implicit manager bootstrap. Build scripts and lifecycle hooks may write files or use network. Python requires pyproject.toml, rejects package/all-packages scope, and runs python -m build --no-isolation using the existing configured/profile/PATH Python interpreter. Default packaging creates an sdist then builds its wheel from the sdist; frontend and backend dependency checks remain enabled. Dependencies must already exist: the adapter never installs packages or creates an environment. dependency_policy.mode=locked retains these same no-install semantics.
Both gateways optionally accept dependency_policy: {"mode":"locked"}. This is a portable dependency-resolution guarantee, not a literal cross-ecosystem flag contract: Rust build/check/lint/test use Cargo --locked, while Go build/vet/test use -mod=readonly. The policy tells the adapter not to repair project dependency selection state in order to make the operation succeed; it does not disable registry/module/toolchain network access. Offline dependency resolution is available as an opt-in Rust-only build/check/test extension in #962. project_validate(action="format_check") rejects the dependency policy instead of silently ignoring it. Policy-bearing planning and typed Job admission both require the additive project_dependency_policy_v1 Runner capability. Locked validation derives a distinct durable validation target identity, while requests that omit the policy preserve the historical argv and identity.
Rust project_build also supports optional profile, targets: {"library": true, "binaries": ["server"]} and artifact_policy: "observe". They require project_build_rust_options_v1; other backends reject them. Omission preserves defaults. Observation is bounded, follows the same durable Job and verifies selected Project-local Cargo outputs, including cached artifacts, without claiming creation, correctness or source freshness. Truncated, missing or unsafe evidence fails observation while retaining the native exit status. See Rust build selection and artifacts.
Rust project_validate(action="lint", adapter="rust"|"auto") selects Runner-owned Cargo Clippy with fixed --all-targets -- -D clippy::correctness. It has distinct cargo_clippy tool/evidence identity and lint kind; Rust check/test and Node lint identities stay unchanged (Node lint still selects only scripts.lint with check evidence). Scope supports 1..8 sorted/deduplicated packages or the proven Cargo workspace through all_packages=true. Independent dependency_policy: {"mode":"locked"} adds --locked and changes target identity. Rust lint accepts dependency_resolution_policy=offline, independently combinable with --locked, and requires additive project_validation_rust_clippy_offline_v1 before planning (including auto) and typed Job admission. Missing cached dependencies fail without online retry; this limits Cargo resolution, not build-script or OS network access (#1274). Explicit Rust lint planning and every resolved Clippy Job admission require project_validation_rust_clippy_v1; auto planning keeps existing Node support and gates the resolved backend before execution. Missing Clippy returns validation_tool_unavailable before the validation command starts, without install, arbitrary argv, shell fallback or redispatch. Go/Python lint are unsupported. Manifest/lock/workspace provenance is revalidated at queue admission and execution; drift fails closed. One durable Job owns execution and observation. Exit zero may include warnings; nonzero, missing exit status, timeout or cancellation cannot become successful lint evidence.
For Rust project_validate(action="check"|"lint"|"test"), the optional dependency_resolution_policy: "offline" requests Cargo dependency resolution/fetching with Runner-owned --offline. It is independent of dependency_policy: {"mode":"locked"} and can be combined with it; omission preserves existing argv and validation identity. Runner-resolved non-Rust recipes and unsupported actions fail before execution instead of silently running online. A missing local dependency cache is an ordinary failed validation, never a reason to retry online. Offline and default executions have distinct canonical invocation and validation-target identities; durable Jobs and test evidence remain unchanged. This does not sandbox the process: build scripts and tests can still access the network, and project_build supports the same policy for Rust builds.
A successful Node build proves the declared script completed. It does not prove a particular output exists or works. Use finish_coding_task(outputs=...) for explicit output metadata inspection; artifact presence is separate from functionality.
For Rust project_build, optional dependency_resolution_policy: "offline" selects Runner-owned cargo build --offline, independently combinable with --locked. Omission preserves canonical argv and execution identity. Unsupported build backends fail before execution, missing cached dependencies cause a normal failure without online fallback, and the additive project_dependency_resolution_offline_v1 capability is checked during planning and Job admission. The typed build, artifact observation and same-Job recovery semantics are unchanged. This is not an OS network sandbox and does not prevent build scripts from accessing the network.
project_build requires the additive project_build_v1 Runner capability at both planning and typed Job admission. Go project-build Job admission additionally requires project_go_single_module_v1. Explicit Python planning and every Python Job admission require additive project_build_python_v1, which defaults false on older Runners. Admission replans the registered project/root, recipe, manifest/lock provenance, package scope, and canonical invocation; the worker rechecks that same plan after any local queue wait, before native process execution. A stale plan fails as not_started and releases its Job slot rather than silently rebuilding or executing the outdated intent. Long builds keep the same durable Job and return the ordinary sparse pending continuation; pending never authorizes retry or redispatch. The closed gateway bounds WebCodex's command authority but is not an OS sandbox: Cargo/Go/Python build logic and project build scripts may still have their own filesystem or network effects. Existing lower-level execution tools remain explicit escape hatches for build forms outside this v1 contract. Python terminal success may include build_artifacts: at most 16 existing regular files in the default dist/ directory (256 MiB total), with Project-relative path, size, SHA-256 and MIME from the existing artifact reader. These observations can include files from previous builds; they prove neither creation by this Job, package correctness nor source freshness. Exit zero without observed sdist and wheel outputs reports build_artifacts_missing with the native exit status preserved. Missing historical metadata stays unknown across recovery, and the same Job retains known observations. Symlinked/escaping/sensitive output paths fail closed. Read or export bytes through the existing artifact tools.
For action="test", optional test selects tests and states the evidence requirement:
{"project":"agent:runner:repo","action":"test","scope":{"packages":["package-a"]},"test":{"filter":"selected_test","min_tests":3}}Rust interprets filter as one libtest substring; Go interprets it as a native
-run regexp, including Go's slash-separated subtest semantics. Python uses a
native pytest -k expression, bounded to 200 UTF-8 bytes with controls and
option-shaped prefixes rejected. Go and Python preserve meaningful whitespace;
this is not a cross-language query syntax. Empty/omitted filters keep
the unfiltered default. Filters cannot introduce arbitrary argv. require_tests
defaults to true (at least one proven executed test); explicit false accepts
native success when min_tests is absent, including proven zero or unknown counts
(unknown counts remain unproven; source freshness is independent). A requested min_tests (1..1,000,000)
still applies with false, and count uncertainty is not zero. These are evidence
postconditions, not extra tests to run. The test block is invalid for check or
format_check. Any supplied test block requires the additive
project_validation_test_options_v1 Runner capability; it is checked at both
planning and Job admission. Old calls without that block retain their old wire
and execution defaults. See project-validation test options
for exact scope and identity; additive lifecycle extensions are tracked in #962.
Adaptive Runtime may expose common tools directly and long-tail tools through call_runtime_tool. Direct versus gateway exposure never changes schema validation, OAuth scope, Project authority, permission policy, Runner capability checks, Session fences, or effects.
The removed ProjectConnector capability names (task_start, files_read, edits_apply, task_finish, and related operations) are not compatibility aliases for runtime tools. Use the current ToolRuntime names returned by tools/list/read_tool_manifest.
Routine Job observations keep one restart-safe observation token rather than also emitting a process-local, evictable observation ref. A cursorless handoff token is an initial baseline, not a log reset; actual generation changes and lost history still report reset/retention evidence. Generic running activity and ordinary command outcome summaries are omitted when lifecycle/exit code already express them. Validation evidence and useful phase changes remain.
Process, script and shell admission applies the last registered Runner timeout
policy as well as the tool ceiling. Only capped active handoffs include
timeout: 3600s (requested 99999; capped by runner policy); fast terminal commands
do not add this notice. The Runner still enforces its live policy. Detached
execution keeps native argv and keyed replay semantics; invoke a virtualenv's
Python executable directly instead of sh -c.
CLI text renders document symbols as identifier positions with nested children, Job/Project inventories and search file/count results as rows, and combines single Job wait/update information. Rust document symbols now wait for index readiness; the LSP client advertises hierarchical symbol support. Explicit file ranges do not suggest reading beyond their requested end; genuinely truncated reads retain snapshot-fenced continuation calls. Synchronous process/script/shell output displays at most 200 lines per stream, with truncation flags and guidance to capture full future output in a Project file.
Adaptive Stateless MCP 2026 execution tools can opt in to _wc.compact_execution=true.
This separates stable output.execution control facts from output.details
(per item for observe_jobs) while retaining logs, recovery and collaboration
obligations. Only outcome=passed proves successful execution; tool acceptance
or a successful observation alone does not. It neither waits nor retries commands.
See Host execution control for supported
tools, gateway placement, unknown outcomes and pending-chain design limits.
Mixed observe_jobs batches compact each eligible successful observation independently.
Failed items and outcome_unknown observations retain their canonical evidence; mixed
or truncated batches preserve the outer success/error, counts, input indexes and single
shared wait. Observation tokens, log reset/truncation recovery and the exact omitted
suffix continuation remain unchanged. An inconsistent batch is returned unchanged.
Canonical Session and audit facts are captured before this model-facing projection.
This presentation does not retry, dispatch or establish successful command execution.
observe_jobs(summary_only=true) is an opt-in presentation mode for proven successful
structured validation Jobs. It removes routine passed-test and Cargo progress lines,
while preserving test summaries, unknown text, warnings, validation evidence, lifecycle,
and truncation/reset/retention flags. Failures, zero/unproven tests, compile-only test
runs, incomplete validation evidence, and ordinary commands keep their normal output.
Tiny results are unchanged when summary metadata would make them larger.
A summarized item includes logs_omitted and a parser-ready suggested_call with
summary_only=false. That call preserves the original observation cursor; using
the newly returned observation token instead would skip omitted lines. Expansion is
bounded by the existing log retention and may report reset or unavailable history.
No log copy, model invocation, Job execution, permission, or waiting policy is added.
Omitting summary_only preserves the existing behavior.
search_file_context reuses ordinary search-result sparsification after read planning.
It omits redundant phase metadata, not source text, query indexes, failure evidence,
read revisions, or snapshot-bound continuations.
Long-running commands and validations use the canonical WebCodex Job lifecycle. Observe the exact Job returned by the initiating call with observe_jobs (or recover it with list_jobs when identity was genuinely lost) instead of starting another copy. Jobs are not wrapped as MCP Tasks; WebCodex does not advertise the former Connector-specific MCP Tasks extension.
The ChatGPT/model turn and one MCP observation request do not own the Job lifetime.
A Host-side Thinking stopped / Thinking failed, request timeout, or dropped
observation therefore does not by itself prove that the Job stopped. Resume the same
conversation and re-observe the existing Job; recover Job inventory before any retry
when identity was lost. Do not redispatch solely because the model turn ended.
Eligible terminal waits may expose best-effort Host continuation, but Host acceptance
does not guarantee that a new model turn actually ran. See
Troubleshooting.
Use the configured WebCodex project. Inspect README.md and summarize the
project structure. Do not edit files or run commands.
No project discovery or runtime identifier belongs in this prompt.
read_filesis the canonical bounded range reader for one to eight files. A one-item batch is the single-range path. Each successful item returns the complete-file SHA-256 and bounded line metadata; partial items carry a positional one-itemread_filescontinuation and are not snapshot-stable.search_project_textsis the canonical bounded search surface for one to eight independent queries (ripgrep first with the existing bounded fallback). A one-query batch is the single-query path.
An empty search result is affirmative no-match evidence only after a recognized
backend reports a successful completed/no-match status. Missing or malformed
backend identity, missing completion status, status/output disagreement,
backend failure, Runner failure, timeout, request drop, and provider failure
return failures instead. Search failures retain the compatibility code and
add bounded failure_stage plus a specific reason_code. Batch failure items
retain their broad reason_code and preserve the single-search provenance as
failure_stage and detail_code; successful batch items remain sparse.
Failures return small structured errors with project-relative paths only — never absolute paths, commands, Runner/provider stderr, or arbitrary provider prose.
list_projects returns 30 Projects by default and clamps explicit limit to
1–100 on both MCP and the canonical Runtime API. Authorization and exact
client_id / project or literal query filters run before stable ascending
Runtime Project ID ordering and offset pagination. Responses include
matched_count, page count, effective offset / limit, and
next_offset (null at the end); truncated means another page remains.
Keep the same filters and pass next_offset as the next request's offset.
Offsets use current authorized inventory on every request, without retained pagination state. New/deleted registrations or changed permissions can repeat or omit rows between pages. Restart at zero and deduplicate exact IDs when that matters; pagination is not an immutable inventory snapshot. A fixed set of 107 matches is fully traversable despite the 100-row page ceiling.
MCP CLI and Adaptive calls default to summary_only=true: exact identity, path,
name, provenance, availability and active-Job counts. Set it to false to retrieve
revision, shell/policy and smoke-test capabilities, including before maintenance
that needs a revision. Canonical API calls retain detailed rows by default within
the same page bounds. Console's explicit inventory query keeps its separate
2,000-row operator ceiling and the shared authorization/filter implementation.
CLI operator fleet reports traverse at most twenty 100-row pages and explicitly
report truncation. Known-target connection/removal/smoke checks use exact IDs.
Automatic registrations remain discoverable, including queries for authoritative
registration_source or kind metadata such as auto_registered and
managed_worktree. Paths are not used to infer provenance. No registrations,
worktrees or branches are removed; no recent-use ordering is inferred.
Project-resolution errors expose at most five authorized suggestions, ranked by
exact short ID/name, case-insensitive equality, prefix/substring, then thresholded
edit distance over at most 64 characters, connection state and stable ID. Labels
and input displays are bounded; overlong identities are omitted rather than
shortened into a different selector. candidate_count describes the authorized
candidate pool for that resolution scope, and candidates_truncated reports
omissions. Candidates appear once, with a bounded list_projects recovery call.
Matching suggestions never authorizes or automatically retargets execution.
| Code | Meaning | Action |
|---|---|---|
project_not_configured |
No canonical setup exists | Run webcodex setup |
project_credential_invalid |
Private Project Credential is missing or mismatched | Restore both matching private files or recreate the profile |
project_credential_rejected |
The reachable server rejected the credential | Restore the server-matching credential |
workspace_unavailable |
The configured Git workspace is unavailable | Restore the workspace, then run doctor |
server_unreachable / agent_offline |
The project Runner/runtime is unavailable | Run webcodex run / webcodex doctor |
required_capability_unavailable |
The current Runner/runtime lacks a required coding capability | Upgrade all binaries |
project_registry_scope_denied |
A project-scoped credential tried to expand or mutate the Project registry outside its granted visibility | Use an already-visible Project or work_on_project(mode=worktree) |
list_runners defaults to summary_only=true on the canonical API, Adaptive MCP,
and CLI MCP. Each page contains at most 30 Runners by default; limit is clamped
to 1–100. Authorization and client_id/client_ids, query, and status
filters run before stable client_id sorting and offset paging. The response
returns matched_count, count, effective limit, offset, has_more,
next_offset, and truncated. Continue with the same filters and the returned
next_offset; null means the current inventory ends.
Pages are fresh observations, not a retained snapshot or authority lease.
Registration, removal, or authorization changes between calls can repeat or skip
entries. Restart at offset zero and reconcile exact client_id values when the
inventory changes. No caller can use another caller's offset to widen visibility.
The default returns identity, online state, Project and active Job counts, shared
Job concurrency, and provider choices. summary_only=false explicitly expands
capabilities, build information, policy and diagnostic metadata. Independently,
include_projects=true adds at most 100 enabled Projects in Project-id order,
including in summary mode. Each Runner reports projects_count (the full enabled
total), projects_returned_count, projects_offset, projects_truncated and
nullable projects_next_offset. Continue list_runners with that exact client_id,
include_projects=true, and projects_offset=projects_next_offset. These fresh
pages require no resource-link root identity and have no total Project source cap;
registration or visibility changes have the same repeat/skip semantics as Runner
pages. list_projects remains the richer filtered Project discovery tool.
project_inventory in detailed mode is path-free synchronization status, not a
second Project collection. It remains available to the CLI controller's explicit
summary_only=false, include_projects=false query. Console operator pages use the
same authorization/filtering query with an explicit complete internal inventory;
the public tool page cap does not truncate their fleet counts.
The same ToolRuntime serves project-scoped local share/run instances and multi-project hosted Servers through one Adaptive Runtime contract. Project-scoped credentials change visibility and authority, not the model-facing runtime shape. Protocol-specific capabilities and MCP Apps may admit additional hidden presentation or resource operations without creating another runtime surface.
Stateless MCP keeps Memory tools and the Skill compatibility tools list_skills
and read_skill_file off the top-level tools/list, even with full OAuth scopes.
Their exact contracts remain available through read_tool_manifest(tool_name=...)
and execute through call_runtime_tool with unchanged scope, Project, permission,
and capability checks. Existing direct protocol compatibility and the
memory.bootstrap context sidecar remain supported. Ordinary Skill selection
and execution keep the direct load_skill and run_skill_resource paths.
The optional closeout helpers check_workspace_hygiene and finish_coding_task
are model-visible gateway tools; review/coding catalogs still recommend them.
Adaptive Stateless MCP 2026 exposes common untrusted invocation metadata only through one optional closed _wc envelope. Depending on the tool, the envelope may admit record, ack, ack_ref, resolve, reply, context, control, and compact_execution. These are adapter metadata only: they never become canonical ToolCall business arguments or grant authority. Legacy flat root wrappers such as recording_session_id, ack_session_message_ids, ack_ref, session_message_resolution, window_reply, context_request, and _control are rejected on this Stateless 2026 surface; legacy/non-stateless transports keep their existing contracts. call_runtime_tool carries _wc only on the outer gateway call; the nested target arguments remain canonical business arguments and reject a second _wc.
WEBCODEX_MCP_COMPACT_SCHEMAS defaults to true. Compact tools/list omits
outputSchema and projects shorter MCP-specific tool/input descriptions for
selection: purpose, nearby tool distinctions, and essential continuation guidance.
Repeated _wc copy is shortened too. Compact discovery preserves the envelope
shape and bounds while omitting only repeated prose and exact opaque-ID regexes on
_wc.record, _wc.ack.items, and _wc.resolve.message_id; the full manifest
retains the complete contracts. Business-ID, hash/Git fence and resource-path
patterns, all bounds, required fields, enums, object/union shape, annotations, and
MCP App/file metadata are preserved. This is discovery presentation only; runtime
argument validation and execution authority do not change.
Use read_tool_manifest(tool_name=...) for the full exact input contract and operational
description, or set compact schemas to false for full discovery schemas.
Canonical ToolSpecs are never rewritten. Focused MCP tests compare inputs against
canonical schemas (with the explicit host-file reference overlay) and enforce
serialized-byte and advertised-tool-count budgets on final Stateless results,
including Session wrappers, gateway tools, and optional App metadata/tools.
For viewing a project PDF, call present_pdf(project, path) directly. It opens
the dedicated PDF App (ui://webcodex/pdf/v7) with a filename, page/zoom/search
toolbar and a full-height continuous-scroll reading area. It does not include Work Result activity,
change lists or collaboration. Unchanged and untracked PDFs are supported;
Git and Workflow Sessions are not prerequisites. The Host controls its outer
sidebar and display mode. Rendering requires an MCP Apps-capable Host.
The dedicated reader uses the App-only read_app_artifact_chunk bridge for bytes.
That bridge is format-neutral and reuses the canonical artifact export chunk
transport: each tools/call reauthorizes Project access, validates the pinned
path/size/SHA-256 identity, and returns at most 512 KiB per Host-facing call through private MCP metadata.
A changed source fails closed. A 9 MiB document needs eighteen Host round trips.
The unreleased PDF-specific read_pdf_chunk adapter has been removed; older
mounted readers must be reopened from the current descriptor. The PDF remains
bounded at 20 MiB and PDF.js
rechecks the assembled digest/header before rendering. Use present_work_result
for substantial coding progress, and present_pdf when the user asks to view a
PDF. See PDF document viewer.
The dedicated reader keeps PDF.js as the rendering engine but uses a small host-compatible continuous-scroll shell with viewport observation and nearby-page lazy rendering; Work Result retains its compact single-page preview. Whole-file transfer keeps one absolute, size-aware deadline: at least 120 seconds and up to 15 minutes based on the bounded 512 KiB Host round trips. Each App-originated chunk call inherits the remaining document budget instead of imposing a second shorter timeout. The transport still assembles and verifies the complete pinned file before PDF.js starts rendering, so progressive first-page range loading remains a separate optimization.
When the connected MCP protocol/host admits the artifact capabilities, WebCodex supports host-native file transfer in both directions without routing complete binary payloads through model text:
import_host_filesimports 1..10 files supplied by the ChatGPT host throughopenai/fileParams. This applies to user-selected conversation attachments and to newly generated files when the host binds them as file parameters. The Control downloads the referenced bytes and commits them through the existing bounded artifact-write path; callers should not construct download URLs or manually Base64-transfer those files.inspect_project_artifactis the preferred Project-to-model/host read surface. Useaction=metadatafor existence/size/MIME/digest/image/archive facts,action=inspectfor one bounded snapshot-fenced Base64 segment,action=imagefor native MCP image delivery, andaction=exportfor complete host/user delivery. Do not loopinspectchunks to transfer a complete file.action=exportreuses the existing artifact export authority and returns a short-lived authenticated MCPResourceLinkplus metadata.tools/calldoes not contain the complete binary. The host followsresources/readto obtain the binary resource; authentication and current project-read authority are checked again, and the artifact metadata is revalidated before the bytes are returned. The resource URI is not standalone bearer authority; export handles are short-lived process-local presentation state, and the normal size, MIME, path, and authorization bounds remain in force.
Artifact uploads reserve the known expected_bytes exactly, including zero;
unknown sizes reserve their bounded limit (256 MiB by default). Each Project
still permits at most 32 active uploads and 512 MiB of reserved bytes. When a new
upload would exceed either quota, the Runner checks its bounded reservation
index, removes upload pairs idle for at least 24 hours, and recalculates usage
under the upload lock. It does not recursively scan the Project or start a
background task. Recent chunk writes keep an upload live; unreadable or
inconsistent recovery evidence fails closed. Successful finish/abort releases
reservations after cleanup. An uncertain transport result never authorizes a
replay. Existing reservations recover with their original limits and unchanged
record format. For older Runners the Server sends a minimum one-byte limit for
empty files; current Runners reserve zero bytes for expected_bytes=0.
Finish or abort these zero-byte reservations before downgrading to a Runner that
requires positive persisted limits.
The lower-level read_project_artifact_metadata and read_project_artifact_chunk
tools remain operator/gateway primitives. The legacy export_project_artifact
compatibility tool has been removed; complete host delivery is exposed only as
inspect_project_artifact(action=export). Office artifacts such as DOCX/PPTX/XLSX and
PDFs use the same underlying artifact transport and can therefore move between
a project and a supporting ChatGPT host without a model manually carrying their
Base64.
Use Coding Workflow for the canonical work_on_project bootstrap, behavioral-role mental model, and validation/closeout guidance. See Architecture and the webcodex CLI for operator tooling.
Current resources are ui://webcodex/goal-plan/v11 (App 11.0.0) and
ui://webcodex/agent-continuation/v25 (App 25.0.0). Retired resource aliases are rejected.
Goal Plan and Agent Continuation cards offer Enable timing diagnostics, off by
default. The local View retains at most 64 timing records: scheduled versus actual
poll delay, monotonic tool RPC start/completion/error duration, visibility and teardown.
The Agent ring also records host_dispatch_start, host_dispatch_complete or
host_dispatch_error around its existing ui/message call, elapsed duration_ms,
and closed outcomes (dispatch_accepted, delivery_unknown). The existing
host_dispatch_result records the same outcome after the call. Errors
carry only a closed failure class; message bodies, consume tokens and raw errors
never enter the ring. Host acceptance remains separate from exact Wake consume.
Disabling clears the ring; remounting starts empty. No additional RPC, browser
storage, model message, timing authority or scheduler is introduced. Goal diagnostics
optionally attach the existing bounded app_call_id; the MCP adapter validates and
strips it before ToolRuntime parsing. Agent calls retain their existing correlation.
Operators may separately enable WEBCODEX_TOOL_REQUEST_TRACE=metadata to correlate
those ids with existing request start/completion records. goal_sync_timing records
closed reconciliation reasons, meaningful activity age, coverage and active request
count, and the durable observation age/remaining 75s lease margin when reached.
continuation_identity links existing Event/Wake/Attempt ids for creation, dispatch
and exact consume. These records use the existing bounded, fail-open trace writer;
they add no prompts, message bodies, consume tokens or raw ClientWindow values and
are never copied into model-facing Goal results. Existing full tracing has its
separate payload/privacy contract. Negative lease margin identifies stale observation;
missing observation/partial coverage are evidence limits, not permission to wake.
Goal Plan targets 30s while hidden, retaining the 75s observation lease and 10s RPC timeout. The elapsed-aware scheduler shortens that target near lease expiry and backs off after an expired attempt. This adds scheduling margin; browser throttling may still exceed it. Agent hidden heartbeat remains 15s. See the real-Host comparison procedure for the user-assisted baseline/candidate evidence gate.
For separately authorized ChatGPT acceptance, bind the actual Agent carrier and present its exact correlated Goal. Enable the local diagnostics and metadata tracing, then compare foreground polling with hiding the chat/browser for more than 75s. Check actual timer gaps and slow/error RPCs against the Server observation margin. A stale card must create no Wake until a later successful observation meets all existing eligibility checks. Hide/show, teardown/remount and a separately authorized Server restart must preserve single-flight coordination and one logical Wake per meaningful activity epoch. Correlate that Wake's dispatch and exact consume; Host acceptance alone does not prove a fresh model turn. Local fake-clock tests do not establish ChatGPT background scheduling or unattended continuation.