@orkestrel/mcp 0.0.21 → 0.0.23
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/dist/src/core/index.d.cts +5 -0
- package/dist/src/core/index.d.ts +5 -0
- package/dist/src/server/index.cjs +97 -9
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +91 -7
- package/dist/src/server/index.d.ts +91 -7
- package/dist/src/server/index.js +96 -10
- package/dist/src/server/index.js.map +1 -1
- package/package.json +17 -15
|
@@ -2300,6 +2300,11 @@ export declare interface MCPClientTransportInterface {
|
|
|
2300
2300
|
* throwing. The client cannot enforce this from its side — the throw and the write are
|
|
2301
2301
|
* indistinguishable to it — so it is stated here, on the contract that owns it.
|
|
2302
2302
|
*
|
|
2303
|
+
* A transport whose channel confirms the write rejects on its failure. A transport whose
|
|
2304
|
+
* exchange reports through the emitter resolves. A transport whose channel cannot confirm a
|
|
2305
|
+
* write answers a closed channel from its own state, and each states which in its own
|
|
2306
|
+
* remarks.
|
|
2307
|
+
*
|
|
2303
2308
|
* @param message - The message to write to the wire
|
|
2304
2309
|
* @returns Resolves once the message has been sent, and rejects — never throws — when the
|
|
2305
2310
|
* write fails
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -2300,6 +2300,11 @@ export declare interface MCPClientTransportInterface {
|
|
|
2300
2300
|
* throwing. The client cannot enforce this from its side — the throw and the write are
|
|
2301
2301
|
* indistinguishable to it — so it is stated here, on the contract that owns it.
|
|
2302
2302
|
*
|
|
2303
|
+
* A transport whose channel confirms the write rejects on its failure. A transport whose
|
|
2304
|
+
* exchange reports through the emitter resolves. A transport whose channel cannot confirm a
|
|
2305
|
+
* write answers a closed channel from its own state, and each states which in its own
|
|
2306
|
+
* remarks.
|
|
2307
|
+
*
|
|
2303
2308
|
* @param message - The message to write to the wire
|
|
2304
2309
|
* @returns Resolves once the message has been sent, and rejects — never throws — when the
|
|
2305
2310
|
* write fails
|
|
@@ -85,6 +85,18 @@ var DEFAULT_MCP_SESSION_CAPACITY = 1024;
|
|
|
85
85
|
* this bounds the replay log paired with it.
|
|
86
86
|
*/
|
|
87
87
|
var DEFAULT_MCP_SESSION_TTL = 3e5;
|
|
88
|
+
/**
|
|
89
|
+
* The default bound in milliseconds on one unconfirmed write to a stdio client transport's
|
|
90
|
+
* child `stdin` — the `delivery` a `createStdioClientTransport` caller who supplies none gets.
|
|
91
|
+
*
|
|
92
|
+
* @remarks
|
|
93
|
+
* Ten seconds. The load-bearing property is the ordering, not the magnitude: this bound stays
|
|
94
|
+
* BELOW {@link import('@orkestrel/mcp').DEFAULT_MCP_REQUEST_TIMEOUT}, so a write the child never
|
|
95
|
+
* reads fails as an undeliverable message while the request that carried it is still open,
|
|
96
|
+
* rather than being masked by that request's own deadline expiring first. Override per
|
|
97
|
+
* transport with `delivery`; an explicit `0` there removes the bound.
|
|
98
|
+
*/
|
|
99
|
+
var DEFAULT_MCP_DELIVERY = 1e4;
|
|
88
100
|
//#endregion
|
|
89
101
|
//#region src/server/helpers.ts
|
|
90
102
|
/**
|
|
@@ -353,6 +365,34 @@ function extractLines(buffer, chunk) {
|
|
|
353
365
|
};
|
|
354
366
|
}
|
|
355
367
|
/**
|
|
368
|
+
* Writes one line to a Node writable stream and waits for its completion callback.
|
|
369
|
+
*
|
|
370
|
+
* @remarks
|
|
371
|
+
* The completion callback is the writable channel's backpressure boundary. A callback error and
|
|
372
|
+
* a synchronous `write` throw reject the returned promise with the original value.
|
|
373
|
+
*
|
|
374
|
+
* @param output - The writable stream that receives the line
|
|
375
|
+
* @param line - The complete line to write
|
|
376
|
+
* @returns Resolves when the stream confirms the write; rejects when the write fails
|
|
377
|
+
*
|
|
378
|
+
* @example
|
|
379
|
+
* ```ts
|
|
380
|
+
* await writeLine(process.stdout, '{"jsonrpc":"2.0","method":"ping"}\n')
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
function writeLine(output, line) {
|
|
384
|
+
return new Promise((resolve, reject) => {
|
|
385
|
+
try {
|
|
386
|
+
output.write(line, (error) => {
|
|
387
|
+
if (error === void 0 || error === null) resolve();
|
|
388
|
+
else reject(error);
|
|
389
|
+
});
|
|
390
|
+
} catch (error) {
|
|
391
|
+
reject(error);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
356
396
|
* Decodes and delivers each complete newline-framed line onto a {@link
|
|
357
397
|
* MCPClientTransportEventMap} emitter — the shared per-chunk dispatch step both stdio
|
|
358
398
|
* transports run their framed lines through: the server transport frames with {@link
|
|
@@ -1381,9 +1421,10 @@ var WebSocketClientTransport = class {
|
|
|
1381
1421
|
* - **Outbound (`send`).** `send(message)` writes one newline-terminated `JSON.stringify`d line
|
|
1382
1422
|
* through the supervisor's `send` and AWAITS its answer, so this promise settles only after the
|
|
1383
1423
|
* host reports the line handled rather than the moment the write is queued. The supervisor never
|
|
1384
|
-
* rejects — it answers `false` for a channel that was closed, destroyed, or ended,
|
|
1385
|
-
* that failed
|
|
1386
|
-
*
|
|
1424
|
+
* rejects — it answers `false` for a channel that was closed, destroyed, or ended, for a write
|
|
1425
|
+
* that failed, or for one that remained unconfirmed through `delivery`. A call made without a
|
|
1426
|
+
* live child rejects as not connected; a `false` answer from a live child rejects as unable to
|
|
1427
|
+
* deliver. The supervisor does not disclose which cause produced that answer.
|
|
1387
1428
|
* - **`close()`** runs the supervisor's bounded termination and teardown, then fires `close` once
|
|
1388
1429
|
* (idempotent). That teardown reaches the child's TERMINAL MOMENT, where the supervisor freezes
|
|
1389
1430
|
* `evidence`, ends `lines`, and settles `exit` together, so this transport needs no release of
|
|
@@ -1423,6 +1464,7 @@ var StdioClientTransport = class {
|
|
|
1423
1464
|
#command;
|
|
1424
1465
|
#args;
|
|
1425
1466
|
#env;
|
|
1467
|
+
#delivery;
|
|
1426
1468
|
#process = void 0;
|
|
1427
1469
|
#closing = void 0;
|
|
1428
1470
|
#closed = false;
|
|
@@ -1431,6 +1473,7 @@ var StdioClientTransport = class {
|
|
|
1431
1473
|
this.#command = options.command;
|
|
1432
1474
|
this.#args = options.args ?? [];
|
|
1433
1475
|
this.#env = options.env;
|
|
1476
|
+
this.#delivery = options.delivery ?? 1e4;
|
|
1434
1477
|
}
|
|
1435
1478
|
get emitter() {
|
|
1436
1479
|
return this.#emitter;
|
|
@@ -1462,6 +1505,7 @@ var StdioClientTransport = class {
|
|
|
1462
1505
|
},
|
|
1463
1506
|
workspace: process.cwd(),
|
|
1464
1507
|
grace: _orkestrel_process.PROCESS_GRACE,
|
|
1508
|
+
delivery: this.#delivery,
|
|
1465
1509
|
writable: true
|
|
1466
1510
|
});
|
|
1467
1511
|
this.#process = child;
|
|
@@ -1469,9 +1513,20 @@ var StdioClientTransport = class {
|
|
|
1469
1513
|
child.exit.then((exit) => this.#onExit(child, exit));
|
|
1470
1514
|
this.#pump(child);
|
|
1471
1515
|
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Sends one newline-delimited JSON-RPC message to the live child.
|
|
1518
|
+
*
|
|
1519
|
+
* @param message - The message to write to the child's `stdin`
|
|
1520
|
+
* @returns Resolves when the supervisor confirms the write
|
|
1521
|
+
* @throws Thrown with `stdio transport is not connected` when no live child is available before
|
|
1522
|
+
* the write
|
|
1523
|
+
* @throws Thrown with `stdio transport could not deliver the message` when a live child's write
|
|
1524
|
+
* resolves `false`
|
|
1525
|
+
*/
|
|
1472
1526
|
async send(message) {
|
|
1473
1527
|
const child = this.#closed ? void 0 : this.#process;
|
|
1474
|
-
if (
|
|
1528
|
+
if (child === void 0) throw new Error("stdio transport is not connected");
|
|
1529
|
+
if (!await child.send(JSON.stringify(message))) throw new Error("stdio transport could not deliver the message");
|
|
1475
1530
|
}
|
|
1476
1531
|
async close() {
|
|
1477
1532
|
if (this.#closed && this.#closing === void 0) return;
|
|
@@ -1532,8 +1587,10 @@ var StdioClientTransport = class {
|
|
|
1532
1587
|
* emits `error` (never throws). `input`'s `close` bridges to this
|
|
1533
1588
|
* transport's `close`.
|
|
1534
1589
|
* - **Outbound (`send`).** `send(message)` writes one newline-terminated
|
|
1535
|
-
* `JSON.stringify`d line to `output
|
|
1536
|
-
*
|
|
1590
|
+
* `JSON.stringify`d line to `output` and awaits the writable completion callback. The
|
|
1591
|
+
* callback is the backpressure boundary and its error rejects the send.
|
|
1592
|
+
* - **`close()`** removes this transport's input and output subscriptions, rejects every
|
|
1593
|
+
* pending send, and fires its `close`
|
|
1537
1594
|
* event (idempotent). It pauses the input only when the caller was not already reading
|
|
1538
1595
|
* it at `start` (`readableFlowing !== true`) AND no `data` listener remains once this
|
|
1539
1596
|
* transport's own is removed — so a process holding `process.stdin` can exit, and a
|
|
@@ -1556,6 +1613,7 @@ var StdioServerTransport = class {
|
|
|
1556
1613
|
#data = (chunk) => this.#receive(chunk.toString());
|
|
1557
1614
|
#ending = () => this.#onClose();
|
|
1558
1615
|
#failure = (error) => this.#emitter.emit("error", error);
|
|
1616
|
+
#pending = /* @__PURE__ */ new Set();
|
|
1559
1617
|
#buffer = "";
|
|
1560
1618
|
#started = false;
|
|
1561
1619
|
#closed = false;
|
|
@@ -1579,9 +1637,30 @@ var StdioServerTransport = class {
|
|
|
1579
1637
|
this.#input.on("data", this.#data);
|
|
1580
1638
|
this.#input.on("close", this.#ending);
|
|
1581
1639
|
this.#input.on("error", this.#failure);
|
|
1640
|
+
this.#output.on("error", this.#failure);
|
|
1582
1641
|
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Sends one newline-delimited JSON-RPC message through the caller-owned output stream.
|
|
1644
|
+
*
|
|
1645
|
+
* @remarks
|
|
1646
|
+
* The writable completion callback is the backpressure boundary. This method awaits that
|
|
1647
|
+
* callback rather than adding a `drain` listener. Closing the transport rejects every send
|
|
1648
|
+
* whose callback has not settled.
|
|
1649
|
+
*
|
|
1650
|
+
* @param message - The message to serialize and write
|
|
1651
|
+
* @returns Resolves when the output confirms the write
|
|
1652
|
+
* @throws Thrown with `stdio transport is not connected` after the transport closes
|
|
1653
|
+
* @throws Thrown with the output callback error or synchronous write failure
|
|
1654
|
+
*/
|
|
1583
1655
|
async send(message) {
|
|
1584
|
-
this.#
|
|
1656
|
+
if (this.#closed) throw new Error("stdio transport is not connected");
|
|
1657
|
+
const pending = Promise.withResolvers();
|
|
1658
|
+
this.#pending.add(pending);
|
|
1659
|
+
try {
|
|
1660
|
+
await Promise.race([writeLine(this.#output, `${JSON.stringify(message)}\n`), pending.promise]);
|
|
1661
|
+
} finally {
|
|
1662
|
+
this.#pending.delete(pending);
|
|
1663
|
+
}
|
|
1585
1664
|
}
|
|
1586
1665
|
async close() {
|
|
1587
1666
|
if (this.#closed) return;
|
|
@@ -1604,6 +1683,9 @@ var StdioServerTransport = class {
|
|
|
1604
1683
|
this.#input.removeListener("data", this.#data);
|
|
1605
1684
|
this.#input.removeListener("close", this.#ending);
|
|
1606
1685
|
this.#input.removeListener("error", this.#failure);
|
|
1686
|
+
this.#output.removeListener("error", this.#failure);
|
|
1687
|
+
for (const pending of this.#pending) pending.reject(/* @__PURE__ */ new Error("stdio transport is not connected"));
|
|
1688
|
+
this.#pending.clear();
|
|
1607
1689
|
if (!this.#flowing && this.#input.listenerCount("data") === 0) this.#input.pause();
|
|
1608
1690
|
}
|
|
1609
1691
|
};
|
|
@@ -1865,10 +1947,14 @@ function createWebSocketClientTransport(options) {
|
|
|
1865
1947
|
* inherits it. Each JSON-RPC message the client `send`s is written as one
|
|
1866
1948
|
* newline-terminated line to the child's `stdin`; each decoded reply line from the
|
|
1867
1949
|
* child's `stdout` is surfaced on the transport's `message` event for the client's
|
|
1868
|
-
* id correlation.
|
|
1950
|
+
* id correlation. That write is bounded: a child that stays alive without ever reading
|
|
1951
|
+
* its `stdin` fills the pipe, and `options.delivery` is how long the unconfirmed write
|
|
1952
|
+
* waits before the `send` rejects. An omitted `delivery` selects {@link
|
|
1953
|
+
* import('./constants.js').DEFAULT_MCP_DELIVERY}; an explicit `0` removes the bound.
|
|
1869
1954
|
*
|
|
1870
1955
|
* @param options - `command` (the executable to spawn; REQUIRED), optional `args`,
|
|
1871
|
-
* and optional `
|
|
1956
|
+
* optional `env`, and an optional `delivery` bound in milliseconds on an unconfirmed
|
|
1957
|
+
* `stdin` write; see {@link StdioClientTransportOptions}
|
|
1872
1958
|
* @returns A working {@link StdioClientTransportInterface} over a child process's stdio,
|
|
1873
1959
|
* whose `evidence` carries the supervised child's bounded stderr tail
|
|
1874
1960
|
*
|
|
@@ -2107,6 +2193,7 @@ function createMCPSession(options) {
|
|
|
2107
2193
|
};
|
|
2108
2194
|
}
|
|
2109
2195
|
//#endregion
|
|
2196
|
+
exports.DEFAULT_MCP_DELIVERY = DEFAULT_MCP_DELIVERY;
|
|
2110
2197
|
exports.DEFAULT_MCP_KEEPALIVE_INTERVAL = DEFAULT_MCP_KEEPALIVE_INTERVAL;
|
|
2111
2198
|
exports.DEFAULT_MCP_PATH = DEFAULT_MCP_PATH;
|
|
2112
2199
|
exports.DEFAULT_MCP_SESSION_CAPACITY = DEFAULT_MCP_SESSION_CAPACITY;
|
|
@@ -2151,5 +2238,6 @@ exports.readSessionHeader = readSessionHeader;
|
|
|
2151
2238
|
exports.rejectUnknownSession = rejectUnknownSession;
|
|
2152
2239
|
exports.sendEventStream = sendEventStream;
|
|
2153
2240
|
exports.upgradeRequestPath = upgradeRequestPath;
|
|
2241
|
+
exports.writeLine = writeLine;
|
|
2154
2242
|
|
|
2155
2243
|
//# sourceMappingURL=index.cjs.map
|