Skip to content

feat(agent): add MCP toolchain shims with config isolation#1879

Draft
wpfleger96 wants to merge 1 commit into
mainfrom
duncan/mcp-toolchain-shims
Draft

feat(agent): add MCP toolchain shims with config isolation#1879
wpfleger96 wants to merge 1 commit into
mainfrom
duncan/mcp-toolchain-shims

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

Bundled shell shims that resolve bare uv, uvx, npx, and node commands to hermit-managed, config-isolated toolchains for MCP server spawning. This fixes the incident where a salt-managed /etc/uv/uv.toml with unsupported system-certs broke all MCP servers using bare uv commands.

Shell shims (crates/buzz-agent/resources/shims/)

  • setup-common.sh: shared hermit bootstrap with SHA-verified installer, mkdir-based lock with PID+timestamp stale detection (600s), isolated HERMIT_STATE_DIR, macOS PATH fix, Linux temp-binary workaround. Logging to $BUZZ_MCP_LOG_DIR/mcp-shim.log with umask 077 — never logs arguments or env var values.
  • uv/uvx: UV_NO_CONFIG=1 suppresses all uv config file discovery — direct defense against the incident.
  • npx/node: two distinct empty npmrc files (empty-user-npmrc + empty-global-npmrc) avoid npm's double-load crash, NPM_CONFIG_LOCATION=global suppresses project .npmrc discovery.

Rust changes

  • Shim resolver (mcp.rs): pure cfg(unix) resolve_shim_command(command, shim_dir) rewrites bare uv/uvx/npx/node to <shim_dir>/<command> when the shim file exists. Absolute paths and unknown commands pass through unchanged.
  • Spawn-boundary env construction (mcp.rs): build_child_env() / build_child_env_with() propagates BUZZ_MCP_SHIM_DIR, BUZZ_MCP_HERMIT_DIR, and BUZZ_MCP_LOG_DIR through env_clear() into the child process, then applies spec.env with last-write-wins semantics so explicit server overrides take precedence.
  • Config timeout (config.rs): mcp_init_timeout default bumped from 30s to 300s (matches Goose). Env-overridable via BUZZ_AGENT_MCP_INIT_TIMEOUT_SECS.

Desktop integration (runtime.rs, tauri.conf.json)

  • Shims bundled as Tauri resources with ensure_shims_executable() for execute-bit preservation.
  • BUZZ_MCP_SHIM_DIR set from resource_dir/shims (read-only bundle resources).
  • BUZZ_MCP_HERMIT_DIR set from app_data_dir/mcp-hermit (writable state) — separated from the signed app bundle.
  • BUZZ_MCP_LOG_DIR set from data_local_dir/xyz.block.buzz.app/logs.

Tests

Unit tests (9 new in mcp.rs):

  • 8 shim resolver tests: bare command resolution for all 4 commands, absolute path passthrough, unknown command passthrough, None shim dir, missing shim file.
  • 1 spawn-boundary test (build_child_env_propagates_shim_vars_and_spec_overrides): verifies all three BUZZ_MCP_* variables propagate through build_child_env_with() and that explicit spec.env overrides win via last-write-wins.

Integration tests (7 in tests/shim_hostile_config.rs):

  • Shim file existence + execute bits for all 5 checked-in scripts.
  • npm_uses_distinct_config_files: user and global npmrc are separate files.
  • Real wrapper suite (5 tests): invokes the actual checked-in uv, uvx, npx, and node wrappers through setup-common.sh with a pre-seeded fake hermit dir containing probe scripts. Verifies UV_NO_CONFIG=1 for uv/uvx, npm isolation vars for npx/node, and explicit UV_INDEX_URL override passthrough. No network dependency.

@wpfleger96 wpfleger96 requested a review from a team as a code owner July 14, 2026 22:52
@wpfleger96 wpfleger96 force-pushed the duncan/mcp-toolchain-shims branch from db73ea3 to ca20a52 Compare July 15, 2026 00:15
Bundled shell shims that resolve bare uv, uvx, npx, and node commands
to hermit-managed, config-isolated toolchains for MCP server spawning.
Fixes the incident where a salt-managed /etc/uv/uv.toml with unsupported
system-certs broke all MCP servers using bare uv commands.

Shell shims (setup-common.sh + per-tool wrappers) bootstrap hermit with
SHA-verified installer and isolated state. uv/uvx set UV_NO_CONFIG=1;
npx/node use distinct empty npmrc files to avoid npm's double-load crash.

Rust resolver rewrites bare commands to shim paths when available.
build_child_env() propagates BUZZ_MCP_SHIM_DIR, BUZZ_MCP_HERMIT_DIR,
and BUZZ_MCP_LOG_DIR through env_clear() with spec.env last-write-wins.
mcp_init_timeout bumped from 30s to 300s (env-overridable).

Desktop integration bundles shims as Tauri resources with
ensure_shims_executable() and separates writable hermit state from
the signed app bundle.
@wpfleger96 wpfleger96 force-pushed the duncan/mcp-toolchain-shims branch from ca20a52 to 3baf39e Compare July 15, 2026 00:18
@wpfleger96 wpfleger96 marked this pull request as draft July 15, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant