Skip to content

docs: correct tool permission examples and read-only guidance (refs #212) [v6] - #216

Merged
ben-vargas merged 1 commit into
ai-sdk-v6from
docs/tool-permissions-followup-v6
Oct 25, 2026
Merged

ben-vargas merged 1 commit into
ai-sdk-v6from
docs/tool-permissions-followup-v6

Conversation

@ben-vargas

Copy link
Copy Markdown
Owner

Refs #212

Follow-up to #213/#214. Changes docs and examples only; nothing in src/ changes.

What changed

  • examples/mcp-filesystem.ts is now actually read-only. It previously used bypassPermissions, which approves every tool, so the allowedTools "restriction" did nothing and write_file succeeded. It now uses permissionMode: 'dontAsk', with only the three MCP read tools pre-approved. The prompt ends with a write_file probe aimed at a file inside a temporary directory created for that run.
    • The example prints "Write blocked" only when the provider's permissionDenials metadata records that exact tool call ID, there was no stream error, and no probe file exists.
    • In every other case it prints INCONCLUSIVE or FAIL and exits 1.
    • A finally block removes only the run-owned directory.
  • Fake tool names removed: Delete was never a Claude Code tool, and current CLIs no longer have NotebookRead. Both are gone from both guides and tool-management.ts. LS (also not in the current CLI) is replaced in the current-version docs and examples, and kept in the 0.x guide, where it was a real tool.
  • "Read-only mode" corrected: denying only Write/Edit is not read-only, because Bash can still write.
    • Current guidance is tools: ['Read', 'Grep', 'Glob'], with MCP tools restricted separately.
    • The 0.x guide uses disallowedTools: ['Write', 'Edit', 'MultiEdit', 'NotebookEdit', 'Bash'], checked against the tools in @anthropic-ai/claude-code 1.0.24.
    • In the v5 guide, tools is labeled "provider 2.3.0+ on 2.x, or 3.1.0+", and dontAsk "3.2.0+". The MCP pattern that works in every version is listing the server's write tools in disallowedTools.
  • examples/README.md: the "MCP tool allowlists" wording is corrected. CHANGELOG entry under Unreleased → Fixed. No version bump.

Example runs

Run from a scratch cwd with CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 set through the provider env, using the /private/tmp realpath as the target.

  • Before: mcp__filesystem__write_file returned a result, and the probe file existed after the run.
  • After: list_allowed_directories, list_directory and read_text_file returned the file contents. write_file failed with "Permission to use mcp__filesystem__write_file has been denied because Claude Code is running in don't ask mode". The run ended with "Write blocked: the permission system denied write_file, and no probe file was created", exited 0, and left no directory behind.
  • tool-management.ts also ran cleanly.

Commands run

npm run lint, npm run typecheck, npm test (1156 tests passed), npm run format:check, npm run build and git diff --check all passed (lint keeps 2 existing warnings).

Independent review (Codex gpt-6-astra, xhigh)

  • Round 1, CHANGES REQUESTED: dontAsk was recommended in the 1.x–2.x guide without a version label; the probe passed on file absence alone; cleanup was skipped when the stream threw.
  • Round 2, CHANGES REQUESTED: cleanup could delete a pre-existing file; an undefined stream-error payload produced a false pass; "2.3.0+" wrongly included 3.0.x.
  • Round 3, SIGN-OFF on both lines. One non-blocking nit, left for later: document that the probe needs a writable target directory.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-25T07:34:02.527130Z f1dd120 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Claude finished @ben-vargas's task in 15s —— View job


Review of PR #216

I read the full diff against origin/ai-sdk-v6. I didn't run the build or tests. The PR description reports lint, typecheck, 1156 tests and build all passing.

Verdict: looks good. I found no blocking issues. The changes are docs and examples only, and the src/ code is untouched.

What's good

  • mcp-filesystem.ts now enforces its read-only claim.
    • bypassPermissions approves every tool, so the old allowedTools list restricted nothing. dontAsk plus a read-only allowedTools list is the correct fix.
    • The probe passes only when the exact toolUseId appears in permissionDenials, there was no stream error, and no probe file exists. A missing file alone doesn't count.
    • Probe cleanup is safe. mkdtempSync creates a run-owned directory, and the finally block removes only that directory, so a pre-existing file can't be deleted.
    • A failed or inconclusive probe sets process.exitCode = 1, so it's usable in CI.
  • Docs
    • Removing Delete, NotebookRead and LS from the current guides is accurate.
    • Saying that denying only Write/Edit is not read-only, because Bash can still write, is an important correction.
    • The version labels (tools on 2.3.0+ or 3.1.0+, dontAsk on 3.2.0+) are specific.
    • The 0.x guide keeps Bash in its deny list.

Minor suggestions (non-blocking)

  1. Writable target directory. mkdtempSync(join(targetDir, ...)) throws if the user passes a read-only directory as the optional argument. You noted this yourself as a follow-up. A one-line comment in the example header or examples/README.md would cover it.
  2. Default target directory. I didn't check what targetDir defaults to. If it's the repo or examples/, a crash between mkdtempSync and the try can't leak anything, because they are adjacent. A hard kill (SIGKILL) could still leave a mcp-write-probe-* directory behind, so you might add that pattern to .gitignore.
  3. Stream-error cleanup. process.exitCode = 1 is set inside finally, but the main().catch handler also calls process.exit(1). That's consistent, so there's nothing to fix.
  4. isWriteTo path matching. It uses strict string equality on path. If Claude normalizes the path (for example a /private/tmp realpath versus /tmp on macOS), the probe reports INCONCLUSIVE rather than a false pass. That fails safe, and your run notes already mention the realpath.
  5. v4 guide wording. The "Read-only built-in tools" bullet is long. It would read better split into two bullets, one for the pattern and one for the MCP caveat.

The CHANGELOG entry is accurate and sits correctly under Unreleased → Fixed.

@ben-vargas
ben-vargas merged commit c6bb907 into ai-sdk-v6 Oct 25, 2026
2 checks passed
@ben-vargas
ben-vargas deleted the docs/tool-permissions-followup-v6 branch October 25, 2026 09:00
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