Problem
WebCodex already provides a remote MCP surface that lets supported web hosts operate authorized Projects and Runners. A useful next capability is to let the same connector reach MCP servers that exist locally beside a Runner without exposing those local servers directly to the internet and without requiring the host to configure a second connector.
The feature should behave as a controlled bridge/provider inside WebCodex:
remote MCP host
|
| existing WebCodex MCP + auth
v
WebCodex Server
|
| exact owner/project/Runner authority
| discovery + bounded call contract
v
Runner
|
| managed local MCP client/session
v
configured local MCP server
This is not an arbitrary proxy. The caller must not be able to supply a command, executable path, environment, cwd, URL, or transport target to create an arbitrary MCP connection.
Existing substrate
WebCodex already contains an experimental Runner-internal Claude Code MCP provider. That path already proves several pieces of the local-provider substrate:
- Runner-owned, explicitly configured local provider process lifecycle;
- MCP
initialize, notifications/initialized, tools/list, and bounded tools/call RPC;
- bounded requests/responses, timeout handling, child teardown, and process cleanup;
- discovered-tool/schema validation and explicit capability mapping;
- provider state/revision and safe bounded status reporting;
- request-time config generations and explicit config reload;
- fake-provider tests plus opt-in real-provider probes/smokes;
- effect-aware handling for the existing internal mutating diagnostic calls.
That provider is intentionally agent-internal today. Its discovered upstream tools are not inserted into the public WebCodex MCP/OpenAPI/tool registries; ordinary public tools remain the static WebCodex tool definitions.
This issue should reuse or narrowly generalize that existing substrate wherever its contracts fit. Do not build a parallel generic MCP-provider/client framework. The main new product capability is the authorized public discovery/call boundary, including exact provider/tool identity, stale fencing, authority projection, bounded result handling, and effect/retry semantics—not implementing local MCP transport from scratch.
Product shape
Add a narrow Runner-local MCP bridge capability with two explicit phases:
- discover the configured MCP providers/tools that the exact authorized Runner/Project makes available;
- call one exact discovered tool through WebCodex.
The model-facing identity must come from bounded discovery. Do not require models to guess server or tool names from memory.
A future convenience surface may group this under the normal tool-discovery experience, but the authority and lifecycle should remain explicit.
Core invariants
- Server owner/project authorization remains authoritative. A local MCP server never widens the caller's WebCodex authority.
- Runner configuration/policy decides which local MCP servers may be exposed. The caller cannot override process command, args, cwd, env, socket/URL, or credentials.
- Local MCP process/session lifecycle is owned and cleaned up by the Runner; no unmanaged orphan process may remain after disconnect/cancel/restart handling.
- Tool discovery is bounded, revisioned, and tied to the exact Runner/Project/provider configuration used to produce it.
- A stale discovery result fails closed when the provider/tool configuration changes.
- Upstream tool results remain bounded. Large binary/file results should reuse WebCodex Artifact/ResourceLink/data-plane mechanisms rather than inline unlimited content.
- Secrets and local MCP credentials never enter model-visible results, audit metadata, Session messages, or ordinary logs.
- An upstream MCP
isError result is business/tool truth, not transport failure. Transport loss after an effect may have started must not be converted into a safe retry claim.
Runner capability and configuration
Expose this as an additive Runner capability. A Runner that does not support the bridge remains fully compatible with existing WebCodex behavior.
Prefer extending the current Runner tool_providers/provider-generation machinery rather than creating a second unrelated configuration system. The Runner should load only explicitly configured local MCP providers. Configuration should bind a stable provider id to a Runner-owned definition such as transport/process information and any private environment required to start it.
The existing Claude Code provider may remain a specialized configured provider while the shared pieces required for public discovery/call are extracted narrowly. Do not force unrelated providers into a broad plugin abstraction before a second real provider demonstrates which pieces are actually common.
Model-facing discovery should reveal only safe metadata, for example:
- provider id/name/description;
- availability;
- bounded tool list or paged discovery;
- tool description/input schema/annotations;
- provider/tool revision;
- whether a fresh local session is required.
Never return the configured command line, absolute private paths, credentials, or secret environment values merely because a provider is discoverable.
Discovery and stale fencing
A successful tool call should carry a discovery identity/revision produced from the exact current provider/tool definition.
Before effect:
- revalidate caller owner/project authority;
- revalidate Runner identity/readiness and bridge capability;
- revalidate provider configuration/generation and discovery revision;
- revalidate the selected tool still exists with the expected schema/revision;
- only then open/reuse the local MCP session and dispatch the call.
Configuration changes between discovery and call should return a structured stale/discovery-required result rather than silently calling a different tool definition.
Local MCP session lifecycle
Prefer the simplest safe first contract and reuse the lifecycle behavior already proven by the experimental provider where appropriate.
A reasonable MVP is one managed upstream client/session per bounded bridge operation or per exact short-lived provider session, with explicit cleanup. Reuse/pooling should be added only if real providers require continuity or process startup cost creates repeated dogfood friction. Existing provider reuse should not automatically become a public guarantee unless the bridge contract requires it.
Define behavior for:
- initialize/capability negotiation;
- tools/list;
- tools/call;
- timeout and cancellation;
- provider process exit;
- Runner disconnect/restart;
- Server restart while the Runner remains connected;
- stdout/stderr/log retention if the provider is a local process.
Do not create a second generic scheduler or detached-process framework. If a future local MCP provider needs long-lived restart-surviving ownership, compose with the existing Job/detached execution substrate rather than inventing another lifecycle model.
Effect and retry semantics
Keep at least these cases distinct:
- admission/discovery/configuration failure before upstream dispatch: definite no effect;
- local MCP process/session startup failure: definite no tool dispatch when provable;
- upstream tool returns a normal result;
- upstream tool returns
isError=true;
- transport/process failure before dispatch is proven;
- transport/process loss after dispatch where the upstream effect may have occurred:
outcome_unknown / reconciliation-required.
Never blind-retry an effectful upstream tool after an unknown post-dispatch result merely because the MCP transport disconnected.
For tools that expose idempotency/reconciliation semantics themselves, preserve that evidence but do not infer guarantees that the upstream server did not declare.
Observation and audit
Record bounded correlation metadata through the existing WebCodex audit/Session/evidence paths where appropriate:
- caller/owner;
- Project/Runner/provider/tool identity;
- discovery/config generation revision;
- start/end/duration;
- result class (
success, upstream isError, transport failure, outcome_unknown);
- bounded/truncation metadata.
Do not record raw arguments when existing secret/privacy rules exclude them, and never record provider credentials/private environment.
Artifact integration
If an upstream MCP tool returns a file/image/large payload, bridge it into the existing WebCodex Artifact/data-plane model when practical rather than routing large base64 through model context.
The resulting Artifact remains governed by the caller's current owner/project authority and should retain safe provenance identifying the local MCP provider/tool and discovery revision that produced it.
Acceptance criteria
- A configured fake/local MCP server on a Runner can be discovered through the existing remote WebCodex connector and one of its tools can be called successfully.
- The implementation reuses or narrowly generalizes the existing Runner-local MCP provider substrate; it does not introduce a parallel generic provider framework.
- Existing experimental Claude Code provider behavior remains compatible unless an explicit migration is required and tested.
- A caller cannot provide or override local MCP executable/args/env/cwd/URL/transport configuration.
- Discovery is bound to exact Project/Runner/provider/tool revision; stale provider/tool configuration fails closed before effect.
- Unsupported Runners do not advertise the capability and existing tool flows remain unchanged.
- Provider startup, disconnect, timeout, cancellation and normal completion do not leave unmanaged child processes/sessions.
- Upstream
isError, definite pre-dispatch failure, and post-dispatch unknown outcome remain distinguishable.
- Effectful unknown outcomes are not blindly retried.
- Large/file/image results retain existing WebCodex bounded Artifact/ResourceLink semantics.
- Secrets/private provider configuration are absent from model results, audit metadata and logs.
- Focused tests cover discovery, stale fencing, successful call, upstream
isError, startup failure, post-dispatch transport loss and cleanup on Linux; add platform-specific lifecycle coverage where the Runner implementation differs.
- Real dogfood demonstrates one useful local MCP server accessed from a remote web host through WebCodex without directly exposing that local MCP server.
Non-goals
- arbitrary TCP/HTTP proxying;
- caller-supplied executable/path/command/env/cwd/URL;
- exposing every locally installed MCP server automatically;
- generic plugin/provider framework;
- a second independent local-MCP client/lifecycle subsystem;
- automatic local-agent spawning/orchestration;
- merging local MCP authority with Project filesystem/shell authority;
- implementing every MCP capability in the first version (start with the capabilities required by real dogfood).
Problem
WebCodex already provides a remote MCP surface that lets supported web hosts operate authorized Projects and Runners. A useful next capability is to let the same connector reach MCP servers that exist locally beside a Runner without exposing those local servers directly to the internet and without requiring the host to configure a second connector.
The feature should behave as a controlled bridge/provider inside WebCodex:
This is not an arbitrary proxy. The caller must not be able to supply a command, executable path, environment, cwd, URL, or transport target to create an arbitrary MCP connection.
Existing substrate
WebCodex already contains an experimental Runner-internal Claude Code MCP provider. That path already proves several pieces of the local-provider substrate:
initialize,notifications/initialized,tools/list, and boundedtools/callRPC;That provider is intentionally agent-internal today. Its discovered upstream tools are not inserted into the public WebCodex MCP/OpenAPI/tool registries; ordinary public tools remain the static WebCodex tool definitions.
This issue should reuse or narrowly generalize that existing substrate wherever its contracts fit. Do not build a parallel generic MCP-provider/client framework. The main new product capability is the authorized public discovery/call boundary, including exact provider/tool identity, stale fencing, authority projection, bounded result handling, and effect/retry semantics—not implementing local MCP transport from scratch.
Product shape
Add a narrow Runner-local MCP bridge capability with two explicit phases:
The model-facing identity must come from bounded discovery. Do not require models to guess server or tool names from memory.
A future convenience surface may group this under the normal tool-discovery experience, but the authority and lifecycle should remain explicit.
Core invariants
isErrorresult is business/tool truth, not transport failure. Transport loss after an effect may have started must not be converted into a safe retry claim.Runner capability and configuration
Expose this as an additive Runner capability. A Runner that does not support the bridge remains fully compatible with existing WebCodex behavior.
Prefer extending the current Runner
tool_providers/provider-generation machinery rather than creating a second unrelated configuration system. The Runner should load only explicitly configured local MCP providers. Configuration should bind a stable provider id to a Runner-owned definition such as transport/process information and any private environment required to start it.The existing Claude Code provider may remain a specialized configured provider while the shared pieces required for public discovery/call are extracted narrowly. Do not force unrelated providers into a broad plugin abstraction before a second real provider demonstrates which pieces are actually common.
Model-facing discovery should reveal only safe metadata, for example:
Never return the configured command line, absolute private paths, credentials, or secret environment values merely because a provider is discoverable.
Discovery and stale fencing
A successful tool call should carry a discovery identity/revision produced from the exact current provider/tool definition.
Before effect:
Configuration changes between discovery and call should return a structured stale/discovery-required result rather than silently calling a different tool definition.
Local MCP session lifecycle
Prefer the simplest safe first contract and reuse the lifecycle behavior already proven by the experimental provider where appropriate.
A reasonable MVP is one managed upstream client/session per bounded bridge operation or per exact short-lived provider session, with explicit cleanup. Reuse/pooling should be added only if real providers require continuity or process startup cost creates repeated dogfood friction. Existing provider reuse should not automatically become a public guarantee unless the bridge contract requires it.
Define behavior for:
Do not create a second generic scheduler or detached-process framework. If a future local MCP provider needs long-lived restart-surviving ownership, compose with the existing Job/detached execution substrate rather than inventing another lifecycle model.
Effect and retry semantics
Keep at least these cases distinct:
isError=true;outcome_unknown/ reconciliation-required.Never blind-retry an effectful upstream tool after an unknown post-dispatch result merely because the MCP transport disconnected.
For tools that expose idempotency/reconciliation semantics themselves, preserve that evidence but do not infer guarantees that the upstream server did not declare.
Observation and audit
Record bounded correlation metadata through the existing WebCodex audit/Session/evidence paths where appropriate:
success, upstreamisError, transport failure,outcome_unknown);Do not record raw arguments when existing secret/privacy rules exclude them, and never record provider credentials/private environment.
Artifact integration
If an upstream MCP tool returns a file/image/large payload, bridge it into the existing WebCodex Artifact/data-plane model when practical rather than routing large base64 through model context.
The resulting Artifact remains governed by the caller's current owner/project authority and should retain safe provenance identifying the local MCP provider/tool and discovery revision that produced it.
Acceptance criteria
isError, definite pre-dispatch failure, and post-dispatch unknown outcome remain distinguishable.isError, startup failure, post-dispatch transport loss and cleanup on Linux; add platform-specific lifecycle coverage where the Runner implementation differs.Non-goals