Skip to content

Add a bounded Runner-local MCP bridge for discovered upstream tools #95

Description

@yyjeqhc

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:

  1. discover the configured MCP providers/tools that the exact authorized Runner/Project makes available;
  2. 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:

  1. revalidate caller owner/project authority;
  2. revalidate Runner identity/readiness and bridge capability;
  3. revalidate provider configuration/generation and discovery revision;
  4. revalidate the selected tool still exists with the expected schema/revision;
  5. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions