@cyanmycelium/mcp-broker 0.4.0 → 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 (151) hide show
  1. package/.mcp-broker.example/CONFIGURATION-EN.md +861 -0
  2. package/.mcp-broker.example/CONFIGURATION-FR.md +871 -0
  3. package/.mcp-broker.example/README.md +8 -3
  4. package/.mcp-broker.example/config.json +86 -0
  5. package/README.md +122 -3
  6. package/dist/bin.d.ts +0 -1
  7. package/dist/bin.js +180 -208
  8. package/dist/bin.js.map +1 -1
  9. package/dist/chunk-FTDKH2C4.js +3670 -0
  10. package/dist/chunk-FTDKH2C4.js.map +1 -0
  11. package/dist/{broker/grammars → grammars}/claude/en.json +1 -1
  12. package/dist/{broker/grammars → grammars}/claude/fr.json +1 -1
  13. package/dist/index.d.ts +1790 -18
  14. package/dist/index.js +2 -14
  15. package/dist/index.js.map +1 -1
  16. package/package.json +14 -8
  17. package/scripts/copy-assets.mjs +16 -10
  18. package/scripts/gen-cert.mjs +5 -5
  19. package/scripts/pack-mcpb.mjs +5 -5
  20. package/scripts/sign-bundle.mjs +6 -6
  21. package/src/auth/auth.config.ts +98 -0
  22. package/src/auth/auth.types.ts +120 -0
  23. package/src/auth/http.auth.ts +128 -0
  24. package/src/auth/index.ts +34 -0
  25. package/src/auth/jwt.validator.ts +63 -0
  26. package/src/auth/provider.auth.ts +114 -0
  27. package/src/auth/resource.metadata.ts +34 -0
  28. package/src/authorization/audit.ts +35 -0
  29. package/src/authorization/capability.classifier.ts +114 -0
  30. package/src/authorization/index.ts +37 -0
  31. package/src/authorization/policy.engine.ts +212 -0
  32. package/src/authorization/policy.types.ts +105 -0
  33. package/src/authorization/resource.path.ts +126 -0
  34. package/src/authorization/runtime.ts +56 -0
  35. package/src/authorization/slot.resource.ts +50 -0
  36. package/src/authorization/subject.mapper.ts +81 -0
  37. package/src/bin.ts +90 -7
  38. package/src/broker/adapters/broker.adapter.info.ts +3 -3
  39. package/src/broker/adapters/broker.adapter.providers.ts +3 -3
  40. package/src/broker/aggregate/aggregate.catalog.ts +49 -21
  41. package/src/broker/aggregate/aggregate.server.ts +149 -19
  42. package/src/broker/aggregate/provider.client.session.ts +22 -22
  43. package/src/broker/behaviors/broker.behavior.info.ts +4 -4
  44. package/src/broker/behaviors/broker.behavior.providers.ts +6 -6
  45. package/src/broker/broker.context.ts +10 -4
  46. package/src/broker/broker.grammars.ts +16 -13
  47. package/src/broker/broker.server.ts +12 -9
  48. package/src/broker/grammars/claude/en.json +1 -1
  49. package/src/broker/grammars/claude/fr.json +1 -1
  50. package/src/broker/index.ts +9 -9
  51. package/src/config.ts +81 -8
  52. package/src/index.ts +121 -20
  53. package/src/{mcpb.loader.ts → mcpb/mcpb.loader.ts} +24 -21
  54. package/src/{mcpb.unzip.ts → mcpb/mcpb.unzip.ts} +2 -2
  55. package/src/remote.transports.ts +11 -8
  56. package/src/remote.upstream.ts +11 -8
  57. package/src/stdio.upstream.ts +9 -6
  58. package/src/upstream.ts +6 -3
  59. package/src/ws/ws.interfaces.ts +357 -0
  60. package/src/{ws.tunnel.builder.ts → ws/ws.tunnel.builder.ts} +112 -9
  61. package/src/{ws.tunnel.ts → ws/ws.tunnel.ts} +646 -457
  62. package/web/README.md +94 -0
  63. package/web/assets/logo.png +0 -0
  64. package/web/broker-self-mcp.html +338 -0
  65. package/web/css/styles.css +580 -0
  66. package/web/demos/DemoPlaceholder.html +258 -0
  67. package/web/demos/broker-explorer/css/app.css +393 -0
  68. package/web/demos/broker-explorer/index.html +94 -0
  69. package/web/demos/broker-explorer/js/app.js +271 -0
  70. package/web/demos/broker-explorer/js/mcp-ws-client.js +132 -0
  71. package/web/demos/oauth-lab/README.md +94 -0
  72. package/web/demos/oauth-lab/config.json +117 -0
  73. package/web/demos/oauth-lab/css/app.css +1097 -0
  74. package/web/demos/oauth-lab/index.html +323 -0
  75. package/web/demos/oauth-lab/js/app.js +654 -0
  76. package/web/demos/oauth-lab/server/auth-server.mjs +426 -0
  77. package/web/demos/oauth-lab/server/factory-provider.mjs +269 -0
  78. package/web/demos/oauth-lab/server/smoke-test.mjs +308 -0
  79. package/web/demos/oauth-lab/server/start.mjs +106 -0
  80. package/web/demos/provider-tunnel/css/app.css +384 -0
  81. package/web/demos/provider-tunnel/index.html +99 -0
  82. package/web/demos/provider-tunnel/js/app.js +226 -0
  83. package/web/demos/provider-tunnel/js/toolbox-server.js +186 -0
  84. package/web/index.html +558 -0
  85. package/web/js/lib/broker-tunnel.js +173 -0
  86. package/dist/broker/adapters/broker.adapter.info.d.ts +0 -16
  87. package/dist/broker/adapters/broker.adapter.info.js +0 -43
  88. package/dist/broker/adapters/broker.adapter.info.js.map +0 -1
  89. package/dist/broker/adapters/broker.adapter.providers.d.ts +0 -18
  90. package/dist/broker/adapters/broker.adapter.providers.js +0 -61
  91. package/dist/broker/adapters/broker.adapter.providers.js.map +0 -1
  92. package/dist/broker/aggregate/aggregate.catalog.d.ts +0 -54
  93. package/dist/broker/aggregate/aggregate.catalog.js +0 -105
  94. package/dist/broker/aggregate/aggregate.catalog.js.map +0 -1
  95. package/dist/broker/aggregate/aggregate.server.d.ts +0 -47
  96. package/dist/broker/aggregate/aggregate.server.js +0 -151
  97. package/dist/broker/aggregate/aggregate.server.js.map +0 -1
  98. package/dist/broker/aggregate/provider.client.session.d.ts +0 -52
  99. package/dist/broker/aggregate/provider.client.session.js +0 -140
  100. package/dist/broker/aggregate/provider.client.session.js.map +0 -1
  101. package/dist/broker/behaviors/broker.behavior.info.d.ts +0 -15
  102. package/dist/broker/behaviors/broker.behavior.info.js +0 -41
  103. package/dist/broker/behaviors/broker.behavior.info.js.map +0 -1
  104. package/dist/broker/behaviors/broker.behavior.providers.d.ts +0 -19
  105. package/dist/broker/behaviors/broker.behavior.providers.js +0 -69
  106. package/dist/broker/behaviors/broker.behavior.providers.js.map +0 -1
  107. package/dist/broker/broker.context.d.ts +0 -59
  108. package/dist/broker/broker.context.js +0 -2
  109. package/dist/broker/broker.context.js.map +0 -1
  110. package/dist/broker/broker.grammars.d.ts +0 -130
  111. package/dist/broker/broker.grammars.js +0 -229
  112. package/dist/broker/broker.grammars.js.map +0 -1
  113. package/dist/broker/broker.server.d.ts +0 -66
  114. package/dist/broker/broker.server.js +0 -73
  115. package/dist/broker/broker.server.js.map +0 -1
  116. package/dist/broker/index.d.ts +0 -9
  117. package/dist/broker/index.js +0 -7
  118. package/dist/broker/index.js.map +0 -1
  119. package/dist/config.d.ts +0 -136
  120. package/dist/config.js +0 -61
  121. package/dist/config.js.map +0 -1
  122. package/dist/mcpb.loader.d.ts +0 -24
  123. package/dist/mcpb.loader.js +0 -161
  124. package/dist/mcpb.loader.js.map +0 -1
  125. package/dist/mcpb.unzip.d.ts +0 -6
  126. package/dist/mcpb.unzip.js +0 -95
  127. package/dist/mcpb.unzip.js.map +0 -1
  128. package/dist/remote.transports.d.ts +0 -16
  129. package/dist/remote.transports.js +0 -297
  130. package/dist/remote.transports.js.map +0 -1
  131. package/dist/remote.upstream.d.ts +0 -36
  132. package/dist/remote.upstream.js +0 -52
  133. package/dist/remote.upstream.js.map +0 -1
  134. package/dist/stdio.upstream.d.ts +0 -45
  135. package/dist/stdio.upstream.js +0 -85
  136. package/dist/stdio.upstream.js.map +0 -1
  137. package/dist/upstream.d.ts +0 -33
  138. package/dist/upstream.js +0 -2
  139. package/dist/upstream.js.map +0 -1
  140. package/dist/version.d.ts +0 -2
  141. package/dist/version.js +0 -9
  142. package/dist/version.js.map +0 -1
  143. package/dist/ws.tunnel.builder.d.ts +0 -139
  144. package/dist/ws.tunnel.builder.js +0 -205
  145. package/dist/ws.tunnel.builder.js.map +0 -1
  146. package/dist/ws.tunnel.d.ts +0 -373
  147. package/dist/ws.tunnel.js +0 -1090
  148. package/dist/ws.tunnel.js.map +0 -1
  149. /package/dist/{broker/grammars → grammars}/default/en.json +0 -0
  150. /package/dist/{broker/grammars → grammars}/default/fr.json +0 -0
  151. /package/dist/{broker/grammars → grammars}/default/zh.json +0 -0
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,155 +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
- const stdioProvider = process.env["MCP_BROKER_STDIO_PROVIDER"];
86
- // In stdio mode stdout is reserved for JSON-RPC — redirect all console output to stderr.
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);
24
+ envFromConfig("MCP_BROKER_PUBLIC_BASE_URL", config.auth?.publicBaseUrl);
25
+ envFromConfig("MCP_BROKER_JWKS", config.auth?.jwks);
26
+ envFromConfig("MCP_BROKER_ISSUER", config.auth?.issuer);
27
+ envFromConfig("MCP_BROKER_PROVIDER_SECRET", config.auth?.providerSecret);
28
+ var stdioProvider = process.env["MCP_BROKER_STDIO_PROVIDER"];
87
29
  if (stdioProvider) {
88
- const toStderr = (...args) => process.stderr.write(args.join(" ") + "\n");
89
- console.log = toStderr;
90
- console.info = toStderr;
91
- console.warn = toStderr;
92
- 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;
93
35
  }
