mcp-filter 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,8 +24,8 @@ npx mcp-filter --exclude "playwright*" -- npx @playwright/mcp
24
24
  # Include mode: only allow specific tools
25
25
  npx mcp-filter --include "browser_navigate" --include "browser_screenshot" -- npx @playwright/mcp
26
26
 
27
- # Combination: include with exceptions
28
- npx mcp-filter --include "browser_*" --exclude "browser_close" -- npx @playwright/mcp
27
+ # Combination: include with exceptions (order matters!)
28
+ npx mcp-filter --exclude "browser_close" --include "browser_*" -- npx @playwright/mcp
29
29
 
30
30
  # Multiple patterns
31
31
  npx mcp-filter --exclude "playwright*" --exclude "unsafe_*" -- npx @playwright/mcp
@@ -36,12 +36,14 @@ npx mcp-filter --exclude "debug*" -- node my-mcp-server.js
36
36
 
37
37
  ## Options
38
38
 
39
- - `--exclude <pattern>` - Exclude tools/resources/prompts matching this pattern (like rsync --exclude)
40
- - `--include <pattern>` - Include ONLY tools/resources/prompts matching this pattern (like rsync --include)
39
+ - `--exclude <pattern>` - Exclude tools/resources/prompts matching this pattern
40
+ - `--include <pattern>` - Include ONLY tools/resources/prompts matching this pattern (whitelist mode)
41
41
  - `--` - Separates filter options from upstream server command
42
42
 
43
43
  Both options can be specified multiple times and combined together.
44
44
 
45
+ **Filtering style:** rsync-style evaluation where patterns are evaluated in the order specified, and first match wins.
46
+
45
47
  ## Filtering Modes
46
48
 
47
49
  ### Exclude Mode (--exclude only)
@@ -64,30 +66,208 @@ npx mcp-filter --include "browser_navigate" --include "browser_screenshot" -- np
64
66
 
65
67
  ### Combination Mode (--include + --exclude)
66
68
 
67
- Include patterns with exceptions. **Exclude patterns always take precedence** (same as rsync):
69
+ **Rsync-style filtering**: patterns evaluated in order, first match wins.
70
+
71
+ ⚠️ **Common mistake**: Putting `--include` before `--exclude` means the exclude never applies!
68
72
 
69
73
  ```bash
70
- # Allow all browser tools EXCEPT close and evaluate
71
- npx mcp-filter --include "browser_*" --exclude "browser_close" --exclude "browser_evaluate" -- npx @playwright/mcp
74
+ # Example 1: Include first, then exclude (DOES NOT WORK AS EXPECTED!)
75
+ npx mcp-filter --include "browser_*" --exclude "browser_close" -- npx @playwright/mcp
76
+ # Result: All browser_* tools are INCLUDED (browser_* matched first)
77
+ # browser_close is also included because it matches browser_* first
78
+ # The --exclude "browser_close" is never evaluated!
79
+
80
+ # Example 2: Exclude first, then include (CORRECT way to exclude exceptions!)
81
+ npx mcp-filter --exclude "browser_close" --include "browser_*" -- npx @playwright/mcp
82
+ # Result: browser_close is EXCLUDED (matched exclude first)
83
+ # Other browser_* tools are included
84
+
85
+ # Example 3: Multiple exclusions, then broad include (recommended pattern)
86
+ npx mcp-filter --exclude "browser_close" --exclude "browser_evaluate" --include "browser_*" -- npx @playwright/mcp
87
+ # Result: browser_close and browser_evaluate excluded (matched first)
88
+ # All other browser_* tools included
72
89
  ```
73
90
 
74
- **Precedence Rule:** `--exclude` > `--include` > default allow
75
-
76
- When a tool matches both `--include` and `--exclude`, it will be **excluded** (rsync-style behavior).
91
+ **Key principle**: Order matters! The first pattern that matches determines if the item is included or excluded.
77
92
 
78
93
  ## Pattern Examples
79
94
 
95
+ Patterns use glob syntax (via minimatch):
96
+
80
97
  - `playwright*` - Match all items starting with "playwright"
81
98
  - `*_admin` - Match all items ending with "\_admin"
82
99
  - `test_*_debug` - Match items with pattern in middle
