@cyanmycelium/mcp-broker 1.0.1 → 1.2.0

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.
Files changed (188) hide show
  1. package/.mcp-broker.example/README.md +3 -3
  2. package/README.md +6 -2
  3. package/dist/bin.d.ts +0 -1
  4. package/dist/bin.js +176 -253
  5. package/dist/bin.js.map +1 -1
  6. package/dist/chunk-FTDKH2C4.js +3670 -0
  7. package/dist/chunk-FTDKH2C4.js.map +1 -0
  8. package/dist/{broker/grammars → grammars}/claude/en.json +1 -1
  9. package/dist/{broker/grammars → grammars}/claude/fr.json +1 -1
  10. package/dist/index.d.ts +1790 -22
  11. package/dist/index.js +2 -18
  12. package/dist/index.js.map +1 -1
  13. package/package.json +9 -7
  14. package/scripts/copy-assets.mjs +16 -10
  15. package/scripts/gen-cert.mjs +5 -5
  16. package/scripts/pack-mcpb.mjs +5 -5
  17. package/scripts/sign-bundle.mjs +6 -6
  18. package/src/auth/auth.config.ts +3 -3
  19. package/src/auth/auth.types.ts +34 -59
  20. package/src/auth/http.auth.ts +18 -22
  21. package/src/auth/index.ts +12 -12
  22. package/src/auth/jwt.validator.ts +3 -3
  23. package/src/auth/provider.auth.ts +1 -1
  24. package/src/auth/resource.metadata.ts +14 -21
  25. package/src/authorization/audit.ts +2 -2
  26. package/src/authorization/capability.classifier.ts +1 -1
  27. package/src/authorization/index.ts +13 -13
  28. package/src/authorization/policy.engine.ts +3 -3
  29. package/src/authorization/policy.types.ts +1 -1
  30. package/src/authorization/runtime.ts +5 -5
  31. package/src/authorization/slot.resource.ts +1 -1
  32. package/src/authorization/subject.mapper.ts +1 -1
  33. package/src/bin.ts +38 -8
  34. package/src/broker/adapters/broker.adapter.info.ts +1 -1
  35. package/src/broker/adapters/broker.adapter.providers.ts +1 -1
  36. package/src/broker/aggregate/aggregate.catalog.ts +1 -1
  37. package/src/broker/aggregate/aggregate.server.ts +7 -7
  38. package/src/broker/aggregate/provider.client.session.ts +2 -2
  39. package/src/broker/behaviors/broker.behavior.info.ts +3 -3
  40. package/src/broker/behaviors/broker.behavior.providers.ts +5 -5
  41. package/src/broker/broker.grammars.ts +9 -9
  42. package/src/broker/broker.server.ts +6 -6
  43. package/src/broker/grammars/claude/en.json +1 -1
  44. package/src/broker/grammars/claude/fr.json +1 -1
  45. package/src/broker/index.ts +9 -9
  46. package/src/config.ts +25 -3
  47. package/src/index.ts +24 -24
  48. package/src/{mcpb.loader.ts → mcpb/mcpb.loader.ts} +11 -11
  49. package/src/{mcpb.unzip.ts → mcpb/mcpb.unzip.ts} +2 -2
  50. package/src/remote.transports.ts +3 -3
  51. package/src/remote.upstream.ts +3 -3
  52. package/src/stdio.upstream.ts +2 -2
  53. package/src/upstream.ts +2 -2
  54. package/src/ws/ws.interfaces.ts +357 -0
  55. package/src/{ws.tunnel.builder.ts → ws/ws.tunnel.builder.ts} +28 -5
  56. package/src/{ws.tunnel.ts → ws/ws.tunnel.ts} +231 -467
  57. package/web/README.md +3 -3
  58. package/web/broker-self-mcp.html +9 -9
  59. package/web/css/styles.css +1 -1
  60. package/web/demos/DemoPlaceholder.html +6 -6
  61. package/web/demos/broker-explorer/css/app.css +1 -1
  62. package/web/demos/broker-explorer/index.html +2 -2
  63. package/web/demos/broker-explorer/js/app.js +4 -4
  64. package/web/demos/broker-explorer/js/mcp-ws-client.js +2 -2
  65. package/web/demos/oauth-lab/README.md +26 -0
  66. package/web/demos/oauth-lab/config.json +1 -0
  67. package/web/demos/oauth-lab/js/app.js +40 -16
  68. package/web/demos/oauth-lab/server/smoke-test.mjs +57 -10
  69. package/web/demos/provider-tunnel/css/app.css +1 -1
  70. package/web/demos/provider-tunnel/index.html +3 -3
  71. package/web/demos/provider-tunnel/js/app.js +10 -10
  72. package/web/demos/provider-tunnel/js/toolbox-server.js +5 -5
  73. package/web/index.html +11 -11
  74. package/web/js/lib/broker-tunnel.js +12 -12
  75. package/dist/auth/auth.config.d.ts +0 -40
  76. package/dist/auth/auth.config.js +0 -62
  77. package/dist/auth/auth.config.js.map +0 -1
  78. package/dist/auth/auth.types.d.ts +0 -119
  79. package/dist/auth/auth.types.js +0 -38
  80. package/dist/auth/auth.types.js.map +0 -1
  81. package/dist/auth/http.auth.d.ts +0 -51
  82. package/dist/auth/http.auth.js +0 -121
  83. package/dist/auth/http.auth.js.map +0 -1
  84. package/dist/auth/index.d.ts +0 -16
  85. package/dist/auth/index.js +0 -12
  86. package/dist/auth/index.js.map +0 -1
  87. package/dist/auth/jwt.validator.d.ts +0 -35
  88. package/dist/auth/jwt.validator.js +0 -46
  89. package/dist/auth/jwt.validator.js.map +0 -1
  90. package/dist/auth/provider.auth.d.ts +0 -51
  91. package/dist/auth/provider.auth.js +0 -80
  92. package/dist/auth/provider.auth.js.map +0 -1
  93. package/dist/auth/resource.metadata.d.ts +0 -32
  94. package/dist/auth/resource.metadata.js +0 -26
  95. package/dist/auth/resource.metadata.js.map +0 -1
  96. package/dist/authorization/audit.d.ts +0 -14
  97. package/dist/authorization/audit.js +0 -20
  98. package/dist/authorization/audit.js.map +0 -1
  99. package/dist/authorization/capability.classifier.d.ts +0 -30
  100. package/dist/authorization/capability.classifier.js +0 -85
  101. package/dist/authorization/capability.classifier.js.map +0 -1
  102. package/dist/authorization/index.d.ts +0 -13
  103. package/dist/authorization/index.js +0 -8
  104. package/dist/authorization/index.js.map +0 -1
  105. package/dist/authorization/policy.engine.d.ts +0 -11
  106. package/dist/authorization/policy.engine.js +0 -192
  107. package/dist/authorization/policy.engine.js.map +0 -1
  108. package/dist/authorization/policy.types.d.ts +0 -92
  109. package/dist/authorization/policy.types.js +0 -2
  110. package/dist/authorization/policy.types.js.map +0 -1
  111. package/dist/authorization/resource.path.d.ts +0 -27
  112. package/dist/authorization/resource.path.js +0 -122
  113. package/dist/authorization/resource.path.js.map +0 -1
  114. package/dist/authorization/runtime.d.ts +0 -22
  115. package/dist/authorization/runtime.js +0 -34
  116. package/dist/authorization/runtime.js.map +0 -1
  117. package/dist/authorization/slot.resource.d.ts +0 -12
  118. package/dist/authorization/slot.resource.js +0 -41
  119. package/dist/authorization/slot.resource.js.map +0 -1
  120. package/dist/authorization/subject.mapper.d.ts +0 -15
  121. package/dist/authorization/subject.mapper.js +0 -67
  122. package/dist/authorization/subject.mapper.js.map +0 -1
  123. package/dist/broker/adapters/broker.adapter.info.d.ts +0 -16
  124. package/dist/broker/adapters/broker.adapter.info.js +0 -43
  125. package/dist/broker/adapters/broker.adapter.info.js.map +0 -1
  126. package/dist/broker/adapters/broker.adapter.providers.d.ts +0 -18
  127. package/dist/broker/adapters/broker.adapter.providers.js +0 -61
  128. package/dist/broker/adapters/broker.adapter.providers.js.map +0 -1
  129. package/dist/broker/aggregate/aggregate.catalog.d.ts +0 -66
  130. package/dist/broker/aggregate/aggregate.catalog.js +0 -119
  131. package/dist/broker/aggregate/aggregate.catalog.js.map +0 -1
  132. package/dist/broker/aggregate/aggregate.server.d.ts +0 -66
  133. package/dist/broker/aggregate/aggregate.server.js +0 -257
  134. package/dist/broker/aggregate/aggregate.server.js.map +0 -1
  135. package/dist/broker/aggregate/provider.client.session.d.ts +0 -52
  136. package/dist/broker/aggregate/provider.client.session.js +0 -140
  137. package/dist/broker/aggregate/provider.client.session.js.map +0 -1
  138. package/dist/broker/behaviors/broker.behavior.info.d.ts +0 -15
  139. package/dist/broker/behaviors/broker.behavior.info.js +0 -41
  140. package/dist/broker/behaviors/broker.behavior.info.js.map +0 -1
  141. package/dist/broker/behaviors/broker.behavior.providers.d.ts +0 -19
  142. package/dist/broker/behaviors/broker.behavior.providers.js +0 -69
  143. package/dist/broker/behaviors/broker.behavior.providers.js.map +0 -1
  144. package/dist/broker/broker.context.d.ts +0 -63
  145. package/dist/broker/broker.context.js +0 -2
  146. package/dist/broker/broker.context.js.map +0 -1
  147. package/dist/broker/broker.grammars.d.ts +0 -132
  148. package/dist/broker/broker.grammars.js +0 -229
  149. package/dist/broker/broker.grammars.js.map +0 -1
  150. package/dist/broker/broker.server.d.ts +0 -68
  151. package/dist/broker/broker.server.js +0 -73
  152. package/dist/broker/broker.server.js.map +0 -1
  153. package/dist/broker/index.d.ts +0 -9
  154. package/dist/broker/index.js +0 -7
  155. package/dist/broker/index.js.map +0 -1
  156. package/dist/config.d.ts +0 -182
  157. package/dist/config.js +0 -61
  158. package/dist/config.js.map +0 -1
  159. package/dist/mcpb.loader.d.ts +0 -26
  160. package/dist/mcpb.loader.js +0 -161
  161. package/dist/mcpb.loader.js.map +0 -1
  162. package/dist/mcpb.unzip.d.ts +0 -6
  163. package/dist/mcpb.unzip.js +0 -95
  164. package/dist/mcpb.unzip.js.map +0 -1
  165. package/dist/remote.transports.d.ts +0 -18
  166. package/dist/remote.transports.js +0 -297
  167. package/dist/remote.transports.js.map +0 -1
  168. package/dist/remote.upstream.d.ts +0 -38
  169. package/dist/remote.upstream.js +0 -52
  170. package/dist/remote.upstream.js.map +0 -1
  171. package/dist/stdio.upstream.d.ts +0 -47
  172. package/dist/stdio.upstream.js +0 -85
  173. package/dist/stdio.upstream.js.map +0 -1
  174. package/dist/upstream.d.ts +0 -35
  175. package/dist/upstream.js +0 -2
  176. package/dist/upstream.js.map +0 -1
  177. package/dist/version.d.ts +0 -2
  178. package/dist/version.js +0 -9
  179. package/dist/version.js.map +0 -1
  180. package/dist/ws.tunnel.builder.d.ts +0 -176
  181. package/dist/ws.tunnel.builder.js +0 -271
  182. package/dist/ws.tunnel.builder.js.map +0 -1
  183. package/dist/ws.tunnel.d.ts +0 -455
  184. package/dist/ws.tunnel.js +0 -1425
  185. package/dist/ws.tunnel.js.map +0 -1
  186. /package/dist/{broker/grammars → grammars}/default/en.json +0 -0
  187. /package/dist/{broker/grammars → grammars}/default/fr.json +0 -0
  188. /package/dist/{broker/grammars → grammars}/default/zh.json +0 -0