94
- const port = parseInt(process.env["MCP_BROKER_PORT"] ?? "3000", 10);
95
- const host = process.env["MCP_BROKER_HOST"];
96
- const providerPath = process.env["MCP_BROKER_PROVIDER_PATH"] ?? "/provider";
97
- const clientPath = process.env["MCP_BROKER_CLIENT_PATH"] ?? "/";
98
- const mcpPath = process.env["MCP_BROKER_MCP_PATH"] ?? "/mcp";
99
- const ssePath = config.paths?.sse ?? "/sse";
100
- // ── TLS material ─────────────────────────────────────────────────────────────
101
- // Env var (relative to cwd) wins over config (relative to baseDir).
102
- 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;
103
- 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;
104
- const protocolOverride = process.env["MCP_BROKER_PROTOCOL"]?.toLowerCase();
105
- if (protocolOverride !== undefined && protocolOverride !== "http" && protocolOverride !== "https") {
106
- console.error(`[mcp-broker] Invalid MCP_BROKER_PROTOCOL="${protocolOverride}". Use "http" or "https".`);
107
- 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);
108
48
  }
109
49
  if (protocolOverride === "https" && (!tlsCertPath || !tlsKeyPath)) {
110
- console.error("[mcp-broker] MCP_BROKER_PROTOCOL=https requires TLS cert+key (via config.tls or MCP_BROKER_TLS_CERT/KEY).");
111
- 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);
112
52
  }
