@aiwerk/mcp-bridge 1.1.1 → 1.1.3

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.
@@ -53,11 +53,9 @@ function resolveConfigValue(value, extraEnv) {
53
53
  * 4. Validate required fields
54
54
  */
55
55
  export function loadConfig(options = {}) {
56
- const configDir = options.configPath
57
- ? join(options.configPath, "..") // If a file path is given, derive directory
58
- : DEFAULT_CONFIG_DIR;
56
+ const configDir = getConfigDir(options.configPath);
59
57
  const configPath = options.configPath || join(DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILE);
60
- const envPath = join(options.configPath ? join(options.configPath, "..") : DEFAULT_CONFIG_DIR, DEFAULT_ENV_FILE);
58
+ const envPath = join(configDir, DEFAULT_ENV_FILE);
61
59
  if (!existsSync(configPath)) {
62
60
  throw new Error(`Config file not found: ${configPath}\nRun 'mcp-bridge init' to set up.`);
63
61
  }
@@ -7,7 +7,7 @@ export type { RouterToolHint, RouterServerStatus, RouterDispatchResponse, Router
7
7
  export { convertJsonSchemaToTypeBox, createToolParameters, setTypeBoxLoader, setSchemaLogger } from "./schema-convert.js";
8
8
  export { initializeProtocol, fetchToolsList, PACKAGE_VERSION } from "./protocol.js";
9
9
  export { loadConfig, parseEnvFile, initConfigDir, getConfigDir } from "./config.js";
10
- export type { Logger, McpServerConfig, McpClientConfig, McpTool, McpRequest, McpResponse, McpTransport, McpServerConnection, BridgeConfig, } from "./types.js";
10
+ export type { Logger, McpServerConfig, McpClientConfig, McpTool, McpRequest, McpCallRequest, McpResponse, McpTransport, McpServerConnection, BridgeConfig, } from "./types.js";
11
11
  export { nextRequestId } from "./types.js";
12
12
  export { pickRegisteredToolName } from "./tool-naming.js";
13
13
  export { StandaloneServer } from "./standalone-server.js";
@@ -84,15 +84,26 @@ export async function convertJsonSchemaToTypeBox(schema, depth = 0) {
84
84
  stringOptions.pattern = schema.pattern;
85
85
  return Type.String(stringOptions);
86
86
  }
87
- case "number":
88
- case "integer": {
87
+ case "number": {
89
88
  const numberOptions = {};
90
89
  if (schema.minimum !== undefined)
91
90
  numberOptions.minimum = schema.minimum;
92
91
  if (schema.maximum !== undefined)
93
92
  numberOptions.maximum = schema.maximum;
93
+ if (schema.enum)
94
+ return Type.Union(schema.enum.map((v) => Type.Literal(v)));
94
95
  return Type.Number(numberOptions);
95
96
  }
97
+ case "integer": {
98
+ const intOptions = {};
99
+ if (schema.minimum !== undefined)
100
+ intOptions.minimum = schema.minimum;
101
+ if (schema.maximum !== undefined)
102
+ intOptions.maximum = schema.maximum;
103
+ if (schema.enum)
104
+ return Type.Union(schema.enum.map((v) => Type.Literal(v)));
105
+ return Type.Integer(intOptions);
106
+ }
96
107
  case "boolean":
97
108
  return Type.Boolean();
98
109
  case "array":
@@ -249,8 +249,13 @@ export class StandaloneServer {
249
249
  async discoverDirectTools(force = false) {
250
250
  if (this.directTools.length > 0 && !force)
251
251
  return; // Already discovered
252
- if (force)
252
+ if (force) {
253
253
  this.directTools = [];
254
+ for (const [, conn] of this.directConnections) {
255
+ await conn.transport.disconnect().catch(() => { });
256
+ }
257
+ this.directConnections.clear();
258
+ }
254
259
  const globalNames = new Set();
255
260
  for (const [serverName, serverConfig] of Object.entries(this.config.servers)) {
256
261
  try {
@@ -52,7 +52,7 @@ export class SseTransport extends BaseTransport {
52
52
  const reader = response.body.getReader();
53
53
  const decoder = new TextDecoder();
54
54
  let buffer = "";
55
- const state = { event: "", dataBuffer: this.currentDataBuffer };
55
+ const state = { event: "", dataBuffer: [] };
56
56
  while (true) {
57
57
  const { done, value } = await reader.read();
58
58
  if (done)
@@ -87,6 +87,7 @@ export class SseTransport extends BaseTransport {
87
87
  return;
88
88
  const data = state.dataBuffer.join("\n");
89
89
  state.dataBuffer.length = 0;
90
+ state.event = "";
90
91
  if (state.event === "endpoint") {
91
92
  if (data.startsWith("/")) {
92
93
  const base = new URL(this.config.url);
@@ -60,31 +60,19 @@ export class StreamableHttpTransport extends BaseTransport {
60
60
  const dataLines = text.split('\n')
61
61
  .filter((line) => line.startsWith('data:'))
62
62
  .map((line) => line.substring(5).trim());
63
- if (dataLines.length > 0) {
64
- for (const dl of dataLines) {
65
- try {
66
- const parsed = JSON.parse(dl);
67
- if (parsed.id !== undefined) {
68
- jsonResponse = parsed;
69
- }
70
- else {
71
- this.handleMessage(parsed);
72
- }
73
- }
74
- catch { /* skip malformed lines */ }
75
- }
76
- if (!jsonResponse) {
77
- jsonResponse = JSON.parse(dataLines[dataLines.length - 1]);
78
- }
79
- }
80
- else {
63
+ if (dataLines.length === 0) {
81
64
  throw new Error("No data lines in SSE response");
82
65
  }
66
+ for (const dl of dataLines) {
67
+ try {
68
+ this.handleMessage(JSON.parse(dl));
69
+ }
70
+ catch { /* skip malformed lines */ }
71
+ }
83
72
  }
84
73
  else {
85
- jsonResponse = await response.json();
74
+ this.handleMessage(await response.json());
86
75
  }
87
- this.handleMessage(jsonResponse);
88
76
  }
89
77
  catch (error) {
90
78
  clearTimeout(timeout);
@@ -151,7 +139,7 @@ export class StreamableHttpTransport extends BaseTransport {
151
139
  }
152
140
  }
153
141
  catch (error) {
154
- this.logger.warn(`[mcp-bridge] Streamable HTTP server probe failed (non-blocking): ${error?.message || error}`);
142
+ this.logger.warn(`[mcp-bridge] Streamable HTTP server probe failed (non-blocking): ${error instanceof Error ? error.message : String(error)}`);
155
143
  }
156
144
  }
157
145
  async disconnect() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Standalone MCP server that multiplexes multiple MCP servers into one interface",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -9,7 +9,7 @@ if ($args.Count -eq 0) {
9
9
  Write-Host "Usage: install-server.ps1 <server-name> [--dry-run] [--remove]"
10
10
  Write-Host ""
11
11
  Write-Host "Available servers:"
12
- Get-ChildItem -Path (Join-Path $ScriptDir "servers") -Directory | ForEach-Object { Write-Host " - $($_.Name)" }
12
+ Get-ChildItem -Path (Join-Path (Split-Path $ScriptDir -Parent) "servers") -Directory | ForEach-Object { Write-Host " - $($_.Name)" }
13
13
  exit 1
14
14
  }
15
15
 
@@ -17,10 +17,10 @@ $ServerName = $args[0]
17
17
  $DryRun = $args -contains "--dry-run"
18
18
  $Remove = $args -contains "--remove"
19
19
 
20
- $ServerDir = Join-Path $ScriptDir "servers\$ServerName"
20
+ $ServerDir = Join-Path (Split-Path $ScriptDir -Parent) "servers\$ServerName"
21
21
  if (-not (Test-Path $ServerDir)) {
22
22
  Write-Host "Error: Server '$ServerName' not found."
23
- Get-ChildItem -Path (Join-Path $ScriptDir "servers") -Directory | ForEach-Object { Write-Host " - $($_.Name)" }
23
+ Get-ChildItem -Path (Join-Path (Split-Path $ScriptDir -Parent) "servers") -Directory | ForEach-Object { Write-Host " - $($_.Name)" }
24
24
  exit 1
25
25
  }
26
26
 
@@ -10,7 +10,7 @@ usage() {
10
10
  echo "Usage: $0 <server-name> [--dry-run] [--remove]"
11
11
  echo ""
12
12
  echo "Available servers:"
13
- for server_dir in "$SCRIPT_DIR/servers"/*; do
13
+ for server_dir in "$SCRIPT_DIR/../servers"/*; do
14
14
  [[ -d "$server_dir" ]] && echo " - $(basename "$server_dir")"
15
15
  done
16
16
  exit 1
@@ -30,7 +30,7 @@ while [[ $# -gt 0 ]]; do
30
30
  shift
31
31
  done
32
32
 
33
- SERVER_DIR="$SCRIPT_DIR/servers/$SERVER_NAME"
33
+ SERVER_DIR="$SCRIPT_DIR/../servers/$SERVER_NAME"
34
34
  if [[ ! -d "$SERVER_DIR" ]]; then
35
35
  echo "Error: Server '$SERVER_NAME' not found."
36
36
  usage