Back to MCP Servers

Chisel

Reduce context usage on file use. Send only unified diffs instead of full files (up to 20-100× fewer tokens), and read large files with targeted `grep`/`sed` instead of full reads (up to 500×). Kernel-enforced path confinement hard-locks the agent to a configured root: no accide…

file-systemspythonrustnodeagent
By ckanthony
123Updated 3 months agoRust

Installation

npx -y Chisel

Configuration

{
  "mcpServers": {
    "Chisel": {
      "command": "npx",
      "args": ["-y", "Chisel"]
    }
  }
}

How to use

  1. Run the installation command above (if needed)
  2. Open your Claude Code settings file (~/.claude/settings.json)
  3. Add the configuration to the mcpServers section
  4. Restart Claude Code to apply changes

Chisel

CI codecov MCP server with tools

<img src="chisel.jpeg" alt="Chisel" width="300" />

🪛 Rust powered precision file operations for agents. Unix-native tools, minimal context footprint, strict path confinement: use directly with Chisel MCP or bring your own MCP, embeddable in any MCP server in Rust, Python, Nodejs.

https://github.com/user-attachments/assets/af84f1af-db47-4e42-808b-00861504cd34

Install — download a pre-built .mcpb bundle (one-click, no build step) or a raw binary from the Releases page — see Standalone usage below.


Agent skill includedskills/chisel/SKILL.md teaches agents how to use Chisel at maximum efficiency. Install with: npx skills add ckanthony/Chisel

Security hardened — Verified properties across two layers: the MCP server (chisel) and the portable core library (chisel-core). See the Security model section for the full breakdown.


Contents


Motivation

Most MCP file tools hand an LLM a blank canvas: read anything, write anything, make any mistake. Chisel takes the opposite approach:

  • Reduce context overhead — every tool call is compact. File edits go through patch_apply: the model sends only a unified diff instead of rewriting an entire file, so large-file edits cost a fraction of the tokens
  • Familiar command patternsshell_exec exposes the same Unix tools (grep, sed, awk, find, cat, …) LLMs already know well from training data, so prompts stay short and outputs are predictable
  • Precision over flexibility — a fixed whitelist and strict path confinement mean the model cannot accidentally escape scope or run arbitrary commands
  • Safety first — bearer-token auth, 127.0.0.1-only binding, symlink-aware root confinement, atomic writes, and a read-only mode are all on by default
  • Reusable corechisel-core is a plain synchronous Rust library; any MCP server (Rust, Node.js via WASM, Python via WASM) can embed it without running a second process

Real-world demo

Six tasks on the same markdown file. Left: typical MCP file server. Right: chisel.

File: docs/api.md — 300 lines, 6 headers, one section of ~20 lines.


Task 1 — find all headers

# Typical                                    # Chisel
tool: read_file                              tool: shell_exec
  path: /data/docs/api.md                     command: grep
                                               args: ["-n", "^#", "/data/docs/api.md"]
← 300 lines returned (~3 000 tokens)         ← 6 lines returned (~30 tokens)
  model must scan the whole file               1:# API Reference
                                              45:## Authentication
                                              89:## Endpoints
                                             134:## Request Format
                                             178:## Response Format
                                             234:## Errors

Task 2 — read the content under ## Endpoints

# Typical                                    # Chisel
tool: read_file  (again, or re-use above)    tool: shell_exec
  path: /data/docs/api.md                     command: sed
                                               args: ["-n", "/^## Endpoints/,/^## /p",
← 300 lines returned again (~3 000 tokens)          "/data/docs/api.md"]
  model must locate the section in context
                                             ← 44 lines returned (~440 tokens)
                                               only the Endpoints section

Task 3 — edit one line in that section

# Typical                                    # Chisel
tool: write_file                             tool: patch_apply
  path: /data/docs/api.md                     path: /data/docs/api.md
  content: <entire 300-line file              patch: |
            with one line changed>              --- a/docs/api.md
                                               +++ b/docs/api.md
← 300 lines uploaded (~3 000 tokens)           @@ -91,1 +91,1 @@
  any hallucination corrupts the file          -GET /v1/items
                                               +GET /v2/items

                                             ← 7 lines uploaded (~50 tokens)
                                               hunk mismatch → PatchFailed, file untouched

Task 4 — replace all - with : in that section

