Skip to content

mcpcage · free and open source

Every MCP server in its own cage.

mcpcage puts your AI assistant's plugins in a locked box. Each plugin does its job and nothing else, and if it changes behind your back, it is blocked. It works with Claude, Cursor, VS Code and Copilot. Without mcpcage, their plugins can read your files and passwords and send them anywhere. With mcpcage they can do that only if you allow it. Both protections start together, with one command, on the assistants you already use.

These plugins are called MCP servers.

See it on GitHub
npm install -g mcpcage

You need Docker and Node.js 22 or later. It runs on macOS, Linux and Windows (with Docker Desktop) and is licensed under Apache-2.0.

$ mcpcage protect
Claude Desktop  ~/Library/Application Support/Claude/claude_desktop_config.json
  filesystem    npx -y @modelcontextprotocol/server-filesystem /Users/you          NOT CAGED
                access: /Users/you: your whole home directory
  github        npx -y @modelcontextprotocol/server-github                         NOT CAGED
                secret in clear text: GITHUB_PERSONAL_ACCESS_TOKEN

Summary
  2 run on your machine with your permissions and no cage.          -> mcpcage protect --fix
  1 keeps a secret in clear text in a configuration file.
  1 can reach your whole home directory, the disk or a directory with credentials.
This is an excerpt from the project's demo (README and docs/demo-output.txt). In a Claude Desktop configuration, mcpcage protect finds two servers without a cage, one that can see the whole home directory and one with a token in clear text.

The problem

Most MCP servers are npm or PyPI packages that the assistant starts on your computer with npx or uvx. They run with your permissions, so they can read your SSH keys, your cloud credentials and your source code and send them anywhere.

A harmless server can also change in an update. If a tool description hides instructions, the assistant reads them along with everything else and may follow them. This is known as a rug pull or tool poisoning.

What it does

  • Locks the server in a container

    Each server starts in a Docker container with no network, a read-only disk and no access to your home directory. It sees only the folders you choose, read-only unless you say otherwise.

    mcpcage run
  • Pins the tools on first use

    The first time, it records the definition of every tool. If an update changes one, the session is locked and no call reaches the server until a person has looked at the change and approved it.

    mcpcage diffmcpcage approve
  • Points out signs of hidden instructions

    Under every change it lists the parts that look like hidden orders, such as tags addressed to the model, paths to secret files, requests to tell the user nothing or invisible characters. The rules are fixed, and nothing is sent off your computer.

    mcpcage protect --inspect
  • Keeps a chained log

    Each log entry holds the fingerprint of the one before it, so mcpcage audit verify notices if anyone has changed or deleted entries. For every call it stores the tool name and a fingerprint of the arguments, never their values.

    mcpcage audit verify
client:     MCP error -32001: mcpcage blocked tools/list: tool definitions of "demo-notes" changed
            since they were approved (rug-pull protection). 3 high-severity signs of hidden
            instructions. Run `mcpcage diff demo-notes`.

$ mcpcage diff demo-notes
~ tool "add_note" changed since it was approved
    ! HIGH    conceal-from-user  description: "Do not tell the user"       asks the model to hide something from you
    ! HIGH    hidden-tag         description: "<IMPORTANT>"                a tag that hides instructions for the model
    ! HIGH    sensitive-path     description: "~/.ssh/id_rsa"              points at a secret file
    ! MEDIUM  before-using       description: "Before calling this tool"   adds an action to every call of this tool
    3 high-severity signs of hidden instructions in "add_note"
In the project's demo (docs/demo-output.txt), a fake server ships a new version that adds a hidden order to a tool description. The assistant gets an error instead of the tool list, and mcpcage diff explains why the change looks suspicious.

Getting started

  1. Install it

    npm install -g mcpcage

    You need Docker running and Node.js 22 or later.

  2. See what runs without a cage

    mcpcage protect

    It reads the configurations of the clients installed on the computer and tells you which servers run without a cage and what they can reach. It also flags secrets written in clear text. The configurations stay as they are.

  3. Cage them

    mcpcage protect --fix

    It first shows what it is about to do and asks for confirmation, then cages the servers started with npx or uvx. It leaves a backup next to every file it changes, and mcpcage unwrap restores the original commands.

It reads the configurations of Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, Devin and GitHub Copilot CLI. The full instructions are in the project README.

Why you can trust it

Each item has a link where you can check it.

Open code
All the code is public, under the Apache-2.0 license.
LICENSE
No dependencies
The package brings no other libraries with it when you run it.
package.json
Traceable releases
Since version 0.6.3, every release reaches npm from the public build on GitHub, with no stored keys (trusted publishing), together with its provenance and a signed build attestation. Since 0.6.4, each release waits until the maintainer approves it with two-factor authentication.
CHANGELOG · npm · release.yml
OpenSSF Scorecard
The project is rated by the OpenSSF Scorecard, which checks the security practices of the repository.
Scorecard
63 servers tested
The 24 most downloaded MCP servers started with npx were tested in the cage on macOS, Windows and Linux, and the 39 most downloaded Python servers started with uvx on macOS and Linux. With the default settings 22 of the 24 start and list their tools, while 2 need the network. Of the 39, on Linux, 27 start, 3 need the network, 3 lack the prebuilt packages the cage requires and 6 stop for reasons of their own, for example because they check their credentials as they start.
compatibility.md
Tests every week
Every week the parts that read untrusted data or decide what is safe get 20,000 randomly generated inputs per test (fuzzing), and the code is changed on purpose, one small change at a time, to see whether the tests notice (mutation testing).
fuzz.yml · mutation.yml
Public advisories
The project publishes security advisories on GitHub. There have been five so far: three fixed in version 0.6.2, one in 0.6.4, one in 0.7.0.
Security advisories
Reporting
Anyone who finds a vulnerability reports it privately, as the project's security policy explains.
SECURITY.md

What it does not do

  • It relies on Docker and the kernel. A vulnerability in Docker or in the kernel that runs the containers can open the cage.
  • It does not filter the network. The network is either fully closed or fully open. A server that needs it, opened with --allow-net, can send data anywhere.
  • It trusts the first list of tools. It accepts that list without asking, unless you use --strict, which asks for an explicit approval the first time too.
  • It does not block results. The rules also read what the tools return and note the signs they find in the log, but they do not stop it, so the assistant gets what the server sent.
  • It only builds a cage for servers started with npx or uvx. A Python server needs prebuilt packages (wheels): one that installs only from source is refused, because installing it would run its code. mcpcage protect lists the others, and remote servers, but leaves them as they are; a server that already ships as a Docker image runs with --image.

The project's threat model, THREAT-MODEL.md, describes these limits in full.

For companies

mcpcage is free. If several people in your company work with AI assistants and MCP servers, we can help you install it and decide which folders each server gets to see.