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
Architecture and trust boundaries
Request path
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.