113
- const useTls = protocolOverride === "http" ? false : protocolOverride === "https" ? true : !!(tlsCertPath && tlsKeyPath);
114
- // ── Env-var static mount shortcuts (relative to cwd) ─────────────────────────
115
- const envWwwDir = process.env["MCP_BROKER_WWW_DIR"] ? path.resolve(cwd, process.env["MCP_BROKER_WWW_DIR"]) : null;
116
- const envBundleDir = process.env["MCP_BROKER_BUNDLE_DIR"] ? path.resolve(cwd, process.env["MCP_BROKER_BUNDLE_DIR"]) : null;
117
- // ---------------------------------------------------------------------------
118
- // Server bootstrap
119
- // ---------------------------------------------------------------------------
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;
120
69
  async function main() {
121
- // Local grammar overrides: when `<baseDir>/grammars/` exists, the broker
122
- // server merges those JSON files on top of the packaged grammars.
123
- const localGrammarsDir = path.join(baseDir, "grammars");
124
- const hasLocalGrammars = fs.existsSync(localGrammarsDir);
125
- const builder = new WsTunnelBuilder().withPort(port).withProviderPath(providerPath).withClientPath(clientPath).withMcpPath(mcpPath);
126
- if (host) {
127
- builder.withHost(host);
128
- }
129
- if (useTls) {
130
- builder.withTlsFiles(tlsCertPath, tlsKeyPath);
131
- }
132
- // ── Static mounts ────────────────────────────────────────────────────────
133
- // First the env-var shortcuts (relative to cwd), then the config `www.mounts`
134
- // (relative to baseDir). Order matters: /bundle before / so the prefix router
135
- // can distinguish them. Subsequent registrations contribute additional mounts;
136
- // longest-prefix match wins at runtime.
137
- if (envBundleDir && fs.existsSync(envBundleDir)) {
138
- builder.withStaticMount("/bundle", envBundleDir);
139
- }
140
- if (envWwwDir && fs.existsSync(envWwwDir)) {
141
- builder.withStaticMount("/", envWwwDir);
142
- }
143
- if (config.www?.mounts) {
144
- for (const mount of config.www.mounts) {
145
- const abs = path.resolve(baseDir, mount.dir);
146
- if (fs.existsSync(abs)) {
147
- builder.withStaticMount(mount.urlPrefix, abs);
148
- }
149
- else {
150
- console.warn(`[mcp-broker] www.mounts entry "${mount.urlPrefix}" → ${abs} skipped (directory not found).`);
151
- }
152
- }
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
+ }
153
96
  }
154
- // ── Stdio upstreams ──────────────────────────────────────────────────────
155
- if (config.stdioUpstreams) {
156
- for (const u of config.stdioUpstreams) {
157
- builder.withStdioUpstream({
158
- name: u.name,
159
- command: u.command,
160
- args: u.args,
161
- env: u.env,
162
- aggregate: u.aggregate,
163
- });
164
- }
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
+ });
165
107
  }
166
- // ── Remote MCP server upstreams (reached by URL) ─────────────────────────
167
- // Config-discovered remote servers join the `_all` aggregate by default;
168
- // an explicit `aggregate: false` opts an entry out.
169
- if (config.mcpServers) {
170
- for (const s of config.mcpServers) {
171
- builder.withRemoteUpstream({ ...s, aggregate: s.aggregate ?? true });
172
- }
108
+ }
109
+ if (config.mcpServers) {
110
+ for (const s of config.mcpServers) {
111
+ builder.withRemoteUpstream({ ...s, aggregate: s.aggregate ?? true });
173
112
  }
174
- // ── Local `.mcpb` bundles ────────────────────────────────────────────────
175
- // Each bundle is signature-verified and unpacked before it is wired in as a
176
- // stdio upstream. A refused bundle is skipped (loadMcpbBundle logs why); it
177
- // never spawns a process. Bundles join `_all` by default (opt-out per entry).
178
- if (config.mcpbBundles) {
179
- for (const b of config.mcpbBundles) {
180
- const upstream = await loadMcpbBundle(b, baseDir);
181
- if (upstream) {
182
- builder.withStdioUpstream(upstream);
183
- }
184
- }
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
+ }
185
120
  }
