New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

mcp-filter

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mcp-filter

MCP server proxy to filter tools, resources, and prompts from upstream MCP servers

latest
Source
npmnpm
Version
1.1.3
Version published
Weekly downloads
271
-35.48%
Maintainers
1
Weekly downloads
 
Created
Source

mcp-filter

MCP proxy that filters tools, resources, and prompts using glob patterns.
Any MCP server. Any MCP client. Local or remote.

npm version CI License: MIT Node version MCP Spec

The Problem

MCP servers are getting bigger. Playwright exposes 22 tools. Supabase has 33. Grafana has 56. Atlassian has 72. GitHub MCP has 79. Connect three or four of these and you're looking at 150+ tools consuming 60,000+ tokens before your first message.

This isn't just a cost problem. Research shows tool selection accuracy drops from 95% with 4 tools to 71% with 46 — a 24-point gap caused purely by context bloat. LLMs start struggling at around 30 tools for large models and 19 for smaller ones. Only 30% of Playwright tools are used in typical workflows — the rest are noise that makes the agent take wrong actions.

Most MCP clients offer blacklists (disabledTools, tool caps). These have two failure modes: you have to manually list every tool to block across every server update, and new tools added upstream silently leak into context because they're not in your blocklist. Cursor hard-caps at 40 tools — exceed it and tools are silently dropped. Claude Code users report 30–72% of their 200K context consumed by tool definitions alone.

Blacklists describe what you don't want. Whitelists describe what you do want — and they're immune to upstream changes.

The Solution

mcp-filter is an MCP proxy that sits between your client and server. It intercepts tool/resource/prompt lists, applies glob patterns, and only passes through what matches — turning 79 tools into 10, or 150 into 15. Works with local servers via stdio, remote servers via HTTP, and legacy servers via SSE.

┌──────────────┐               ┌──────────────────────┐               ┌──────────────┐
│  MCP Client  │               │      mcp-filter      │   stdio /     │   Upstream   │
│              │     stdio     │                      │    HTTP       │   Server     │
│  Claude      │◄───────────►│  --include "pr_*"    │◄───────────►│              │
│  Cursor      │   10 tools    │  --exclude "del_*"   │   79 tools    │  GitHub      │
│  VS Code     │               │                      │               │  Playwright  │
└──────────────┘               └──────────────────────┘               └──────────────┘

Add it to your MCP client's JSON config:

{
  "mcpServers": {
    "playwright-safe": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--exclude", "browser_close",
        "--exclude", "browser_evaluate",
        "--include", "browser_*",
        "--",
        "npx", "@playwright/mcp@latest"
      ]
    }
  }
}

No install needed — npx downloads it automatically. This config format works with Cursor, VS Code, Claude Desktop, and any MCP client that supports stdio servers.

Remote server (HTTP)
{
  "mcpServers": {
    "stripe-safe": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--exclude", "create_refund",
        "--exclude", "delete_*",
        "--upstream-url", "https://mcp.stripe.com"
      ]
    }
  }
}
Remote server with authentication
{
  "mcpServers": {
    "api-readonly": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--exclude", "write_*",
        "--exclude", "delete_*",
        "--upstream-url", "https://api.example.com/mcp",
        "--authorization", "Bearer your-oauth-token"
      ]
    }
  }
}

For additional headers, use --header "Key: Value" (repeatable).

Claude Code

Claude Code uses claude mcp add instead of JSON config:

# Local server (two -- separators: first for Claude, second for mcp-filter)
claude mcp add playwright-safe -- \
  npx mcp-filter \
    --exclude "browser_close" \
    --exclude "browser_evaluate" \
    --include "browser_*" \
    -- npx @playwright/mcp@latest

# Remote HTTP server (no second --)
claude mcp add stripe-safe -- \
  npx mcp-filter \
    --exclude "create_refund" \
    --exclude "delete_*" \
    --upstream-url https://mcp.stripe.com

First -- separates Claude's options from mcp-filter. Second -- separates mcp-filter's options from the upstream command.

How Filtering Works

mcp-filter supports three filtering modes:

Exclude mode blocks specific tools and allows everything else. Use --exclude when you trust most tools but want to remove a few dangerous ones: --exclude "delete_*" blocks all delete operations.

Include mode (whitelist) allows only what you specify and blocks everything else. Use --include when you want a tight perimeter: --include "pull_request_*" passes through only PR tools. New tools added upstream are automatically blocked.

Combined mode uses rsync-style ordering — patterns are evaluated in the order you write them, and the first match wins. This lets you create exceptions within a category:

--exclude "merge_pull_request" --include "pull_request_*"

Here, merge_pull_request hits the exclude rule first, so it's blocked. Other pull_request_* tools match the include rule and pass through. Anything that doesn't match any pattern is excluded (because --include exists).

Reversing the order would break this: --include "pull_request_*" --exclude "merge_pull_request" — now merge_pull_request matches pull_request_* first and gets included.