83
100
  - `exact_name` - Match exact name
84
101
  - `browser_*` - Match all browser-related tools
102
+ - `*` - Match everything
103
+
104
+ ## Rsync-Style Filtering
105
+
106
+ mcp-filter uses rsync-style pattern evaluation:
107
+
108
+ 1. **Order matters**: Patterns are evaluated in the order you specify them
109
+ 2. **First match wins**: Once a pattern matches, that determines the outcome
110
+ 3. **Default behavior**:
111
+ - If no patterns specified: allow everything (passthrough)
112
+ - If only `--include`: items not matching any include are excluded (whitelist mode)
113
+ - If only `--exclude`: items not matching any exclude are included
114
+ - If mixed: items not matching any pattern use whitelist mode if includes exist
115
+
116
+ **Example workflow**:
117
+
118
+ ```bash
119
+ # Put more specific patterns first
120
+ npx mcp-filter \
121
+ --exclude "browser_close" \
122
+ --exclude "browser_evaluate" \
123
+ --include "browser_*" \
124
+ -- npx @playwright/mcp
125
+
126
+ # This works because:
127
+ # 1. browser_close matches --exclude "browser_close" first → excluded
128
+ # 2. browser_evaluate matches --exclude "browser_evaluate" first → excluded
129
+ # 3. browser_navigate matches --include "browser_*" → included
130
+ # 4. other_tool doesn't match any pattern, but --include exists → excluded (whitelist mode)
131
+ ```
132
+
133
+ ## Using with Claude Code
134
+
135
+ ### Adding Filtered MCP Servers
136
+
137
+ Add filtered MCP servers to Claude Code using the `claude mcp add` command:
138
+
139
+ ```bash
140
+ # Basic syntax
141
+ claude mcp add <name> -- npx mcp-filter [filter-options] -- <upstream-command>
142
+
143
+ # Example: Safe Playwright with read-only browser access
144
+ claude mcp add playwright-safe -- \
145
+ npx mcp-filter \
146
+ --include "browser_navigate" \
147
+ --include "browser_screenshot" \
148
+ --include "browser_snapshot" \
149
+ -- npx @playwright/mcp@latest
150
+
151
+ # Example: Block dangerous operations
152
+ claude mcp add playwright-filtered -- \
153
+ npx mcp-filter \
154
+ --exclude "browser_close" \
155
+ --exclude "browser_evaluate" \
156
+ -- npx @playwright/mcp@latest
157
+
158
+ # Example: Include category with exceptions (rsync-style)
159
+ claude mcp add playwright -- \
160
+ npx mcp-filter \
161
+ --exclude "browser_close" \
162
+ --exclude "browser_evaluate" \
163
+ --include "browser_*" \
164
+ -- npx @playwright/mcp@latest
165
+ ```
166
+
167
+ **Understanding the command structure:**
168
+
169
+ - First `--` separates Claude's options from the mcp-filter command
170
+ - Second `--` separates mcp-filter options from the upstream MCP server command
171
+
172
+ ### Scope Options
173
+
174
+ Choose where to store the configuration:
175
+
176
+ ```bash
177
+ # Local scope (default): Only you, only this project
178
+ claude mcp add playwright-safe -- npx mcp-filter --include "browser_*" -- npx @playwright/mcp@latest
179
+
180
+ # User scope: Available across all your projects
181
+ claude mcp add --scope user playwright-safe -- \
182
+ npx mcp-filter --include "browser_*" -- npx @playwright/mcp@latest
183
+
184
+ # Project scope: Share with team via .mcp.json (checked into git)
185
+ claude mcp add --scope project playwright-safe -- \
186
+ npx mcp-filter --include "browser_*" -- npx @playwright/mcp@latest
187
+ ```
188
+
189
+ **Security Note**: Claude Code prompts for approval before using project-scoped servers from `.mcp.json` files. To reset approval choices, use `claude mcp reset-project-choices`.
190
+
191
+ ### Managing Filtered Servers
192
+
193
+ ```bash
194
+ # List all configured servers
195
+ claude mcp list
196
+
197
+ # Get details for a specific server
198
+ claude mcp get playwright-safe
199
+
200
+ # Remove a server
201
+ claude mcp remove playwright-safe
202
+
203
+ # Check server status in Claude Code
204
+ /mcp
205
+ ```
206
+
207
+ ### Practical Examples
208
+
209
+ **Monitoring agent (read-only)**
210
+
211
+ ```bash
212
+ claude mcp add browser-monitor -- \
213
+ npx mcp-filter \
214
+ --include "browser_navigate" \
215
+ --include "browser_snapshot" \
216
+ --include "browser_console_messages" \
217
+ --include "browser_network_requests" \
218
+ --include "browser_take_screenshot" \
219
+ -- npx @playwright/mcp@latest
220
+ ```
221
+
222
+ **Testing agent (no destructive actions)**
223
+
224
+ ```bash
225
+ claude mcp add browser-test -- \
226
+ npx mcp-filter \
227
+ --exclude "browser_close" \
228
+ --exclude "browser_tabs" \
229
+ --exclude "browser_evaluate" \
230
+ --include "browser_*" \
231
+ -- npx @playwright/mcp@latest
232
+ ```
233
+
234
+ Note: Exclude patterns must come BEFORE the include pattern to match first.
235
+
236
+ **Production debugging (safe operations only)**
237
+
238
+ ```bash
239
+ # Add as user-scoped for use across projects
240
+ claude mcp add --scope user prod-debugger -- \
241
+ npx mcp-filter \
242
+ --exclude "browser_click" \
243
+ --exclude "browser_type" \
244
+ --exclude "browser_evaluate" \
245
+ --exclude "browser_fill_form" \
246
+ --include "browser_*" \
247
+ -- npx @playwright/mcp@latest
248
+ ```
249
+
250
+ ### Updating Server Configuration
251
+
252
+ To update filter rules, remove and re-add the server:
253
+
254
+ ```bash
255
+ # Remove existing configuration
256
+ claude mcp remove playwright-safe
257
+
258
+ # Add with new filter rules
259
+ claude mcp add playwright-safe -- \
260
+ npx mcp-filter \
261
+ --include "browser_navigate" \
262
+ --include "browser_screenshot" \
263
+ -- npx @playwright/mcp@latest
264
+ ```
85
265
 
86
266
  ## Using with Cursor IDE
87
267
 
88
268
  Add to your `.cursor/mcp.json` or `~/.cursor/mcp.json`:
89
269
 
90
- ### Example 1: Exclude dangerous tools
270
+ ### Example 1: Exclude specific dangerous tools
91
271
 
92
272
  ```json
93
273
  {
@@ -133,7 +313,7 @@ Add to your `.cursor/mcp.json` or `~/.cursor/mcp.json`:
133
313
  }
134
314
  ```
135
315
 
136
- ### Example 3: Include category with exceptions
316
+ ### Example 3: Include category with exceptions (rsync-style)
137
317
 
138
318
  ```json
139
319
  {
@@ -142,10 +322,12 @@ Add to your `.cursor/mcp.json` or `~/.cursor/mcp.json`:
142
322
  "command": "npx",
143
323
  "args": [
144
324
  "mcp-filter",
145
- "--include",
146
- "browser_*",
147
325
  "--exclude",
148
326
  "browser_close",
327
+ "--exclude",
328
+ "browser_evaluate",
329
+ "--include",
330
+ "browser_*",
149
331
  "--",
150
332
  "npx",
151
333
  "@playwright/mcp@latest"
@@ -155,6 +337,8 @@ Add to your `.cursor/mcp.json` or `~/.cursor/mcp.json`:
155
337
  }
156
338
  ```
157
339
 
340
+ Note: Exclude patterns come first to match before the broader include pattern.
341
+
158
342
  After adding the configuration, restart Cursor completely to apply the changes.
159
343
 
160
344
  ## How It Works
@@ -180,7 +364,7 @@ pnpm run build
180
364
  pnpm test
181
365
 
182
366
  # Test locally
183
- ./dist/index.js --disable "playwright*" -- npx tsx test-server.ts
367
+ ./dist/index.js --exclude "playwright*" -- npx tsx test-server.ts
184
368
  ```
185
369
 
186
370
  ## Links
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,9 @@
1
+ export interface FilterPattern {
2
+ type: "include" | "exclude";
3
+ pattern: string;
4
+ }
1
5
  export interface FilterConfig {
2
- excludePatterns: string[];
3
- includePatterns: string[];
6
+ patterns: FilterPattern[];
4
7
  upstreamCommand: string[];
5
8
  }
6
9
  export declare function parseArgs(args: string[]): FilterConfig;
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAoDtD"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAkDtD"}
package/dist/cli.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export function parseArgs(args) {
2
- const excludePatterns = [];
3
- const includePatterns = [];
2
+ const patterns = [];
4
3
  const upstreamCommand = [];
5
4
  let inUpstreamCommand = false;
6
5
  for (let i = 0; i < args.length; i++) {
@@ -18,7 +17,7 @@ export function parseArgs(args) {
18
17
  if (!pattern) {
19
18
  throw new Error("--exclude requires a pattern argument");
20
19
  }
21
- excludePatterns.push(pattern);
20
+ patterns.push({ type: "exclude", pattern });
22
21
  continue;
23
22
  }
24
23
  if (arg === "--include") {
@@ -26,7 +25,7 @@ export function parseArgs(args) {
26
25
  if (!pattern) {
27
26
  throw new Error("--include requires a pattern argument");
28
27
  }
29
- includePatterns.push(pattern);
28
+ patterns.push({ type: "include", pattern });
30
29
  continue;
31
30
  }
32
31
  throw new Error(`Unknown argument: ${arg}`);
@@ -35,8 +34,7 @@ export function parseArgs(args) {
35
34
  throw new Error("No upstream command specified. Use -- to separate filter args from upstream command");
36
35
  }
37
36
  return {
38
- excludePatterns,
39
- includePatterns,
37
+ patterns,
40
38
  upstreamCommand,
41
39
  };
42
40
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,iBAAiB,EAAE,CAAC;YACtB,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,iBAAiB,GAAG,IAAI,CAAC;YACzB,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;YACD,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;YACD,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,eAAe;QACf,eAAe;QACf,eAAe;KAChB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,iBAAiB,EAAE,CAAC;YACtB,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,iBAAiB,GAAG,IAAI,CAAC;YACzB,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ;QACR,eAAe;KAChB,CAAC;AACJ,CAAC"}
package/dist/filter.d.ts CHANGED
@@ -1,7 +1,8 @@
1
+ import { FilterPattern } from "./cli.js";
1
2
  export declare class Filter {
2
- private excludePatterns;
3
- private includePatterns;
4
- constructor(excludePatterns: string[], includePatterns?: string[]);
3
+ private patterns;
4
+ private hasIncludePatterns;
5
+ constructor(patterns: FilterPattern[]);
5
6
  shouldExclude(name: string): boolean;
6
7
  filterList<T extends {
7
8
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAEA,qBAAa,MAAM;IAEf,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,eAAe;gBADf,eAAe,EAAE,MAAM,EAAE,EACzB,eAAe,GAAE,MAAM,EAAO;IAGxC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAmBpC,UAAU,CAAC,CAAC,SAAS;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE;CAGxD"}
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,qBAAa,MAAM;IAGL,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,kBAAkB,CAAU;gBAEhB,QAAQ,EAAE,aAAa,EAAE;IAI7C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAepC,UAAU,CAAC,CAAC,SAAS;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE;CAGxD"}
package/dist/filter.js CHANGED
@@ -1,24 +1,23 @@
1
1
  import { minimatch } from "minimatch";
2
2
  export class Filter {
3
- excludePatterns;
4
- includePatterns;
5
- constructor(excludePatterns, includePatterns = []) {
6
- this.excludePatterns = excludePatterns;
7
- this.includePatterns = includePatterns;
3
+ patterns;
4
+ hasIncludePatterns;
5
+ constructor(patterns) {
6
+ this.patterns = patterns;
7
+ this.hasIncludePatterns = patterns.some((p) => p.type === "include");
8
8
  }
9
9
  shouldExclude(name) {
10
- // Step 1: Check include patterns (if specified)
11
- if (this.includePatterns.length > 0) {
12
- const isIncluded = this.includePatterns.some((pattern) => minimatch(name, pattern));
13
- if (!isIncluded)
14
- return true; // Not included = excluded
10
+ // Evaluate patterns in order - first match wins (rsync-style)
11
+ for (const pattern of this.patterns) {
12
+ if (minimatch(name, pattern.pattern)) {
13
+ // First pattern that matches determines the outcome
14
+ return pattern.type === "exclude";
15
+ }
15
16
  }
16
- // Step 2: Check exclude patterns (explicit exclude always wins)
17
- const isExcluded = this.excludePatterns.some((pattern) => minimatch(name, pattern));
18
- if (isExcluded)
19
- return true;
20
- // Step 3: Default allow
21
- return false;
17
+ // No pattern matched - determine default behavior
18
+ // If there are include patterns, default is exclude (whitelist mode)
19
+ // Otherwise, default is include (allow all)
20
+ return this.hasIncludePatterns;
22
21
  }
23
22
  filterList(items) {
24
23
  return items.filter((item) => !this.shouldExclude(item.name));
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,OAAO,MAAM;IAEP;IACA;IAFV,YACU,eAAyB,EACzB,kBAA4B,EAAE;QAD9B,oBAAe,GAAf,eAAe,CAAU;QACzB,oBAAe,GAAf,eAAe,CAAe;IACrC,CAAC;IAEJ,aAAa,CAAC,IAAY;QACxB,gDAAgD;QAChD,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACvD,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CACzB,CAAC;YACF,IAAI,CAAC,UAAU;gBAAE,OAAO,IAAI,CAAC,CAAC,0BAA0B;QAC1D,CAAC;QAED,gEAAgE;QAChE,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACvD,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CACzB,CAAC;QACF,IAAI,UAAU;YAAE,OAAO,IAAI,CAAC;QAE5B,wBAAwB;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU,CAA6B,KAAU;QAC/C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC;CACF"}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,OAAO,MAAM;IAGG;IAFZ,kBAAkB,CAAU;IAEpC,YAAoB,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;QAC3C,IAAI,CAAC,kBAAkB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IACvE,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,8DAA8D;QAC9D,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,oDAAoD;gBACpD,OAAO,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC;YACpC,CAAC;QACH,CAAC;QAED,kDAAkD;QAClD,qEAAqE;QACrE,4CAA4C;QAC5C,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAED,UAAU,CAA6B,KAAU;QAC/C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC;CACF"}
package/dist/index.js CHANGED
@@ -21,20 +21,21 @@ async function main() {
21
21
  console.error(' mcp-filter --include "browser_*" --exclude "browser_close" -- npx @playwright/mcp');
22
22
  process.exit(1);
23
23
  }
24
- console.error(`Starting MCP filter with ${config.excludePatterns.length + config.includePatterns.length} pattern(s)`);
25
- config.excludePatterns.forEach((p) => console.error(` Exclude: ${p}`));
26
- config.includePatterns.forEach((p) => console.error(` Include: ${p}`));
27
- if (config.includePatterns.length > 0 && config.excludePatterns.length > 0) {
28
- console.error("Warning: Using both --include and --exclude. Exclude patterns take precedence.");
24
+ console.error(`Starting MCP filter with ${config.patterns.length} pattern(s)`);
25
+ config.patterns.forEach((p) => console.error(` ${p.type === "include" ? "Include" : "Exclude"}: ${p.pattern}`));
26
+ const hasInclude = config.patterns.some((p) => p.type === "include");
27
+ const hasExclude = config.patterns.some((p) => p.type === "exclude");
28
+ if (hasInclude && hasExclude) {
29
+ console.error("Note: Using rsync-style filtering - patterns evaluated in order, first match wins.");
29
30
  }
30
31
  // Spawn upstream server
31
32
  const upstreamProcess = spawnUpstream(config.upstreamCommand);
32
33
  // Create filter
33
- const filter = new Filter(config.excludePatterns, config.includePatterns);
34
+ const filter = new Filter(config.patterns);
34
35
  // Create proxy server
35
36
  const proxy = new ProxyServer({
36
37
  name: "mcp-filter",
37
- version: "0.1.0",
38
+ version: "0.2.0",
38
39
  }, filter);
39
40
  // Connect client to upstream server via subprocess stdio
40
41
  const clientTransport = new StdioClientTransport({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-filter",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server proxy to filter tools, resources, and prompts from upstream MCP servers",
5
5
  "type": "module",
6
6
  "bin": {