mcp-filter 1.0.0 → 1.0.2
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/CHANGELOG.md +5 -0
- package/README.md +23 -13
- package/dist/index.js +0 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +3 -1
- package/dist/logger.js.map +1 -1
- package/package.json +10 -9
- package/dist/core/config-loader.d.ts +0 -22
- package/dist/core/config-loader.d.ts.map +0 -1
- package/dist/core/config-loader.js +0 -308
- package/dist/core/config-loader.js.map +0 -1
- package/dist/core/config-schema.d.ts +0 -1363
- package/dist/core/config-schema.d.ts.map +0 -1
- package/dist/core/config-schema.js +0 -139
- package/dist/core/config-schema.js.map +0 -1
- package/dist/core/server-manager.d.ts +0 -51
- package/dist/core/server-manager.d.ts.map +0 -1
- package/dist/core/server-manager.js +0 -149
- package/dist/core/server-manager.js.map +0 -1
- package/dist/features/discovery/config-init.d.ts +0 -37
- package/dist/features/discovery/config-init.d.ts.map +0 -1
- package/dist/features/discovery/config-init.js +0 -95
- package/dist/features/discovery/config-init.js.map +0 -1
- package/dist/features/discovery/discovery-handler.d.ts +0 -128
- package/dist/features/discovery/discovery-handler.d.ts.map +0 -1
- package/dist/features/discovery/discovery-handler.js +0 -629
- package/dist/features/discovery/discovery-handler.js.map +0 -1
- package/dist/features/discovery/initialization.d.ts +0 -126
- package/dist/features/discovery/initialization.d.ts.map +0 -1
- package/dist/features/discovery/initialization.js +0 -314
- package/dist/features/discovery/initialization.js.map +0 -1
- package/dist/features/discovery/search-phase.d.ts +0 -19
- package/dist/features/discovery/search-phase.d.ts.map +0 -1
- package/dist/features/discovery/search-phase.js +0 -76
- package/dist/features/discovery/search-phase.js.map +0 -1
- package/dist/features/discovery/simple-rag.d.ts +0 -30
- package/dist/features/discovery/simple-rag.d.ts.map +0 -1
- package/dist/features/discovery/simple-rag.js +0 -85
- package/dist/features/discovery/simple-rag.js.map +0 -1
- package/dist/features/filtering/filter.d.ts +0 -18
- package/dist/features/filtering/filter.d.ts.map +0 -1
- package/dist/features/filtering/filter.js +0 -43
- package/dist/features/filtering/filter.js.map +0 -1
- package/dist/features/overrides/override-manager.d.ts +0 -25
- package/dist/features/overrides/override-manager.d.ts.map +0 -1
- package/dist/features/overrides/override-manager.js +0 -67
- package/dist/features/overrides/override-manager.js.map +0 -1
- package/dist/utils/debug-logger.d.ts +0 -2
- package/dist/utils/debug-logger.d.ts.map +0 -1
- package/dist/utils/debug-logger.js +0 -33
- package/dist/utils/debug-logger.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.1] - 2026-03-15
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Logger was writing info/success messages to stdout, corrupting MCP JSON-RPC stream and causing "not valid JSON" errors in clients like Cursor
|
|
12
|
+
|
|
8
13
|
## [1.0.0] - 2026-03-14
|
|
9
14
|
|
|
10
15
|
### Added
|
package/README.md
CHANGED
|
@@ -37,8 +37,8 @@ npm install -g mcp-filter
|
|
|
37
37
|
# Filter a local MCP server (stdio)
|
|
38
38
|
npx mcp-filter --exclude "browser_close" --exclude "browser_evaluate" -- npx @playwright/mcp
|
|
39
39
|
|
|
40
|
-
# Filter a remote MCP server (HTTP)
|
|
41
|
-
npx mcp-filter --exclude "
|
|
40
|
+
# Filter a remote MCP server (HTTP) — block refunds on Stripe
|
|
41
|
+
npx mcp-filter --exclude "create_refund" --upstream-url https://mcp.stripe.com
|
|
42
42
|
|
|
43
43
|
# Whitelist mode — only allow specific tools
|
|
44
44
|
npx mcp-filter --include "browser_navigate" --include "browser_screenshot" -- npx @playwright/mcp
|
|
@@ -77,13 +77,14 @@ npx mcp-filter --exclude "debug*" -- node my-mcp-server.js
|
|
|
77
77
|
### Remote Servers (HTTP)
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
#
|
|
81
|
-
npx mcp-filter --exclude "delete_*"
|
|
80
|
+
# Block refunds and customer deletion on Stripe
|
|
81
|
+
npx mcp-filter --exclude "create_refund" --exclude "delete_*" \
|
|
82
|
+
--upstream-url https://mcp.stripe.com
|
|
82
83
|
|
|
83
|
-
#
|
|
84
|
-
npx mcp-filter
|
|
85
|
-
--
|
|
86
|
-
--
|
|
84
|
+
# Read-only Notion (block all mutations)
|
|
85
|
+
npx mcp-filter \
|
|
86
|
+
--exclude "create_*" --exclude "update_*" --exclude "delete_*" --exclude "archive_*" \
|
|
87
|
+
--upstream-url https://mcp.notion.com/mcp
|
|
87
88
|
|
|
88
89
|
# Multiple headers
|
|
89
90
|
npx mcp-filter --exclude "write_*" \
|
|
@@ -282,6 +283,16 @@ claude mcp add --scope user playwright-safe -- \
|
|
|
282
283
|
npx mcp-filter --include "browser_*" -- npx @playwright/mcp@latest
|
|
283
284
|
```
|
|
284
285
|
|
|
286
|
+
**Remote HTTP server (no second `--`):**
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
claude mcp add stripe-safe -- \
|
|
290
|
+
npx mcp-filter \
|
|
291
|
+
--exclude "create_refund" \
|
|
292
|
+
--exclude "delete_*" \
|
|
293
|
+
--upstream-url https://mcp.stripe.com
|
|
294
|
+
```
|
|
295
|
+
|
|
285
296
|
**Command structure:** first `--` separates Claude options from mcp-filter; second `--` separates mcp-filter options from the upstream command.
|
|
286
297
|
|
|
287
298
|
<details>
|
|
@@ -367,19 +378,18 @@ Add to `.cursor/mcp.json` or `~/.cursor/mcp.json`:
|
|
|
367
378
|
}
|
|
368
379
|
```
|
|
369
380
|
|
|
370
|
-
**Remote server
|
|
381
|
+
**Remote HTTP server (Stripe — block refunds):**
|
|
371
382
|
|
|
372
383
|
```json
|
|
373
384
|
{
|
|
374
385
|
"mcpServers": {
|
|
375
|
-
"
|
|
386
|
+
"stripe-safe": {
|
|
376
387
|
"command": "npx",
|
|
377
388
|
"args": [
|
|
378
389
|
"mcp-filter",
|
|
390
|
+
"--exclude", "create_refund",
|
|
379
391
|
"--exclude", "delete_*",
|
|
380
|
-
"--
|
|
381
|
-
"--upstream-url", "https://mcp.notion.com/mcp",
|
|
382
|
-
"--header", "Authorization: Bearer your-token"
|
|
392
|
+
"--upstream-url", "https://mcp.stripe.com"
|
|
383
393
|
]
|
|
384
394
|
}
|
|
385
395
|
}
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,mCAGjB,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createConsola } from "consola";
|
|
2
|
-
//
|
|
2
|
+
// Force ALL output to stderr so nothing interferes with MCP JSON-RPC on stdout.
|
|
3
|
+
// By default consola sends info/success/log to stdout — we must override both streams.
|
|
3
4
|
export const logger = createConsola({
|
|
5
|
+
stdout: process.stderr,
|
|
4
6
|
stderr: process.stderr,
|
|
5
7
|
});
|
|
6
8
|
//# sourceMappingURL=logger.js.map
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,gFAAgF;AAChF,uFAAuF;AACvF,MAAM,CAAC,MAAM,MAAM,GAAG,aAAa,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,MAAM,EAAE,OAAO,CAAC,MAAM;CACvB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-filter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "MCP server proxy to filter tools, resources, and prompts from upstream MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,6 +18,14 @@
|
|
|
18
18
|
"CHANGELOG.md",
|
|
19
19
|
"LICENSE"
|
|
20
20
|
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsc --watch",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest --watch",
|
|
26
|
+
"test:coverage": "vitest --coverage",
|
|
27
|
+
"prepublishOnly": "pnpm test && pnpm run build"
|
|
28
|
+
},
|
|
21
29
|
"keywords": [
|
|
22
30
|
"mcp",
|
|
23
31
|
"model-context-protocol",
|
|
@@ -53,12 +61,5 @@
|
|
|
53
61
|
},
|
|
54
62
|
"engines": {
|
|
55
63
|
"node": ">=20"
|
|
56
|
-
},
|
|
57
|
-
"scripts": {
|
|
58
|
-
"build": "tsc",
|
|
59
|
-
"dev": "tsc --watch",
|
|
60
|
-
"test": "vitest run",
|
|
61
|
-
"test:watch": "vitest --watch",
|
|
62
|
-
"test:coverage": "vitest --coverage"
|
|
63
64
|
}
|
|
64
|
-
}
|
|
65
|
+
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ConfigFile, ServerConfig, DiscoveryConfig, FilterConfig } from "../types.js";
|
|
2
|
-
import { ConfigValidationResult } from "./config-schema.js";
|
|
3
|
-
/**
|
|
4
|
-
* Loads and validates the config file from project root
|
|
5
|
-
* Returns config even if validation fails (for graceful error reporting)
|
|
6
|
-
*/
|
|
7
|
-
export declare function loadConfigFile(configPath?: string): ConfigFile | null;
|
|
8
|
-
/**
|
|
9
|
-
* Validates config file structure
|
|
10
|
-
*/
|
|
11
|
-
export declare function validateConfigFile(config: ConfigFile): void;
|
|
12
|
-
/**
|
|
13
|
-
* Merges CLI config with config file
|
|
14
|
-
* CLI args take precedence over config file values
|
|
15
|
-
* Returns validation errors if config file is invalid
|
|
16
|
-
*/
|
|
17
|
-
export declare function mergeConfigs(cliConfig: FilterConfig | null, fileConfig: ConfigFile | null): {
|
|
18
|
-
servers: Map<string, ServerConfig>;
|
|
19
|
-
discovery: DiscoveryConfig;
|
|
20
|
-
validationErrors?: ConfigValidationResult;
|
|
21
|
-
};
|
|
22
|
-
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAuC,MAAM,aAAa,CAAC;AAE3H,OAAO,EAAyB,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEnF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAwDrE;AA8CD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CA0E3D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,YAAY,GAAG,IAAI,EAC9B,UAAU,EAAE,UAAU,GAAG,IAAI,GAC5B;IAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAAC,SAAS,EAAE,eAAe,CAAC;IAAC,gBAAgB,CAAC,EAAE,sBAAsB,CAAA;CAAE,CAyJ/G"}
|
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
|
-
import { resolve } from "path";
|
|
3
|
-
import { logger } from "../logger.js";
|
|
4
|
-
import { validateConfigWithZod } from "./config-schema.js";
|
|
5
|
-
/**
|
|
6
|
-
* Loads and validates the config file from project root
|
|
7
|
-
* Returns config even if validation fails (for graceful error reporting)
|
|
8
|
-
*/
|
|
9
|
-
export function loadConfigFile(configPath) {
|
|
10
|
-
const searchPaths = configPath
|
|
11
|
-
? [resolve(configPath)]
|
|
12
|
-
: [
|
|
13
|
-
resolve(process.cwd(), ".mcp-filter.json"),
|
|
14
|
-
resolve(process.cwd(), "mcp-filter.json"),
|
|
15
|
-
];
|
|
16
|
-
// #region agent log
|
|
17
|
-
fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'config-loader.ts:9', message: 'loadConfigFile entry', data: { configPath: configPath, cwd: process.cwd(), searchPaths: searchPaths }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
|
|
18
|
-
// #endregion
|
|
19
|
-
for (const path of searchPaths) {
|
|
20
|
-
try {
|
|
21
|
-
// #region agent log
|
|
22
|
-
fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'config-loader.ts:20', message: 'trying config path', data: { path: path }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
|
|
23
|
-
// #endregion
|
|
24
|
-
const content = readFileSync(path, "utf-8");
|
|
25
|
-
const rawConfig = JSON.parse(content);
|
|
26
|
-
// Validate with Zod but don't throw - return config even if invalid
|
|
27
|
-
const validation = validateConfigWithZod(rawConfig);
|
|
28
|
-
// #region agent log
|
|
29
|
-
const configServers = rawConfig.mcpServers || rawConfig.servers;
|
|
30
|
-
fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'config-loader.ts:23', message: 'config file loaded', data: { path: path, serversCount: configServers ? Object.keys(configServers).length : 0, hasMcpServers: !!rawConfig.mcpServers, hasServers: !!rawConfig.servers, valid: validation.valid, errorsCount: validation.errors?.errors.length || 0 }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
|
|
31
|
-
// #endregion
|
|
32
|
-
if (validation.valid) {
|
|
33
|
-
logger.info(`Loaded config file: ${path}`);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
logger.warn(`Config file ${path} has validation errors (will still attempt to load)`);
|
|
37
|
-
}
|
|
38
|
-
// Return config even if invalid - errors will be reported in init method
|
|
39
|
-
return rawConfig;
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
// #region agent log
|
|
43
|
-
fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'config-loader.ts:27', message: 'config path error', data: { path: path, errorCode: error.code, errorMessage: error.message }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
|
|
44
|
-
// #endregion
|
|
45
|
-
if (error.code === "ENOENT") {
|
|
46
|
-
continue; // Try next path
|
|
47
|
-
}
|
|
48
|
-
if (error instanceof SyntaxError) {
|
|
49
|
-
throw new Error(`Invalid JSON in config file ${path}: ${error.message}`);
|
|
50
|
-
}
|
|
51
|
-
throw error;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// #region agent log
|
|
55
|
-
fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'config-loader.ts:36', message: 'no config file found', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
|
|
56
|
-
// #endregion
|
|
57
|
-
return null; // No config file found
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Converts Cursor format server config to internal ServerConfig format
|
|
61
|
-
*/
|
|
62
|
-
function convertCursorConfigToServerConfig(serverId, cursorConfig) {
|
|
63
|
-
let transport;
|
|
64
|
-
// Determine transport type from Cursor format
|
|
65
|
-
if (cursorConfig.url) {
|
|
66
|
-
// HTTP or SSE transport
|
|
67
|
-
// Default to HTTP unless explicitly specified as SSE (we'll detect later if needed)
|
|
68
|
-
transport = {
|
|
69
|
-
type: "http",
|
|
70
|
-
url: cursorConfig.url,
|
|
71
|
-
headers: cursorConfig.headers,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
else if (cursorConfig.command) {
|
|
75
|
-
// Stdio transport
|
|
76
|
-
const command = cursorConfig.args
|
|
77
|
-
? [cursorConfig.command, ...cursorConfig.args]
|
|
78
|
-
: [cursorConfig.command];
|
|
79
|
-
transport = {
|
|
80
|
-
type: "stdio",
|
|
81
|
-
command,
|
|
82
|
-
env: cursorConfig.env,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
throw new Error(`Server '${serverId}' must have either 'command' (for stdio) or 'url' (for HTTP/SSE)`);
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
enabled: cursorConfig.enabled,
|
|
90
|
-
transport,
|
|
91
|
-
filters: cursorConfig.filters,
|
|
92
|
-
toolOverrides: cursorConfig.toolOverrides,
|
|
93
|
-
initialized: cursorConfig.initialized,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Validates config file structure
|
|
98
|
-
*/
|
|
99
|
-
export function validateConfigFile(config) {
|
|
100
|
-
// Support both new (mcpServers) and old (servers) format
|
|
101
|
-
const servers = config.mcpServers || config.servers;
|
|
102
|
-
if (!servers || typeof servers !== "object") {
|
|
103
|
-
throw new Error("Config file must have a 'mcpServers' or 'servers' object");
|
|
104
|
-
}
|
|
105
|
-
for (const [serverId, serverConfig] of Object.entries(servers)) {
|
|
106
|
-
// New Cursor format
|
|
107
|
-
if (config.mcpServers) {
|
|
108
|
-
const cursorConfig = serverConfig;
|
|
109
|
-
// Must have either command (stdio) or url (HTTP/SSE)
|
|
110
|
-
if (!cursorConfig.command && !cursorConfig.url) {
|
|
111
|
-
throw new Error(`Server '${serverId}' must have either 'command' (for stdio) or 'url' (for HTTP/SSE)`);
|
|
112
|
-
}
|
|
113
|
-
if (cursorConfig.command && cursorConfig.url) {
|
|
114
|
-
throw new Error(`Server '${serverId}' cannot have both 'command' and 'url'. Use 'command' for stdio or 'url' for HTTP/SSE.`);
|
|
115
|
-
}
|
|
116
|
-
if (cursorConfig.command && (!cursorConfig.args || cursorConfig.args.length === 0)) {
|
|
117
|
-
// Command without args is valid (single command)
|
|
118
|
-
}
|
|
119
|
-
if (cursorConfig.url) {
|
|
120
|
-
try {
|
|
121
|
-
new URL(cursorConfig.url);
|
|
122
|
-
}
|
|
123
|
-
catch {
|
|
124
|
-
throw new Error(`Server '${serverId}' has invalid URL: ${cursorConfig.url}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
// Old format (backward compatibility)
|
|
130
|
-
const oldConfig = serverConfig;
|
|
131
|
-
if (!oldConfig.transport) {
|
|
132
|
-
throw new Error(`Server '${serverId}' must have a 'transport' configuration`);
|
|
133
|
-
}
|
|
134
|
-
if (!oldConfig.transport.type) {
|
|
135
|
-
throw new Error(`Server '${serverId}' transport must have a 'type'`);
|
|
136
|
-
}
|
|
137
|
-
const validTransportTypes = ["stdio", "http", "sse"];
|
|
138
|
-
if (!validTransportTypes.includes(oldConfig.transport.type)) {
|
|
139
|
-
throw new Error(`Server '${serverId}' has invalid transport type '${oldConfig.transport.type}'. Must be one of: ${validTransportTypes.join(", ")}`);
|
|
140
|
-
}
|
|
141
|
-
if (oldConfig.transport.type === "stdio") {
|
|
142
|
-
const stdioTransport = oldConfig.transport;
|
|
143
|
-
if (!Array.isArray(stdioTransport.command) || stdioTransport.command.length === 0) {
|
|
144
|
-
throw new Error(`Server '${serverId}' stdio transport must have a non-empty 'command' array`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
if (oldConfig.transport.type === "http" || oldConfig.transport.type === "sse") {
|
|
148
|
-
const httpTransport = oldConfig.transport;
|
|
149
|
-
if (!httpTransport.url) {
|
|
150
|
-
throw new Error(`Server '${serverId}' ${oldConfig.transport.type} transport must have a 'url'`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Merges CLI config with config file
|
|
158
|
-
* CLI args take precedence over config file values
|
|
159
|
-
* Returns validation errors if config file is invalid
|
|
160
|
-
*/
|
|
161
|
-
export function mergeConfigs(cliConfig, fileConfig) {
|
|
162
|
-
const servers = new Map();
|
|
163
|
-
const discovery = {
|
|
164
|
-
enabled: true,
|
|
165
|
-
searchMode: "phase",
|
|
166
|
-
ragEnabled: false,
|
|
167
|
-
};
|
|
168
|
-
// Start with config file if available
|
|
169
|
-
let validationErrors;
|
|
170
|
-
if (fileConfig) {
|
|
171
|
-
// Validate with Zod
|
|
172
|
-
const validation = validateConfigWithZod(fileConfig);
|
|
173
|
-
if (!validation.valid) {
|
|
174
|
-
validationErrors = validation;
|
|
175
|
-
// Continue loading even with errors - try to use what we can
|
|
176
|
-
}
|
|
177
|
-
// Try to merge discovery config (may fail if config is invalid)
|
|
178
|
-
try {
|
|
179
|
-
if (fileConfig.discovery) {
|
|
180
|
-
Object.assign(discovery, fileConfig.discovery);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
// Ignore discovery config errors
|
|
185
|
-
}
|
|
186
|
-
// Add servers from config file (support both new and old format)
|
|
187
|
-
// Try to load servers even if validation failed
|
|
188
|
-
try {
|
|
189
|
-
const configServers = fileConfig.mcpServers || fileConfig.servers;
|
|
190
|
-
if (configServers) {
|
|
191
|
-
for (const [serverId, serverConfig] of Object.entries(configServers)) {
|
|
192
|
-
try {
|
|
193
|
-
if (serverConfig.enabled !== false) {
|
|
194
|
-
// Convert Cursor format to internal format if needed
|
|
195
|
-
if (fileConfig.mcpServers) {
|
|
196
|
-
const converted = convertCursorConfigToServerConfig(serverId, serverConfig);
|
|
197
|
-
servers.set(serverId, converted);
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// Old format - use as-is
|
|
201
|
-
servers.set(serverId, { ...serverConfig });
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
// Skip invalid server configs but continue with others
|
|
207
|
-
logger.warn(`Skipping invalid server config '${serverId}': ${error}`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
catch (error) {
|
|
213
|
-
// If we can't parse servers at all, that's okay - validation errors will be reported
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// If CLI config exists, create a default server entry for backward compatibility
|
|
217
|
-
if (cliConfig && servers.size === 0) {
|
|
218
|
-
// Convert CLI patterns to filters format
|
|
219
|
-
const filters = {
|
|
220
|
-
include: cliConfig.patterns
|
|
221
|
-
.filter((p) => p.type === "include")
|
|
222
|
-
.map((p) => p.pattern),
|
|
223
|
-
exclude: cliConfig.patterns
|
|
224
|
-
.filter((p) => p.type === "exclude")
|
|
225
|
-
.map((p) => p.pattern),
|
|
226
|
-
};
|
|
227
|
-
servers.set("default", {
|
|
228
|
-
enabled: true,
|
|
229
|
-
transport: cliConfig.transportConfig,
|
|
230
|
-
filters: Object.keys(filters.include || {}).length > 0 ||
|
|
231
|
-
Object.keys(filters.exclude || {}).length > 0
|
|
232
|
-
? filters
|
|
233
|
-
: undefined,
|
|
234
|
-
initialized: false,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
else if (cliConfig && servers.size > 0) {
|
|
238
|
-
// CLI config overrides first server's transport and filters
|
|
239
|
-
// BUT: Only merge if CLI config has actual transport config (not empty command)
|
|
240
|
-
const hasValidTransport = cliConfig.transportConfig.type === "stdio"
|
|
241
|
-
? (cliConfig.transportConfig.command && cliConfig.transportConfig.command.length > 0)
|
|
242
|
-
: cliConfig.transportConfig.type === "http" || cliConfig.transportConfig.type === "sse"
|
|
243
|
-
? !!cliConfig.transportConfig.url
|
|
244
|
-
: false;
|
|
245
|
-
if (hasValidTransport) {
|
|
246
|
-
const firstServerId = Array.from(servers.keys())[0];
|
|
247
|
-
const firstServer = servers.get(firstServerId);
|
|
248
|
-
// Merge CLI patterns into first server's filters
|
|
249
|
-
const cliFilters = {
|
|
250
|
-
include: cliConfig.patterns
|
|
251
|
-
.filter((p) => p.type === "include")
|
|
252
|
-
.map((p) => p.pattern),
|
|
253
|
-
exclude: cliConfig.patterns
|
|
254
|
-
.filter((p) => p.type === "exclude")
|
|
255
|
-
.map((p) => p.pattern),
|
|
256
|
-
};
|
|
257
|
-
servers.set(firstServerId, {
|
|
258
|
-
...firstServer,
|
|
259
|
-
transport: cliConfig.transportConfig, // CLI transport takes precedence
|
|
260
|
-
filters: {
|
|
261
|
-
include: [
|
|
262
|
-
...(firstServer.filters?.include || []),
|
|
263
|
-
...(cliFilters.include || []),
|
|
264
|
-
],
|
|
265
|
-
exclude: [
|
|
266
|
-
...(firstServer.filters?.exclude || []),
|
|
267
|
-
...(cliFilters.exclude || []),
|
|
268
|
-
],
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
else if (cliConfig.patterns.length > 0) {
|
|
273
|
-
// Only merge filters if CLI has patterns but no valid transport
|
|
274
|
-
const firstServerId = Array.from(servers.keys())[0];
|
|
275
|
-
const firstServer = servers.get(firstServerId);
|
|
276
|
-
const cliFilters = {
|
|
277
|
-
include: cliConfig.patterns
|
|
278
|
-
.filter((p) => p.type === "include")
|
|
279
|
-
.map((p) => p.pattern),
|
|
280
|
-
exclude: cliConfig.patterns
|
|
281
|
-
.filter((p) => p.type === "exclude")
|
|
282
|
-
.map((p) => p.pattern),
|
|
283
|
-
};
|
|
284
|
-
servers.set(firstServerId, {
|
|
285
|
-
...firstServer,
|
|
286
|
-
filters: {
|
|
287
|
-
include: [
|
|
288
|
-
...(firstServer.filters?.include || []),
|
|
289
|
-
...(cliFilters.include || []),
|
|
290
|
-
],
|
|
291
|
-
exclude: [
|
|
292
|
-
...(firstServer.filters?.exclude || []),
|
|
293
|
-
...(cliFilters.exclude || []),
|
|
294
|
-
],
|
|
295
|
-
},
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
const result = {
|
|
300
|
-
servers,
|
|
301
|
-
discovery,
|
|
302
|
-
};
|
|
303
|
-
if (validationErrors) {
|
|
304
|
-
result.validationErrors = validationErrors;
|
|
305
|
-
}
|
|
306
|
-
return result;
|
|
307
|
-
}
|
|
308
|
-
//# sourceMappingURL=config-loader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"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"}
|