nuwax-mcp-stdio-proxy 1.4.0 → 1.4.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/dist/index.js +54 -23
- package/dist/modes/stdio.d.ts +1 -1
- package/dist/modes/stdio.js +15 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23761,7 +23761,7 @@ var StdioServerTransport = class {
|
|
|
23761
23761
|
|
|
23762
23762
|
// src/constants.ts
|
|
23763
23763
|
var PKG_NAME = "nuwax-mcp-stdio-proxy";
|
|
23764
|
-
var PKG_VERSION = "1.4.
|
|
23764
|
+
var PKG_VERSION = "1.4.1";
|
|
23765
23765
|
|
|
23766
23766
|
// src/shared.ts
|
|
23767
23767
|
async function discoverTools(client) {
|
|
@@ -23825,8 +23825,19 @@ function setupGracefulShutdown(cleanupFn) {
|
|
|
23825
23825
|
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
23826
23826
|
}
|
|
23827
23827
|
|
|
23828
|
+
// src/filter.ts
|
|
23829
|
+
function filterTools(tools, filter) {
|
|
23830
|
+
if (filter.allowTools && filter.allowTools.size > 0) {
|
|
23831
|
+
return tools.filter((t) => filter.allowTools.has(t.name));
|
|
23832
|
+
}
|
|
23833
|
+
if (filter.denyTools && filter.denyTools.size > 0) {
|
|
23834
|
+
return tools.filter((t) => !filter.denyTools.has(t.name));
|
|
23835
|
+
}
|
|
23836
|
+
return tools;
|
|
23837
|
+
}
|
|
23838
|
+
|
|
23828
23839
|
// src/modes/stdio.ts
|
|
23829
|
-
async function runStdio(config2) {
|
|
23840
|
+
async function runStdio(config2, allowTools, denyTools) {
|
|
23830
23841
|
const entries = Object.entries(config2.mcpServers);
|
|
23831
23842
|
if (entries.length === 0) {
|
|
23832
23843
|
logError("No MCP servers configured in mcpServers");
|
|
@@ -23878,9 +23889,17 @@ async function runStdio(config2) {
|
|
|
23878
23889
|
}
|
|
23879
23890
|
const aggregatedTools = Array.from(toolsByName.values());
|
|
23880
23891
|
logInfo(`Aggregated ${aggregatedTools.length} unique tool(s) from ${clients.size} server(s)`);
|
|
23892
|
+
const toolFilter = {};
|
|
23893
|
+
if (allowTools) toolFilter.allowTools = new Set(allowTools);
|
|
23894
|
+
if (denyTools) toolFilter.denyTools = new Set(denyTools);
|
|
23895
|
+
const filteredTools = filterTools(aggregatedTools, toolFilter);
|
|
23896
|
+
const filteredNames = new Set(filteredTools.map((t) => t.name));
|
|
23897
|
+
if (filteredTools.length !== aggregatedTools.length) {
|
|
23898
|
+
logInfo(`After filtering: ${filteredTools.length} tool(s) \u2014 ${filteredTools.map((t) => t.name).join(", ")}`);
|
|
23899
|
+
}
|
|
23881
23900
|
const { server } = await createToolProxyServer({
|
|
23882
|
-
tools:
|
|
23883
|
-
resolveClient: (name) => toolToClient.get(name),
|
|
23901
|
+
tools: filteredTools,
|
|
23902
|
+
resolveClient: (name) => filteredNames.has(name) ? toolToClient.get(name) : void 0,
|
|
23884
23903
|
errorLabel: (name) => `"${name}" (server: "${toolToServer.get(name) || "unknown"}")`
|
|
23885
23904
|
});
|
|
23886
23905
|
logInfo("Proxy server running on stdio");
|
|
@@ -23907,17 +23926,6 @@ async function runStdio(config2) {
|
|
|
23907
23926
|
});
|
|
23908
23927
|
}
|
|
23909
23928
|
|
|
23910
|
-
// src/filter.ts
|
|
23911
|
-
function filterTools(tools, filter) {
|
|
23912
|
-
if (filter.allowTools && filter.allowTools.size > 0) {
|
|
23913
|
-
return tools.filter((t) => filter.allowTools.has(t.name));
|
|
23914
|
-
}
|
|
23915
|
-
if (filter.denyTools && filter.denyTools.size > 0) {
|
|
23916
|
-
return tools.filter((t) => !filter.denyTools.has(t.name));
|
|
23917
|
-
}
|
|
23918
|
-
return tools;
|
|
23919
|
-
}
|
|
23920
|
-
|
|
23921
23929
|
// src/detect.ts
|
|
23922
23930
|
async function detectProtocol(url2, headers) {
|
|
23923
23931
|
logInfo(`Auto-detecting protocol for ${url2}...`);
|
|
@@ -25753,14 +25761,33 @@ function parseCliArgs() {
|
|
|
25753
25761
|
return parseStdioArgs(args);
|
|
25754
25762
|
}
|
|
25755
25763
|
function parseStdioArgs(args) {
|
|
25756
|
-
|
|
25757
|
-
|
|
25764
|
+
let configJson;
|
|
25765
|
+
let allowTools;
|
|
25766
|
+
let denyTools;
|
|
25767
|
+
for (let i = 0; i < args.length; i++) {
|
|
25768
|
+
const arg = args[i];
|
|
25769
|
+
if (arg === "--config" && i + 1 < args.length) {
|
|
25770
|
+
i++;
|
|
25771
|
+
configJson = args[i];
|
|
25772
|
+
} else if (arg === "--allow-tools" && i + 1 < args.length) {
|
|
25773
|
+
i++;
|
|
25774
|
+
allowTools = args[i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
25775
|
+
} else if (arg === "--deny-tools" && i + 1 < args.length) {
|
|
25776
|
+
i++;
|
|
25777
|
+
denyTools = args[i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
25778
|
+
}
|
|
25779
|
+
}
|
|
25780
|
+
if (!configJson) {
|
|
25758
25781
|
logError("Missing --config argument");
|
|
25759
25782
|
logError(`Usage: nuwax-mcp-stdio-proxy --config '{"mcpServers":{...}}'`);
|
|
25760
25783
|
process.exit(1);
|
|
25761
25784
|
}
|
|
25762
|
-
|
|
25763
|
-
|
|
25785
|
+
if (allowTools && denyTools) {
|
|
25786
|
+
logError("Cannot use both --allow-tools and --deny-tools");
|
|
25787
|
+
process.exit(1);
|
|
25788
|
+
}
|
|
25789
|
+
const config2 = parseConfigJson(configJson);
|
|
25790
|
+
return { mode: "stdio", config: config2, allowTools, denyTools };
|
|
25764
25791
|
}
|
|
25765
25792
|
function parseConvertArgs(args) {
|
|
25766
25793
|
let url2;
|
|
@@ -25858,9 +25885,13 @@ function parseConfigJson(json2) {
|
|
|
25858
25885
|
}
|
|
25859
25886
|
function printUsage() {
|
|
25860
25887
|
logError("Usage:");
|
|
25861
|
-
logError(` nuwax-mcp-stdio-proxy --config '{"mcpServers":{...}}'
|
|
25862
|
-
logError(" nuwax-mcp-stdio-proxy convert [URL] [OPTIONS]
|
|
25863
|
-
logError(" nuwax-mcp-stdio-proxy proxy --port <PORT> --config '...'
|
|
25888
|
+
logError(` nuwax-mcp-stdio-proxy --config '{"mcpServers":{...}}' [OPTIONS] (stdio aggregation)`);
|
|
25889
|
+
logError(" nuwax-mcp-stdio-proxy convert [URL] [OPTIONS] (remote \u2192 stdio)");
|
|
25890
|
+
logError(" nuwax-mcp-stdio-proxy proxy --port <PORT> --config '...' (HTTP server)");
|
|
25891
|
+
logError("");
|
|
25892
|
+
logError("Options (stdio / convert):");
|
|
25893
|
+
logError(" --allow-tools <TOOLS> Tool whitelist (comma-separated)");
|
|
25894
|
+
logError(" --deny-tools <TOOLS> Tool blacklist (comma-separated)");
|
|
25864
25895
|
}
|
|
25865
25896
|
function printConvertUsage() {
|
|
25866
25897
|
logError("Usage: nuwax-mcp-stdio-proxy convert [URL] [OPTIONS]");
|
|
@@ -25882,7 +25913,7 @@ async function main() {
|
|
|
25882
25913
|
const args = parseCliArgs();
|
|
25883
25914
|
switch (args.mode) {
|
|
25884
25915
|
case "stdio":
|
|
25885
|
-
await runStdio(args.config);
|
|
25916
|
+
await runStdio(args.config, args.allowTools, args.denyTools);
|
|
25886
25917
|
break;
|
|
25887
25918
|
case "convert":
|
|
25888
25919
|
await runConvert(args);
|
package/dist/modes/stdio.d.ts
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
* into a single stdio MCP endpoint.
|
|
6
6
|
*/
|
|
7
7
|
import type { McpServersConfig } from '../types.js';
|
|
8
|
-
export declare function runStdio(config: McpServersConfig): Promise<void>;
|
|
8
|
+
export declare function runStdio(config: McpServersConfig, allowTools?: string[], denyTools?: string[]): Promise<void>;
|
package/dist/modes/stdio.js
CHANGED
|
@@ -8,7 +8,8 @@ import { isSseEntry, isStreamableEntry } from '../types.js';
|
|
|
8
8
|
import { logInfo, logWarn, logError } from '../logger.js';
|
|
9
9
|
import { buildBaseEnv, connectStdio, connectStreamable, connectSse } from '../transport.js';
|
|
10
10
|
import { discoverTools, createToolProxyServer, setupGracefulShutdown } from '../shared.js';
|
|
11
|
-
|
|
11
|
+
import { filterTools } from '../filter.js';
|
|
12
|
+
export async function runStdio(config, allowTools, denyTools) {
|
|
12
13
|
const entries = Object.entries(config.mcpServers);
|
|
13
14
|
if (entries.length === 0) {
|
|
14
15
|
logError('No MCP servers configured in mcpServers');
|
|
@@ -59,10 +60,21 @@ export async function runStdio(config) {
|
|
|
59
60
|
}
|
|
60
61
|
const aggregatedTools = Array.from(toolsByName.values());
|
|
61
62
|
logInfo(`Aggregated ${aggregatedTools.length} unique tool(s) from ${clients.size} server(s)`);
|
|
63
|
+
// ---- Phase 1.5: Apply tool filtering (allow/deny) ----
|
|
64
|
+
const toolFilter = {};
|
|
65
|
+
if (allowTools)
|
|
66
|
+
toolFilter.allowTools = new Set(allowTools);
|
|
67
|
+
if (denyTools)
|
|
68
|
+
toolFilter.denyTools = new Set(denyTools);
|
|
69
|
+
const filteredTools = filterTools(aggregatedTools, toolFilter);
|
|
70
|
+
const filteredNames = new Set(filteredTools.map((t) => t.name));
|
|
71
|
+
if (filteredTools.length !== aggregatedTools.length) {
|
|
72
|
+
logInfo(`After filtering: ${filteredTools.length} tool(s) — ${filteredTools.map((t) => t.name).join(', ')}`);
|
|
73
|
+
}
|
|
62
74
|
// ---- Phase 2: Create the aggregating MCP server ----
|
|
63
75
|
const { server } = await createToolProxyServer({
|
|
64
|
-
tools:
|
|
65
|
-
resolveClient: (name) => toolToClient.get(name),
|
|
76
|
+
tools: filteredTools,
|
|
77
|
+
resolveClient: (name) => filteredNames.has(name) ? toolToClient.get(name) : undefined,
|
|
66
78
|
errorLabel: (name) => `"${name}" (server: "${toolToServer.get(name) || 'unknown'}")`,
|
|
67
79
|
});
|
|
68
80
|
logInfo('Proxy server running on stdio');
|
package/package.json
CHANGED