mcp-tool-filter
by kais-radwan
README.md
# mcp-tool-filter
A generic MCP proxy that filters which tools are exposed from a remote MCP server. Reduces context window token usage by only loading the tools you actually need.
## The Problem
Remote MCP servers (Linear, GitHub, Notion, etc.) expose **all** their tools to your AI coding assistant. A single server can blast 20,000+ tokens of tool definitions into your context window — even if you only use 5 of them. That's 10% of your context gone before you type a single message.
## The Solution
`mcp-tool-filter` sits between your AI client and the remote MCP server as a lightweight stdio proxy. It fetches all tools from upstream but only exposes the ones you whitelist. Everything else is filtered out, saving thousands of tokens per conversation.
```
┌─────────────┐ stdio ┌──────────────────┐ HTTP ┌──────────────┐
│ Claude Code │ ◄────────────► │ mcp-tool-filter │ ◄──────────► │ Remote MCP │
│ (6 tools) │ │ (filters tools) │ │ (29 tools) │
└─────────────┘ └──────────────────┘ └──────────────┘
```
## Quick Start
### Interactive Setup (Recommended)
```bash
npx mcp-tool-filter add
```
This walks you through:
1. Enter the upstream MCP server URL
2. Confirm the server name
3. Authenticate (if needed — opens browser automatically)
4. Select which tools to expose from the full list
5. Choose where to save the config
### Manual Setup
Add to your `.mcp.json`:
```json
{
"mcpServers": {
"linear": {
"command": "npx",
"args": [
"-y", "mcp-tool-filter",
"--url", "https://mcp.linear.app/mcp",
"--tools", "get_issue", "update_issue", "create_issue"
]
}
}
}
```
Or with the Claude Code CLI:
```bash
claude mcp add linear -- npx -y mcp-tool-filter \
--url https://mcp.linear.app/mcp \
--tools get_issue update_issue create_issue
```
## Usage
```
mcp-tool-filter --url <upstream-mcp-url> [--name <server-name>] [--tools <tool1> <tool2> ...]
```
### Options
| Flag | Required | Description |
|------|----------|-------------|
| `--url` | Yes | The upstream MCP server URL |
| `--tools` | No | Space-separated list of tool names to expose. If omitted, all tools are passed through |
| `--name` | No | Server name for token storage. Auto-derived from URL if not provided |
### Updating Tool Selection
Need to add or remove tools from an existing server? Run `update` with the server name from your `.mcp.json`:
```bash
npx mcp-tool-filter update linear
```
This will:
1. Read the existing config from your `.mcp.json`
2. Connect to the upstream server
3. Show all available tools with your current selection pre-checked
4. Update the config with your new selection
### Pass-through Mode
Omit `--tools` to proxy all tools without filtering (useful if you only need the OAuth/auth handling):
```json
{
"mcpServers": {
"linear": {
"command": "npx",
"args": ["-y", "mcp-tool-filter", "--url", "https://mcp.linear.app/mcp"]
}
}
}
```
## Authentication
`mcp-tool-filter` handles OAuth automatically:
1. **First run**: The upstream server returns 401, the proxy opens your browser for OAuth login, waits for the callback, and saves the tokens
2. **Subsequent runs**: Stored tokens are reused automatically — no browser needed
Tokens are persisted in `~/.mcp-tool-filter/<server-name>.json`.
To re-authenticate, delete the token file:
```bash
rm ~/.mcp-tool-filter/linear.json
```
### Servers Without OAuth
If the upstream server doesn't require authentication, the proxy connects directly — no OAuth flow needed.
## Examples
### Linear (6 tools instead of 29)
```json
{
"mcpServers": {
"linear": {
"command": "npx",
"args": [
"-y", "mcp-tool-filter",
"--url", "https://mcp.linear.app/mcp",
"--tools", "get_issue", "update_issue", "create_issue",
"list_issues", "list_issue_labels", "get_project"
]
}
}
}
```
### Multiple Filtered Servers
```json
{
"mcpServers": {
"linear": {
"command": "npx",
"args": [
"-y", "mcp-tool-filter",
"--url", "https://mcp.linear.app/mcp",
"--tools", "get_issue", "update_issue"
]
},
"another-server": {
"command": "npx",
"args": [
"-y", "mcp-tool-filter",
"--url", "https://another-mcp-server.com/mcp",
"--tools", "read_document", "search"
]
}
}
}
```
## How It Works
1. Starts as a **stdio** MCP server (what your AI client connects to)
2. Connects to the upstream server via **Streamable HTTP** (with SSE fallback)
3. On `tools/list` — fetches all tools from upstream, returns only the allowed ones
4. On `tools/call` — forwards the call to upstream, returns the response unchanged
5. Handles OAuth automatically with token persistence
## Transport Support
| Transport | Status |
|-----------|--------|
| Streamable HTTP | Supported (preferred) |
| Server-Sent Events (SSE) | Supported (fallback) |
| stdio upstream | Not supported (use for local servers directly) |
## Compatibility
Works with any MCP client that supports stdio servers:
- Claude Code
- Claude Desktop
- Cursor
- Windsurf
- Any MCP-compatible client
## Development
```bash
git clone https://github.com/kais-radwan/mcp-tool-filter.git
cd mcp-tool-filter
npm install
npm run build
```
Test locally:
```json
{
"mcpServers": {
"linear": {
"command": "node",
"args": [
"/path/to/mcp-tool-filter/dist/index.js",
"--url", "https://mcp.linear.app/mcp",
"--tools", "get_issue"
]
}
}
}
```
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues