过滤器
STDIO过滤上游工具的代理MCP服务器
过滤上游工具的代理MCP服务器
  A proxy MCP (Model Context Protocol) server that filters the upstream tool surface to just the tools you need. Expose one or two critical tools (for example, execute_sql on Supabase) while filtering out the token-costly ones, without having to modify the upstream implementation.
Before: Unfiltered MCP servers consumed ~50k tokens on a fresh Claude Code session
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   claude-sonnet-4-5 · 112k/200k tokens (56%)
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   ⛁ System: 2.3k tokens
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   ⛁ System tools: 11.8k tokens
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁   ⛁ MCP tools: 50.1k tokens (25%)  ← Large!
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛶ Free space: 88k (44%)
After: With mcp-filter, reduced to ~13.7k tokens (72% reduction) while keeping all necessary tools.
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛶ ⛶   claude-sonnet-4-5 · 80k/200k tokens (40%)
⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛁ ⛶ ⛶ ⛶
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System: 2.3k tokens
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ System tools: 11.8k tokens
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛁ MCP tools: 13.7k tokens (6.9%)  ← Filtered!
⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶ ⛶   ⛶ Free space: 120k (60%)  ← +32k gained
Filter only the tools you need, save context for longer sessions.
To see your token usage: Open Claude Code and run /context to view the breakdown.
Python 3.10+ is supported; 3.11 is recommended.
pip install mcp-filter
# Run directly without installing (like npx) uvx mcp-filter --version # Or install globally uv tool install mcp-filter
From source (development):
pyenv install 3.11.9 pyenv local 3.11.9 python -m venv .venv source .venv/bin/activate pip install -e '.[dev]'
mcp-filter run \ -t stdio \ --stdio-command npx \ --stdio-arg "-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN" \ -a "execute_sql,list_tables,get_project"
Shorthand flags: -t (transport), -a (allow-tool), -d (deny-pattern), -p (prefix)
Note: Both --stdio-arg and -a support flexible input - use repeatable flags or comma-separated strings, whichever is cleaner for your use case.
Transform any existing MCP server config by wrapping it with mcp-filter. The filter proxies your original command and only exposes the tools you specify with -a.
Before (original Supabase config):
{ "mcpServers": { "supabase": { "command": "npx", "args": [ "-y", "@supabase/mcp-server-supabase@latest", "--access-token", "YOUR_TOKEN" ] } } }
This exposes all 29 tools (~20.8k tokens):
└ mcp__supabase__search_docs (supabase): 2.8k tokens
└ mcp__supabase__list_organizations (supabase): 582 tokens
└ mcp__supabase__get_organization (supabase): 604 tokens
└ mcp__supabase__list_projects (supabase): 600 tokens
└ mcp__supabase__get_project (supabase): 603 tokens
└ mcp__supabase__get_cost (supabase): 646 tokens
└ mcp__supabase__confirm_cost (supabase): 682 tokens
└ mcp__supabase__create_project (supabase): 832 tokens
└ mcp__supabase__pause_project (supabase): 599 tokens
└ mcp__supabase__restore_project (supabase): 599 tokens
└ mcp__supabase__list_tables (supabase): 640 tokens
└ mcp__supabase__list_extensions (supabase): 596 tokens
└ mcp__supabase__list_migrations (supabase): 596 tokens
└ mcp__supabase__apply_migration (supabase): 668 tokens
└ mcp__supabase__execute_sql (supabase): 657 tokens
└ mcp__supabase__get_logs (supabase): 677 tokens
└ mcp__supabase__get_advisors (supabase): 699 tokens
└ mcp__supabase__get_project_url (supabase): 599 tokens
└ mcp__supabase__get_anon_key (supabase): 601 tokens
└ mcp__supabase__generate_typescript_types (supabase): 600 tokens
└ mcp__supabase__list_edge_functions (supabase): 603 tokens
└ mcp__supabase__get_edge_function (supabase): 625 tokens
└ mcp__supabase__deploy_edge_function (supabase): 907 tokens
└ mcp__supabase__create_branch (supabase): 718 tokens
└ mcp__supabase__list_branches (supabase): 625 tokens
└ mcp__supabase__delete_branch (supabase): 596 tokens
└ mcp__supabase__merge_branch (supabase): 603 tokens
└ mcp__supabase__reset_branch (supabase): 636 tokens
└ mcp__supabase__rebase_branch (supabase): 617 tokens
After (wrapped with mcp-filter):
{ "mcpServers": { "supabase": { "command": "mcp-filter", "args": [ "run", "-t", "stdio", "--stdio-command", "npx", "--stdio-arg", "-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN", "-a", "execute_sql,list_tables,get_project" ] } } }
This only exposes 3 tools we allowed (~1.9k tokens = 91% reduction!):
└ mcp__supabase__get_project (supabase): 605 tokens
└ mcp__supabase__list_tables (supabase): 642 tokens
└ mcp__supabase__execute_sql (supabase): 659 tokens
examples/mcp.json.sample includes common setups. Add to your mcp.json:
Supabase (stdio) – wrap the official MCP binary:
"supabase": { "command": "mcp-filter", "args": [ "run", "-t", "stdio", "--stdio-command", "npx", "--stdio-arg", "-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN", "-a", "execute_sql,list_tables,get_project" ] }
Or use uvx for faster, ephemeral execution:
"supabase": { "command": "uvx", "args": [ "mcp-filter", "run", "-t", "stdio", "--stdio-command", "npx", "--stdio-arg", "-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN", "-a", "execute_sql,list_tables,get_project" ] }
Linear (stdio wrapping mcp-remote) – preserves OAuth browser flow:
"linear": { "command": "mcp-filter", "args": [ "run", "-t", "stdio", "--stdio-command", "npx", "--stdio-arg", "-y mcp-remote https://mcp.linear.app/sse", "-a", "get_issue,list_issues,create_issue,update_issue,create_comment" ] }
Adjust auth-tokens/headers to match your environment; the filter never logs or exposes them.
Environment variables (prefixed with MF_) override CLI flags. See .env.example for a template.
MF_TRANSPORT / -t: stdio (default) or httpMF_STDIO_COMMAND / MF_STDIO_ARGS: upstream binary + argsMF_HTTP_URL / MF_HTTP_HEADERS: SSE/HTTP endpoint and extra headers (key=value;Another=Value)MF_ALLOW_TOOLS / -a: exact tool names (repeatable, or comma-separated)MF_ALLOW_PATTERNS: regex patterns for tool names (repeatable, or comma-separated)MF_DENY_PATTERNS / -d: regex patterns to block (repeatable, or comma-separated)MF_RENAME_PREFIX / -p / --prefix: prefix exposed tool names (e.g., supabase_)MF_INCLUDE_HEALTH_TOOL=1 / --health: enable built-in health tool (disabled by default)MF_SHOW_TOKEN_ESTIMATES=1: enable token estimate logging (disabled by default)Can I expose more than one tool? Yes—pass multiple --allow-tool flags or use regex patterns. All exposed tools share the optional rename prefix.
Are my credentials safe? Yes. The filter never logs secrets passed as CLI arguments or headers.
What if the upstream goes down? Health checks surface the failure while the filter continues to reject new calls with a clear error.
Can I merge config files? Env + CLI merging is built in. For more complex setups, script the CLI invocation or add a thin wrapper that loads mf.toml and passes flags.
MF_INCLUDE_HEALTH_TOOL=1 or --health.MF_STDIO_ARGS) to avoid exposing credentials in process lists.mcp>=1.0.0 and fastmcp>=0.3.0 (installed automatically)Schema Pruning — Additional 30-60% token reduction
--prune-schema [off|safe|aggressive] to strip non-essential schema fieldstitle, description, examples, default while preserving contractEnhanced Error Handling
-32602 for blocked tools){"public_tools": [...], "tool_requested": "...", "reason": "not_allowlisted"}Collision-Safe Naming
tool_name_{hash[:4]})Full JSON Schema Validation
Structured Logging & Monitoring
--log-format [pretty|json] for production-friendly JSON lines--redact-keys to automatically redact sensitive field namesOperational Controls
--timeout-ms (default: 120000) for per-call timeouts--max-concurrency (default: 8) to limit parallel upstream callsResources & Prompts Filtering
--allow-resources and --allow-prompts (off by default)--upstream NAME=cmd... for managing multiple filtered servers--deny-dangerous-verbs to block destructive operations by defaultsource .venv/bin/activate python -m pytest
The suite exercises filtering precedence, rename collisions, schema validation, health handling, and call forwarding against a fake upstream server.