Pattern syntax and default behavior

Patterns use glob syntax via minimatch:

PatternMatches
browser_*All items starting with browser_
*_adminAll items ending with _admin
test_*_debugItems like test_foo_debug
exact_nameExact match only
*Everything

Default behavior for unmatched items:

ConfigurationUnmatched items are...
No patternsAllowed (passthrough)
--exclude onlyAllowed
--include onlyExcluded (whitelist mode)
MixedExcluded if any --include exists

Real-World Examples

Playwright — navigation agent (22 → 3 tools)

Playwright MCP has 22 tools, but only ~30% are used in typical workflows. A navigation agent only needs to navigate and take screenshots:

{
  "mcpServers": {
    "playwright-nav": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--include", "browser_navigate",
        "--include", "browser_screenshot",
        "--include", "browser_click",
        "--",
        "npx", "@playwright/mcp@latest"
      ]
    }
  }
}

Without filtering, the agent wastes actions calling browser_console_messages and browser_snapshot when it doesn't need them.

GitHub MCP — PR review agent (79 → ~10 tools)

GitHub MCP exposes 79 tools across 19 toolsets. A code review agent only needs PRs, issues, file contents, and search:

{
  "mcpServers": {
    "github-pr-review": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--include", "pull_request_*",
        "--include", "issue_*",
        "--include", "get_file_contents",
        "--include", "list_commits",
        "--include", "search_code",
        "--",
        "github-mcp-server", "stdio"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<your-token>"
      }
    }
  }
}

The other 69 tools (gists, stars, security advisories, dependabot, discussions...) are excluded. When GitHub adds new tools, they won't leak through.

Any server — read-only mode

An analytics or reporting agent shouldn't be able to mutate anything. This pattern works with any MCP server that follows create_*/update_*/delete_* naming conventions:

{
  "mcpServers": {
    "github-readonly": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--exclude", "create_*",
        "--exclude", "update_*",
        "--exclude", "delete_*",
        "--exclude", "push_*",
        "--exclude", "merge_*",
        "--exclude", "*_write",
        "--",
        "github-mcp-server", "stdio"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<your-token>"
      }
    }
  }
}
Rsync-style — exceptions within a category

Allow all PR tools except the ability to merge. The --exclude fires first:

{
  "mcpServers": {
    "github-pr-safe": {
      "command": "npx",
      "args": [
        "mcp-filter",
        "--exclude", "merge_pull_request",
        "--include", "pull_request_*",
        "--include", "list_pull_requests",
        "--include", "search_pull_requests",
        "--",
        "github-mcp-server", "stdio"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<your-token>"
      }
    }
  }
}

merge_pull_request hits --exclude first and gets blocked. The remaining PR tools match --include and pass through.

Options

OptionDescription
--exclude <pattern>Exclude items matching glob pattern (repeatable)
--include <pattern>Include only items matching glob pattern (repeatable)
--upstream-url <url>Connect to remote HTTP/SSE server (mutually exclusive with --)
--transport <type>Transport type: stdio, http, sse (auto-detected)
--authorization <value>Set Authorization header (e.g. "Bearer token", HTTP/SSE only)
--header <header>HTTP header as "Key: Value" (repeatable, HTTP/SSE only)
--Separates mcp-filter options from upstream command (stdio only)

Transport is auto-detected: --upstream-url selects HTTP, -- <command> selects stdio.

Common mistakes

JSON args must be separate strings. In JSON configs, each argument must be its own array element:

// WRONG
"args": ["mcp-filter", "--include browser_*", "--", "npx", "server"]

// CORRECT
"args": ["mcp-filter", "--include", "browser_*", "--", "npx", "server"]

mcp-filter detects this mistake and shows a corrective error message.

Pattern order matters. Put --exclude before --include to create exceptions. First match wins:

--exclude "browser_close" --include "browser_*"   (browser_close blocked)
--include "browser_*" --exclude "browser_close"   (browser_close allowed!)

Two -- in Claude Code. First -- separates Claude's options. Second -- separates mcp-filter's options from the upstream command:

claude mcp add my-server -- npx mcp-filter --exclude "dangerous_*" -- npx upstream-server
#                        ^^                                        ^^
#                   Claude's --                              mcp-filter's --
Transports
TransportFlagUse CaseStatus
Stdio-- <command>Local servers spawned as subprocessesStable
HTTP--upstream-url <url>Remote servers via Streamable HTTPStable
SSE--transport sse --upstream-url <url>Legacy remote servers via Server-Sent EventsDeprecated
Development
git clone https://github.com/baranovxyz/mcp-filter.git
cd mcp-filter
pnpm install
pnpm run build
pnpm test

See CONTRIBUTING.md for contribution guidelines and TESTING.md for the testing guide.

License

MIT

Keywords

mcp

FAQs

Package last updated on 26 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts