mcp-filter 0.0.1 → 0.1.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 +137 -7
- package/dist/cli.d.ts +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -8
- package/dist/cli.js.map +1 -1
- package/dist/filter.d.ts +4 -3
- package/dist/filter.d.ts.map +1 -1
- package/dist/filter.js +20 -7
- package/dist/filter.js.map +1 -1
- package/dist/index.js +31 -24
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +3 -3
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +7 -7
- package/dist/proxy.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# mcp-filter
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/mcp-filter)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
3
6
|
MCP server proxy to filter tools, resources, and prompts from upstream MCP servers.
|
|
4
7
|
|
|
5
8
|
## Installation
|
|
@@ -12,28 +15,147 @@ npx mcp-filter [options] -- <upstream-command>
|
|
|
12
15
|
|
|
13
16
|
## Usage
|
|
14
17
|
|
|
18
|
+
### Basic Usage
|
|
19
|
+
|
|
15
20
|
```bash
|
|
16
|
-
#
|
|
17
|
-
npx mcp-filter --
|
|
21
|
+
# Exclude mode: filter out specific tools
|
|
22
|
+
npx mcp-filter --exclude "playwright*" -- npx @playwright/mcp
|
|
23
|
+
|
|
24
|
+
# Include mode: only allow specific tools
|
|
25
|
+
npx mcp-filter --include "browser_navigate" --include "browser_screenshot" -- npx @playwright/mcp
|
|
26
|
+
|
|
27
|
+
# Combination: include with exceptions
|
|
28
|
+
npx mcp-filter --include "browser_*" --exclude "browser_close" -- npx @playwright/mcp
|
|
18
29
|
|
|
19
|
-
#
|
|
20
|
-
npx mcp-filter --
|
|
30
|
+
# Multiple patterns
|
|
31
|
+
npx mcp-filter --exclude "playwright*" --exclude "unsafe_*" -- npx @playwright/mcp
|
|
21
32
|
|
|
22
33
|
# Use with any MCP server
|
|
23
|
-
npx mcp-filter --
|
|
34
|
+
npx mcp-filter --exclude "debug*" -- node my-mcp-server.js
|
|
24
35
|
```
|
|
25
36
|
|
|
26
37
|
## Options
|
|
27
38
|
|
|
28
|
-
- `--
|
|
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)
|
|
29
41
|
- `--` - Separates filter options from upstream server command
|
|
30
42
|
|
|
43
|
+
Both options can be specified multiple times and combined together.
|
|
44
|
+
|
|
45
|
+
## Filtering Modes
|
|
46
|
+
|
|
47
|
+
### Exclude Mode (--exclude only)
|
|
48
|
+
|
|
49
|
+
Blocks specific items, allows everything else:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Block browser_close and browser_evaluate tools
|
|
53
|
+
npx mcp-filter --exclude "browser_close" --exclude "browser_evaluate" -- npx @playwright/mcp
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Include Mode (--include only)
|
|
57
|
+
|
|
58
|
+
Allows ONLY specified items, blocks everything else:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Only allow safe, read-only browser tools
|
|
62
|
+
npx mcp-filter --include "browser_navigate" --include "browser_screenshot" -- npx @playwright/mcp
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Combination Mode (--include + --exclude)
|
|
66
|
+
|
|
67
|
+
Include patterns with exceptions. **Exclude patterns always take precedence** (same as rsync):
|
|
68
|
+
|
|
69
|
+
```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
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Precedence Rule:** `--exclude` > `--include` > default allow
|
|
75
|
+
|
|
76
|
+
When a tool matches both `--include` and `--exclude`, it will be **excluded** (rsync-style behavior).
|
|
77
|
+
|
|
31
78
|
## Pattern Examples
|
|
32
79
|
|
|
33
80
|
- `playwright*` - Match all items starting with "playwright"
|
|
34
|
-
- `*_admin` - Match all items ending with "_admin"
|
|
81
|
+
- `*_admin` - Match all items ending with "\_admin"
|
|
35
82
|
- `test_*_debug` - Match items with pattern in middle
|
|
36
83
|
- `exact_name` - Match exact name
|
|
84
|
+
- `browser_*` - Match all browser-related tools
|
|
85
|
+
|
|
86
|
+
## Using with Cursor IDE
|
|
87
|
+
|
|
88
|
+
Add to your `.cursor/mcp.json` or `~/.cursor/mcp.json`:
|
|
89
|
+
|
|
90
|
+
### Example 1: Exclude dangerous tools
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcpServers": {
|
|
95
|
+
"playwright": {
|
|
96
|
+
"command": "npx",
|
|
97
|
+
"args": [
|
|
98
|
+
"mcp-filter",
|
|
99
|
+
"--exclude",
|
|
100
|
+
"browser_close",
|
|
101
|
+
"--exclude",
|
|
102
|
+
"browser_evaluate",
|
|
103
|
+
"--",
|
|
104
|
+
"npx",
|
|
105
|
+
"@playwright/mcp@latest"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Example 2: Include safe tools only
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"mcpServers": {
|
|
117
|
+
"playwright-safe": {
|
|
118
|
+
"command": "npx",
|
|
119
|
+
"args": [
|
|
120
|
+
"mcp-filter",
|
|
121
|
+
"--include",
|
|
122
|
+
"browser_navigate",
|
|
123
|
+
"--include",
|
|
124
|
+
"browser_screenshot",
|
|
125
|
+
"--include",
|
|
126
|
+
"browser_snapshot",
|
|
127
|
+
"--",
|
|
128
|
+
"npx",
|
|
129
|
+
"@playwright/mcp@latest"
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Example 3: Include category with exceptions
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"mcpServers": {
|
|
141
|
+
"playwright-filtered": {
|
|
142
|
+
"command": "npx",
|
|
143
|
+
"args": [
|
|
144
|
+
"mcp-filter",
|
|
145
|
+
"--include",
|
|
146
|
+
"browser_*",
|
|
147
|
+
"--exclude",
|
|
148
|
+
"browser_close",
|
|
149
|
+
"--",
|
|
150
|
+
"npx",
|
|
151
|
+
"@playwright/mcp@latest"
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
After adding the configuration, restart Cursor completely to apply the changes.
|
|
37
159
|
|
|
38
160
|
## How It Works
|
|
39
161
|
|
|
@@ -54,10 +176,18 @@ pnpm install
|
|
|
54
176
|
# Build
|
|
55
177
|
pnpm run build
|
|
56
178
|
|
|
179
|
+
# Run tests
|
|
180
|
+
pnpm test
|
|
181
|
+
|
|
57
182
|
# Test locally
|
|
58
183
|
./dist/index.js --disable "playwright*" -- npx tsx test-server.ts
|
|
59
184
|
```
|
|
60
185
|
|
|
186
|
+
## Links
|
|
187
|
+
|
|
188
|
+
- [npm package](https://www.npmjs.com/package/mcp-filter)
|
|
189
|
+
- [GitHub repository](https://github.com/baranovxyz/mcp-filter)
|
|
190
|
+
|
|
61
191
|
## License
|
|
62
192
|
|
|
63
193
|
MIT
|
package/dist/cli.d.ts
CHANGED
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;CAC3B;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,
|
|
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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export function parseArgs(args) {
|
|
2
|
-
const
|
|
2
|
+
const excludePatterns = [];
|
|
3
|
+
const includePatterns = [];
|
|
3
4
|
const upstreamCommand = [];
|
|
4
5
|
let inUpstreamCommand = false;
|
|
5
6
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -8,26 +9,35 @@ export function parseArgs(args) {
|
|
|
8
9
|
upstreamCommand.push(arg);
|
|
9
10
|
continue;
|
|
10
11
|
}
|
|
11
|
-
if (arg ===
|
|
12
|
+
if (arg === "--") {
|
|
12
13
|
inUpstreamCommand = true;
|
|
13
14
|
continue;
|
|
14
15
|
}
|
|
15
|
-
if (arg ===
|
|
16
|
+
if (arg === "--exclude") {
|
|
16
17
|
const pattern = args[++i];
|
|
17
18
|
if (!pattern) {
|
|
18
|
-
throw new Error(
|
|
19
|
+
throw new Error("--exclude requires a pattern argument");
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
+
excludePatterns.push(pattern);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (arg === "--include") {
|
|
25
|
+
const pattern = args[++i];
|
|
26
|
+
if (!pattern) {
|
|
27
|
+
throw new Error("--include requires a pattern argument");
|
|
28
|
+
}
|
|
29
|
+
includePatterns.push(pattern);
|
|
21
30
|
continue;
|
|
22
31
|
}
|
|
23
32
|
throw new Error(`Unknown argument: ${arg}`);
|
|
24
33
|
}
|
|
25
34
|
if (upstreamCommand.length === 0) {
|
|
26
|
-
throw new Error(
|
|
35
|
+
throw new Error("No upstream command specified. Use -- to separate filter args from upstream command");
|
|
27
36
|
}
|
|
28
37
|
return {
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
excludePatterns,
|
|
39
|
+
includePatterns,
|
|
40
|
+
upstreamCommand,
|
|
31
41
|
};
|
|
32
42
|
}
|
|
33
43
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/filter.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export declare class Filter {
|
|
2
|
-
private
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
private excludePatterns;
|
|
3
|
+
private includePatterns;
|
|
4
|
+
constructor(excludePatterns: string[], includePatterns?: string[]);
|
|
5
|
+
shouldExclude(name: string): boolean;
|
|
5
6
|
filterList<T extends {
|
|
6
7
|
name: string;
|
|
7
8
|
}>(items: T[]): T[];
|
package/dist/filter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAEA,qBAAa,MAAM;
|
|
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"}
|
package/dist/filter.js
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
import { minimatch } from
|
|
1
|
+
import { minimatch } from "minimatch";
|
|
2
2
|
export class Filter {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
excludePatterns;
|
|
4
|
+
includePatterns;
|
|
5
|
+
constructor(excludePatterns, includePatterns = []) {
|
|
6
|
+
this.excludePatterns = excludePatterns;
|
|
7
|
+
this.includePatterns = includePatterns;
|
|
6
8
|
}
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
15
|
+
}
|
|
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;
|
|
9
22
|
}
|
|
10
23
|
filterList(items) {
|
|
11
|
-
return items.filter(item => !this.
|
|
24
|
+
return items.filter((item) => !this.shouldExclude(item.name));
|
|
12
25
|
}
|
|
13
26
|
}
|
|
14
27
|
//# sourceMappingURL=filter.js.map
|
package/dist/filter.js.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from
|
|
3
|
-
import { StdioServerTransport } from
|
|
4
|
-
import { StdioClientTransport } from
|
|
5
|
-
import { parseArgs } from
|
|
6
|
-
import { Filter } from
|
|
7
|
-
import { ProxyServer } from
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
5
|
+
import { parseArgs } from "./cli.js";
|
|
6
|
+
import { Filter } from "./filter.js";
|
|
7
|
+
import { ProxyServer } from "./proxy.js";
|
|
8
8
|
async function main() {
|
|
9
9
|
// Parse command line arguments
|
|
10
10
|
const args = process.argv.slice(2);
|
|
@@ -14,63 +14,70 @@ async function main() {
|
|
|
14
14
|
}
|
|
15
15
|
catch (error) {
|
|
16
16
|
console.error(`Error: ${error.message}`);
|
|
17
|
-
console.error(
|
|
18
|
-
console.error(
|
|
17
|
+
console.error("Usage: mcp-filter [--exclude <pattern>]... [--include <pattern>]... -- <upstream-command> [args...]");
|
|
18
|
+
console.error("Examples:");
|
|
19
|
+
console.error(' mcp-filter --exclude "playwright*" -- npx @playwright/mcp');
|
|
20
|
+
console.error(' mcp-filter --include "browser_navigate" --include "browser_screenshot" -- npx @playwright/mcp');
|
|
21
|
+
console.error(' mcp-filter --include "browser_*" --exclude "browser_close" -- npx @playwright/mcp');
|
|
19
22
|
process.exit(1);
|
|
20
23
|
}
|
|
21
|
-
console.error(`Starting MCP filter with ${config.
|
|
22
|
-
config.
|
|
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.");
|
|
29
|
+
}
|
|
23
30
|
// Spawn upstream server
|
|
24
31
|
const upstreamProcess = spawnUpstream(config.upstreamCommand);
|
|
25
32
|
// Create filter
|
|
26
|
-
const filter = new Filter(config.
|
|
33
|
+
const filter = new Filter(config.excludePatterns, config.includePatterns);
|
|
27
34
|
// Create proxy server
|
|
28
35
|
const proxy = new ProxyServer({
|
|
29
|
-
name:
|
|
30
|
-
version:
|
|
36
|
+
name: "mcp-filter",
|
|
37
|
+
version: "0.1.0",
|
|
31
38
|
}, filter);
|
|
32
39
|
// Connect client to upstream server via subprocess stdio
|
|
33
40
|
const clientTransport = new StdioClientTransport({
|
|
34
41
|
command: config.upstreamCommand[0],
|
|
35
42
|
args: config.upstreamCommand.slice(1),
|
|
36
|
-
stderr:
|
|
43
|
+
stderr: "pipe",
|
|
37
44
|
});
|
|
38
45
|
await proxy.getClient().connect(clientTransport);
|
|
39
|
-
console.error(
|
|
46
|
+
console.error("Connected to upstream server");
|
|
40
47
|
// Connect server to current process stdio (for the MCP client calling us)
|
|
41
48
|
const serverTransport = new StdioServerTransport();
|
|
42
49
|
await proxy.getServer().connect(serverTransport);
|
|
43
|
-
console.error(
|
|
50
|
+
console.error("MCP filter proxy ready");
|
|
44
51
|
// Handle cleanup
|
|
45
52
|
const cleanup = () => {
|
|
46
|
-
console.error(
|
|
53
|
+
console.error("Shutting down...");
|
|
47
54
|
upstreamProcess.kill();
|
|
48
55
|
process.exit(0);
|
|
49
56
|
};
|
|
50
|
-
process.on(
|
|
51
|
-
process.on(
|
|
57
|
+
process.on("SIGINT", cleanup);
|
|
58
|
+
process.on("SIGTERM", cleanup);
|
|
52
59
|
}
|
|
53
60
|
function spawnUpstream(command) {
|
|
54
61
|
const [cmd, ...args] = command;
|
|
55
62
|
const proc = spawn(cmd, args, {
|
|
56
|
-
stdio: [
|
|
63
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
57
64
|
});
|
|
58
65
|
// Forward stderr to our stderr
|
|
59
|
-
proc.stderr.on(
|
|
66
|
+
proc.stderr.on("data", (data) => {
|
|
60
67
|
process.stderr.write(data);
|
|
61
68
|
});
|
|
62
|
-
proc.on(
|
|
69
|
+
proc.on("error", (error) => {
|
|
63
70
|
console.error(`Failed to start upstream server: ${error.message}`);
|
|
64
71
|
process.exit(1);
|
|
65
72
|
});
|
|
66
|
-
proc.on(
|
|
73
|
+
proc.on("exit", (code) => {
|
|
67
74
|
console.error(`Upstream server exited with code ${code}`);
|
|
68
75
|
process.exit(code || 0);
|
|
69
76
|
});
|
|
70
77
|
return proc;
|
|
71
78
|
}
|
|
72
79
|
main().catch((error) => {
|
|
73
|
-
console.error(
|
|
80
|
+
console.error("Fatal error:", error);
|
|
74
81
|
process.exit(1);
|
|
75
82
|
});
|
|
76
83
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAkC,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,KAAK,UAAU,IAAI;IACjB,+BAA+B;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,UAAW,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Client } from
|
|
2
|
-
import { Server } from
|
|
3
|
-
import { Filter } from
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { Filter } from "./filter.js";
|
|
4
4
|
export declare class ProxyServer {
|
|
5
5
|
private server;
|
|
6
6
|
private client;
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AASnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AASnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;gBAEX,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,EAAE,MAAM;IAuBzE,OAAO,CAAC,aAAa;IAwDrB,SAAS,IAAI,MAAM;IAInB,SAAS,IAAI,MAAM;CAGpB"}
|
package/dist/proxy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Client } from
|
|
2
|
-
import { Server } from
|
|
3
|
-
import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
export class ProxyServer {
|
|
5
5
|
server;
|
|
6
6
|
client;
|
|
@@ -31,8 +31,8 @@ export class ProxyServer {
|
|
|
31
31
|
};
|
|
32
32
|
});
|
|
33
33
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
34
|
-
if (this.filter.
|
|
35
|
-
throw new Error(`Tool '${request.params.name}' is
|
|
34
|
+
if (this.filter.shouldExclude(request.params.name)) {
|
|
35
|
+
throw new Error(`Tool '${request.params.name}' is excluded by filter`);
|
|
36
36
|
}
|
|
37
37
|
return await this.client.callTool(request.params);
|
|
38
38
|
});
|
|
@@ -56,8 +56,8 @@ export class ProxyServer {
|
|
|
56
56
|
};
|
|
57
57
|
});
|
|
58
58
|
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
59
|
-
if (this.filter.
|
|
60
|
-
throw new Error(`Prompt '${request.params.name}' is
|
|
59
|
+
if (this.filter.shouldExclude(request.params.name)) {
|
|
60
|
+
throw new Error(`Prompt '${request.params.name}' is excluded by filter`);
|
|
61
61
|
}
|
|
62
62
|
return await this.client.getPrompt(request.params);
|
|
63
63
|
});
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAG5C,MAAM,OAAO,WAAW;IACd,MAAM,CAAS;IACf,MAAM,CAAS;IACf,MAAM,CAAS;IAEvB,
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|