mcp-filter 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 mcp-filter contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # mcp-filter
2
+
3
+ MCP server proxy to filter tools, resources, and prompts from upstream MCP servers.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g mcp-filter
9
+ # or use with npx
10
+ npx mcp-filter [options] -- <upstream-command>
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Filter out playwright tools
17
+ npx mcp-filter --disable "playwright*" -- npx @playwright/mcp
18
+
19
+ # Filter multiple patterns
20
+ npx mcp-filter --disable "playwright*" --disable "unsafe_*" -- npx @playwright/mcp
21
+
22
+ # Use with any MCP server
23
+ npx mcp-filter --disable "debug*" -- node my-mcp-server.js
24
+ ```
25
+
26
+ ## Options
27
+
28
+ - `--disable <pattern>` - Glob pattern for tools/resources/prompts to disable (can be specified multiple times)
29
+ - `--` - Separates filter options from upstream server command
30
+
31
+ ## Pattern Examples
32
+
33
+ - `playwright*` - Match all items starting with "playwright"
34
+ - `*_admin` - Match all items ending with "_admin"
35
+ - `test_*_debug` - Match items with pattern in middle
36
+ - `exact_name` - Match exact name
37
+
38
+ ## How It Works
39
+
40
+ mcp-filter acts as a proxy between an MCP client and an upstream MCP server:
41
+
42
+ 1. Spawns the upstream MCP server as a subprocess
43
+ 2. Connects to it as an MCP client
44
+ 3. Exposes a filtered MCP server interface
45
+ 4. Filters `tools/list`, `resources/list`, and `prompts/list` responses
46
+ 5. Blocks calls to filtered items with error responses
47
+
48
+ ## Development
49
+
50
+ ```bash
51
+ # Install dependencies
52
+ pnpm install
53
+
54
+ # Build
55
+ pnpm run build
56
+
57
+ # Test locally
58
+ ./dist/index.js --disable "playwright*" -- npx tsx test-server.ts
59
+ ```
60
+
61
+ ## License
62
+
63
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export interface FilterConfig {
2
+ disablePatterns: string[];
3
+ upstreamCommand: string[];
4
+ }
5
+ export declare function parseArgs(args: string[]): FilterConfig;
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +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,CAuCtD"}
package/dist/cli.js ADDED
@@ -0,0 +1,33 @@
1
+ export function parseArgs(args) {
2
+ const disablePatterns = [];
3
+ const upstreamCommand = [];
4
+ let inUpstreamCommand = false;
5
+ for (let i = 0; i < args.length; i++) {
6
+ const arg = args[i];
7
+ if (inUpstreamCommand) {
8
+ upstreamCommand.push(arg);
9
+ continue;
10
+ }
11
+ if (arg === '--') {
12
+ inUpstreamCommand = true;
13
+ continue;
14
+ }
15
+ if (arg === '--disable') {
16
+ const pattern = args[++i];
17
+ if (!pattern) {
18
+ throw new Error('--disable requires a pattern argument');
19
+ }
20
+ disablePatterns.push(pattern);
21
+ continue;
22
+ }
23
+ throw new Error(`Unknown argument: ${arg}`);
24
+ }
25
+ if (upstreamCommand.length === 0) {
26
+ throw new Error('No upstream command specified. Use -- to separate filter args from upstream command');
27
+ }
28
+ return {
29
+ disablePatterns,
30
+ upstreamCommand
31
+ };
32
+ }
33
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,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,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IACzG,CAAC;IAED,OAAO;QACL,eAAe;QACf,eAAe;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare class Filter {
2
+ private patterns;
3
+ constructor(patterns: string[]);
4
+ shouldDisable(name: string): boolean;
5
+ filterList<T extends {
6
+ name: string;
7
+ }>(items: T[]): T[];
8
+ }
9
+ //# sourceMappingURL=filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAEA,qBAAa,MAAM;IACL,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM,EAAE;IAEtC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIpC,UAAU,CAAC,CAAC,SAAS;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE;CAGxD"}
package/dist/filter.js ADDED
@@ -0,0 +1,14 @@
1
+ import { minimatch } from 'minimatch';
2
+ export class Filter {
3
+ patterns;
4
+ constructor(patterns) {
5
+ this.patterns = patterns;
6
+ }
7
+ shouldDisable(name) {
8
+ return this.patterns.some(pattern => minimatch(name, pattern));
9
+ }
10
+ filterList(items) {
11
+ return items.filter(item => !this.shouldDisable(item.name));
12
+ }
13
+ }
14
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +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;IACG;IAApB,YAAoB,QAAkB;QAAlB,aAAQ,GAAR,QAAQ,CAAU;IAAG,CAAC;IAE1C,aAAa,CAAC,IAAY;QACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,UAAU,CAA6B,KAAU;QAC/C,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
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
+ async function main() {
9
+ // Parse command line arguments
10
+ const args = process.argv.slice(2);
11
+ let config;
12
+ try {
13
+ config = parseArgs(args);
14
+ }
15
+ catch (error) {
16
+ console.error(`Error: ${error.message}`);
17
+ console.error('Usage: mcp-filter [--disable <pattern>]... -- <upstream-command> [args...]');
18
+ console.error('Example: mcp-filter --disable "playwright*" -- npx @playwright/mcp');
19
+ process.exit(1);
20
+ }
21
+ console.error(`Starting MCP filter with ${config.disablePatterns.length} pattern(s)`);
22
+ config.disablePatterns.forEach(p => console.error(` Disable: ${p}`));
23
+ // Spawn upstream server
24
+ const upstreamProcess = spawnUpstream(config.upstreamCommand);
25
+ // Create filter
26
+ const filter = new Filter(config.disablePatterns);
27
+ // Create proxy server
28
+ const proxy = new ProxyServer({
29
+ name: 'mcp-filter',
30
+ version: '0.1.0',
31
+ }, filter);
32
+ // Connect client to upstream server via subprocess stdio
33
+ const clientTransport = new StdioClientTransport({
34
+ command: config.upstreamCommand[0],
35
+ args: config.upstreamCommand.slice(1),
36
+ stderr: 'pipe',
37
+ });
38
+ await proxy.getClient().connect(clientTransport);
39
+ console.error('Connected to upstream server');
40
+ // Connect server to current process stdio (for the MCP client calling us)
41
+ const serverTransport = new StdioServerTransport();
42
+ await proxy.getServer().connect(serverTransport);
43
+ console.error('MCP filter proxy ready');
44
+ // Handle cleanup
45
+ const cleanup = () => {
46
+ console.error('Shutting down...');
47
+ upstreamProcess.kill();
48
+ process.exit(0);
49
+ };
50
+ process.on('SIGINT', cleanup);
51
+ process.on('SIGTERM', cleanup);
52
+ }
53
+ function spawnUpstream(command) {
54
+ const [cmd, ...args] = command;
55
+ const proc = spawn(cmd, args, {
56
+ stdio: ['pipe', 'pipe', 'pipe'],
57
+ });
58
+ // Forward stderr to our stderr
59
+ proc.stderr.on('data', (data) => {
60
+ process.stderr.write(data);
61
+ });
62
+ proc.on('error', (error) => {
63
+ console.error(`Failed to start upstream server: ${error.message}`);
64
+ process.exit(1);
65
+ });
66
+ proc.on('exit', (code) => {
67
+ console.error(`Upstream server exited with code ${code}`);
68
+ process.exit(code || 0);
69
+ });
70
+ return proc;
71
+ }
72
+ main().catch((error) => {
73
+ console.error('Fatal error:', error);
74
+ process.exit(1);
75
+ });
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
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
+ export declare class ProxyServer {
5
+ private server;
6
+ private client;
7
+ private filter;
8
+ constructor(serverInfo: {
9
+ name: string;
10
+ version: string;
11
+ }, filter: Filter);
12
+ private setupHandlers;
13
+ getClient(): Client;
14
+ getServer(): Server;
15
+ }
16
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +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;gBAGrB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAC7C,MAAM,EAAE,MAAM;IA2BhB,OAAO,CAAC,aAAa;IAmDrB,SAAS,IAAI,MAAM;IAInB,SAAS,IAAI,MAAM;CAGpB"}
package/dist/proxy.js ADDED
@@ -0,0 +1,72 @@
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
+ export class ProxyServer {
5
+ server;
6
+ client;
7
+ filter;
8
+ constructor(serverInfo, filter) {
9
+ this.filter = filter;
10
+ this.client = new Client({
11
+ name: `${serverInfo.name}-client`,
12
+ version: serverInfo.version,
13
+ }, {
14
+ capabilities: {},
15
+ });
16
+ this.server = new Server(serverInfo, {
17
+ capabilities: {
18
+ tools: {},
19
+ resources: {},
20
+ prompts: {},
21
+ },
22
+ });
23
+ this.setupHandlers();
24
+ }
25
+ setupHandlers() {
26
+ // Tools
27
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
28
+ const response = await this.client.listTools();
29
+ return {
30
+ tools: this.filter.filterList(response.tools),
31
+ };
32
+ });
33
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
34
+ if (this.filter.shouldDisable(request.params.name)) {
35
+ throw new Error(`Tool '${request.params.name}' is disabled by filter`);
36
+ }
37
+ return await this.client.callTool(request.params);
38
+ });
39
+ // Resources
40
+ this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
41
+ const response = await this.client.listResources();
42
+ return {
43
+ resources: this.filter.filterList(response.resources),
44
+ };
45
+ });
46
+ this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
47
+ // Resources are identified by URI, not name, so we can't easily filter calls
48
+ // We'll allow reads but they won't be in the list if filtered
49
+ return await this.client.readResource(request.params);
50
+ });
51
+ // Prompts
52
+ this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
53
+ const response = await this.client.listPrompts();
54
+ return {
55
+ prompts: this.filter.filterList(response.prompts),
56
+ };
57
+ });
58
+ this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
59
+ if (this.filter.shouldDisable(request.params.name)) {
60
+ throw new Error(`Prompt '${request.params.name}' is disabled by filter`);
61
+ }
62
+ return await this.client.getPrompt(request.params);
63
+ });
64
+ }
65
+ getClient() {
66
+ return this.client;
67
+ }
68
+ getServer() {
69
+ return this.server;
70
+ }
71
+ }
72
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +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,YACE,UAA6C,EAC7C,MAAc;QAEd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CACtB;YACE,IAAI,EAAE,GAAG,UAAU,CAAC,IAAI,SAAS;YACjC,OAAO,EAAE,UAAU,CAAC,OAAO;SAC5B,EACD;YACE,YAAY,EAAE,EAAE;SACjB,CACF,CAAC;QAEF,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CACtB,UAAU,EACV;YACE,YAAY,EAAE;gBACZ,KAAK,EAAE,EAAE;gBACT,SAAS,EAAE,EAAE;gBACb,OAAO,EAAE,EAAE;aACZ;SACF,CACF,CAAC;QAEF,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAEO,aAAa;QACnB,QAAQ;QACR,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAE/C,OAAO;gBACL,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;aAC9C,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACrE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,IAAI,yBAAyB,CAAC,CAAC;YACzE,CAAC;YAED,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,YAAY;QACZ,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAEnD,OAAO;gBACL,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC;aACtD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,yBAAyB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACzE,6EAA6E;YAC7E,8DAA8D;YAC9D,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,UAAU;QACV,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAEjD,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC;aAClD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACtE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,CAAC,MAAM,CAAC,IAAI,yBAAyB,CAAC,CAAC;YAC3E,CAAC;YAED,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "mcp-filter",
3
+ "version": "0.0.1",
4
+ "description": "MCP server proxy to filter tools, resources, and prompts from upstream MCP servers",
5
+ "type": "module",
6
+ "bin": {
7
+ "mcp-filter": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "proxy",
18
+ "filter"
19
+ ],
20
+ "author": "baranovxyz",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/baranovxyz/mcp-filter.git"
25
+ },
26
+ "homepage": "https://github.com/baranovxyz/mcp-filter#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/baranovxyz/mcp-filter/issues"
29
+ },
30
+ "dependencies": {
31
+ "minimatch": "10.0.1"
32
+ },
33
+ "peerDependencies": {
34
+ "@modelcontextprotocol/sdk": "1.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@modelcontextprotocol/sdk": "1.0.4",
38
+ "@types/node": "22.10.5",
39
+ "@vitest/coverage-v8": "2.1.8",
40
+ "typescript": "5.7.3",
41
+ "vitest": "2.1.8",
42
+ "zod": "3.24.1"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc",
49
+ "dev": "tsc --watch",
50
+ "test": "vitest run",
51
+ "test:watch": "vitest --watch",
52
+ "test:coverage": "vitest --coverage"
53
+ }
54
+ }