Architecture and trust boundaries

Request path

flowchart LR
  U["Untrusted workspace<br/>harness + project code"] -->|"MCP tool call"| T["Transport<br/>SSE / HTTP"]
  T --> K{"Capability source"}
  K --> P["CLI policy<br/>deny > allow > constraints"]
  P -->|allowed| E["Executor<br/>explicit argv + timeout"]
  E --> C["Host CLI"]
  C --> S["Scrub + output cap"]
  S --> U
  K --> M["MCP policy<br/>tool-name allow / deny"]
  M -->|allowed| X["Local stdio<br/>MCP server"]
  X --> MS["Scrub text results"]
  MS --> U
  P -->|denied| R["Capability request log"]
  O["Host operator"] --> R
  O --> F["Policy config"]
  F --> P

The host process, its YAML policy, configured binaries, spawned MCP servers, and host credentials are trusted. The harness, writable workspace, builds, tests, and dependencies are untrusted. The MCP token is an authorization credential available to the container and grants every capability exposed on that listener.

Components

Component Responsibility
cmd/serve.go Strict config load, transports, auth, admin listener, lifecycle
internal/whitelist Default-deny CLI and upstream MCP policy evaluation
internal/executor Sanitization, explicit argv execution, environment, limits, scrubbing
internal/introspect Parse CLI help and cache generated schema metadata
internal/mcpproxy Spawn and filter local stdio MCP servers
internal/requestlog Append-only request, decision, and tool-call event stream
internal/webui Local operator request review and CLI-rule editing
internal/harness Generate client-specific MCP configuration and manage descriptors

Process and filesystem boundary

wraptool up keeps wraptool on the host and runs the harness in either a Guix container or Dev Container. Both deliberately share the writable source tree and a harness-state HOME. The Guix runtime also uses the host network namespace. These shares are convenience domains, not security boundaries.

Wrapped CLI processes run on the host. Their environment includes a curated PATH, the host HOME, fixed LANG=C.UTF-8, and configured values. Because HOME is inherited, tools may discover user-global configuration or credentials; operators should override HOME and tool-specific config variables where a dedicated profile is required.

Configured MCP servers also run as host children over stdio with a curated environment. Wraptool forwards their declared input schemas and call arguments unchanged after filtering exact tool names. This is a coarser boundary than CLI rules: there are no per-argument MCP constraints, and only text results and errors are scrubbed.

Working directory

For CLI calls, the runtime working directory is selected from the network client’s ?cwd=, the Linux Unix-socket peer’s process CWD, or the tool’s configured working_dir. Client-derived paths are checked against mcp.allowed_cwd_roots only when that list is non-empty. Configured working_dir is operator-trusted and bypasses that check.

Reload boundary

Tool policy and registrations hot-reload after strict parsing and validation. Invalid edits leave the previous policy active. Listener addresses, HTTP auth, CWD roots, the admin listener, and request-log location are startup state and require a restart when changed.

Back to top