186
- if (stdioProvider) {
187
- builder.withStdioClient(stdioProvider);
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);
188
140
  }
189
- if (hasLocalGrammars) {
190
- builder.withBrokerLocalGrammarsDir(localGrammarsDir);
191
- }
192
- const tunnel = builder.build();
193
- await tunnel.start();
194
- // ── Startup banner ──────────────────────────────────────────────────────
195
- const httpScheme = useTls ? "https" : "http";
196
- const wsScheme = useTls ? "wss" : "ws";
197
- const hr = "─".repeat(64);
198
- const localhost = `${httpScheme}://localhost:${port}`;
199
- const mcpSuffix = mcpPath.replace(/^\//, "");
200
- const sseSuffix = ssePath.replace(/^\//, "");
201
- const hasWwwRoot = !!(envWwwDir && fs.existsSync(envWwwDir)) || (config.www?.mounts ?? []).some((m) => m.urlPrefix === "/");
202
- console.log();
203
- console.log(`⚙️ mcp-broker started${useTls ? " (TLS)" : ""}`);
204
- console.log(hr);
205
- console.log(`📡 Provider WebSocket ${wsScheme}://localhost:${port}${providerPath}/<name>`);
206
- console.log(`🔌 MCP (Streamable HTTP) ${localhost}/<name>/${mcpSuffix}`);
207
- console.log(`📺 Legacy SSE ${localhost}/<name>/${sseSuffix}`);
208
- if (hasLocalGrammars) {
209
- console.log(`🌐 Local grammars ${localGrammarsDir}`);
210
- }
211
- console.log(hr);
212
- console.log(` Press Ctrl+C to stop.`);
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}`);
213
190
  console.log();
214
- // Auto-launch browser only if explicitly opted in via MCP_BROKER_OPEN=1
215
- // AND a mount at "/" is configured.
216
- if (hasWwwRoot && process.env["MCP_BROKER_OPEN"] === "1") {
217
- const url = `${localhost}/`;
218
- console.log(`🚀 Opening browser: ${url}`);
219
- console.log();
220
- await open(url);
221
- }
222
- // ── Signal handlers ─────────────────────────────────────────────────────
223
- const shutdown = async (signal) => {
224
- console.log(`\n⛔ ${signal} received — shutting down…`);
225
- await tunnel.stop();
226
- process.exit(0);
227
- };
228
- process.on("SIGINT", () => void shutdown("SIGINT"));
229
- 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"));
230
201
  }
231
202
  main().catch((err) => {
232
- console.error("[mcp-broker] Fatal error:", err);
233
- process.exit(1);
203
+ console.error("[mcp-broker] Fatal error:", err);
204
+ process.exit(1);
234
205
  });
206
+ //# sourceMappingURL=bin.js.map
235
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"]}