From c1f51fe0eb965cf80b69c01c361adc195ca06068 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Sat, 31 Oct 2026 08:32:43 -0700 Subject: [PATCH 1/2] fix(mcp): tell the agent where run_command runs Commands run with HOME and TMPDIR in Chat's private scratch directory and a PATH of system directories only, but the tool description said neither. The agent read the results as if they came from the user's shell: go clean -modcache reported success after clearing an empty cache in scratch, and npm failed with exit code 127 without the agent knowing why. The description now states HOME, TMPDIR and PATH, asks for full paths to other programs, and says writes outside the project and scratch are refused. --- internal/mcp/actions.go | 2 +- site/src/content/docs/reference/mcp-tools.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/mcp/actions.go b/internal/mcp/actions.go index 48db76a..cf8e5f8 100644 --- a/internal/mcp/actions.go +++ b/internal/mcp/actions.go @@ -16,7 +16,7 @@ func registerActions(s *sdk.Server, o Options) { name, description string properties map[string]any }{ - {"run_command", "Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person.", map[string]any{"argv": map[string]any{"type": "array", "items": map[string]string{"type": "string"}, "minItems": 1}, "script": map[string]any{"type": "string", "minLength": 1}, "cwd": map[string]string{"type": "string"}, "timeout_seconds": map[string]any{"type": "integer", "minimum": 0, "maximum": 600}, "network": map[string]string{"type": "boolean"}}}, + {"run_command", "Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. Commands run with HOME and TMPDIR in a private scratch directory, so tools that default to the home directory (caches, config) act on that scratch copy, and with PATH=/usr/bin:/bin:/usr/sbin:/sbin, so give the full path of other programs, such as /opt/homebrew/bin/npm. Writes outside the project and scratch are refused.", map[string]any{"argv": map[string]any{"type": "array", "items": map[string]string{"type": "string"}, "minItems": 1}, "script": map[string]any{"type": "string", "minLength": 1}, "cwd": map[string]string{"type": "string"}, "timeout_seconds": map[string]any{"type": "integer", "minimum": 0, "maximum": 600}, "network": map[string]string{"type": "boolean"}}}, {"answer_prompt", "Answer one pending local Claude permission prompt. Always requires a person in every mode.", map[string]any{"id": map[string]string{"type": "string"}, "allow": map[string]string{"type": "boolean"}}}, {"ack_inbox", "Acknowledge a local inbox id or all local items.", map[string]any{"id": map[string]string{"type": "string"}, "all": map[string]string{"type": "boolean"}}}, {"jump", "Jump to a local session terminal. Never types into the terminal.", map[string]any{"session_id": map[string]string{"type": "integer"}}}, diff --git a/site/src/content/docs/reference/mcp-tools.mdx b/site/src/content/docs/reference/mcp-tools.mdx index c099661..c50fd05 100644 --- a/site/src/content/docs/reference/mcp-tools.mdx +++ b/site/src/content/docs/reference/mcp-tools.mdx @@ -378,7 +378,7 @@ No inputs. ### run_command -Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. +Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. Commands run with HOME and TMPDIR in a private scratch directory, so tools that default to the home directory (caches, config) act on that scratch copy, and with PATH=/usr/bin:/bin:/usr/sbin:/sbin, so give the full path of other programs, such as /opt/homebrew/bin/npm. Writes outside the project and scratch are refused. | Input | Type | Required | Description | |---|---|---|---| From f067ee1f63bc42e205e13ec553154915eede5945 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Sat, 31 Oct 2026 09:15:55 -0700 Subject: [PATCH 2/2] fix(mcp): describe the empty scratch home and how to extend PATH Address review: the scratch home starts empty, and Homebrew programs such as npm start node through /usr/bin/env, so a full path alone fails; set PATH in a script instead. --- internal/mcp/actions.go | 2 +- site/src/content/docs/reference/mcp-tools.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/mcp/actions.go b/internal/mcp/actions.go index cf8e5f8..128596a 100644 --- a/internal/mcp/actions.go +++ b/internal/mcp/actions.go @@ -16,7 +16,7 @@ func registerActions(s *sdk.Server, o Options) { name, description string properties map[string]any }{ - {"run_command", "Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. Commands run with HOME and TMPDIR in a private scratch directory, so tools that default to the home directory (caches, config) act on that scratch copy, and with PATH=/usr/bin:/bin:/usr/sbin:/sbin, so give the full path of other programs, such as /opt/homebrew/bin/npm. Writes outside the project and scratch are refused.", map[string]any{"argv": map[string]any{"type": "array", "items": map[string]string{"type": "string"}, "minItems": 1}, "script": map[string]any{"type": "string", "minLength": 1}, "cwd": map[string]string{"type": "string"}, "timeout_seconds": map[string]any{"type": "integer", "minimum": 0, "maximum": 600}, "network": map[string]string{"type": "boolean"}}}, + {"run_command", "Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. Commands run with HOME and TMPDIR in a private, initially empty scratch directory, so tools that default to the home directory see no user caches, config or credentials and act on scratch instead, and with PATH=/usr/bin:/bin:/usr/sbin:/sbin. To run other programs, set PATH in a script, such as PATH=/opt/homebrew/bin:$PATH npm test, since many of them start their interpreter through /usr/bin/env. Writes outside the project and scratch are refused.", map[string]any{"argv": map[string]any{"type": "array", "items": map[string]string{"type": "string"}, "minItems": 1}, "script": map[string]any{"type": "string", "minLength": 1}, "cwd": map[string]string{"type": "string"}, "timeout_seconds": map[string]any{"type": "integer", "minimum": 0, "maximum": 600}, "network": map[string]string{"type": "boolean"}}}, {"answer_prompt", "Answer one pending local Claude permission prompt. Always requires a person in every mode.", map[string]any{"id": map[string]string{"type": "string"}, "allow": map[string]string{"type": "boolean"}}}, {"ack_inbox", "Acknowledge a local inbox id or all local items.", map[string]any{"id": map[string]string{"type": "string"}, "all": map[string]string{"type": "boolean"}}}, {"jump", "Jump to a local session terminal. Never types into the terminal.", map[string]any{"session_id": map[string]string{"type": "integer"}}}, diff --git a/site/src/content/docs/reference/mcp-tools.mdx b/site/src/content/docs/reference/mcp-tools.mdx index c50fd05..788dd42 100644 --- a/site/src/content/docs/reference/mcp-tools.mdx +++ b/site/src/content/docs/reference/mcp-tools.mdx @@ -378,7 +378,7 @@ No inputs. ### run_command -Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. Commands run with HOME and TMPDIR in a private scratch directory, so tools that default to the home directory (caches, config) act on that scratch copy, and with PATH=/usr/bin:/bin:/usr/sbin:/sbin, so give the full path of other programs, such as /opt/homebrew/bin/npm. Writes outside the project and scratch are refused. +Run one local bounded command through broker preparation and approval. Use literal argv or an explicit shell script; 120 second default, 600 maximum. Process and destructive commands always need a person. Commands run with HOME and TMPDIR in a private, initially empty scratch directory, so tools that default to the home directory see no user caches, config or credentials and act on scratch instead, and with PATH=/usr/bin:/bin:/usr/sbin:/sbin. To run other programs, set PATH in a script, such as PATH=/opt/homebrew/bin:$PATH npm test, since many of them start their interpreter through /usr/bin/env. Writes outside the project and scratch are refused. | Input | Type | Required | Description | |---|---|---|---|