# Typical                                    # Chisel
tool: read_file                              tool: shell_exec
  path: /data/docs/api.md                     command: sed
                                               args: ["-i", "s/-/:/g",
← 300 lines returned (~3 000 tokens)                "/data/docs/api.md"]
tool: write_file
  content: <300 lines with replacement>       ← 1 line call, 0 file content transmitted
← 300 lines uploaded (~3 000 tokens)           sed runs the replacement in-place

Total: ~12 000 tokens                        Total: ~520 tokens   (23× less)

Task 5 — model tries to run rm -rf ~

# Typical                                    # Chisel
  (no shell tool exposed)                    tool: shell_exec
                                               command: rm
                                               args: ["-rf", "~"]
  not applicable — typical MCP file
  servers have no shell tool, so the        ← CommandNotAllowed
  model would need a separate shell           "rm" is not in the whitelist.
  MCP or use write_file to script it          Permitted: grep sed awk find cat
                                               head tail wc sort uniq cut tr
                                               diff file stat ls du rg
                                             process is never spawned

rm, bash, sh, curl, chmod, sudo — none of these are in the whitelist. The list is fixed at compile time; it cannot be extended at runtime by the model.

Task 6 — model tries to edit /Users/home/.ssh/config directly

# Typical                                    # Chisel
tool: write_file                             tool: patch_apply
  path: /Users/home/jor/.ssh/config               path: /Users/home/jor/.ssh/config
  content: <malicious key appended>           patch: <adds authorized_keys entry>

← succeeds if the server process            ← OutsideRoot
  has filesystem access — no path             resolved path /Users/home/.ssh/config
  confinement in a naive file server          does not start with root /data
                                             I/O is never performed

Every path — including those passed to shell_exec — is validated against the configured root before any I/O or process spawn. An absolute path outside root is always rejected, regardless of which tool is called.


Context cost comparison

Estimates use Claude Sonnet 4.6 tokenisation: typical source code averages ~10 tokens/line (identifiers, punctuation, and whitespace each count as tokens under BPE).

Single edit — 500-line file, 5 lines changed:

Naive (read_filewrite_file)Chisel (patch_apply)Reduction
Tokens in (upload)~5 000 (full file)~120 (11 diff lines + headers)42×
Tokens out (model output)~5 000 (full file rewrite)~15 (success ack)333×
Round-trip total~10 000~135~74×
Failure modeSilent hallucination corrupts entire filePatchFailed — original untouched

Read / search — 2 000-line file:

TaskNaive (read_file full)Chisel (shell_exec)Reduction
Find a symbol~20 000 tokens (full read)~40 tokens (grep matched lines)500×
Count occurrences~20 000 tokens~5 tokens (grep -c integer)4 000×
Extract lines 40–60~20 000 tokens~210 tokens (sed -n '40,60p')95×
Directory tree~20 000 tokens~300 tokens (find / ls -R)67×

Savings scale linearly with file size. A 2 000-line file costs 4× more than the 500-line baseline above.


Tools

Every path argument is canonicalized and confined to the configured root before any I/O — .. traversal and symlink escapes are rejected. This confinement is enforced inside chisel-core and applies equally when the library is embedded directly.

When using the MCP server (chisel), all tools additionally require Authorization: Bearer <secret>.

ToolDescription
patch_applyApply a unified diff atomically; accepts raw or ````diff` fenced patches — primary edit tool; sends only changed lines, not the full file
appendAppend content to an existing file
write_fileWrite (create or overwrite) a file; creates parent dirs automatically
create_directoryCreate a directory tree (mkdir -p semantics)
move_fileMove or rename a file within root
shell_execRun a whitelisted command — grep sed awk find cat head tail wc sort uniq cut tr diff file stat ls du rg

Full reference: docs/tools.md


Bring your own MCP

Chisel ships two embeddable libraries alongside the standalone server. Neither carries any HTTP, MCP protocol, or async runtime dependency — drop them into your own server and own the transport entirely.

PackageWhat it isUse it when
chisel-corePure Rust sync library — path confinement, all file ops, shell execWriting a Rust MCP server
chisel-wasmchisel-core compiled to wasm32-wasip1Writing an MCP server in Node.js, Python, Deno, or any WASI runtime

Full integration guide → **[chisel-core/README.md]

View source on GitHub