@cyanmycelium/mcp-broker-provider 0.2.0 → 0.3.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.
- package/README.md +100 -0
- package/dist/index.d.ts +297 -3
- package/dist/index.js +257 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/broker.client.ts +407 -0
- package/src/direct.transport.ts +45 -2
- package/src/index.ts +30 -0
- package/src/multiplex.transport.ts +72 -13
- package/src/transport.support.ts +35 -0
package/dist/index.js
CHANGED
|
@@ -53,6 +53,177 @@ function tunnelErrorOf(payload) {
|
|
|
53
53
|
return error;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// src/broker.client.ts
|
|
57
|
+
var CALLER_META_KEY = "io.cyanmycelium/caller";
|
|
58
|
+
var TRACEPARENT_META_KEY = "traceparent";
|
|
59
|
+
var TELEMETRY_NOTIFICATION_METHOD = "broker/telemetry";
|
|
60
|
+
var AUDIT_RESULT_NOTIFICATION_METHOD = "broker/audit/result";
|
|
61
|
+
var TRACEPARENT = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
|
|
62
|
+
var TRACE_ID = /^[0-9a-f]{32}$/;
|
|
63
|
+
var SPAN_ID = /^[0-9a-f]{16}$/;
|
|
64
|
+
var UNIX_NANO = /^(0|[1-9][0-9]{0,19})$/;
|
|
65
|
+
function parseTraceparent(value) {
|
|
66
|
+
if (typeof value !== "string") return void 0;
|
|
67
|
+
const match = TRACEPARENT.exec(value);
|
|
68
|
+
if (!match || /^0+$/.test(match[1]) || /^0+$/.test(match[2])) return void 0;
|
|
69
|
+
return { version: "00", traceId: match[1], parentId: match[2], traceFlags: match[3] };
|
|
70
|
+
}
|
|
71
|
+
function formatTraceparent(context) {
|
|
72
|
+
return `${context.version}-${context.traceId}-${context.parentId}-${context.traceFlags}`;
|
|
73
|
+
}
|
|
74
|
+
function traceparentOf(meta) {
|
|
75
|
+
return parseTraceparent(meta?.[TRACEPARENT_META_KEY]);
|
|
76
|
+
}
|
|
77
|
+
function withTraceparent(meta, context) {
|
|
78
|
+
const encoded = formatTraceparent(context);
|
|
79
|
+
if (!parseTraceparent(encoded)) throw new TypeError("traceparent must be a valid W3C version 00 context");
|
|
80
|
+
return { ...meta ?? {}, [TRACEPARENT_META_KEY]: encoded };
|
|
81
|
+
}
|
|
82
|
+
function childTraceparent(parent, spanId) {
|
|
83
|
+
if (!SPAN_ID.test(spanId) || /^0+$/.test(spanId)) throw new TypeError("spanId must be 16 lowercase hexadecimal characters and not all zero");
|
|
84
|
+
return { ...parent, parentId: spanId };
|
|
85
|
+
}
|
|
86
|
+
function validAttributes(attributes) {
|
|
87
|
+
if (attributes === void 0) return true;
|
|
88
|
+
const entries = Object.entries(attributes);
|
|
89
|
+
return entries.length <= 64 && entries.every(
|
|
90
|
+
([key, value]) => key.length > 0 && key.length <= 128 && (typeof value === "boolean" || typeof value === "string" && value.length <= 4096 || typeof value === "number" && Number.isFinite(value))
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
function validSpan(span) {
|
|
94
|
+
return TRACE_ID.test(span.traceId) && !/^0+$/.test(span.traceId) && SPAN_ID.test(span.spanId) && !/^0+$/.test(span.spanId) && (span.parentSpanId === void 0 || SPAN_ID.test(span.parentSpanId) && !/^0+$/.test(span.parentSpanId)) && span.name.length > 0 && span.name.length <= 256 && UNIX_NANO.test(span.startTimeUnixNano) && UNIX_NANO.test(span.endTimeUnixNano) && (span.kind === void 0 || Number.isInteger(span.kind) && span.kind >= 0 && span.kind <= 5) && validAttributes(span.attributes) && (span.events === void 0 || span.events.length <= 32 && span.events.every((event) => event.name.length > 0 && event.name.length <= 256 && UNIX_NANO.test(event.timeUnixNano) && validAttributes(event.attributes))) && (span.status === void 0 || Number.isInteger(span.status.code) && span.status.code >= 0 && span.status.code <= 2 && (span.status.message === void 0 || span.status.message.length <= 1024));
|
|
95
|
+
}
|
|
96
|
+
function callerReferenceOf(meta) {
|
|
97
|
+
const value = meta?.[CALLER_META_KEY];
|
|
98
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
99
|
+
const { ref, correlationId, traceId } = value;
|
|
100
|
+
return typeof ref === "string" && typeof correlationId === "string" ? { ref, correlationId, ...typeof traceId === "string" ? { traceId } : {} } : void 0;
|
|
101
|
+
}
|
|
102
|
+
var BrokerRequestError = class extends Error {
|
|
103
|
+
constructor(message, code, data) {
|
|
104
|
+
super(message);
|
|
105
|
+
this.code = code;
|
|
106
|
+
this.data = data;
|
|
107
|
+
this.name = "BrokerRequestError";
|
|
108
|
+
}
|
|
109
|
+
code;
|
|
110
|
+
data;
|
|
111
|
+
};
|
|
112
|
+
var ID_PREFIX = "provider-broker-";
|
|
113
|
+
var BrokerClient = class {
|
|
114
|
+
_write;
|
|
115
|
+
_writeTelemetry;
|
|
116
|
+
_timeoutMs;
|
|
117
|
+
_waiting = /* @__PURE__ */ new Map();
|
|
118
|
+
_next = 1;
|
|
119
|
+
constructor(write, options = {}, writeTelemetry) {
|
|
120
|
+
this._write = write;
|
|
121
|
+
this._writeTelemetry = writeTelemetry ?? ((frame) => {
|
|
122
|
+
write(frame);
|
|
123
|
+
return true;
|
|
124
|
+
});
|
|
125
|
+
this._timeoutMs = Math.max(0, options.requestTimeoutMs ?? 0);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Declares this provider's authorization domain. Resolves when the broker
|
|
129
|
+
* accepted it; rejects with a {@link BrokerRequestError} whose `data.errors`
|
|
130
|
+
* lists every problem otherwise. Until it resolves, serve nothing that
|
|
131
|
+
* needs a decision.
|
|
132
|
+
*/
|
|
133
|
+
declare(declaration) {
|
|
134
|
+
return this._request("broker/authorization/declare", declaration);
|
|
135
|
+
}
|
|
136
|
+
/** Asks for one decision per check. */
|
|
137
|
+
authorize(query) {
|
|
138
|
+
return this._request("broker/authorize", query);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Reports what happened after a decision, so the broker's audit shows the
|
|
142
|
+
* outcome next to the decision. A notification: nothing comes back, and a
|
|
143
|
+
* report the broker cannot match is counted on its side.
|
|
144
|
+
*/
|
|
145
|
+
reportResult(report) {
|
|
146
|
+
if (typeof report?.decisionId !== "string" || report.decisionId.length === 0) throw new TypeError("decisionId must be the non-empty id the broker returned");
|
|
147
|
+
if (report.result !== "success" && report.result !== "failure" && report.result !== "refused") throw new TypeError('result must be "success", "failure" or "refused"');
|
|
148
|
+
const params = {
|
|
149
|
+
decisionId: report.decisionId,
|
|
150
|
+
result: report.result,
|
|
151
|
+
...report.nativeStatus !== void 0 ? { nativeStatus: report.nativeStatus } : {},
|
|
152
|
+
...report.errorCode !== void 0 ? { errorCode: report.errorCode } : {}
|
|
153
|
+
};
|
|
154
|
+
this._write(JSON.stringify({ jsonrpc: "2.0", method: AUDIT_RESULT_NOTIFICATION_METHOD, params }));
|
|
155
|
+
}
|
|
156
|
+
/** Emits one complete provider span, or returns false when the link is down. */
|
|
157
|
+
span(span) {
|
|
158
|
+
if (!validSpan(span)) throw new TypeError("span is not a valid broker telemetry span");
|
|
159
|
+
return this._writeTelemetry(
|
|
160
|
+
JSON.stringify({
|
|
161
|
+
jsonrpc: "2.0",
|
|
162
|
+
method: TELEMETRY_NOTIFICATION_METHOD,
|
|
163
|
+
params: { version: 1, signal: "traces", span }
|
|
164
|
+
})
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
/** Number of requests still waiting for the broker. */
|
|
168
|
+
get pendingCount() {
|
|
169
|
+
return this._waiting.size;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Consumes a frame when it answers one of this client's requests. Returns
|
|
173
|
+
* `true` when it did, and the frame must not reach the MCP server.
|
|
174
|
+
* @internal Called by the transports.
|
|
175
|
+
*/
|
|
176
|
+
handleIncoming(frame) {
|
|
177
|
+
if (this._waiting.size === 0 || !frame.includes(ID_PREFIX)) return false;
|
|
178
|
+
let message;
|
|
179
|
+
try {
|
|
180
|
+
message = JSON.parse(frame);
|
|
181
|
+
} catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
if (typeof message.id !== "string" || message.method !== void 0) return false;
|
|
185
|
+
const waiting = this._waiting.get(message.id);
|
|
186
|
+
if (!waiting) return false;
|
|
187
|
+
this._waiting.delete(message.id);
|
|
188
|
+
if (waiting.timer) clearTimeout(waiting.timer);
|
|
189
|
+
if (message.error) {
|
|
190
|
+
waiting.reject(
|
|
191
|
+
new BrokerRequestError(String(message.error.message ?? "broker error"), typeof message.error.code === "number" ? message.error.code : void 0, message.error.data)
|
|
192
|
+
);
|
|
193
|
+
} else {
|
|
194
|
+
waiting.resolve(message.result);
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Fails every waiting request: the socket they went out on is gone, and a
|
|
200
|
+
* reconnected one will not carry their answers.
|
|
201
|
+
* @internal Called by the transports.
|
|
202
|
+
*/
|
|
203
|
+
rejectAll(reason) {
|
|
204
|
+
for (const [id, waiting] of this._waiting) {
|
|
205
|
+
if (waiting.timer) clearTimeout(waiting.timer);
|
|
206
|
+
waiting.reject(new BrokerRequestError(`${reason} (request ${id})`));
|
|
207
|
+
}
|
|
208
|
+
this._waiting.clear();
|
|
209
|
+
}
|
|
210
|
+
_request(method, params) {
|
|
211
|
+
const id = `${ID_PREFIX}${this._next++}`;
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
const timer = this._timeoutMs > 0 ? setTimeout(() => {
|
|
214
|
+
this._waiting.delete(id);
|
|
215
|
+
reject(
|
|
216
|
+
new BrokerRequestError(
|
|
217
|
+
`The broker did not answer ${method} within ${this._timeoutMs}ms. A broker older than 1.4.1 drops methods it does not know; ${method} needs broker 1.5.0 or later.`
|
|
218
|
+
)
|
|
219
|
+
);
|
|
220
|
+
}, this._timeoutMs) : null;
|
|
221
|
+
this._waiting.set(id, { resolve, reject, timer });
|
|
222
|
+
this._write(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
56
227
|
// src/transport.support.ts
|
|
57
228
|
var PENDING_FRAME_LIMIT = 64;
|
|
58
229
|
var PendingFrames = class {
|
|
@@ -173,11 +344,32 @@ function warnIfSlotScopedPath(wsUrl) {
|
|
|
173
344
|
`[mcp-provider] MultiplexTransport is connecting to "${wsUrl}", whose path "${path}" is a slot-scoped provider endpoint. That endpoint carries plain JSON-RPC frames, while MultiplexTransport writes multiplex envelopes { provider, payload }, which the broker never unwraps, so nothing sent here is answered. Either publish through new DirectTransport("${wsUrl}"), or point MultiplexTransport at the shared multiplex base "${withPath(url, DEFAULT_MULTIPLEX_PATH)}". ` + RECONFIGURED_HINT
|
|
174
345
|
);
|
|
175
346
|
}
|
|
347
|
+
function handshakeHeaders(options) {
|
|
348
|
+
const headers = { ...options?.headers ?? {} };
|
|
349
|
+
if (options?.secret) headers["x-provider-token"] = options.secret;
|
|
350
|
+
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
351
|
+
}
|
|
352
|
+
function openWebSocket(url, headers) {
|
|
353
|
+
if (typeof WebSocket === "undefined") {
|
|
354
|
+
throw new Error(
|
|
355
|
+
`Cannot open ${url}: this runtime has no global WebSocket (Node before 22). Assign one before connecting: import { WebSocket } from "ws"; globalThis.WebSocket = WebSocket as unknown as typeof globalThis.WebSocket;`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
if (!headers) return new WebSocket(url);
|
|
359
|
+
try {
|
|
360
|
+
return new WebSocket(url, { headers });
|
|
361
|
+
} catch (error) {
|
|
362
|
+
throw new Error(
|
|
363
|
+
`Cannot open ${url} with handshake headers (secret / headers): this runtime's WebSocket does not accept them. Node 22 and later do; a browser never does, so a browser provider cannot authenticate to the broker. ${error.message}`
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
176
367
|
|
|
177
368
|
// src/direct.transport.ts
|
|
178
369
|
var DirectTransport = class {
|
|
179
370
|
_wsUrl;
|
|
180
371
|
_aggregate;
|
|
372
|
+
_headers;
|
|
181
373
|
_pending;
|
|
182
374
|
/** Throttles the "wrote to a closed transport" line, which repeats per frame. */
|
|
183
375
|
_afterCloseNotice = new ThrottledNotice();
|
|
@@ -187,10 +379,26 @@ var DirectTransport = class {
|
|
|
187
379
|
onOpen = null;
|
|
188
380
|
onClose = null;
|
|
189
381
|
onError = null;
|
|
382
|
+
/**
|
|
383
|
+
* The broker's own methods for this slot: declaring an authorization
|
|
384
|
+
* domain, asking for decisions. Its answers are taken off the socket
|
|
385
|
+
* before {@link onMessage} sees anything.
|
|
386
|
+
*/
|
|
387
|
+
broker;
|
|
190
388
|
constructor(wsUrl, options) {
|
|
191
389
|
this._wsUrl = wsUrl;
|
|
192
390
|
this._aggregate = options?.aggregate;
|
|
391
|
+
this._headers = handshakeHeaders(options);
|
|
193
392
|
this._pending = new PendingFrames(`DirectTransport ${wsUrl}`);
|
|
393
|
+
this.broker = new BrokerClient(
|
|
394
|
+
(frame) => this.send(frame),
|
|
395
|
+
{ requestTimeoutMs: options?.brokerRequestTimeoutMs },
|
|
396
|
+
(frame) => {
|
|
397
|
+
if (this._ws?.readyState !== WebSocket.OPEN) return false;
|
|
398
|
+
this._ws.send(frame);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
);
|
|
194
402
|
}
|
|
195
403
|
get isOpen() {
|
|
196
404
|
return this._ws?.readyState === WebSocket.OPEN;
|
|
@@ -201,7 +409,7 @@ var DirectTransport = class {
|
|
|
201
409
|
*/
|
|
202
410
|
connect() {
|
|
203
411
|
warnIfMultiplexPath(this._wsUrl);
|
|
204
|
-
const ws =
|
|
412
|
+
const ws = openWebSocket(this._wsUrl, this._headers);
|
|
205
413
|
this._closed = false;
|
|
206
414
|
this._ws = ws;
|
|
207
415
|
ws.onopen = () => {
|
|
@@ -218,11 +426,13 @@ var DirectTransport = class {
|
|
|
218
426
|
if (this._ws !== ws) return;
|
|
219
427
|
this._ws = null;
|
|
220
428
|
const discarded = this._pending.clear();
|
|
429
|
+
this.broker.rejectAll(`DirectTransport: the socket to ${this._wsUrl} closed before the broker answered`);
|
|
221
430
|
const error = this._closeError(event, discarded);
|
|
222
431
|
if (error) this.onError?.(new Error(error));
|
|
223
432
|
this.onClose?.();
|
|
224
433
|
};
|
|
225
434
|
ws.onmessage = (event) => {
|
|
435
|
+
if (this.broker.handleIncoming(event.data)) return;
|
|
226
436
|
this.onMessage?.(event.data);
|
|
227
437
|
};
|
|
228
438
|
}
|
|
@@ -287,6 +497,9 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
287
497
|
/** Per-URL cache so all transports targeting the same tunnel share one socket. */
|
|
288
498
|
static _instances = /* @__PURE__ */ new Map();
|
|
289
499
|
_wsUrl;
|
|
500
|
+
/** Cache key: the URL, and the handshake headers, since two secrets are two identities and need two sockets. */
|
|
501
|
+
_key;
|
|
502
|
+
_headers;
|
|
290
503
|
_transports = /* @__PURE__ */ new Map();
|
|
291
504
|
/** Aggregate opt-in per slot, absent when the caller did not express one. */
|
|
292
505
|
_aggregates = /* @__PURE__ */ new Map();
|
|
@@ -302,16 +515,19 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
302
515
|
_pathWarned = false;
|
|
303
516
|
/** Throttles the "wrote to a closed tunnel" line, which repeats per frame. */
|
|
304
517
|
_afterStopNotice = new ThrottledNotice();
|
|
305
|
-
constructor(wsUrl) {
|
|
518
|
+
constructor(wsUrl, key, headers) {
|
|
306
519
|
this._wsUrl = wsUrl;
|
|
520
|
+
this._key = key;
|
|
521
|
+
this._headers = headers;
|
|
307
522
|
this._pending = new PendingFrames(`MultiplexSocket ${wsUrl}`);
|
|
308
523
|
}
|
|
309
|
-
/** Returns (or creates) the singleton socket for a given tunnel URL. */
|
|
310
|
-
static getOrCreate(wsUrl) {
|
|
311
|
-
|
|
524
|
+
/** Returns (or creates) the singleton socket for a given tunnel URL and handshake headers. */
|
|
525
|
+
static getOrCreate(wsUrl, headers) {
|
|
526
|
+
const key = headers ? `${wsUrl}\0${JSON.stringify(Object.entries(headers).sort())}` : wsUrl;
|
|
527
|
+
let instance = _MultiplexSocket._instances.get(key);
|
|
312
528
|
if (!instance) {
|
|
313
|
-
instance = new _MultiplexSocket(wsUrl);
|
|
314
|
-
_MultiplexSocket._instances.set(
|
|
529
|
+
instance = new _MultiplexSocket(wsUrl, key, headers);
|
|
530
|
+
_MultiplexSocket._instances.set(key, instance);
|
|
315
531
|
}
|
|
316
532
|
return instance;
|
|
317
533
|
}
|
|
@@ -342,7 +558,7 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
342
558
|
this._ws?.close();
|
|
343
559
|
this._ws = null;
|
|
344
560
|
this._dead = true;
|
|
345
|
-
_MultiplexSocket._instances.delete(this.
|
|
561
|
+
_MultiplexSocket._instances.delete(this._key);
|
|
346
562
|
}
|
|
347
563
|
}
|
|
348
564
|
/**
|
|
@@ -356,9 +572,9 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
356
572
|
_revive() {
|
|
357
573
|
this._dead = false;
|
|
358
574
|
this._stopped = false;
|
|
359
|
-
const live = _MultiplexSocket._instances.get(this.
|
|
575
|
+
const live = _MultiplexSocket._instances.get(this._key);
|
|
360
576
|
if (!live) {
|
|
361
|
-
_MultiplexSocket._instances.set(this.
|
|
577
|
+
_MultiplexSocket._instances.set(this._key, this);
|
|
362
578
|
return;
|
|
363
579
|
}
|
|
364
580
|
if (live !== this) {
|
|
@@ -399,13 +615,19 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
399
615
|
}
|
|
400
616
|
this._pending.push(frame);
|
|
401
617
|
}
|
|
618
|
+
/** Sends low-priority telemetry only while the shared link is open. */
|
|
619
|
+
sendTelemetry(provider, data) {
|
|
620
|
+
if (this._ws?.readyState !== WebSocket.OPEN) return false;
|
|
621
|
+
this._ws.send(encodeEnvelope(provider, data));
|
|
622
|
+
return true;
|
|
623
|
+
}
|
|
402
624
|
// ── Connection lifecycle ────────────────────────────────────────────────
|
|
403
625
|
_connect() {
|
|
404
626
|
if (!this._pathWarned) {
|
|
405
627
|
this._pathWarned = true;
|
|
406
628
|
warnIfSlotScopedPath(this._wsUrl);
|
|
407
629
|
}
|
|
408
|
-
const ws =
|
|
630
|
+
const ws = openWebSocket(this._wsUrl, this._headers);
|
|
409
631
|
const notices = {
|
|
410
632
|
notEnvelope: new ThrottledNotice(),
|
|
411
633
|
unknownProvider: new ThrottledNotice(),
|
|
@@ -433,6 +655,7 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
433
655
|
if (this._ws !== ws) return;
|
|
434
656
|
this._ws = null;
|
|
435
657
|
for (const transport of this._transports.values()) {
|
|
658
|
+
transport.broker.rejectAll(`MultiplexTransport: the shared socket to ${this._wsUrl} closed before the broker answered`);
|
|
436
659
|
transport.onClose?.();
|
|
437
660
|
}
|
|
438
661
|
if (!this._stopped) {
|
|
@@ -482,7 +705,7 @@ var MultiplexSocket = class _MultiplexSocket {
|
|
|
482
705
|
return;
|
|
483
706
|
}
|
|
484
707
|
}
|
|
485
|
-
transport.
|
|
708
|
+
transport._receive(envelopeFrame(envelope));
|
|
486
709
|
}
|
|
487
710
|
_scheduleReconnect() {
|
|
488
711
|
const base = 1e3;
|
|
@@ -512,10 +735,30 @@ var MultiplexTransport = class _MultiplexTransport {
|
|
|
512
735
|
onOpen = null;
|
|
513
736
|
onClose = null;
|
|
514
737
|
onError = null;
|
|
738
|
+
/**
|
|
739
|
+
* The broker's own methods for this slot: declaring an authorization
|
|
740
|
+
* domain, asking for decisions. Its answers are taken off the socket
|
|
741
|
+
* before {@link onMessage} sees anything.
|
|
742
|
+
*/
|
|
743
|
+
broker;
|
|
515
744
|
constructor(name, socket, options) {
|
|
516
745
|
this._name = name;
|
|
517
746
|
this._socket = socket;
|
|
518
747
|
this._aggregate = options?.aggregate;
|
|
748
|
+
this.broker = new BrokerClient(
|
|
749
|
+
(frame) => this.send(frame),
|
|
750
|
+
{ requestTimeoutMs: options?.brokerRequestTimeoutMs },
|
|
751
|
+
(frame) => this._socket.sendTelemetry(this._name, frame)
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* One frame from the broker for this slot: the broker's answer to one of
|
|
756
|
+
* {@link broker}'s requests, or MCP traffic for the server.
|
|
757
|
+
* @internal Called by the shared socket.
|
|
758
|
+
*/
|
|
759
|
+
_receive(frame) {
|
|
760
|
+
if (this.broker.handleIncoming(frame)) return;
|
|
761
|
+
this.onMessage?.(frame);
|
|
519
762
|
}
|
|
520
763
|
/**
|
|
521
764
|
* Convenience factory: creates a {@link MultiplexTransport} backed by a
|
|
@@ -528,7 +771,7 @@ var MultiplexTransport = class _MultiplexTransport {
|
|
|
528
771
|
* {@link DirectTransport} and is warned about on connect.
|
|
529
772
|
*/
|
|
530
773
|
static create(name, wsUrl, options) {
|
|
531
|
-
return new _MultiplexTransport(name, MultiplexSocket.getOrCreate(wsUrl), options);
|
|
774
|
+
return new _MultiplexTransport(name, MultiplexSocket.getOrCreate(wsUrl, handshakeHeaders(options)), options);
|
|
532
775
|
}
|
|
533
776
|
get isOpen() {
|
|
534
777
|
return this._socket.isOpen;
|
|
@@ -565,6 +808,6 @@ var MultiplexTransport = class _MultiplexTransport {
|
|
|
565
808
|
}
|
|
566
809
|
};
|
|
567
810
|
|
|
568
|
-
export { DirectTransport, MultiplexTransport, TUNNEL_REGISTER_METHOD, TunnelErrorCodes, decodeEnvelope, encodeEnvelope, encodeEnvelopeMessage, encodeErrorEnvelope, encodeRegisterEnvelope, encodeRegisterFrame, envelopeFrame, tunnelErrorOf };
|
|
811
|
+
export { AUDIT_RESULT_NOTIFICATION_METHOD, BrokerClient, BrokerRequestError, CALLER_META_KEY, DirectTransport, MultiplexTransport, TELEMETRY_NOTIFICATION_METHOD, TRACEPARENT_META_KEY, TUNNEL_REGISTER_METHOD, TunnelErrorCodes, callerReferenceOf, childTraceparent, decodeEnvelope, encodeEnvelope, encodeEnvelopeMessage, encodeErrorEnvelope, encodeRegisterEnvelope, encodeRegisterFrame, envelopeFrame, formatTraceparent, parseTraceparent, traceparentOf, tunnelErrorOf, withTraceparent };
|
|
569
812
|
//# sourceMappingURL=index.js.map
|
|
570
813
|
//# sourceMappingURL=index.js.map
|