nuwax-mcp-stdio-proxy 1.4.3 → 1.4.5
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 +130 -86
- package/dist/modes/stdio.js +13 -2
- package/dist/types.d.ts +2 -0
- package/dist/types.js +9 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6785,12 +6785,12 @@ var require_dist = __commonJS({
|
|
|
6785
6785
|
throw new Error(`Unknown format "${name}"`);
|
|
6786
6786
|
return f;
|
|
6787
6787
|
};
|
|
6788
|
-
function addFormats(ajv, list,
|
|
6788
|
+
function addFormats(ajv, list, fs3, exportName) {
|
|
6789
6789
|
var _a2;
|
|
6790
6790
|
var _b;
|
|
6791
6791
|
(_a2 = (_b = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6792
6792
|
for (const f of list)
|
|
6793
|
-
ajv.addFormat(f,
|
|
6793
|
+
ajv.addFormat(f, fs3[f]);
|
|
6794
6794
|
}
|
|
6795
6795
|
module.exports = exports = formatsPlugin;
|
|
6796
6796
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -6798,6 +6798,9 @@ var require_dist = __commonJS({
|
|
|
6798
6798
|
}
|
|
6799
6799
|
});
|
|
6800
6800
|
|
|
6801
|
+
// src/index.ts
|
|
6802
|
+
import * as fs2 from "fs";
|
|
6803
|
+
|
|
6801
6804
|
// src/logger.ts
|
|
6802
6805
|
function log(level, msg) {
|
|
6803
6806
|
process.stderr.write(`[nuwax-mcp-proxy] ${level}: ${msg}
|
|
@@ -6809,12 +6812,13 @@ var logError = (msg) => log("ERROR", msg);
|
|
|
6809
6812
|
|
|
6810
6813
|
// src/types.ts
|
|
6811
6814
|
function isSseEntry(entry) {
|
|
6812
|
-
|
|
6813
|
-
const e = entry;
|
|
6814
|
-
return e.transport === "sse" || !e.transport && /\/sse(?:\?|$)/i.test(e.url);
|
|
6815
|
+
return "url" in entry && entry.transport === "sse";
|
|
6815
6816
|
}
|
|
6816
6817
|
function isStreamableEntry(entry) {
|
|
6817
|
-
return "url" in entry && typeof entry.url === "string" &&
|
|
6818
|
+
return "url" in entry && typeof entry.url === "string" && entry.transport === "streamable-http";
|
|
6819
|
+
}
|
|
6820
|
+
function needsProtocolDetection(entry) {
|
|
6821
|
+
return "url" in entry && typeof entry.url === "string" && !isSseEntry(entry) && !isStreamableEntry(entry);
|
|
6818
6822
|
}
|
|
6819
6823
|
|
|
6820
6824
|
// node_modules/zod/v3/helpers/util.js
|
|
@@ -23763,7 +23767,7 @@ var StdioServerTransport = class {
|
|
|
23763
23767
|
|
|
23764
23768
|
// src/constants.ts
|
|
23765
23769
|
var PKG_NAME = "nuwax-mcp-stdio-proxy";
|
|
23766
|
-
var PKG_VERSION = "1.4.
|
|
23770
|
+
var PKG_VERSION = "1.4.5";
|
|
23767
23771
|
|
|
23768
23772
|
// src/shared.ts
|
|
23769
23773
|
async function discoverTools(client) {
|
|
@@ -23838,6 +23842,81 @@ function filterTools(tools, filter) {
|
|
|
23838
23842
|
return tools;
|
|
23839
23843
|
}
|
|
23840
23844
|
|
|
23845
|
+
// src/detect.ts
|
|
23846
|
+
async function detectProtocol(url2, headers) {
|
|
23847
|
+
logInfo(`Auto-detecting protocol for ${url2}...`);
|
|
23848
|
+
try {
|
|
23849
|
+
const reqHeaders = {
|
|
23850
|
+
"Content-Type": "application/json",
|
|
23851
|
+
Accept: "application/json, text/event-stream",
|
|
23852
|
+
...headers
|
|
23853
|
+
};
|
|
23854
|
+
const controller = new AbortController();
|
|
23855
|
+
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
23856
|
+
const res = await fetch(url2, {
|
|
23857
|
+
method: "POST",
|
|
23858
|
+
headers: reqHeaders,
|
|
23859
|
+
body: JSON.stringify({
|
|
23860
|
+
jsonrpc: "2.0",
|
|
23861
|
+
id: 1,
|
|
23862
|
+
method: "initialize",
|
|
23863
|
+
params: {
|
|
23864
|
+
protocolVersion: "2025-03-26",
|
|
23865
|
+
capabilities: {},
|
|
23866
|
+
clientInfo: { name: "nuwax-mcp-detect", version: "1.0.0" }
|
|
23867
|
+
}
|
|
23868
|
+
}),
|
|
23869
|
+
signal: controller.signal
|
|
23870
|
+
});
|
|
23871
|
+
clearTimeout(timeout);
|
|
23872
|
+
const ct = res.headers.get("content-type") || "";
|
|
23873
|
+
if (res.ok && (ct.includes("application/json") || ct.includes("text/event-stream"))) {
|
|
23874
|
+
logInfo(`Detected streamable-http protocol for ${url2}`);
|
|
23875
|
+
await res.text().catch(() => {
|
|
23876
|
+
});
|
|
23877
|
+
const sessionId = res.headers.get("mcp-session-id");
|
|
23878
|
+
if (sessionId) {
|
|
23879
|
+
fetch(url2, {
|
|
23880
|
+
method: "DELETE",
|
|
23881
|
+
headers: { "mcp-session-id": sessionId, ...headers },
|
|
23882
|
+
signal: AbortSignal.timeout(5e3)
|
|
23883
|
+
}).catch(() => {
|
|
23884
|
+
});
|
|
23885
|
+
}
|
|
23886
|
+
return "stream";
|
|
23887
|
+
}
|
|
23888
|
+
await res.text().catch(() => {
|
|
23889
|
+
});
|
|
23890
|
+
} catch {
|
|
23891
|
+
}
|
|
23892
|
+
try {
|
|
23893
|
+
const reqHeaders = {
|
|
23894
|
+
Accept: "text/event-stream",
|
|
23895
|
+
...headers
|
|
23896
|
+
};
|
|
23897
|
+
const controller = new AbortController();
|
|
23898
|
+
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
23899
|
+
const res = await fetch(url2, {
|
|
23900
|
+
method: "GET",
|
|
23901
|
+
headers: reqHeaders,
|
|
23902
|
+
signal: controller.signal
|
|
23903
|
+
});
|
|
23904
|
+
const ct = res.headers.get("content-type") || "";
|
|
23905
|
+
if (ct.includes("text/event-stream")) {
|
|
23906
|
+
clearTimeout(timeout);
|
|
23907
|
+
logInfo(`Detected SSE protocol for ${url2}`);
|
|
23908
|
+
controller.abort();
|
|
23909
|
+
return "sse";
|
|
23910
|
+
}
|
|
23911
|
+
clearTimeout(timeout);
|
|
23912
|
+
await res.text().catch(() => {
|
|
23913
|
+
});
|
|
23914
|
+
} catch {
|
|
23915
|
+
}
|
|
23916
|
+
logWarn(`Could not auto-detect protocol for ${url2}, defaulting to streamable-http`);
|
|
23917
|
+
return "stream";
|
|
23918
|
+
}
|
|
23919
|
+
|
|
23841
23920
|
// src/modes/stdio.ts
|
|
23842
23921
|
async function runStdio(config2, allowTools, denyTools) {
|
|
23843
23922
|
const entries = Object.entries(config2.mcpServers);
|
|
@@ -23861,6 +23940,13 @@ async function runStdio(config2, allowTools, denyTools) {
|
|
|
23861
23940
|
connected = await connectSse(id, entry);
|
|
23862
23941
|
} else if (isStreamableEntry(entry)) {
|
|
23863
23942
|
connected = await connectStreamable(id, entry);
|
|
23943
|
+
} else if (needsProtocolDetection(entry)) {
|
|
23944
|
+
const detected = await detectProtocol(entry.url, buildRequestHeaders(entry));
|
|
23945
|
+
if (detected === "sse") {
|
|
23946
|
+
connected = await connectSse(id, { ...entry, transport: "sse" });
|
|
23947
|
+
} else {
|
|
23948
|
+
connected = await connectStreamable(id, entry);
|
|
23949
|
+
}
|
|
23864
23950
|
} else {
|
|
23865
23951
|
connected = await connectStdio(id, entry, baseEnv);
|
|
23866
23952
|
}
|
|
@@ -23938,81 +24024,6 @@ async function runStdio(config2, allowTools, denyTools) {
|
|
|
23938
24024
|
});
|
|
23939
24025
|
}
|
|
23940
24026
|
|
|
23941
|
-
// src/detect.ts
|
|
23942
|
-
async function detectProtocol(url2, headers) {
|
|
23943
|
-
logInfo(`Auto-detecting protocol for ${url2}...`);
|
|
23944
|
-
try {
|
|
23945
|
-
const reqHeaders = {
|
|
23946
|
-
"Content-Type": "application/json",
|
|
23947
|
-
Accept: "application/json, text/event-stream",
|
|
23948
|
-
...headers
|
|
23949
|
-
};
|
|
23950
|
-
const controller = new AbortController();
|
|
23951
|
-
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
23952
|
-
const res = await fetch(url2, {
|
|
23953
|
-
method: "POST",
|
|
23954
|
-
headers: reqHeaders,
|
|
23955
|
-
body: JSON.stringify({
|
|
23956
|
-
jsonrpc: "2.0",
|
|
23957
|
-
id: 1,
|
|
23958
|
-
method: "initialize",
|
|
23959
|
-
params: {
|
|
23960
|
-
protocolVersion: "2025-03-26",
|
|
23961
|
-
capabilities: {},
|
|
23962
|
-
clientInfo: { name: "nuwax-mcp-detect", version: "1.0.0" }
|
|
23963
|
-
}
|
|
23964
|
-
}),
|
|
23965
|
-
signal: controller.signal
|
|
23966
|
-
});
|
|
23967
|
-
clearTimeout(timeout);
|
|
23968
|
-
const ct = res.headers.get("content-type") || "";
|
|
23969
|
-
if (res.ok && (ct.includes("application/json") || ct.includes("text/event-stream"))) {
|
|
23970
|
-
logInfo(`Detected streamable-http protocol for ${url2}`);
|
|
23971
|
-
await res.text().catch(() => {
|
|
23972
|
-
});
|
|
23973
|
-
const sessionId = res.headers.get("mcp-session-id");
|
|
23974
|
-
if (sessionId) {
|
|
23975
|
-
fetch(url2, {
|
|
23976
|
-
method: "DELETE",
|
|
23977
|
-
headers: { "mcp-session-id": sessionId, ...headers },
|
|
23978
|
-
signal: AbortSignal.timeout(5e3)
|
|
23979
|
-
}).catch(() => {
|
|
23980
|
-
});
|
|
23981
|
-
}
|
|
23982
|
-
return "stream";
|
|
23983
|
-
}
|
|
23984
|
-
await res.text().catch(() => {
|
|
23985
|
-
});
|
|
23986
|
-
} catch {
|
|
23987
|
-
}
|
|
23988
|
-
try {
|
|
23989
|
-
const reqHeaders = {
|
|
23990
|
-
Accept: "text/event-stream",
|
|
23991
|
-
...headers
|
|
23992
|
-
};
|
|
23993
|
-
const controller = new AbortController();
|
|
23994
|
-
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
23995
|
-
const res = await fetch(url2, {
|
|
23996
|
-
method: "GET",
|
|
23997
|
-
headers: reqHeaders,
|
|
23998
|
-
signal: controller.signal
|
|
23999
|
-
});
|
|
24000
|
-
const ct = res.headers.get("content-type") || "";
|
|
24001
|
-
if (ct.includes("text/event-stream")) {
|
|
24002
|
-
clearTimeout(timeout);
|
|
24003
|
-
logInfo(`Detected SSE protocol for ${url2}`);
|
|
24004
|
-
controller.abort();
|
|
24005
|
-
return "sse";
|
|
24006
|
-
}
|
|
24007
|
-
clearTimeout(timeout);
|
|
24008
|
-
await res.text().catch(() => {
|
|
24009
|
-
});
|
|
24010
|
-
} catch {
|
|
24011
|
-
}
|
|
24012
|
-
logWarn(`Could not auto-detect protocol for ${url2}, defaulting to streamable-http`);
|
|
24013
|
-
return "stream";
|
|
24014
|
-
}
|
|
24015
|
-
|
|
24016
24027
|
// src/modes/convert.ts
|
|
24017
24028
|
async function runConvert(args) {
|
|
24018
24029
|
let targetUrl;
|
|
@@ -25774,6 +25785,7 @@ function parseCliArgs() {
|
|
|
25774
25785
|
}
|
|
25775
25786
|
function parseStdioArgs(args) {
|
|
25776
25787
|
let configJson;
|
|
25788
|
+
let configFile;
|
|
25777
25789
|
let allowTools;
|
|
25778
25790
|
let denyTools;
|
|
25779
25791
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -25781,6 +25793,9 @@ function parseStdioArgs(args) {
|
|
|
25781
25793
|
if (arg === "--config" && i + 1 < args.length) {
|
|
25782
25794
|
i++;
|
|
25783
25795
|
configJson = args[i];
|
|
25796
|
+
} else if (arg === "--config-file" && i + 1 < args.length) {
|
|
25797
|
+
i++;
|
|
25798
|
+
configFile = args[i];
|
|
25784
25799
|
} else if (arg === "--allow-tools" && i + 1 < args.length) {
|
|
25785
25800
|
i++;
|
|
25786
25801
|
allowTools = args[i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -25789,16 +25804,21 @@ function parseStdioArgs(args) {
|
|
|
25789
25804
|
denyTools = args[i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
25790
25805
|
}
|
|
25791
25806
|
}
|
|
25792
|
-
if (!configJson) {
|
|
25793
|
-
logError("Missing --config argument");
|
|
25807
|
+
if (!configJson && !configFile) {
|
|
25808
|
+
logError("Missing --config or --config-file argument");
|
|
25794
25809
|
logError(`Usage: nuwax-mcp-stdio-proxy --config '{"mcpServers":{...}}'`);
|
|
25810
|
+
logError(" or: nuwax-mcp-stdio-proxy --config-file /path/to/config.json");
|
|
25811
|
+
process.exit(1);
|
|
25812
|
+
}
|
|
25813
|
+
if (configJson && configFile) {
|
|
25814
|
+
logError("Cannot use both --config and --config-file");
|
|
25795
25815
|
process.exit(1);
|
|
25796
25816
|
}
|
|
25797
25817
|
if (allowTools && denyTools) {
|
|
25798
25818
|
logError("Cannot use both --allow-tools and --deny-tools");
|
|
25799
25819
|
process.exit(1);
|
|
25800
25820
|
}
|
|
25801
|
-
const config2 = parseConfigJson(configJson);
|
|
25821
|
+
const config2 = configFile ? parseConfigFile(configFile) : parseConfigJson(configJson);
|
|
25802
25822
|
return { mode: "stdio", config: config2, allowTools, denyTools };
|
|
25803
25823
|
}
|
|
25804
25824
|
function parseConvertArgs(args) {
|
|
@@ -25852,6 +25872,7 @@ function parseConvertArgs(args) {
|
|
|
25852
25872
|
function parseProxyArgs(args) {
|
|
25853
25873
|
let port;
|
|
25854
25874
|
let config2;
|
|
25875
|
+
let configFile;
|
|
25855
25876
|
for (let i = 0; i < args.length; i++) {
|
|
25856
25877
|
const arg = args[i];
|
|
25857
25878
|
if (arg === "--port" && i + 1 < args.length) {
|
|
@@ -25865,6 +25886,9 @@ function parseProxyArgs(args) {
|
|
|
25865
25886
|
} else if (arg === "--config" && i + 1 < args.length) {
|
|
25866
25887
|
i++;
|
|
25867
25888
|
config2 = parseConfigJson(args[i]);
|
|
25889
|
+
} else if (arg === "--config-file" && i + 1 < args.length) {
|
|
25890
|
+
i++;
|
|
25891
|
+
configFile = args[i];
|
|
25868
25892
|
} else {
|
|
25869
25893
|
logError(`Unknown argument: "${arg}"`);
|
|
25870
25894
|
printProxyUsage();
|
|
@@ -25876,8 +25900,11 @@ function parseProxyArgs(args) {
|
|
|
25876
25900
|
printProxyUsage();
|
|
25877
25901
|
process.exit(1);
|
|
25878
25902
|
}
|
|
25903
|
+
if (configFile) {
|
|
25904
|
+
config2 = parseConfigFile(configFile);
|
|
25905
|
+
}
|
|
25879
25906
|
if (!config2) {
|
|
25880
|
-
logError("--config is required for proxy mode");
|
|
25907
|
+
logError("--config or --config-file is required for proxy mode");
|
|
25881
25908
|
printProxyUsage();
|
|
25882
25909
|
process.exit(1);
|
|
25883
25910
|
}
|
|
@@ -25895,13 +25922,29 @@ function parseConfigJson(json2) {
|
|
|
25895
25922
|
process.exit(1);
|
|
25896
25923
|
}
|
|
25897
25924
|
}
|
|
25925
|
+
function parseConfigFile(filePath) {
|
|
25926
|
+
try {
|
|
25927
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
25928
|
+
const config2 = JSON.parse(content);
|
|
25929
|
+
if (!config2.mcpServers || typeof config2.mcpServers !== "object") {
|
|
25930
|
+
throw new Error('config must contain a "mcpServers" object');
|
|
25931
|
+
}
|
|
25932
|
+
return config2;
|
|
25933
|
+
} catch (e) {
|
|
25934
|
+
logError(`Failed to read or parse config file "${filePath}": ${e}`);
|
|
25935
|
+
process.exit(1);
|
|
25936
|
+
}
|
|
25937
|
+
}
|
|
25898
25938
|
function printUsage() {
|
|
25899
25939
|
logError("Usage:");
|
|
25900
25940
|
logError(` nuwax-mcp-stdio-proxy --config '{"mcpServers":{...}}' [OPTIONS] (stdio aggregation)`);
|
|
25941
|
+
logError(" nuwax-mcp-stdio-proxy --config-file <FILE> [OPTIONS] (stdio aggregation from file)");
|
|
25901
25942
|
logError(" nuwax-mcp-stdio-proxy convert [URL] [OPTIONS] (remote \u2192 stdio)");
|
|
25902
25943
|
logError(" nuwax-mcp-stdio-proxy proxy --port <PORT> --config '...' (HTTP server)");
|
|
25903
25944
|
logError("");
|
|
25904
25945
|
logError("Options (stdio / convert):");
|
|
25946
|
+
logError(" --config <JSON> MCP config JSON string");
|
|
25947
|
+
logError(" --config-file <FILE> MCP config JSON file path");
|
|
25905
25948
|
logError(" --allow-tools <TOOLS> Tool whitelist (comma-separated)");
|
|
25906
25949
|
logError(" --deny-tools <TOOLS> Tool blacklist (comma-separated)");
|
|
25907
25950
|
}
|
|
@@ -25920,6 +25963,7 @@ function printConvertUsage() {
|
|
|
25920
25963
|
}
|
|
25921
25964
|
function printProxyUsage() {
|
|
25922
25965
|
logError(`Usage: nuwax-mcp-stdio-proxy proxy --port <PORT> --config '{"mcpServers":{...}}'`);
|
|
25966
|
+
logError(" or: nuwax-mcp-stdio-proxy proxy --port <PORT> --config-file <FILE>");
|
|
25923
25967
|
}
|
|
25924
25968
|
async function main() {
|
|
25925
25969
|
const args = parseCliArgs();
|
package/dist/modes/stdio.js
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* Aggregates multiple MCP servers (stdio + streamable-http + SSE)
|
|
5
5
|
* into a single stdio MCP endpoint.
|
|
6
6
|
*/
|
|
7
|
-
import { isSseEntry, isStreamableEntry } from '../types.js';
|
|
7
|
+
import { isSseEntry, isStreamableEntry, needsProtocolDetection } from '../types.js';
|
|
8
8
|
import { logInfo, logWarn, logError } from '../logger.js';
|
|
9
|
-
import { buildBaseEnv, connectStdio, connectStreamable, connectSse } from '../transport.js';
|
|
9
|
+
import { buildBaseEnv, connectStdio, connectStreamable, connectSse, buildRequestHeaders } from '../transport.js';
|
|
10
10
|
import { discoverTools, createToolProxyServer, setupGracefulShutdown } from '../shared.js';
|
|
11
11
|
import { filterTools } from '../filter.js';
|
|
12
|
+
import { detectProtocol } from '../detect.js';
|
|
12
13
|
export async function runStdio(config, allowTools, denyTools) {
|
|
13
14
|
const entries = Object.entries(config.mcpServers);
|
|
14
15
|
if (entries.length === 0) {
|
|
@@ -32,6 +33,16 @@ export async function runStdio(config, allowTools, denyTools) {
|
|
|
32
33
|
else if (isStreamableEntry(entry)) {
|
|
33
34
|
connected = await connectStreamable(id, entry);
|
|
34
35
|
}
|
|
36
|
+
else if (needsProtocolDetection(entry)) {
|
|
37
|
+
// No explicit transport — probe the URL to determine protocol
|
|
38
|
+
const detected = await detectProtocol(entry.url, buildRequestHeaders(entry));
|
|
39
|
+
if (detected === 'sse') {
|
|
40
|
+
connected = await connectSse(id, { ...entry, transport: 'sse' });
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
connected = await connectStreamable(id, entry);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
35
46
|
else {
|
|
36
47
|
connected = await connectStdio(id, entry, baseEnv);
|
|
37
48
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -45,6 +45,8 @@ export interface SseServerEntry {
|
|
|
45
45
|
export type McpServerEntry = StdioServerEntry | StreamableServerEntry | SseServerEntry;
|
|
46
46
|
export declare function isSseEntry(entry: McpServerEntry): entry is SseServerEntry;
|
|
47
47
|
export declare function isStreamableEntry(entry: McpServerEntry): entry is StreamableServerEntry;
|
|
48
|
+
/** Check if URL entry has no explicit transport → needs auto-detection */
|
|
49
|
+
export declare function needsProtocolDetection(entry: McpServerEntry): entry is StreamableServerEntry;
|
|
48
50
|
/** @deprecated Use StreamableServerEntry instead */
|
|
49
51
|
export type BridgeServerEntry = StreamableServerEntry;
|
|
50
52
|
/** @deprecated Use StreamableServerEntry instead */
|
package/dist/types.js
CHANGED
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
* Types for MCP server configuration
|
|
3
3
|
*/
|
|
4
4
|
export function isSseEntry(entry) {
|
|
5
|
-
|
|
6
|
-
return false;
|
|
7
|
-
const e = entry;
|
|
8
|
-
// Explicit transport: 'sse' or URL path contains /sse (auto-detect)
|
|
9
|
-
return e.transport === 'sse' || (!e.transport && /\/sse(?:\?|$)/i.test(e.url));
|
|
5
|
+
return 'url' in entry && entry.transport === 'sse';
|
|
10
6
|
}
|
|
11
7
|
export function isStreamableEntry(entry) {
|
|
12
8
|
return ('url' in entry &&
|
|
13
9
|
typeof entry.url === 'string' &&
|
|
14
|
-
|
|
10
|
+
entry.transport === 'streamable-http');
|
|
11
|
+
}
|
|
12
|
+
/** Check if URL entry has no explicit transport → needs auto-detection */
|
|
13
|
+
export function needsProtocolDetection(entry) {
|
|
14
|
+
return ('url' in entry &&
|
|
15
|
+
typeof entry.url === 'string' &&
|
|
16
|
+
!isSseEntry(entry) &&
|
|
17
|
+
!isStreamableEntry(entry));
|
|
15
18
|
}
|
|
16
19
|
/** @deprecated Use isStreamableEntry instead */
|
|
17
20
|
export const isBridgeEntry = isStreamableEntry;
|
package/package.json
CHANGED