@@ -31,7 +31,7 @@ Property-by-property educational guides:
31
31
  └── index.html
32
32
  ```
33
33
 
34
- A ready-made instance UI lives at [`node/web/`](../web/) — point a `www`
34
+ A ready-made instance UI lives at [`node/web/`](../web/), point a `www`
35
35
  mount at it (`"dir": "../web"`) to serve it. See [`node/web/README.md`](../web/README.md).
36
36
 
37
37
  ## Path resolution
@@ -41,14 +41,14 @@ config file** (i.e. `.mcp-broker/`). So `"certs/cert.pem"` in the config
41
41
  points at `.mcp-broker/certs/cert.pem`. The folder is self-contained.
42
42
 
43
43
  Env vars (`MCP_BROKER_TLS_CERT`, `MCP_BROKER_WWW_DIR`, ...) are still
44
- resolved against `process.cwd()` — they are the deploy-time override
44
+ resolved against `process.cwd()`: they are the deploy-time override
45
45
  mechanism and not tied to the config file's location.
46
46
 
47
47
  ## `.mcpb` bundles
48
48
 
49
49
  `mcpbBundles` entries load local `.mcpb` bundles as stdio provider slots.
50
50
  Each bundle is verified against a **detached signature** before it is
51
- unpacked and run — the broker never spawns an unverified bundle.
51
+ unpacked and run: the broker never spawns an unverified bundle.
52
52
 
53
53
  1. Generate a signing key pair (once):
54
54
  `node ../scripts/sign-bundle.mjs keygen bundles`
package/README.md CHANGED
@@ -32,7 +32,7 @@ The broker starts on `http://localhost:3000` by default.
32
32
 
33
33
  Two sources, env vars **always win** over the file. The file is the static baseline you ship with the broker; env vars are deploy-specific overrides.
34
34
 
35
- ### Option A — `.mcp-broker/` folder (recommended)
35
+ ### Option A: `.mcp-broker/` folder (recommended)
36
36
 
37
37
  Drop a `.mcp-broker/` folder next to where you launch the broker. Paths
38
38
  inside `config.json` are resolved against this folder, so it stays
@@ -79,7 +79,7 @@ cp -r node_modules/@cyanmycelium/mcp-broker/.mcp-broker.example .mcp-broker
79
79
 
80
80
  Full reference (every field, defaults, recipes, grammar overrides): **[docs/config.md](docs/config.md)**.
81
81
 
82
- ### Option B — Environment variables
82
+ ### Option B: Environment variables
83
83
 
84
84
  | Variable | Default | Notes |
85
85
  |---|---|---|
@@ -111,6 +111,10 @@ providers, and filter the `_all` aggregate per caller.
111
111
 
112
112
  Enabled via the `auth` config block (or env vars). Minimal `.mcp-broker/config.json`:
113
113
 
114
+ The resource paths below use a compact ISA-95 / IEC 62264-aligned industrial
115
+ profile. The engine remains domain-neutral, does not claim full ISA-95
116
+ compliance, and can map UMD-style namespaces through `slotResources`.
117
+
114
118
  ```json
115
119
  {
116
120
  "auth": {
package/dist/bin.d.ts CHANGED
@@ -1,2 +1 @@
1
1
  #!/usr/bin/env node
2
- export {};
package/dist/bin.js CHANGED
@@ -1,77 +1,15 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Standalone entry-point that starts the mcp-broker WebSocket server.
4
- *
5
- * ## Configuration sources (highest priority first)
6
- *
7
- * 1. Environment variables (`MCP_BROKER_*`).
8
- * 2. JSON config file. Resolved in order:
9
- * a. `MCP_BROKER_CONFIG` env var.
10
- * b. `./.mcp-broker/config.json` in the current working directory.
11
- * c. `./mcp-broker.config.json` (legacy, with a deprecation warning).
12
- * 3. Built-in defaults.
13
- *
14
- * ## Path resolution
15
- *
16
- * - Env-var paths (`MCP_BROKER_*_DIR`, `MCP_BROKER_TLS_*`) are resolved
17
- * against `process.cwd()`.
18
- * - Config-file paths (`tls.cert`, `www.mounts[*].dir`, `stdioUpstreams[*]`,
19
- * `mcpbBundles[*]`) are resolved against the **config file's directory** — so a config in
20
- * `./.mcp-broker/config.json` referring to `"certs/cert.pem"` points at
21
- * `./.mcp-broker/certs/cert.pem`. The folder is self-contained.
22
- *
23
- * ## Local grammar overrides
24
- *
25
- * When `.mcp-broker/grammars/<userAgent>/<locale>.json` files exist next to
26
- * the config file, they are merged **on top of** the packaged grammars. Lets
27
- * users customize tool/resource descriptions for their organization without
28
- * forking the package.
29
- *
30
- * ## Environment variables
31
- *
32
- * | Variable | Default | Notes |
33
- * |--------------------------------|----------|--------------------------------------------------------|
34
- * | MCP_BROKER_CONFIG | (none) | Path to a JSON config file (see above). |
35
- * | MCP_BROKER_PORT | 3000 | |
36
- * | MCP_BROKER_HOST | 0.0.0.0 | |
37
- * | MCP_BROKER_PROVIDER_PATH | /provider| Prefix for provider WS |
38
- * | MCP_BROKER_CLIENT_PATH | / | Prefix for raw WS clients |
39
- * | MCP_BROKER_MCP_PATH | /mcp | Suffix for Streamable HTTP transport |
40
- * | MCP_BROKER_WWW_DIR | (none) | Ergonomic shortcut: mount this directory at "/" |
41
- * | MCP_BROKER_BUNDLE_DIR | (none) | Ergonomic shortcut: mount this directory at "/bundle" |
42
- * | MCP_BROKER_OPEN | (unset) | "1" to auto-launch the default browser at the root URL |
43
- * | MCP_BROKER_TLS_CERT | (none) | Path to a PEM TLS certificate |
44
- * | MCP_BROKER_TLS_KEY | (none) | Path to a PEM private key |
45
- * | MCP_BROKER_PROTOCOL | auto | "http" to force plain, "https" to force TLS, otherwise |
46
- * | | | TLS is enabled iff cert+key are both set |
47
- * | MCP_BROKER_STDIO_PROVIDER | (none) | When set, stdin/stdout carry JSON-RPC for the named |
48
- * | | | provider (Claude Desktop bridge). |
49
- * | MCP_BROKER_LOCALE | en | Locale used for tool descriptions on the `_broker` |
50
- * | | | slot. ISO 639-1 base; regional variants accepted. |
51
- */
52
- import * as fs from "fs";
53
- import * as path from "path";
54
- import open from "open";
55
- import { WsTunnelBuilder } from "./index.js";
56
- import { loadBrokerConfig } from "./config.js";
57
- import { loadMcpbBundle } from "./mcpb.loader.js";
58
- // ---------------------------------------------------------------------------
59
- // Configuration
60
- // ---------------------------------------------------------------------------
61
- const { config, baseDir } = loadBrokerConfig();
62
- const cwd = process.cwd();
63
- /**
64
- * Fills an env var from the config file when the env var is not already set.
65
- * Used for **non-path** scalars — path-bearing fields are read directly so
66
- * they can be resolved against `baseDir` (config file's directory) instead
67
- * of `cwd` (deploy environment).
68
- */
2
+ import { loadBrokerConfig, WsTunnelBuilder, loadMcpbBundle } from './chunk-FTDKH2C4.js';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import open from 'open';
6
+
7
+ var { config, baseDir } = loadBrokerConfig();
8
+ var cwd = process.cwd();
69
9
  function envFromConfig(envName, configValue) {
70
- if (configValue === undefined || configValue === null)
71
- return;
72
- if (process.env[envName] !== undefined && process.env[envName] !== "")
73
- return;
74
- process.env[envName] = String(configValue);
10
+ if (configValue === void 0 || configValue === null) return;
11
+ if (process.env[envName] !== void 0 && process.env[envName] !== "") return;
12
+ process.env[envName] = String(configValue);
75
13
  }
76
14
  envFromConfig("MCP_BROKER_PORT", config.port);
77
15
  envFromConfig("MCP_BROKER_HOST", config.host);
@@ -81,204 +19,189 @@ envFromConfig("MCP_BROKER_STDIO_PROVIDER", config.stdioProvider);
81
19
  envFromConfig("MCP_BROKER_PROVIDER_PATH", config.paths?.provider);
82
20
  envFromConfig("MCP_BROKER_CLIENT_PATH", config.paths?.client);
83
21
  envFromConfig("MCP_BROKER_MCP_PATH", config.paths?.mcp);
84
- envFromConfig("MCP_BROKER_OPEN", config.www?.open === true ? "1" : undefined);
85
- envFromConfig("MCP_BROKER_AUTH_ENABLED", config.auth?.enabled === true ? "1" : undefined);
22
+ envFromConfig("MCP_BROKER_OPEN", config.www?.open === true ? "1" : void 0);
23
+ envFromConfig("MCP_BROKER_AUTH_ENABLED", config.auth?.enabled === true ? "1" : void 0);
86
24
  envFromConfig("MCP_BROKER_PUBLIC_BASE_URL", config.auth?.publicBaseUrl);
87
25
  envFromConfig("MCP_BROKER_JWKS", config.auth?.jwks);
88
26
  envFromConfig("MCP_BROKER_ISSUER", config.auth?.issuer);
89
27
  envFromConfig("MCP_BROKER_PROVIDER_SECRET", config.auth?.providerSecret);
90
- const stdioProvider = process.env["MCP_BROKER_STDIO_PROVIDER"];
91
- // In stdio mode stdout is reserved for JSON-RPC — redirect all console output to stderr.
28
+ var stdioProvider = process.env["MCP_BROKER_STDIO_PROVIDER"];
92
29
  if (stdioProvider) {
93
- const toStderr = (...args) => process.stderr.write(args.join(" ") + "\n");
94
- console.log = toStderr;
95
- console.info = toStderr;
96
- console.warn = toStderr;
97
- console.error = toStderr;
30
+ const toStderr = (...args) => process.stderr.write(args.join(" ") + "\n");
31
+ console.log = toStderr;
32
+ console.info = toStderr;
33
+ console.warn = toStderr;
34
+ console.error = toStderr;
98
35
  }
99
- const port = parseInt(process.env["MCP_BROKER_PORT"] ?? "3000", 10);
100
- const host = process.env["MCP_BROKER_HOST"];
101
- const providerPath = process.env["MCP_BROKER_PROVIDER_PATH"] ?? "/provider";
102
- const clientPath = process.env["MCP_BROKER_CLIENT_PATH"] ?? "/";
103
- const mcpPath = process.env["MCP_BROKER_MCP_PATH"] ?? "/mcp";
104
- const ssePath = config.paths?.sse ?? "/sse";
105
- // ── TLS material ─────────────────────────────────────────────────────────────
106
- // Env var (relative to cwd) wins over config (relative to baseDir).
107
- const tlsCertPath = process.env["MCP_BROKER_TLS_CERT"] ? path.resolve(cwd, process.env["MCP_BROKER_TLS_CERT"]) : config.tls?.cert ? path.resolve(baseDir, config.tls.cert) : null;
108
- const tlsKeyPath = process.env["MCP_BROKER_TLS_KEY"] ? path.resolve(cwd, process.env["MCP_BROKER_TLS_KEY"]) : config.tls?.key ? path.resolve(baseDir, config.tls.key) : null;
109
- const protocolOverride = process.env["MCP_BROKER_PROTOCOL"]?.toLowerCase();
110
- if (protocolOverride !== undefined && protocolOverride !== "http" && protocolOverride !== "https") {
111
- console.error(`[mcp-broker] Invalid MCP_BROKER_PROTOCOL="${protocolOverride}". Use "http" or "https".`);
112
- process.exit(1);
36
+ var port = parseInt(process.env["MCP_BROKER_PORT"] ?? "3000", 10);
37
+ var host = process.env["MCP_BROKER_HOST"];
38
+ var providerPath = process.env["MCP_BROKER_PROVIDER_PATH"] ?? "/provider";
39
+ var clientPath = process.env["MCP_BROKER_CLIENT_PATH"] ?? "/";
40
+ var mcpPath = process.env["MCP_BROKER_MCP_PATH"] ?? "/mcp";
41
+ var ssePath = config.paths?.sse ?? "/sse";
42
+ var tlsCertPath = process.env["MCP_BROKER_TLS_CERT"] ? path.resolve(cwd, process.env["MCP_BROKER_TLS_CERT"]) : config.tls?.cert ? path.resolve(baseDir, config.tls.cert) : null;
43
+ var tlsKeyPath = process.env["MCP_BROKER_TLS_KEY"] ? path.resolve(cwd, process.env["MCP_BROKER_TLS_KEY"]) : config.tls?.key ? path.resolve(baseDir, config.tls.key) : null;
44
+ var protocolOverride = process.env["MCP_BROKER_PROTOCOL"]?.toLowerCase();
45
+ if (protocolOverride !== void 0 && protocolOverride !== "http" && protocolOverride !== "https") {
46
+ console.error(`[mcp-broker] Invalid MCP_BROKER_PROTOCOL="${protocolOverride}". Use "http" or "https".`);
47
+ process.exit(1);
113
48
  }
114
49
  if (protocolOverride === "https" && (!tlsCertPath || !tlsKeyPath)) {
115
- console.error("[mcp-broker] MCP_BROKER_PROTOCOL=https requires TLS cert+key (via config.tls or MCP_BROKER_TLS_CERT/KEY).");
116
- process.exit(1);
50
+ console.error("[mcp-broker] MCP_BROKER_PROTOCOL=https requires TLS cert+key (via config.tls or MCP_BROKER_TLS_CERT/KEY).");
51
+ process.exit(1);
117
52
  }
118
- const useTls = protocolOverride === "http" ? false : protocolOverride === "https" ? true : !!(tlsCertPath && tlsKeyPath);
119
- // ── Env-var static mount shortcuts (relative to cwd) ─────────────────────────
120
- const envWwwDir = process.env["MCP_BROKER_WWW_DIR"] ? path.resolve(cwd, process.env["MCP_BROKER_WWW_DIR"]) : null;
121
- const envBundleDir = process.env["MCP_BROKER_BUNDLE_DIR"] ? path.resolve(cwd, process.env["MCP_BROKER_BUNDLE_DIR"]) : null;
122
- // ---------------------------------------------------------------------------
123
- // Server bootstrap
124
- // ---------------------------------------------------------------------------
53
+ var useTls = protocolOverride === "http" ? false : protocolOverride === "https" ? true : !!(tlsCertPath && tlsKeyPath);
54
+ var envOrigins = process.env["MCP_BROKER_ALLOWED_ORIGINS"]?.split(",").map((origin) => origin.trim()).filter(Boolean);
55
+ var allowedOrigins;
56
+ if (envOrigins?.length) {
57
+ allowedOrigins = envOrigins;
58
+ } else if (Array.isArray(config.allowedOrigins)) {
59
+ allowedOrigins = config.allowedOrigins;
60
+ } else if (config.allowedOrigins) {
61
+ try {
62
+ allowedOrigins = new RegExp(config.allowedOrigins.pattern, config.allowedOrigins.flags);
63
+ } catch (err) {
64
+ console.error(`[mcp-broker] Ignoring allowedOrigins.pattern: ${err.message}`);
65
+ }
66
+ }
67
+ var envWwwDir = process.env["MCP_BROKER_WWW_DIR"] ? path.resolve(cwd, process.env["MCP_BROKER_WWW_DIR"]) : null;
68
+ var envBundleDir = process.env["MCP_BROKER_BUNDLE_DIR"] ? path.resolve(cwd, process.env["MCP_BROKER_BUNDLE_DIR"]) : null;
125
69
  async function main() {
126
- // Local grammar overrides: when `<baseDir>/grammars/` exists, the broker
127
- // server merges those JSON files on top of the packaged grammars.
128
- const localGrammarsDir = path.join(baseDir, "grammars");
129
- const hasLocalGrammars = fs.existsSync(localGrammarsDir);
130
- const builder = new WsTunnelBuilder().withPort(port).withProviderPath(providerPath).withClientPath(clientPath).withMcpPath(mcpPath);
131
- if (host) {
132
- builder.withHost(host);
133
- }
134
- if (useTls) {
135
- builder.withTlsFiles(tlsCertPath, tlsKeyPath);
136
- }
137
- // ── Static mounts ────────────────────────────────────────────────────────
138
- // First the env-var shortcuts (relative to cwd), then the config `www.mounts`
139
- // (relative to baseDir). Order matters: /bundle before / so the prefix router
140
- // can distinguish them. Subsequent registrations contribute additional mounts;
141
- // longest-prefix match wins at runtime.
142
- if (envBundleDir && fs.existsSync(envBundleDir)) {
143
- builder.withStaticMount("/bundle", envBundleDir);
144
- }
145
- if (envWwwDir && fs.existsSync(envWwwDir)) {
146
- builder.withStaticMount("/", envWwwDir);
147
- }
148
- if (config.www?.mounts) {
149
- for (const mount of config.www.mounts) {
150
- const abs = path.resolve(baseDir, mount.dir);
151
- if (fs.existsSync(abs)) {
152
- builder.withStaticMount(mount.urlPrefix, abs);
153
- }
154
- else {
155
- console.warn(`[mcp-broker] www.mounts entry "${mount.urlPrefix}" → ${abs} skipped (directory not found).`);
156
- }
157
- }
158
- }
159
- // ── Stdio upstreams ──────────────────────────────────────────────────────
160
- if (config.stdioUpstreams) {
161
- for (const u of config.stdioUpstreams) {
162
- builder.withStdioUpstream({
163
- name: u.name,
164
- command: u.command,
165
- args: u.args,
166
- env: u.env,
167
- aggregate: u.aggregate,
168
- });
169
- }
70
+ const localGrammarsDir = path.join(baseDir, "grammars");
71
+ const hasLocalGrammars = fs.existsSync(localGrammarsDir);
72
+ const builder = new WsTunnelBuilder().withPort(port).withProviderPath(providerPath).withClientPath(clientPath).withMcpPath(mcpPath);
73
+ if (host) {
74
+ builder.withHost(host);
75
+ }
76
+ if (useTls) {
77
+ builder.withTlsFiles(tlsCertPath, tlsKeyPath);
78
+ }
79
+ if (allowedOrigins) {
80
+ builder.withAllowedOrigins(allowedOrigins);
81
+ }
82
+ if (envBundleDir && fs.existsSync(envBundleDir)) {
83
+ builder.withStaticMount("/bundle", envBundleDir);
84
+ }
85
+ if (envWwwDir && fs.existsSync(envWwwDir)) {
86
+ builder.withStaticMount("/", envWwwDir);
87
+ }
88
+ if (config.www?.mounts) {
89
+ for (const mount of config.www.mounts) {
90
+ const abs = path.resolve(baseDir, mount.dir);
91
+ if (fs.existsSync(abs)) {
92
+ builder.withStaticMount(mount.urlPrefix, abs);
93
+ } else {
94
+ console.warn(`[mcp-broker] www.mounts entry "${mount.urlPrefix}" \u2192 ${abs} skipped (directory not found).`);
95
+ }
170
96
  }
171
- // ── Remote MCP server upstreams (reached by URL) ─────────────────────────
172
- // Config-discovered remote servers join the `_all` aggregate by default;
173
- // an explicit `aggregate: false` opts an entry out.
174
- if (config.mcpServers) {
175
- for (const s of config.mcpServers) {
176
- builder.withRemoteUpstream({ ...s, aggregate: s.aggregate ?? true });
177
- }
97
+ }
98
+ if (config.stdioUpstreams) {
99
+ for (const u of config.stdioUpstreams) {
100
+ builder.withStdioUpstream({
101
+ name: u.name,
102
+ command: u.command,
103
+ args: u.args,
104
+ env: u.env,
105
+ aggregate: u.aggregate
106
+ });
178
107
  }
179
- // ── Local `.mcpb` bundles ────────────────────────────────────────────────
180
- // Each bundle is signature-verified and unpacked before it is wired in as a
181
- // stdio upstream. A refused bundle is skipped (loadMcpbBundle logs why); it
182
- // never spawns a process. Bundles join `_all` by default (opt-out per entry).
183
- if (config.mcpbBundles) {
184
- for (const b of config.mcpbBundles) {
185
- const upstream = await loadMcpbBundle(b, baseDir);
186
- if (upstream) {
187
- builder.withStdioUpstream(upstream);
188
- }
189
- }
108
+ }
109
+ if (config.mcpServers) {
110
+ for (const s of config.mcpServers) {
111
+ builder.withRemoteUpstream({ ...s, aggregate: s.aggregate ?? true });
190
112
  }
191
- if (stdioProvider) {
192
- builder.withStdioClient(stdioProvider);
113
+ }
114
+ if (config.mcpbBundles) {
115
+ for (const b of config.mcpbBundles) {
116
+ const upstream = await loadMcpbBundle(b, baseDir);
117
+ if (upstream) {
118
+ builder.withStdioUpstream(upstream);
119
+ }
193
120
  }
194
- if (hasLocalGrammars) {
195
- builder.withBrokerLocalGrammarsDir(localGrammarsDir);
121
+ }
122
+ if (stdioProvider) {
123
+ builder.withStdioClient(stdioProvider);
124
+ }
125
+ if (hasLocalGrammars) {
126
+ builder.withBrokerLocalGrammarsDir(localGrammarsDir);
127
+ }
128
+ const authEnabledEnv = process.env["MCP_BROKER_AUTH_ENABLED"];
129
+ const authEnabled = authEnabledEnv === "1" || authEnabledEnv === "true";
130
+ if (authEnabled) {
131
+ const publicBaseUrl = process.env["MCP_BROKER_PUBLIC_BASE_URL"];
132
+ const jwks = process.env["MCP_BROKER_JWKS"];
133
+ const issuer = process.env["MCP_BROKER_ISSUER"];
134
+ const authorizationServers = config.auth?.authorizationServers ?? (issuer ? [issuer] : []);
135
+ if (!publicBaseUrl || !jwks || authorizationServers.length === 0) {
136
+ console.error(
137
+ "[mcp-broker] auth.enabled requires publicBaseUrl, jwks, and at least one authorizationServers entry (or issuer). Set them via config.auth or MCP_BROKER_PUBLIC_BASE_URL / MCP_BROKER_JWKS / MCP_BROKER_ISSUER."
138
+ );
139
+ process.exit(1);
196
140
  }
197
- // ── Authorization (OAuth 2.1 resource server) ────────────────────────────
198
- // Opt-in: only wired when MCP_BROKER_AUTH_ENABLED / config.auth.enabled is on.
199
- // Env scalars win over config; array/object fields are read from config.
200
- const authEnabledEnv = process.env["MCP_BROKER_AUTH_ENABLED"];
201
- const authEnabled = authEnabledEnv === "1" || authEnabledEnv === "true";
202
- if (authEnabled) {
203
- const publicBaseUrl = process.env["MCP_BROKER_PUBLIC_BASE_URL"];
204
- const jwks = process.env["MCP_BROKER_JWKS"];
205
- const issuer = process.env["MCP_BROKER_ISSUER"];
206
- const authorizationServers = config.auth?.authorizationServers ?? (issuer ? [issuer] : []);
207
- if (!publicBaseUrl || !jwks || authorizationServers.length === 0) {
208
- console.error("[mcp-broker] auth.enabled requires publicBaseUrl, jwks, and at least one " +
209
- "authorizationServers entry (or issuer). Set them via config.auth or " +
210
- "MCP_BROKER_PUBLIC_BASE_URL / MCP_BROKER_JWKS / MCP_BROKER_ISSUER.");
211
- process.exit(1);
212
- }
213
- builder.withJwtAuth({
214
- publicBaseUrl,
215
- authorizationServers,
216
- jwksUri: jwks,
217
- issuer,
218
- scopesSupported: config.auth?.scopesSupported,
219
- requiredScopes: config.auth?.requiredScopes,
220
- perSlotScopes: config.auth?.perSlotScopes,
221
- providerScopes: config.auth?.providerScopes,
222
- subjectMapping: config.auth?.subjectMapping,
223
- roles: config.auth?.roles,
224
- assignments: config.auth?.assignments,
225
- denies: config.auth?.denies,
226
- slotResources: config.auth?.slotResources,
227
- toolCapabilities: config.auth?.toolCapabilities,
228
- providerToolCapabilities: config.auth?.providerToolCapabilities,
229
- audit: config.auth?.audit,
230
- });
231
- }
232
- // ── Provider authentication (independent of client OAuth) ────────────────
233
- // Requires every provider connecting to /provider/<slot> or /providers to
234
- // present the shared secret — closes off slot occupation by strangers.
235
- const providerSecret = process.env["MCP_BROKER_PROVIDER_SECRET"];
236
- if (providerSecret) {
237
- builder.withProviderSecret(providerSecret);
238
- }
239
- const tunnel = builder.build();
240
- await tunnel.start();
241
- // ── Startup banner ──────────────────────────────────────────────────────
242
- const httpScheme = useTls ? "https" : "http";
243
- const wsScheme = useTls ? "wss" : "ws";
244
- const hr = "─".repeat(64);
245
- const localhost = `${httpScheme}://localhost:${port}`;
246
- const mcpSuffix = mcpPath.replace(/^\//, "");
247
- const sseSuffix = ssePath.replace(/^\//, "");
248
- const hasWwwRoot = !!(envWwwDir && fs.existsSync(envWwwDir)) || (config.www?.mounts ?? []).some((m) => m.urlPrefix === "/");
141
+ builder.withJwtAuth({
142
+ publicBaseUrl,
143
+ authorizationServers,
144
+ jwksUri: jwks,
145
+ issuer,
146
+ scopesSupported: config.auth?.scopesSupported,
147
+ requiredScopes: config.auth?.requiredScopes,
148
+ perSlotScopes: config.auth?.perSlotScopes,
149
+ providerScopes: config.auth?.providerScopes,
150
+ subjectMapping: config.auth?.subjectMapping,
151
+ roles: config.auth?.roles,
152
+ assignments: config.auth?.assignments,
153
+ denies: config.auth?.denies,
154
+ slotResources: config.auth?.slotResources,
155
+ toolCapabilities: config.auth?.toolCapabilities,
156
+ providerToolCapabilities: config.auth?.providerToolCapabilities,
157
+ audit: config.auth?.audit
158
+ });
159
+ }
160
+ const providerSecret = process.env["MCP_BROKER_PROVIDER_SECRET"];
161
+ if (providerSecret) {
162
+ builder.withProviderSecret(providerSecret);
163
+ }
164
+ const tunnel = builder.build();
165
+ await tunnel.start();
166
+ const httpScheme = useTls ? "https" : "http";
167
+ const wsScheme = useTls ? "wss" : "ws";
168
+ const hr = "\u2500".repeat(64);
169
+ const localhost = `${httpScheme}://localhost:${port}`;
170
+ const mcpSuffix = mcpPath.replace(/^\//, "");
171
+ const sseSuffix = ssePath.replace(/^\//, "");
172
+ const hasWwwRoot = !!(envWwwDir && fs.existsSync(envWwwDir)) || (config.www?.mounts ?? []).some((m) => m.urlPrefix === "/");
173
+ console.log();
174
+ console.log(`\u2699\uFE0F mcp-broker started${useTls ? " (TLS)" : ""}`);
175
+ console.log(hr);
176
+ console.log(`\u{1F4E1} Provider WebSocket ${wsScheme}://localhost:${port}${providerPath}/<name>`);
177
+ console.log(`\u{1F50C} MCP (Streamable HTTP) ${localhost}/<name>/${mcpSuffix}`);
178
+ console.log(`\u{1F4FA} Legacy SSE ${localhost}/<name>/${sseSuffix}`);
179
+ if (hasLocalGrammars) {
180
+ console.log(`\u{1F310} Local grammars ${localGrammarsDir}`);
181
+ }
182
+ console.log(`\u{1F510} Authorization ${authEnabled ? "OAuth 2.1 (Bearer required)" : "disabled (trusted network only)"}`);
183
+ console.log(`\u{1F6E1}\uFE0F Provider auth ${providerSecret ? "shared secret required" : "disabled"}`);
184
+ console.log(hr);
185
+ console.log(` Press Ctrl+C to stop.`);
186
+ console.log();
187
+ if (hasWwwRoot && process.env["MCP_BROKER_OPEN"] === "1") {
188
+ const url = `${localhost}/`;
189
+ console.log(`\u{1F680} Opening browser: ${url}`);
249
190
  console.log();
250
- console.log(`⚙️ mcp-broker started${useTls ? " (TLS)" : ""}`);
251
- console.log(hr);
252
- console.log(`📡 Provider WebSocket ${wsScheme}://localhost:${port}${providerPath}/<name>`);
253
- console.log(`🔌 MCP (Streamable HTTP) ${localhost}/<name>/${mcpSuffix}`);
254
- console.log(`📺 Legacy SSE ${localhost}/<name>/${sseSuffix}`);
255
- if (hasLocalGrammars) {
256
- console.log(`🌐 Local grammars ${localGrammarsDir}`);
257
- }
258
- console.log(`🔐 Authorization ${authEnabled ? "OAuth 2.1 (Bearer required)" : "disabled (trusted network only)"}`);
259
- console.log(`🛡️ Provider auth ${providerSecret ? "shared secret required" : "disabled"}`);
260
- console.log(hr);
261
- console.log(` Press Ctrl+C to stop.`);
262
- console.log();
263
- // Auto-launch browser only if explicitly opted in via MCP_BROKER_OPEN=1
264
- // AND a mount at "/" is configured.
265
- if (hasWwwRoot && process.env["MCP_BROKER_OPEN"] === "1") {
266
- const url = `${localhost}/`;
267
- console.log(`🚀 Opening browser: ${url}`);
268
- console.log();
269
- await open(url);
270
- }
271
- // ── Signal handlers ─────────────────────────────────────────────────────
272
- const shutdown = async (signal) => {
273
- console.log(`\n⛔ ${signal} received — shutting down…`);
274
- await tunnel.stop();
275
- process.exit(0);
276
- };
277
- process.on("SIGINT", () => void shutdown("SIGINT"));
278
- process.on("SIGTERM", () => void shutdown("SIGTERM"));
191
+ await open(url);
192
+ }
193
+ const shutdown = async (signal) => {
194
+ console.log(`
195
+ \u26D4 ${signal} received, shutting down\u2026`);
196
+ await tunnel.stop();
197
+ process.exit(0);
198
+ };
199
+ process.on("SIGINT", () => void shutdown("SIGINT"));
200
+ process.on("SIGTERM", () => void shutdown("SIGTERM"));
279
201
  }
280
202
  main().catch((err) => {
281
- console.error("[mcp-broker] Fatal error:", err);
282
- process.exit(1);
203
+ console.error("[mcp-broker] Fatal error:", err);
204
+ process.exit(1);
283
205
  });
206
+ //# sourceMappingURL=bin.js.map
284
207
  //# sourceMappingURL=bin.js.map
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"sources":["../src/bin.ts"],"names":[],"mappings":"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","file":"bin.js","sourcesContent":["#!/usr/bin/env node\n/**\n * Standalone entry-point that starts the mcp-broker WebSocket server.\n *\n * ## Configuration sources (highest priority first)\n *\n * 1. Environment variables (`MCP_BROKER_*`).\n * 2. JSON config file. Resolved in order:\n * a. `MCP_BROKER_CONFIG` env var.\n * b. `./.mcp-broker/config.json` in the current working directory.\n * c. `./mcp-broker.config.json` (legacy, with a deprecation warning).\n * 3. Built-in defaults.\n *\n * ## Path resolution\n *\n * - Env-var paths (`MCP_BROKER_*_DIR`, `MCP_BROKER_TLS_*`) are resolved\n * against `process.cwd()`.\n * - Config-file paths (`tls.cert`, `www.mounts[*].dir`, `stdioUpstreams[*]`,\n * `mcpbBundles[*]`) are resolved against the **config file's directory**: so a config in\n * `./.mcp-broker/config.json` referring to `\"certs/cert.pem\"` points at\n * `./.mcp-broker/certs/cert.pem`. The folder is self-contained.\n *\n * ## Local grammar overrides\n *\n * When `.mcp-broker/grammars/<userAgent>/<locale>.json` files exist next to\n * the config file, they are merged **on top of** the packaged grammars. Lets\n * users customize tool/resource descriptions for their organization without\n * forking the package.\n *\n * ## Environment variables\n *\n * | Variable | Default | Notes |\n * |--------------------------------|----------|--------------------------------------------------------|\n * | MCP_BROKER_CONFIG | (none) | Path to a JSON config file (see above). |\n * | MCP_BROKER_PORT | 3000 | |\n * | MCP_BROKER_HOST | 0.0.0.0 | |\n * | MCP_BROKER_PROVIDER_PATH | /provider| Prefix for provider WS |\n * | MCP_BROKER_CLIENT_PATH | / | Prefix for raw WS clients |\n * | MCP_BROKER_MCP_PATH | /mcp | Suffix for Streamable HTTP transport |\n * | MCP_BROKER_WWW_DIR | (none) | Ergonomic shortcut: mount this directory at \"/\" |\n * | MCP_BROKER_BUNDLE_DIR | (none) | Ergonomic shortcut: mount this directory at \"/bundle\" |\n * | MCP_BROKER_OPEN | (unset) | \"1\" to auto-launch the default browser at the root URL |\n * | MCP_BROKER_TLS_CERT | (none) | Path to a PEM TLS certificate |\n * | MCP_BROKER_TLS_KEY | (none) | Path to a PEM private key |\n * | MCP_BROKER_PROTOCOL | auto | \"http\" to force plain, \"https\" to force TLS, otherwise |\n * | | | TLS is enabled iff cert+key are both set |\n * | MCP_BROKER_STDIO_PROVIDER | (none) | When set, stdin/stdout carry JSON-RPC for the named |\n * | | | provider (Claude Desktop bridge). |\n * | MCP_BROKER_LOCALE | en | Locale used for tool descriptions on the `_broker` |\n * | | | slot. ISO 639-1 base; regional variants accepted. |\n * | MCP_BROKER_ALLOWED_ORIGINS | (none) | Comma-separated browser origins allowed on |\n * | | | `/<slot>/mcp`. None means no browser origin passes. |\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport open from \"open\";\nimport { WsTunnelBuilder } from \"./index\";\nimport { loadBrokerConfig } from \"./config\";\nimport { loadMcpbBundle } from \"./mcpb/mcpb.loader\";\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\nconst { config, baseDir } = loadBrokerConfig();\nconst cwd = process.cwd();\n\n/**\n * Fills an env var from the config file when the env var is not already set.\n * Used for **non-path** scalars, path-bearing fields are read directly so\n * they can be resolved against `baseDir` (config file's directory) instead\n * of `cwd` (deploy environment).\n */\nfunction envFromConfig(envName: string, configValue: string | number | boolean | undefined): void {\n if (configValue === undefined || configValue === null) return;\n if (process.env[envName] !== undefined && process.env[envName] !== \"\") return;\n process.env[envName] = String(configValue);\n}\n\nenvFromConfig(\"MCP_BROKER_PORT\", config.port);\nenvFromConfig(\"MCP_BROKER_HOST\", config.host);\nenvFromConfig(\"MCP_BROKER_PROTOCOL\", config.protocol);\nenvFromConfig(\"MCP_BROKER_LOCALE\", config.locale);\nenvFromConfig(\"MCP_BROKER_STDIO_PROVIDER\", config.stdioProvider);\nenvFromConfig(\"MCP_BROKER_PROVIDER_PATH\", config.paths?.provider);\nenvFromConfig(\"MCP_BROKER_CLIENT_PATH\", config.paths?.client);\nenvFromConfig(\"MCP_BROKER_MCP_PATH\", config.paths?.mcp);\nenvFromConfig(\"MCP_BROKER_OPEN\", config.www?.open === true ? \"1\" : undefined);\nenvFromConfig(\"MCP_BROKER_AUTH_ENABLED\", config.auth?.enabled === true ? \"1\" : undefined);\nenvFromConfig(\"MCP_BROKER_PUBLIC_BASE_URL\", config.auth?.publicBaseUrl);\nenvFromConfig(\"MCP_BROKER_JWKS\", config.auth?.jwks);\nenvFromConfig(\"MCP_BROKER_ISSUER\", config.auth?.issuer);\nenvFromConfig(\"MCP_BROKER_PROVIDER_SECRET\", config.auth?.providerSecret);\n\nconst stdioProvider = process.env[\"MCP_BROKER_STDIO_PROVIDER\"];\n\n// In stdio mode stdout is reserved for JSON-RPC, redirect all console output to stderr.\nif (stdioProvider) {\n const toStderr = (...args: unknown[]) => process.stderr.write(args.join(\" \") + \"\\n\");\n console.log = toStderr;\n console.info = toStderr;\n console.warn = toStderr;\n console.error = toStderr;\n}\n\nconst port = parseInt(process.env[\"MCP_BROKER_PORT\"] ?? \"3000\", 10);\nconst host = process.env[\"MCP_BROKER_HOST\"];\nconst providerPath = process.env[\"MCP_BROKER_PROVIDER_PATH\"] ?? \"/provider\";\nconst clientPath = process.env[\"MCP_BROKER_CLIENT_PATH\"] ?? \"/\";\nconst mcpPath = process.env[\"MCP_BROKER_MCP_PATH\"] ?? \"/mcp\";\nconst ssePath = config.paths?.sse ?? \"/sse\";\n\n// ── TLS material ─────────────────────────────────────────────────────────────\n// Env var (relative to cwd) wins over config (relative to baseDir).\nconst tlsCertPath = process.env[\"MCP_BROKER_TLS_CERT\"] ? path.resolve(cwd, process.env[\"MCP_BROKER_TLS_CERT\"]) : config.tls?.cert ? path.resolve(baseDir, config.tls.cert) : null;\nconst tlsKeyPath = process.env[\"MCP_BROKER_TLS_KEY\"] ? path.resolve(cwd, process.env[\"MCP_BROKER_TLS_KEY\"]) : config.tls?.key ? path.resolve(baseDir, config.tls.key) : null;\n\nconst protocolOverride = process.env[\"MCP_BROKER_PROTOCOL\"]?.toLowerCase();\nif (protocolOverride !== undefined && protocolOverride !== \"http\" && protocolOverride !== \"https\") {\n console.error(`[mcp-broker] Invalid MCP_BROKER_PROTOCOL=\"${protocolOverride}\". Use \"http\" or \"https\".`);\n process.exit(1);\n}\nif (protocolOverride === \"https\" && (!tlsCertPath || !tlsKeyPath)) {\n console.error(\"[mcp-broker] MCP_BROKER_PROTOCOL=https requires TLS cert+key (via config.tls or MCP_BROKER_TLS_CERT/KEY).\");\n process.exit(1);\n}\n\nconst useTls = protocolOverride === \"http\" ? false : protocolOverride === \"https\" ? true : !!(tlsCertPath && tlsKeyPath);\n\n// ── Allowed browser origins for /<slot>/mcp ──────────────────────────────────\n// Absent leaves the endpoint closed to browsers, which is the safe default.\n// The env var only carries the list form; a pattern needs the config file,\n// since a regular expression cannot survive comma-splitting.\nconst envOrigins = process.env[\"MCP_BROKER_ALLOWED_ORIGINS\"]\n ?.split(\",\")\n .map((origin) => origin.trim())\n .filter(Boolean);\n\nlet allowedOrigins: readonly string[] | RegExp | undefined;\nif (envOrigins?.length) {\n allowedOrigins = envOrigins;\n} else if (Array.isArray(config.allowedOrigins)) {\n allowedOrigins = config.allowedOrigins;\n} else if (config.allowedOrigins) {\n try {\n allowedOrigins = new RegExp(config.allowedOrigins.pattern, config.allowedOrigins.flags);\n } catch (err) {\n // Falling back to the closed default rather than starting with a rule\n // the operator believes is in force but which never compiled.\n console.error(`[mcp-broker] Ignoring allowedOrigins.pattern: ${(err as Error).message}`);\n }\n}\n\n// ── Env-var static mount shortcuts (relative to cwd) ─────────────────────────\nconst envWwwDir = process.env[\"MCP_BROKER_WWW_DIR\"] ? path.resolve(cwd, process.env[\"MCP_BROKER_WWW_DIR\"]) : null;\nconst envBundleDir = process.env[\"MCP_BROKER_BUNDLE_DIR\"] ? path.resolve(cwd, process.env[\"MCP_BROKER_BUNDLE_DIR\"]) : null;\n\n// ---------------------------------------------------------------------------\n// Server bootstrap\n// ---------------------------------------------------------------------------\n\nasync function main(): Promise<void> {\n // Local grammar overrides: when `<baseDir>/grammars/` exists, the broker\n // server merges those JSON files on top of the packaged grammars.\n const localGrammarsDir = path.join(baseDir, \"grammars\");\n const hasLocalGrammars = fs.existsSync(localGrammarsDir);\n\n const builder = new WsTunnelBuilder().withPort(port).withProviderPath(providerPath).withClientPath(clientPath).withMcpPath(mcpPath);\n\n if (host) {\n builder.withHost(host);\n }\n\n if (useTls) {\n builder.withTlsFiles(tlsCertPath!, tlsKeyPath!);\n }\n\n if (allowedOrigins) {\n builder.withAllowedOrigins(allowedOrigins);\n }\n\n // ── Static mounts ────────────────────────────────────────────────────────\n // First the env-var shortcuts (relative to cwd), then the config `www.mounts`\n // (relative to baseDir). Order matters: /bundle before / so the prefix router\n // can distinguish them. Subsequent registrations contribute additional mounts;\n // longest-prefix match wins at runtime.\n if (envBundleDir && fs.existsSync(envBundleDir)) {\n builder.withStaticMount(\"/bundle\", envBundleDir);\n }\n if (envWwwDir && fs.existsSync(envWwwDir)) {\n builder.withStaticMount(\"/\", envWwwDir);\n }\n if (config.www?.mounts) {\n for (const mount of config.www.mounts) {\n const abs = path.resolve(baseDir, mount.dir);\n if (fs.existsSync(abs)) {\n builder.withStaticMount(mount.urlPrefix, abs);\n } else {\n console.warn(`[mcp-broker] www.mounts entry \"${mount.urlPrefix}\" → ${abs} skipped (directory not found).`);\n }\n }\n }\n\n // ── Stdio upstreams ──────────────────────────────────────────────────────\n if (config.stdioUpstreams) {\n for (const u of config.stdioUpstreams) {\n builder.withStdioUpstream({\n name: u.name,\n command: u.command,\n args: u.args,\n env: u.env as NodeJS.ProcessEnv | undefined,\n aggregate: u.aggregate,\n });\n }\n }\n\n // ── Remote MCP server upstreams (reached by URL) ─────────────────────────\n // Config-discovered remote servers join the `_all` aggregate by default;\n // an explicit `aggregate: false` opts an entry out.\n if (config.mcpServers) {\n for (const s of config.mcpServers) {\n builder.withRemoteUpstream({ ...s, aggregate: s.aggregate ?? true });\n }\n }\n\n // ── Local `.mcpb` bundles ────────────────────────────────────────────────\n // Each bundle is signature-verified and unpacked before it is wired in as a\n // stdio upstream. A refused bundle is skipped (loadMcpbBundle logs why); it\n // never spawns a process. Bundles join `_all` by default (opt-out per entry).\n if (config.mcpbBundles) {\n for (const b of config.mcpbBundles) {\n const upstream = await loadMcpbBundle(b, baseDir);\n if (upstream) {\n builder.withStdioUpstream(upstream);\n }\n }\n }\n\n if (stdioProvider) {\n builder.withStdioClient(stdioProvider);\n }\n\n if (hasLocalGrammars) {\n builder.withBrokerLocalGrammarsDir(localGrammarsDir);\n }\n\n // ── Authorization (OAuth 2.1 resource server) ────────────────────────────\n // Opt-in: only wired when MCP_BROKER_AUTH_ENABLED / config.auth.enabled is on.\n // Env scalars win over config; array/object fields are read from config.\n const authEnabledEnv = process.env[\"MCP_BROKER_AUTH_ENABLED\"];\n const authEnabled = authEnabledEnv === \"1\" || authEnabledEnv === \"true\";\n if (authEnabled) {\n const publicBaseUrl = process.env[\"MCP_BROKER_PUBLIC_BASE_URL\"];\n const jwks = process.env[\"MCP_BROKER_JWKS\"];\n const issuer = process.env[\"MCP_BROKER_ISSUER\"];\n const authorizationServers = config.auth?.authorizationServers ?? (issuer ? [issuer] : []);\n if (!publicBaseUrl || !jwks || authorizationServers.length === 0) {\n console.error(\n \"[mcp-broker] auth.enabled requires publicBaseUrl, jwks, and at least one \" +\n \"authorizationServers entry (or issuer). Set them via config.auth or \" +\n \"MCP_BROKER_PUBLIC_BASE_URL / MCP_BROKER_JWKS / MCP_BROKER_ISSUER.\"\n );\n process.exit(1);\n }\n builder.withJwtAuth({\n publicBaseUrl,\n authorizationServers,\n jwksUri: jwks,\n issuer,\n scopesSupported: config.auth?.scopesSupported,\n requiredScopes: config.auth?.requiredScopes,\n perSlotScopes: config.auth?.perSlotScopes,\n providerScopes: config.auth?.providerScopes,\n subjectMapping: config.auth?.subjectMapping,\n roles: config.auth?.roles,\n assignments: config.auth?.assignments,\n denies: config.auth?.denies,\n slotResources: config.auth?.slotResources,\n toolCapabilities: config.auth?.toolCapabilities,\n providerToolCapabilities: config.auth?.providerToolCapabilities,\n audit: config.auth?.audit,\n });\n }\n\n // ── Provider authentication (independent of client OAuth) ────────────────\n // Requires every provider connecting to /provider/<slot> or /providers to\n // present the shared secret, closes off slot occupation by strangers.\n const providerSecret = process.env[\"MCP_BROKER_PROVIDER_SECRET\"];\n if (providerSecret) {\n builder.withProviderSecret(providerSecret);\n }\n\n const tunnel = builder.build();\n await tunnel.start();\n\n // ── Startup banner ──────────────────────────────────────────────────────\n const httpScheme = useTls ? \"https\" : \"http\";\n const wsScheme = useTls ? \"wss\" : \"ws\";\n const hr = \"─\".repeat(64);\n const localhost = `${httpScheme}://localhost:${port}`;\n const mcpSuffix = mcpPath.replace(/^\\//, \"\");\n const sseSuffix = ssePath.replace(/^\\//, \"\");\n const hasWwwRoot = !!(envWwwDir && fs.existsSync(envWwwDir)) || (config.www?.mounts ?? []).some((m) => m.urlPrefix === \"/\");\n\n console.log();\n console.log(`⚙️ mcp-broker started${useTls ? \" (TLS)\" : \"\"}`);\n console.log(hr);\n console.log(`📡 Provider WebSocket ${wsScheme}://localhost:${port}${providerPath}/<name>`);\n console.log(`🔌 MCP (Streamable HTTP) ${localhost}/<name>/${mcpSuffix}`);\n console.log(`📺 Legacy SSE ${localhost}/<name>/${sseSuffix}`);\n if (hasLocalGrammars) {\n console.log(`🌐 Local grammars ${localGrammarsDir}`);\n }\n console.log(`🔐 Authorization ${authEnabled ? \"OAuth 2.1 (Bearer required)\" : \"disabled (trusted network only)\"}`);\n console.log(`🛡️ Provider auth ${providerSecret ? \"shared secret required\" : \"disabled\"}`);\n console.log(hr);\n console.log(` Press Ctrl+C to stop.`);\n console.log();\n\n // Auto-launch browser only if explicitly opted in via MCP_BROKER_OPEN=1\n // AND a mount at \"/\" is configured.\n if (hasWwwRoot && process.env[\"MCP_BROKER_OPEN\"] === \"1\") {\n const url = `${localhost}/`;\n console.log(`🚀 Opening browser: ${url}`);\n console.log();\n await open(url);\n }\n\n // ── Signal handlers ─────────────────────────────────────────────────────\n const shutdown = async (signal: string): Promise<void> => {\n console.log(`\\n⛔ ${signal} received, shutting down…`);\n await tunnel.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"));\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"));\n}\n\nmain().catch((err: unknown) => {\n console.error(\"[mcp-broker] Fatal error:\", err);\n process.exit(1);\n});\n"]}