@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
@@ -1,373 +0,0 @@
1
- import type { GrammarResolverOptions, IMessageTransport } from "@cyanmycelium/mcp-core";
2
- import { type StdioUpstreamConfig } from "./stdio.upstream.js";
3
- import { type RemoteUpstreamConfig } from "./remote.upstream.js";
4
- import type { BrokerContext, BrokerProviderInfo } from "./broker/index.js";
5
- /**
6
- * A single static-file mount: serves the contents of `dir` under `urlPrefix`.
7
- *
8
- * @example
9
- * { urlPrefix: "/", dir: "/absolute/path/to/www" }
10
- * { urlPrefix: "/bundle", dir: "/absolute/path/to/bundle" }
11
- */
12
- export interface StaticMount {
13
- /** URL prefix that triggers this mount (e.g. `"/"` or `"/bundle"`). */
14
- urlPrefix: string;
15
- /** Absolute path to the directory to serve. */
16
- dir: string;
17
- }
18
- /**
19
- * In-process client handle for a provider slot — the symmetric counterpart of
20
- * {@link WsTunnel.registerLoopbackProvider}. Lets a component inside the broker
21
- * process (e.g. the aggregate server) issue MCP requests to a provider slot and
22
- * receive both the responses and the provider's broadcast notifications,
23
- * without opening a real network connection.
24
- */
25
- export interface InternalClient {
26
- /**
27
- * Sends a JSON-RPC message to the provider slot. When the message carries an
28
- * `id`, the matching response is delivered to {@link onMessage}. When the
29
- * provider is not connected, a JSON-RPC error is delivered synchronously.
30
- */
31
- send(message: string): void;
32
- /** Receives responses to this client's requests and the provider's notifications. */
33
- onMessage: ((data: string) => void) | null;
34
- /** Fires when the provider slot loses its connection. */
35
- onClose: (() => void) | null;
36
- /** Detaches this internal client; pending requests are dropped. */
37
- close(): void;
38
- }
39
- /**
40
- * Configuration options for a {@link WsTunnel} instance.
41
- */
42
- export interface WsTunnelOptions {
43
- /** TCP port to listen on. */
44
- port: number;
45
- /**
46
- * Host/interface to bind to.
47
- * @default "0.0.0.0"
48
- */
49
- host?: string;
50
- /**
51
- * URL path **prefix** the MCP provider connects to via WebSocket.
52
- * Each provider appends its name: `<providerPath>/<encodedName>`.
53
- * @default "/provider"
54
- */
55
- providerPath?: string;
56
- /**
57
- * URL path for **multiplexed** provider connections.
58
- * A single WebSocket carries traffic for multiple providers using the
59
- * envelope protocol `{ provider: string, payload: object }`.
60
- * @default "/providers"
61
- */
62
- providersPath?: string;
63
- /**
64
- * URL path raw WebSocket MCP clients connect to.
65
- * @default "/"
66
- */
67
- clientPath?: string;
68
- /**
69
- * **Suffix** appended to a provider name for the SSE endpoint.
70
- * Full URL: `/<providerName>/sse`
71
- * @default "/sse"
72
- */
73
- ssePath?: string;
74
- /**
75
- * **Suffix** appended to a provider name for the legacy SSE POST endpoint.
76
- * Full URL: `/<providerName>/messages`
77
- * @default "/messages"
78
- */
79
- messagesPath?: string;
80
- /**
81
- * **Suffix** appended to a provider name for the Streamable HTTP endpoint (MCP 2025-03-26).
82
- * Full URL: `/<providerName>/mcp`
83
- * MCP Inspector connects here.
84
- * @default "/mcp"
85
- */
86
- mcpPath?: string;
87
- /**
88
- * URL path that returns a `{ files: string[] }` JSON listing of every file
89
- * inside the `samples/` subdirectory of the root static mount.
90
- * @default "/__samples_index__"
91
- */
92
- samplesIndexPath?: string;
93
- /**
94
- * Optional static-file mounts served over plain HTTP.
95
- * Matched by longest URL prefix; directory requests fall back to `index.html`.
96
- */
97
- staticMounts?: StaticMount[];
98
- /**
99
- * Stdio upstream providers. Each entry spawns a child process and wires its
100
- * stdin/stdout as an MCP transport. Clients reach the process using its `name`
101
- * directly.
102
- *
103
- * If a WebSocket provider connects with the same name as a stdio upstream, the
104
- * connection is rejected and a warning is logged — stdio takes priority.
105
- * @default undefined — no stdio providers
106
- */
107
- stdioUpstreams?: StdioUpstreamConfig[];
108
- /** Remote MCP servers reached by URL, exposed as provider slots. */
109
- remoteUpstreams?: RemoteUpstreamConfig[];
110
- /**
111
- * Stdio client transport. When set, the broker reads JSON-RPC from
112
- * `process.stdin` and writes responses to `process.stdout`, bridging an
113
- * external MCP client (e.g. Claude Desktop) to the named provider.
114
- *
115
- * In this mode ALL logging is redirected to stderr so stdout stays clean
116
- * for the JSON-RPC stream.
117
- *
118
- * Claude Desktop config example:
119
- * ```json
120
- * {
121
- * "command": "npx",
122
- * "args": ["-y", "@cyanmycelium/mcp-broker"],
123
- * "env": { "MCP_BROKER_STDIO_PROVIDER": "my-provider" }
124
- * }
125
- * ```
126
- * @default undefined — stdio client transport disabled
127
- */
128
- stdioClient?: {
129
- providerName: string;
130
- };
131
- /**
132
- * TLS configuration. When provided, the server uses HTTPS and WSS instead of HTTP and WS.
133
- * Both `cert` and `key` must be PEM-encoded strings (file contents, not file paths).
134
- * Use {@link WsTunnelBuilder.withTlsFiles} to load from disk paths.
135
- * @default undefined — plain HTTP/WS
136
- */
137
- tls?: {
138
- /** PEM-encoded TLS certificate. */
139
- cert: string;
140
- /** PEM-encoded private key. */
141
- key: string;
142
- };
143
- /**
144
- * When `true` (default), the broker exposes itself as an MCP server under the
145
- * reserved slot `_broker`. Tier-1 behaviors (`broker_info`, `providers_list`,
146
- * `provider_status`) become callable at `<host>/_broker/mcp`.
147
- *
148
- * Set to `false` to keep the broker invisible to MCP clients.
149
- * @default true
150
- */
151
- enableBrokerProvider?: boolean;
152
- /**
153
- * When `true` (default), the broker exposes the reserved slot `_all` — an
154
- * aggregate MCP server that unions the tools and prompts of every provider
155
- * that opted in via the registration handshake. Reachable like any other
156
- * slot (`<host>/_all/mcp`, etc.).
157
- *
158
- * Set to `false` to disable aggregation entirely.
159
- * @default true
160
- */
161
- enableAggregateProvider?: boolean;
162
- /**
163
- * Logical name reported by `broker_info`. Useful when running multiple
164
- * broker instances and you want to tell them apart from the agent side
165
- * (e.g. `"broker-eu-west"`).
166
- * @default PACKAGE_NAME — `@cyanmycelium/mcp-broker`
167
- */
168
- brokerName?: string;
169
- /**
170
- * Overrides for the embedded broker server's grammar resolver — passed
171
- * straight through to `mcp-core`'s `grammarResolverFromOptions`. The
172
- * broker installs its own default `localeSource` (reads
173
- * `process.env.MCP_BROKER_LOCALE`); anything you set here wins.
174
- *
175
- * Use this to inject a custom `localeSource` (e.g. read from an HTTP
176
- * header proxied by your transport), enable the optional `versionFrom`
177
- * dimension, or extend the `agents` map with additional LLM families.
178
- */
179
- brokerGrammarResolverOptions?: Partial<GrammarResolverOptions>;
180
- /**
181
- * Path to a user-supplied grammars directory whose `<userAgent>/<locale>.json`
182
- * files are registered alongside the packaged grammars used by the
183
- * embedded broker server. Typically pointed at `.mcp-broker/grammars/`.
184
- *
185
- * The candidate-chain resolution in `McpServer.initialize`
186
- * (mcp-core@0.3.0) handles cascade across user-agent and locale
187
- * dimensions, so partial files no longer need to be pre-merged with a
188
- * baseline.
189
- */
190
- brokerLocalGrammarsDir?: string;
191
- }
192
- /**
193
- * A multi-provider relay that bridges any number of MCP server instances
194
- * (the **providers**) with their respective MCP clients.
195
- *
196
- * ## Transport overview
197
- * ```
198
- * Provider "<name>"
199
- * ws://host/provider/<name> ← WebSocket registration
200
- *
201
- * MCP Inspector (Streamable HTTP, 2025-03-26)
202
- * GET http://host/<name>/mcp ← persistent SSE notification stream
203
- * POST http://host/<name>/mcp → JSON-RPC requests
204
- *
205
- * Claude (legacy SSE transport)
206
- * GET http://host/<name>/sse ← SSE notification stream
207
- * POST http://host/<name>/messages → JSON-RPC requests
208
- * ```
209
- *
210
- * Each provider gets its own isolated set of sessions, pending requests, and
211
- * notification streams. Multiple providers can be connected simultaneously.
212
- */
213
- export declare class WsTunnel implements BrokerContext {
214
- private readonly _options;
215
- private _httpServer;
216
- private _wss;
217
- /**
218
- * Per-provider state, keyed by provider name.
219
- * Created lazily: a slot is allocated the first time any client references
220
- * a provider name, even before the provider WebSocket connects.
221
- */
222
- private readonly _providers;
223
- /** Maps a multiplexed WebSocket to the set of provider names it feeds. */
224
- private readonly _multiplexSockets;
225
- /** Upstream providers (stdio child processes and remote URL servers), keyed by name. */
226
- private readonly _upstreams;
227
- /**
228
- * In-process loopback transports registered as provider slots.
229
- * Used by the embedded broker server (`_broker`) and any other component
230
- * that wants to expose itself as a provider without going through a network.
231
- */
232
- private readonly _loopbackProviders;
233
- /** The embedded broker MCP server, when {@link WsTunnelOptions.enableBrokerProvider} is on. */
234
- private _brokerServer;
235
- /** The aggregate MCP server (`_all` slot), when {@link WsTunnelOptions.enableAggregateProvider} is on. */
236
- private _aggregateServer;
237
- /** Provider name that the stdio client transport is bridged to, or null when disabled. */
238
- private _stdioClientProvider;
239
- /** Buffered partial line from stdin (stdio client transport). */
240
- private _stdioClientBuffer;
241
- /** Timestamp of the most recent successful `start()`. */
242
- private _startedAt;
243
- constructor(options: WsTunnelOptions);
244
- get version(): string;
245
- get name(): string;
246
- get startedAt(): Date | null;
247
- get uptimeSeconds(): number;
248
- get host(): string | undefined;
249
- get port(): number;
250
- get tls(): boolean;
251
- get paths(): BrokerContext["paths"];
252
- getProvidersInfo(): BrokerProviderInfo[];
253
- getProviderInfo(name: string): BrokerProviderInfo | undefined;
254
- private _buildProviderInfo;
255
- /**
256
- * Registers an in-process transport as a provider slot. Used by the embedded
257
- * broker server and may be used by application code that wants to host an
258
- * MCP server inside the same process without opening a real WebSocket.
259
- *
260
- * @throws if the name is already used by a stdio upstream or another loopback.
261
- */
262
- registerLoopbackProvider(name: string, transport: IMessageTransport): void;
263
- /**
264
- * Opens an in-process client to a provider slot. The returned handle can
265
- * issue MCP requests and receives both the responses and the provider's
266
- * broadcast notifications. Used by the aggregate server to fan a single
267
- * in-process client out to every aggregated provider.
268
- *
269
- * The slot does not need a provider attached yet — `send` returns a
270
- * JSON-RPC error while the provider is disconnected.
271
- */
272
- openInternalClient(providerName: string): InternalClient;
273
- get isListening(): boolean;
274
- /** Total number of connected MCP clients across all providers. */
275
- get clientCount(): number;
276
- /** Names of all providers that currently have an active connection. */
277
- get providerNames(): readonly string[];
278
- /** @deprecated Check `providerNames.length > 0` instead. */
279
- get hasProvider(): boolean;
280
- /**
281
- * Starts the broker. Resolves once the HTTP server is listening.
282
- */
283
- start(): Promise<void>;
284
- /**
285
- * Starts the in-process MCP server that exposes the broker's own behaviors
286
- * (`broker_info`, `providers_list`, `provider_status`) under the reserved
287
- * provider slot `_broker`. No-op when {@link WsTunnelOptions.enableBrokerProvider}
288
- * is `false`.
289
- */
290
- private _maybeStartBrokerServer;
291
- /**
292
- * Starts the aggregate MCP server and registers it on the reserved `_all`
293
- * slot. No-op when {@link WsTunnelOptions.enableAggregateProvider} is `false`.
294
- */
295
- private _maybeStartAggregateServer;
296
- /**
297
- * Gracefully closes all connections and stops the HTTP server.
298
- */
299
- stop(): Promise<void>;
300
- private _handleHttp;
301
- /**
302
- * Parses `/<providerName>/<endpoint>` from a URL path.
303
- * Returns `null` if the URL does not match this two-segment pattern.
304
- */
305
- private _parseProviderRoute;
306
- /**
307
- * Handles `GET /<providerName>/sse` — opens a long-lived SSE stream for Claude.
308
- * Sends an `endpoint` event so Claude knows where to POST its requests.
309
- */
310
- private _handleSseConnect;
311
- /**
312
- * Handles `POST /<providerName>/messages?sessionId=…` — receives a JSON-RPC
313
- * request from Claude and forwards it to the provider.
314
- * Always responds 202 Accepted; the real response arrives over SSE.
315
- */
316
- private _handleSseMessage;
317
- /**
318
- * Handles `POST /<providerName>/mcp` — Streamable HTTP transport (MCP 2025-03-26).
319
- * Forwards the JSON-RPC request to the provider and holds the HTTP response
320
- * open until the reply arrives, then writes it as `application/json`.
321
- */
322
- private _handleMcpPost;
323
- /**
324
- * Handles `GET /<providerName>/mcp` — opens a persistent SSE stream per MCP 2025-03-26.
325
- * Streamable HTTP clients (e.g. MCP Inspector) use this to receive
326
- * server-initiated notifications without re-polling.
327
- */
328
- private _handleMcpGetStream;
329
- /** Writes one JSON-RPC message as an SSE `message` event. */
330
- private _sendSseEvent;
331
- private _onProviderConnect;
332
- /**
333
- * Inspects a provider's first WebSocket message for an optional registration
334
- * control frame `{ "type": "register", "aggregate": boolean }`. Returns
335
- * `true` when the message was a registration frame — and thus consumed, not
336
- * routed as MCP traffic. A normal MCP frame always carries `jsonrpc`, so it
337
- * returns `false` and the provider stays non-aggregated.
338
- */
339
- private _tryHandleRegistration;
340
- private _onClientConnect;
341
- /**
342
- * Handles a multiplexed provider WebSocket (`/providers`).
343
- * A single socket carries traffic for multiple providers using the
344
- * envelope format `{ provider: string, payload: object }`.
345
- * Provider names are registered lazily on first message.
346
- */
347
- private _onMultiplexProviderConnect;
348
- /**
349
- * Sends a raw JSON-RPC message to a provider, wrapping it in a multiplex
350
- * envelope when the provider's WebSocket is a multiplexed connection.
351
- */
352
- private _sendToProvider;
353
- private _routeFromStdioClient;
354
- private _routeFromClient;
355
- private _routeFromProvider;
356
- /** Sends a message to all clients connected to one provider. */
357
- private _broadcast;
358
- /**
359
- * Notifies every pending sink and internal client that the provider slot
360
- * has disconnected, then clears the pending map. Shared by all provider
361
- * close handlers (dedicated WS, multiplexed WS, loopback).
362
- */
363
- private _failProviderDisconnected;
364
- /**
365
- * Returns `true` if the provider is reachable — via a WebSocket connection,
366
- * a stdio upstream, or an in-process loopback transport.
367
- */
368
- private _isProviderConnected;
369
- /** Returns the state for `name`, creating it lazily if it doesn't exist yet. */
370
- private _getOrCreateProviderState;
371
- private _handleSamplesIndex;
372
- private _serveStatic;
373
- }