Use Warden

Integration seams

Integrate Warden with MCP Runtime, Node isolated launchers, Orchestrator and Sandbox Policy.

Maelys Executor is the mechanical layer shared by MCP Runtime and Maelys Orchestrator. Neither adapter puts authorization logic in this library.

CODE
trusted manifest/profile                         approved agent request
          |                                               |
          v                                               v
  MCP Runtime adapter                           Orchestrator adapter
  request + sealed plan                         request + sealed plan
          |                                               |
          +------------------+  +-------------------------+
                             v  v
                       Maelys Executor
                    POSIX | Bubblewrap | Seatbelt

MCP Runtime

Both external providers and mcp-proxy upstreams must cross the same launcher adapter. The adapter converts the runtime's complete process specification into an opaque maelys_execution_request_t; it never lets a proxy's full argv bypass execution. The adapter is the only component that includes both public APIs.

For an isolated provider protocol:

  • use MAELYS_EXEC_IO_ISOLATED_DUPLEX;
  • copy the runtime's closed environment exactly for the "local" platform;
  • use inherited stderr so a pipe the runtime never drains cannot block a noisy provider;
  • transfer only the protocol descriptor with maelys_execution_take_fd();
  • map the runtime's launcher wait, stop and release operations to the corresponding Executor operations, with release remaining local-only;
  • build and seal the plan from trusted manifest/profile data before spawn.

Native, TypeScript and Python providers differ only in executable and argv. The fd layout and sandbox enforcement are applied by the host before the target program image starts.

Node isolated protocol launcher

The Node SDK exposes the same core contract through spawnIsolated(). Node talks to maelys-warden over ordinary stdin/stdout pipes; the CLI copies those opaque bytes to and from Executor's isolated fd 3 socket. No descriptor passing or MAELYS_PRESERVE_FDS convention is involved.

The SDK creates separate private control, workspace and writable temp locations. Workspace access remains governed by the selected policy. It passes the temp location as the launcher's TMPDIR, requests an empty child environment and keeps receipts outside the sandbox-writable root. Callers own continuous drainage of both the returned protocol duplex stream and stderr. wait() and stop() are idempotent; stop() relies on the CLI's bounded graceful/forced Executor shutdown.

Maelys Orchestrator

The orchestrator adapter uses the same execution specification for Codex, Claude Code or another agent process. Captured stdio or duplex stdio exposes the agent endpoint, while the approved workspace, writable paths, environment and network mode become a sealed plan. A policy decision point may produce that plan, but policy evaluation remains outside this repository.

Executions and the MCP launcher retain their executor. Adapters transfer only the descriptors they own. A host performs bounded shutdown when it owns the lifecycle; maelys_execution_release() itself never signals or waits.

Published MCP contract

E3 is compiled against the published mcp-runtime v0.23.0 contract at the exact tag commit recorded in adapter/MCP_RUNTIME_PIN. ABI 6 keeps the ABI 5 launcher function signatures and requires out-of-tree launchers to recompile with .abi_version = 6. It also authorizes a confining profile to augment the runtime's closed environment without replacing any base entry, and reserves child descriptors from 4 upward for explicit profile-installed channels. max_message_bytes is deliberately not consumed: the adapter transports bytes and does not parse or buffer MCP frames.

The hook itself belongs to the distribution that builds maelys-mcp, because that distribution owns the trusted profile registry. Its strong definition creates an Executor, registers the permitted backends, then calls maelys_mcp_executor_launcher_create() with its profile resolver. Linking that object through mcp-runtime's MCP_HOST_LAUNCHER_OBJECTS replaces the weak POSIX default for every process provider and proxied upstream. A failed hook or an unknown profile must return an error; neither may fall back to an unconfined launch.

The current adapter supports only the MCP environment platform token "local". Non-local targets are refused explicitly until the OCI target contract defines how their profile produces PATH; no value is guessed, dropped or translated.

The pure adapter can request an unconfined POSIX plan or a host-selected confined plan without depending on a concrete backend. It deliberately rejects EXTERNAL_CHANNEL plans: after removal of Executor's internal connector, only a Egress-aware host owns enough state to create the authenticated connector, retain its broker for the whole execution and stop it after the workload. Environment injection is not a channel and is never used as a fallback. An MCP distribution that needs mediated networking must compose the MCP launcher and Executor-Egress adapter in its host integration; the pure adapter remains useful for INHERIT and NONE plans.

Portable SandboxPlan compiler

maelys-sandbox-policy and Executor are joined by a separate optional adapter, not by sharing an opaque type. See sandbox-policy-integration.md. The former owns maelys_sandbox_policy_plan_t; Executor ABI 10 owns maelys_executor_plan_t. This keeps MIR compilation independent of launch mechanics and allows both libraries to be linked into the same registry host.