<div align="center">
<img src="logo.png" alt="MCP Filter" width="300">
<h1>MCP Filter</h1>
<p>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, <code>execute_sql</code> on Supabase) while filtering out the token-costly ones, without having to modify the upstream implementation.</p>
</div>
## Before & After
**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.
## What & Why
- **Static allowlist** keeps the exposed tool list tiny, cutting context usage for clients that serialize tool schemas.
- **Drop-in proxy**: stands in front of any MCP server that speaks stdio or HTTP/SSE, forwarding calls transparently.
- **Safety guardrails**: optional regex-based deny list, optional prefix, and optional health tool for observability.
## Installation
Python 3.10+ is supported; 3.11 is recommended.
```bash
pip install mcp-filter
```
**From source (development):**
```bash
pyenv install 3.11.9
pyenv local 3.11.9
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
```
## Quick Start
```bash
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.
## How to Wrap Your MCP
### Concept
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):**
```json
{
"mcpServers": {
"supabase": {
"command": "npx",
"args": [
"-y",
"@supabase/mcp-server-supabase@latest",
"--access-token",
"YOUR_TOKEN"
]
}
}
}
```
This exposes all 29 tools (**~20.8k tokens**):
<details>
<summary>Show all tools</summary>
```
└ 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
```
</details>
**After (wrapped with mcp-filter):**
```json
{
"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 for Claude Code / Claude Desktop
`examples/mcp.json.sample` includes common setups. Add to your `mcp.json`:
**Supabase (stdio)** – wrap the official MCP binary:
```json
"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"
]
}
```
**Linear (stdio wrapping mcp-remote)** – preserves OAuth browser flow:
```json
"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.
## Configuration Reference
Environment variables (prefixed with `MF_`) override CLI flags. See `.env.example` for a template.
- `MF_TRANSPORT` / `-t`: `stdio` (default) or `http`
- `MF_STDIO_COMMAND` / `MF_STDIO_ARGS`: upstream binary + args
- `MF_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)
## FAQ
**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.
## Advanced
### Observability & Health
- Rich-based structured logging annotates server name, transport, and exposed tool count.
- Optional built-in health tool (disabled by default, ~500 tokens per server) returns upstream liveness and exposed tool names; output is safe JSON. Enable with `MF_INCLUDE_HEALTH_TOOL=1` or `--health`.
### Security Notes
- Only tools explicitly allowlisted or matching an allow regex are exposed.
- Deny-patterns apply last to ensure sensitive tools stay hidden.
- Optional rename prefix avoids tool collisions when multiple filtered proxies run side-by-side.
- Health payload (when enabled) avoids secrets—only structural metadata is emitted.
- **Credentials & secrets**: Arguments and headers passed via CLI flags are never logged. For production deployments, prefer environment variables (e.g., `MF_STDIO_ARGS`) to avoid exposing credentials in process lists.
### Requirements
- Python 3.10+ (3.11 recommended)
- `mcp>=1.0.0` and `fastmcp>=0.3.0` (installed automatically)
- Upstream tool list is fixed per session; mid-run changes require restart
- HTTP transport requires SSE-compatible upstream servers
## Roadmap
### v0.2.0 (Planned)
**Schema Pruning** — Additional 30-60% token reduction
- Add `--prune-schema [off|safe|aggressive]` to strip non-essential schema fields
- Safe mode: remove `title`, `description`, `examples`, `default` while preserving contract
- Aggressive mode: strip all descriptions except top-level (≤140 chars)
**Enhanced Error Handling**
- Return proper JSON-RPC error codes (e.g., `-32602` for blocked tools)
- Include helpful error details: `{"public_tools": [...], "tool_requested": "...", "reason": "not_allowlisted"}`
**Collision-Safe Naming**
- Replace collision failures with deterministic suffixes (`tool_name_{hash[:4]}`)
- Log warnings but continue operation
**Full JSON Schema Validation**
- Validate tool arguments locally before forwarding upstream
- Provide clear, early error messages for invalid calls
- Compile schemas at startup for performance
**Structured Logging & Monitoring**
- Add `--log-format [pretty|json]` for production-friendly JSON lines
- Add `--redact-keys` to automatically redact sensitive field names
- Expose metrics for blocked calls, latency, and tool usage
**Operational Controls**
- Add `--timeout-ms` (default: 120000) for per-call timeouts
- Add `--max-concurrency` (default: 8) to limit parallel upstream calls
**Resources & Prompts Filtering**
- Add `--allow-resources` and `--allow-prompts` (off by default)
- Apply same pattern-based filtering as tools
### Future Considerations
- Multi-upstream mode: `--upstream NAME=cmd...` for managing multiple filtered servers
- Compressor mode: meta-tools with on-demand forwarding (separate from filter mode)
- Built-in deny presets: `--deny-dangerous-verbs` to block destructive operations by default
## Testing
```bash
source .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.
Raw data
{
"_id": null,
"home_page": null,
"name": "mcp-filter",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "filter, mcp, model-context-protocol, proxy",
"author": "MCP Filter Contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/41/a6/6de00a67249b1fc0d14d5df2daf2bb574b78688eed0a8c26225515f1add5/mcp_filter-0.1.0.tar.gz",
"platform": null,
"description": "<div align=\"center\">\n <img src=\"logo.png\" alt=\"MCP Filter\" width=\"300\">\n <h1>MCP Filter</h1>\n <p>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, <code>execute_sql</code> on Supabase) while filtering out the token-costly ones, without having to modify the upstream implementation.</p>\n</div>\n\n## Before & After\n\n**Before:** Unfiltered MCP servers consumed ~50k tokens on a fresh Claude Code session\n\n```\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 claude-sonnet-4-5 \u00b7 112k/200k tokens (56%)\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 System: 2.3k tokens\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 System tools: 11.8k tokens\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 MCP tools: 50.1k tokens (25%) \u2190 Large!\n\u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 Free space: 88k (44%)\n```\n\n**After:** With mcp-filter, reduced to ~13.7k tokens (72% reduction) while keeping all necessary tools.\n\n```\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26f6 \u26f6 claude-sonnet-4-5 \u00b7 80k/200k tokens (40%)\n\u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26c1 \u26f6 \u26f6 \u26f6\n\u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26c1 System: 2.3k tokens\n\u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26c1 System tools: 11.8k tokens\n\u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26c1 MCP tools: 13.7k tokens (6.9%) \u2190 Filtered!\n\u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 \u26f6 Free space: 120k (60%) \u2190 +32k gained\n```\n\nFilter only the tools you need, save context for longer sessions.\n\n**To see your token usage:** Open Claude Code and run `/context` to view the breakdown.\n\n## What & Why\n\n- **Static allowlist** keeps the exposed tool list tiny, cutting context usage for clients that serialize tool schemas.\n- **Drop-in proxy**: stands in front of any MCP server that speaks stdio or HTTP/SSE, forwarding calls transparently.\n- **Safety guardrails**: optional regex-based deny list, optional prefix, and optional health tool for observability.\n\n## Installation\n\nPython 3.10+ is supported; 3.11 is recommended.\n\n```bash\npip install mcp-filter\n```\n\n**From source (development):**\n\n```bash\npyenv install 3.11.9\npyenv local 3.11.9\npython -m venv .venv\nsource .venv/bin/activate\npip install -e '.[dev]'\n```\n\n## Quick Start\n\n```bash\nmcp-filter run \\\n -t stdio \\\n --stdio-command npx \\\n --stdio-arg \"-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN\" \\\n -a \"execute_sql,list_tables,get_project\"\n```\n\n**Shorthand flags:** `-t` (transport), `-a` (allow-tool), `-d` (deny-pattern), `-p` (prefix)\n\n**Note:** Both `--stdio-arg` and `-a` support flexible input - use repeatable flags or comma-separated strings, whichever is cleaner for your use case.\n\n## How to Wrap Your MCP\n\n### Concept\n\nTransform 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`.\n\n**Before (original Supabase config):**\n\n```json\n{\n \"mcpServers\": {\n \"supabase\": {\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@supabase/mcp-server-supabase@latest\",\n \"--access-token\",\n \"YOUR_TOKEN\"\n ]\n }\n }\n}\n```\n\nThis exposes all 29 tools (**~20.8k tokens**):\n\n<details>\n<summary>Show all tools</summary>\n\n```\n\u2514 mcp__supabase__search_docs (supabase): 2.8k tokens\n\u2514 mcp__supabase__list_organizations (supabase): 582 tokens\n\u2514 mcp__supabase__get_organization (supabase): 604 tokens\n\u2514 mcp__supabase__list_projects (supabase): 600 tokens\n\u2514 mcp__supabase__get_project (supabase): 603 tokens\n\u2514 mcp__supabase__get_cost (supabase): 646 tokens\n\u2514 mcp__supabase__confirm_cost (supabase): 682 tokens\n\u2514 mcp__supabase__create_project (supabase): 832 tokens\n\u2514 mcp__supabase__pause_project (supabase): 599 tokens\n\u2514 mcp__supabase__restore_project (supabase): 599 tokens\n\u2514 mcp__supabase__list_tables (supabase): 640 tokens\n\u2514 mcp__supabase__list_extensions (supabase): 596 tokens\n\u2514 mcp__supabase__list_migrations (supabase): 596 tokens\n\u2514 mcp__supabase__apply_migration (supabase): 668 tokens\n\u2514 mcp__supabase__execute_sql (supabase): 657 tokens\n\u2514 mcp__supabase__get_logs (supabase): 677 tokens\n\u2514 mcp__supabase__get_advisors (supabase): 699 tokens\n\u2514 mcp__supabase__get_project_url (supabase): 599 tokens\n\u2514 mcp__supabase__get_anon_key (supabase): 601 tokens\n\u2514 mcp__supabase__generate_typescript_types (supabase): 600 tokens\n\u2514 mcp__supabase__list_edge_functions (supabase): 603 tokens\n\u2514 mcp__supabase__get_edge_function (supabase): 625 tokens\n\u2514 mcp__supabase__deploy_edge_function (supabase): 907 tokens\n\u2514 mcp__supabase__create_branch (supabase): 718 tokens\n\u2514 mcp__supabase__list_branches (supabase): 625 tokens\n\u2514 mcp__supabase__delete_branch (supabase): 596 tokens\n\u2514 mcp__supabase__merge_branch (supabase): 603 tokens\n\u2514 mcp__supabase__reset_branch (supabase): 636 tokens\n\u2514 mcp__supabase__rebase_branch (supabase): 617 tokens\n```\n\n</details>\n\n**After (wrapped with mcp-filter):**\n\n```json\n{\n \"mcpServers\": {\n \"supabase\": {\n \"command\": \"mcp-filter\",\n \"args\": [\n \"run\",\n \"-t\",\n \"stdio\",\n \"--stdio-command\",\n \"npx\",\n \"--stdio-arg\",\n \"-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN\",\n \"-a\",\n \"execute_sql,list_tables,get_project\"\n ]\n }\n }\n}\n```\n\nThis only exposes 3 tools we allowed (**~1.9k tokens** = 91% reduction!):\n\n```\n\u2514 mcp__supabase__get_project (supabase): 605 tokens\n\u2514 mcp__supabase__list_tables (supabase): 642 tokens\n\u2514 mcp__supabase__execute_sql (supabase): 659 tokens\n```\n\n### Examples for Claude Code / Claude Desktop\n\n`examples/mcp.json.sample` includes common setups. Add to your `mcp.json`:\n\n**Supabase (stdio)** \u2013 wrap the official MCP binary:\n\n```json\n\"supabase\": {\n \"command\": \"mcp-filter\",\n \"args\": [\n \"run\",\n \"-t\", \"stdio\",\n \"--stdio-command\", \"npx\",\n \"--stdio-arg\", \"-y @supabase/mcp-server-supabase@latest --access-token YOUR_TOKEN\",\n \"-a\", \"execute_sql,list_tables,get_project\"\n ]\n}\n```\n\n**Linear (stdio wrapping mcp-remote)** \u2013 preserves OAuth browser flow:\n\n```json\n\"linear\": {\n \"command\": \"mcp-filter\",\n \"args\": [\n \"run\",\n \"-t\", \"stdio\",\n \"--stdio-command\", \"npx\",\n \"--stdio-arg\", \"-y mcp-remote https://mcp.linear.app/sse\",\n \"-a\", \"get_issue,list_issues,create_issue,update_issue,create_comment\"\n ]\n}\n```\n\nAdjust auth-tokens/headers to match your environment; the filter never logs or exposes them.\n\n## Configuration Reference\n\nEnvironment variables (prefixed with `MF_`) override CLI flags. See `.env.example` for a template.\n\n- `MF_TRANSPORT` / `-t`: `stdio` (default) or `http`\n- `MF_STDIO_COMMAND` / `MF_STDIO_ARGS`: upstream binary + args\n- `MF_HTTP_URL` / `MF_HTTP_HEADERS`: SSE/HTTP endpoint and extra headers (`key=value;Another=Value`)\n- `MF_ALLOW_TOOLS` / `-a`: exact tool names (repeatable, or comma-separated)\n- `MF_ALLOW_PATTERNS`: regex patterns for tool names (repeatable, or comma-separated)\n- `MF_DENY_PATTERNS` / `-d`: regex patterns to block (repeatable, or comma-separated)\n- `MF_RENAME_PREFIX` / `-p` / `--prefix`: prefix exposed tool names (e.g., `supabase_`)\n- `MF_INCLUDE_HEALTH_TOOL=1` / `--health`: enable built-in health tool (disabled by default)\n- `MF_SHOW_TOKEN_ESTIMATES=1`: enable token estimate logging (disabled by default)\n\n## FAQ\n\n**Can I expose more than one tool?** Yes\u2014pass multiple `--allow-tool` flags or use regex patterns. All exposed tools share the optional rename prefix.\n\n**Are my credentials safe?** Yes. The filter never logs secrets passed as CLI arguments or headers.\n\n**What if the upstream goes down?** Health checks surface the failure while the filter continues to reject new calls with a clear error.\n\n**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.\n\n## Advanced\n\n### Observability & Health\n\n- Rich-based structured logging annotates server name, transport, and exposed tool count.\n- Optional built-in health tool (disabled by default, ~500 tokens per server) returns upstream liveness and exposed tool names; output is safe JSON. Enable with `MF_INCLUDE_HEALTH_TOOL=1` or `--health`.\n\n### Security Notes\n\n- Only tools explicitly allowlisted or matching an allow regex are exposed.\n- Deny-patterns apply last to ensure sensitive tools stay hidden.\n- Optional rename prefix avoids tool collisions when multiple filtered proxies run side-by-side.\n- Health payload (when enabled) avoids secrets\u2014only structural metadata is emitted.\n- **Credentials & secrets**: Arguments and headers passed via CLI flags are never logged. For production deployments, prefer environment variables (e.g., `MF_STDIO_ARGS`) to avoid exposing credentials in process lists.\n\n### Requirements\n\n- Python 3.10+ (3.11 recommended)\n- `mcp>=1.0.0` and `fastmcp>=0.3.0` (installed automatically)\n- Upstream tool list is fixed per session; mid-run changes require restart\n- HTTP transport requires SSE-compatible upstream servers\n\n## Roadmap\n\n### v0.2.0 (Planned)\n\n**Schema Pruning** \u2014 Additional 30-60% token reduction\n\n- Add `--prune-schema [off|safe|aggressive]` to strip non-essential schema fields\n- Safe mode: remove `title`, `description`, `examples`, `default` while preserving contract\n- Aggressive mode: strip all descriptions except top-level (\u2264140 chars)\n\n**Enhanced Error Handling**\n\n- Return proper JSON-RPC error codes (e.g., `-32602` for blocked tools)\n- Include helpful error details: `{\"public_tools\": [...], \"tool_requested\": \"...\", \"reason\": \"not_allowlisted\"}`\n\n**Collision-Safe Naming**\n\n- Replace collision failures with deterministic suffixes (`tool_name_{hash[:4]}`)\n- Log warnings but continue operation\n\n**Full JSON Schema Validation**\n\n- Validate tool arguments locally before forwarding upstream\n- Provide clear, early error messages for invalid calls\n- Compile schemas at startup for performance\n\n**Structured Logging & Monitoring**\n\n- Add `--log-format [pretty|json]` for production-friendly JSON lines\n- Add `--redact-keys` to automatically redact sensitive field names\n- Expose metrics for blocked calls, latency, and tool usage\n\n**Operational Controls**\n\n- Add `--timeout-ms` (default: 120000) for per-call timeouts\n- Add `--max-concurrency` (default: 8) to limit parallel upstream calls\n\n**Resources & Prompts Filtering**\n\n- Add `--allow-resources` and `--allow-prompts` (off by default)\n- Apply same pattern-based filtering as tools\n\n### Future Considerations\n\n- Multi-upstream mode: `--upstream NAME=cmd...` for managing multiple filtered servers\n- Compressor mode: meta-tools with on-demand forwarding (separate from filter mode)\n- Built-in deny presets: `--deny-dangerous-verbs` to block destructive operations by default\n\n## Testing\n\n```bash\nsource .venv/bin/activate\npython -m pytest\n```\n\nThe suite exercises filtering precedence, rename collisions, schema validation, health handling, and call forwarding against a fake upstream server.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "MCP server proxy that exposes a filtered tool surface from upstream servers.",
"version": "0.1.0",
"project_urls": null,
"split_keywords": [
"filter",
" mcp",
" model-context-protocol",
" proxy"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9268cbd6a72bcdae79d82c51fe0d88b18b6d2b110563a34e88316d0ae401093a",
"md5": "483e7e0693fd44772cdd63e082805224",
"sha256": "d2175206ec4f7e7d4374abfc5f92234d3ecf7e398de80c103aa52fbc13db2d0f"
},
"downloads": -1,
"filename": "mcp_filter-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "483e7e0693fd44772cdd63e082805224",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 18464,
"upload_time": "2025-10-11T06:08:22",
"upload_time_iso_8601": "2025-10-11T06:08:22.430861Z",
"url": "https://files.pythonhosted.org/packages/92/68/cbd6a72bcdae79d82c51fe0d88b18b6d2b110563a34e88316d0ae401093a/mcp_filter-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "41a66de00a67249b1fc0d14d5df2daf2bb574b78688eed0a8c26225515f1add5",
"md5": "6343286c66ed753b4b7d5df13f41edf9",
"sha256": "62c8c84fa1db1359e126cca3ff3fc1f42c934fbaec4125a799a6dfce3ac1f1eb"
},
"downloads": -1,
"filename": "mcp_filter-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "6343286c66ed753b4b7d5df13f41edf9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 3259577,
"upload_time": "2025-10-11T06:08:29",
"upload_time_iso_8601": "2025-10-11T06:08:29.966214Z",
"url": "https://files.pythonhosted.org/packages/41/a6/6de00a67249b1fc0d14d5df2daf2bb574b78688eed0a8c26225515f1add5/mcp_filter-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-11 06:08:29",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "mcp-filter"
}