minecraft-bedrock-mcp-server 0.1.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/LICENSE +21 -0
- package/README.md +577 -0
- package/dist/bridge/event-route.d.ts +11 -0
- package/dist/bridge/event-route.d.ts.map +1 -0
- package/dist/bridge/event-route.js +28 -0
- package/dist/bridge/event-route.js.map +1 -0
- package/dist/bridge/handshake-route.d.ts +11 -0
- package/dist/bridge/handshake-route.d.ts.map +1 -0
- package/dist/bridge/handshake-route.js +45 -0
- package/dist/bridge/handshake-route.js.map +1 -0
- package/dist/bridge/poll-route.d.ts +11 -0
- package/dist/bridge/poll-route.d.ts.map +1 -0
- package/dist/bridge/poll-route.js +28 -0
- package/dist/bridge/poll-route.js.map +1 -0
- package/dist/bridge/result-route.d.ts +10 -0
- package/dist/bridge/result-route.d.ts.map +1 -0
- package/dist/bridge/result-route.js +23 -0
- package/dist/bridge/result-route.js.map +1 -0
- package/dist/config/config-error.d.ts +12 -0
- package/dist/config/config-error.d.ts.map +1 -0
- package/dist/config/config-error.js +13 -0
- package/dist/config/config-error.js.map +1 -0
- package/dist/config/environment.d.ts +89 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +73 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/config/tls.d.ts +15 -0
- package/dist/config/tls.d.ts.map +1 -0
- package/dist/config/tls.js +27 -0
- package/dist/config/tls.js.map +1 -0
- package/dist/errors/bridge-error.d.ts +41 -0
- package/dist/errors/bridge-error.d.ts.map +1 -0
- package/dist/errors/bridge-error.js +33 -0
- package/dist/errors/bridge-error.js.map +1 -0
- package/dist/errors/error-codes.d.ts +13 -0
- package/dist/errors/error-codes.d.ts.map +1 -0
- package/dist/errors/error-codes.js +41 -0
- package/dist/errors/error-codes.js.map +1 -0
- package/dist/events/subscription-registry.d.ts +55 -0
- package/dist/events/subscription-registry.d.ts.map +1 -0
- package/dist/events/subscription-registry.js +64 -0
- package/dist/events/subscription-registry.js.map +1 -0
- package/dist/http/app.d.ts +26 -0
- package/dist/http/app.d.ts.map +1 -0
- package/dist/http/app.js +88 -0
- package/dist/http/app.js.map +1 -0
- package/dist/http/authentication.d.ts +11 -0
- package/dist/http/authentication.d.ts.map +1 -0
- package/dist/http/authentication.js +36 -0
- package/dist/http/authentication.js.map +1 -0
- package/dist/http/health-route.d.ts +10 -0
- package/dist/http/health-route.d.ts.map +1 -0
- package/dist/http/health-route.js +18 -0
- package/dist/http/health-route.js.map +1 -0
- package/dist/http/metrics-route.d.ts +8 -0
- package/dist/http/metrics-route.d.ts.map +1 -0
- package/dist/http/metrics-route.js +11 -0
- package/dist/http/metrics-route.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +134 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/mcp-route.d.ts +12 -0
- package/dist/mcp/mcp-route.d.ts.map +1 -0
- package/dist/mcp/mcp-route.js +49 -0
- package/dist/mcp/mcp-route.js.map +1 -0
- package/dist/mcp/mcp-server-factory.d.ts +20 -0
- package/dist/mcp/mcp-server-factory.d.ts.map +1 -0
- package/dist/mcp/mcp-server-factory.js +23 -0
- package/dist/mcp/mcp-server-factory.js.map +1 -0
- package/dist/mcp/session-manager.d.ts +30 -0
- package/dist/mcp/session-manager.d.ts.map +1 -0
- package/dist/mcp/session-manager.js +38 -0
- package/dist/mcp/session-manager.js.map +1 -0
- package/dist/mcp/tool-registry.d.ts +15 -0
- package/dist/mcp/tool-registry.d.ts.map +1 -0
- package/dist/mcp/tool-registry.js +27 -0
- package/dist/mcp/tool-registry.js.map +1 -0
- package/dist/observability/logger.d.ts +16 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +19 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +27 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +72 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/protocol/command.d.ts +92 -0
- package/dist/protocol/command.d.ts.map +1 -0
- package/dist/protocol/command.js +37 -0
- package/dist/protocol/command.js.map +1 -0
- package/dist/protocol/event.d.ts +82 -0
- package/dist/protocol/event.d.ts.map +1 -0
- package/dist/protocol/event.js +37 -0
- package/dist/protocol/event.js.map +1 -0
- package/dist/protocol/handshake.d.ts +150 -0
- package/dist/protocol/handshake.d.ts.map +1 -0
- package/dist/protocol/handshake.js +65 -0
- package/dist/protocol/handshake.js.map +1 -0
- package/dist/protocol/index.d.ts +14 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +14 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/protocol-version.d.ts +18 -0
- package/dist/protocol/protocol-version.d.ts.map +1 -0
- package/dist/protocol/protocol-version.js +28 -0
- package/dist/protocol/protocol-version.js.map +1 -0
- package/dist/protocol/result.d.ts +79 -0
- package/dist/protocol/result.d.ts.map +1 -0
- package/dist/protocol/result.js +35 -0
- package/dist/protocol/result.js.map +1 -0
- package/dist/queue/command-id.d.ts +15 -0
- package/dist/queue/command-id.d.ts.map +1 -0
- package/dist/queue/command-id.js +38 -0
- package/dist/queue/command-id.js.map +1 -0
- package/dist/queue/command-queue.d.ts +90 -0
- package/dist/queue/command-queue.d.ts.map +1 -0
- package/dist/queue/command-queue.js +151 -0
- package/dist/queue/command-queue.js.map +1 -0
- package/dist/queue/command-throttle.d.ts +38 -0
- package/dist/queue/command-throttle.d.ts.map +1 -0
- package/dist/queue/command-throttle.js +26 -0
- package/dist/queue/command-throttle.js.map +1 -0
- package/dist/queue/instrumented-command-queue.d.ts +9 -0
- package/dist/queue/instrumented-command-queue.d.ts.map +1 -0
- package/dist/queue/instrumented-command-queue.js +39 -0
- package/dist/queue/instrumented-command-queue.js.map +1 -0
- package/dist/queue/pending-commands.d.ts +35 -0
- package/dist/queue/pending-commands.d.ts.map +1 -0
- package/dist/queue/pending-commands.js +41 -0
- package/dist/queue/pending-commands.js.map +1 -0
- package/dist/server-info.d.ts +5 -0
- package/dist/server-info.d.ts.map +1 -0
- package/dist/server-info.js +22 -0
- package/dist/server-info.js.map +1 -0
- package/dist/structures/structure-file-store.d.ts +22 -0
- package/dist/structures/structure-file-store.d.ts.map +1 -0
- package/dist/structures/structure-file-store.js +89 -0
- package/dist/structures/structure-file-store.js.map +1 -0
- package/dist/tools/block-tools.d.ts +4 -0
- package/dist/tools/block-tools.d.ts.map +1 -0
- package/dist/tools/block-tools.js +111 -0
- package/dist/tools/block-tools.js.map +1 -0
- package/dist/tools/command-tools.d.ts +4 -0
- package/dist/tools/command-tools.d.ts.map +1 -0
- package/dist/tools/command-tools.js +23 -0
- package/dist/tools/command-tools.js.map +1 -0
- package/dist/tools/common-schemas.d.ts +65 -0
- package/dist/tools/common-schemas.d.ts.map +1 -0
- package/dist/tools/common-schemas.js +32 -0
- package/dist/tools/common-schemas.js.map +1 -0
- package/dist/tools/effect-tools.d.ts +4 -0
- package/dist/tools/effect-tools.d.ts.map +1 -0
- package/dist/tools/effect-tools.js +32 -0
- package/dist/tools/effect-tools.js.map +1 -0
- package/dist/tools/entity-tools.d.ts +4 -0
- package/dist/tools/entity-tools.d.ts.map +1 -0
- package/dist/tools/entity-tools.js +133 -0
- package/dist/tools/entity-tools.js.map +1 -0
- package/dist/tools/event-tools.d.ts +4 -0
- package/dist/tools/event-tools.d.ts.map +1 -0
- package/dist/tools/event-tools.js +84 -0
- package/dist/tools/event-tools.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +30 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inventory-tools.d.ts +4 -0
- package/dist/tools/inventory-tools.d.ts.map +1 -0
- package/dist/tools/inventory-tools.js +52 -0
- package/dist/tools/inventory-tools.js.map +1 -0
- package/dist/tools/player-tools.d.ts +4 -0
- package/dist/tools/player-tools.d.ts.map +1 -0
- package/dist/tools/player-tools.js +117 -0
- package/dist/tools/player-tools.js.map +1 -0
- package/dist/tools/property-tools.d.ts +4 -0
- package/dist/tools/property-tools.d.ts.map +1 -0
- package/dist/tools/property-tools.js +45 -0
- package/dist/tools/property-tools.js.map +1 -0
- package/dist/tools/scoreboard-tools.d.ts +4 -0
- package/dist/tools/scoreboard-tools.d.ts.map +1 -0
- package/dist/tools/scoreboard-tools.js +68 -0
- package/dist/tools/scoreboard-tools.js.map +1 -0
- package/dist/tools/server-tools.d.ts +4 -0
- package/dist/tools/server-tools.d.ts.map +1 -0
- package/dist/tools/server-tools.js +25 -0
- package/dist/tools/server-tools.js.map +1 -0
- package/dist/tools/structure-file-tools.d.ts +4 -0
- package/dist/tools/structure-file-tools.d.ts.map +1 -0
- package/dist/tools/structure-file-tools.js +57 -0
- package/dist/tools/structure-file-tools.js.map +1 -0
- package/dist/tools/structure-tools.d.ts +4 -0
- package/dist/tools/structure-tools.d.ts.map +1 -0
- package/dist/tools/structure-tools.js +91 -0
- package/dist/tools/structure-tools.js.map +1 -0
- package/dist/tools/tool-definition.d.ts +68 -0
- package/dist/tools/tool-definition.d.ts.map +1 -0
- package/dist/tools/tool-definition.js +40 -0
- package/dist/tools/tool-definition.js.map +1 -0
- package/dist/tools/tool-result.d.ts +17 -0
- package/dist/tools/tool-result.d.ts.map +1 -0
- package/dist/tools/tool-result.js +52 -0
- package/dist/tools/tool-result.js.map +1 -0
- package/dist/tools/world-tools.d.ts +4 -0
- package/dist/tools/world-tools.d.ts.map +1 -0
- package/dist/tools/world-tools.js +97 -0
- package/dist/tools/world-tools.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { HandshakeRequestSchema, PROTOCOL_VERSION, isProtocolCompatible, } from "../protocol/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Registers `POST /handshake` (mounted at `/bridge/handshake`).
|
|
4
|
+
*
|
|
5
|
+
* Negotiates the bridge protocol version on behavior-pack startup. A pack
|
|
6
|
+
* whose major version differs is refused with `409`. On acceptance the
|
|
7
|
+
* response replays active subscriptions so a restarted pack re-arms them.
|
|
8
|
+
*/
|
|
9
|
+
export function registerHandshakeRoute(app, serverVersion, pollTimeoutMs, subscriptions) {
|
|
10
|
+
app.post("/handshake", (request, reply) => {
|
|
11
|
+
const parsed = HandshakeRequestSchema.safeParse(request.body);
|
|
12
|
+
if (!parsed.success) {
|
|
13
|
+
return reply
|
|
14
|
+
.code(400)
|
|
15
|
+
.send({ error: { code: "INVALID_INPUT", message: "malformed handshake request" } });
|
|
16
|
+
}
|
|
17
|
+
if (!isProtocolCompatible(parsed.data.protocol_version)) {
|
|
18
|
+
request.log.warn({ peerProtocolVersion: parsed.data.protocol_version }, "refused behavior pack with incompatible bridge protocol");
|
|
19
|
+
const rejection = {
|
|
20
|
+
accepted: false,
|
|
21
|
+
reason: `incompatible bridge protocol version '${parsed.data.protocol_version}'`,
|
|
22
|
+
server_protocol_version: PROTOCOL_VERSION,
|
|
23
|
+
};
|
|
24
|
+
return reply.code(409).send(rejection);
|
|
25
|
+
}
|
|
26
|
+
request.log.info({
|
|
27
|
+
worldId: parsed.data.world_id,
|
|
28
|
+
behaviorPackVersion: parsed.data.behavior_pack_version,
|
|
29
|
+
minecraftVersion: parsed.data.minecraft_version,
|
|
30
|
+
}, "behavior pack connected");
|
|
31
|
+
const acceptance = {
|
|
32
|
+
accepted: true,
|
|
33
|
+
server_version: serverVersion,
|
|
34
|
+
protocol_version: PROTOCOL_VERSION,
|
|
35
|
+
poll_timeout_ms: pollTimeoutMs,
|
|
36
|
+
resync_subscriptions: subscriptions.list().map((subscription) => ({
|
|
37
|
+
subscription_id: subscription.id,
|
|
38
|
+
event_type: subscription.eventType,
|
|
39
|
+
filter: subscription.filter,
|
|
40
|
+
})),
|
|
41
|
+
};
|
|
42
|
+
return reply.code(200).send(acceptance);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=handshake-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake-route.js","sourceRoot":"","sources":["../../src/bridge/handshake-route.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAoB,EACpB,aAAqB,EACrB,aAAqB,EACrB,aAAmC;IAEnC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,KAAK;iBACT,IAAI,CAAC,GAAG,CAAC;iBACT,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,6BAA6B,EAAE,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,IAAI,CACd,EAAE,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,EACrD,yDAAyD,CAC1D,CAAC;YACF,MAAM,SAAS,GAAsB;gBACnC,QAAQ,EAAE,KAAK;gBACf,MAAM,EAAE,yCAAyC,MAAM,CAAC,IAAI,CAAC,gBAAgB,GAAG;gBAChF,uBAAuB,EAAE,gBAAgB;aAC1C,CAAC;YACF,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CACd;YACE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ;YAC7B,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB;YACtD,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB;SAChD,EACD,yBAAyB,CAC1B,CAAC;QACF,MAAM,UAAU,GAAsB;YACpC,QAAQ,EAAE,IAAI;YACd,cAAc,EAAE,aAAa;YAC7B,gBAAgB,EAAE,gBAAgB;YAClC,eAAe,EAAE,aAAa;YAC9B,oBAAoB,EAAE,aAAa,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;gBAChE,eAAe,EAAE,YAAY,CAAC,EAAE;gBAChC,UAAU,EAAE,YAAY,CAAC,SAAS;gBAClC,MAAM,EAAE,YAAY,CAAC,MAAM;aAC5B,CAAC,CAAC;SACJ,CAAC;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { CommandQueue } from "../queue/command-queue.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registers `GET /poll` (mounted at `/bridge/poll`).
|
|
5
|
+
*
|
|
6
|
+
* Long-polls the command queue: the request is held open until commands are
|
|
7
|
+
* available or the poll timeout elapses. Closing the connection aborts the
|
|
8
|
+
* wait so commands are never handed to a dead socket.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerPollRoute(app: FastifyInstance, queue: CommandQueue, pollTimeoutMs: number): void;
|
|
11
|
+
//# sourceMappingURL=poll-route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-route.d.ts","sourceRoot":"","sources":["../../src/bridge/poll-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAK9D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,GACpB,IAAI,CAmBN"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Maximum number of commands handed to the behavior pack in one poll. */
|
|
2
|
+
const POLL_BATCH_SIZE = 32;
|
|
3
|
+
/**
|
|
4
|
+
* Registers `GET /poll` (mounted at `/bridge/poll`).
|
|
5
|
+
*
|
|
6
|
+
* Long-polls the command queue: the request is held open until commands are
|
|
7
|
+
* available or the poll timeout elapses. Closing the connection aborts the
|
|
8
|
+
* wait so commands are never handed to a dead socket.
|
|
9
|
+
*/
|
|
10
|
+
export function registerPollRoute(app, queue, pollTimeoutMs) {
|
|
11
|
+
app.get("/poll", async (request) => {
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
request.raw.on("close", () => {
|
|
14
|
+
controller.abort();
|
|
15
|
+
});
|
|
16
|
+
const commands = await queue.dequeue({
|
|
17
|
+
max: POLL_BATCH_SIZE,
|
|
18
|
+
timeoutMs: pollTimeoutMs,
|
|
19
|
+
signal: controller.signal,
|
|
20
|
+
});
|
|
21
|
+
const response = {
|
|
22
|
+
commands,
|
|
23
|
+
server_time: new Date().toISOString(),
|
|
24
|
+
};
|
|
25
|
+
return response;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=poll-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-route.js","sourceRoot":"","sources":["../../src/bridge/poll-route.ts"],"names":[],"mappings":"AAIA,0EAA0E;AAC1E,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAoB,EACpB,KAAmB,EACnB,aAAqB;IAErB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACjC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;YACnC,GAAG,EAAE,eAAe;YACpB,SAAS,EAAE,aAAa;YACxB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAiB;YAC7B,QAAQ;YACR,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC,CAAC;QACF,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { CommandQueue } from "../queue/command-queue.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registers `POST /result` (mounted at `/bridge/result`).
|
|
5
|
+
*
|
|
6
|
+
* Settles the command correlated by `id`. A result for an unknown or expired
|
|
7
|
+
* command is acknowledged but logged — it is not an error for the pack.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerResultRoute(app: FastifyInstance, queue: CommandQueue): void;
|
|
10
|
+
//# sourceMappingURL=result-route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-route.d.ts","sourceRoot":"","sources":["../../src/bridge/result-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAkBnF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CommandResultSchema } from "../protocol/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Registers `POST /result` (mounted at `/bridge/result`).
|
|
4
|
+
*
|
|
5
|
+
* Settles the command correlated by `id`. A result for an unknown or expired
|
|
6
|
+
* command is acknowledged but logged — it is not an error for the pack.
|
|
7
|
+
*/
|
|
8
|
+
export function registerResultRoute(app, queue) {
|
|
9
|
+
app.post("/result", (request, reply) => {
|
|
10
|
+
const parsed = CommandResultSchema.safeParse(request.body);
|
|
11
|
+
if (!parsed.success) {
|
|
12
|
+
return reply
|
|
13
|
+
.code(400)
|
|
14
|
+
.send({ error: { code: "INVALID_INPUT", message: "malformed command result" } });
|
|
15
|
+
}
|
|
16
|
+
const matched = queue.settle(parsed.data);
|
|
17
|
+
if (!matched) {
|
|
18
|
+
request.log.warn({ commandId: parsed.data.id }, "received result for an unknown or expired command");
|
|
19
|
+
}
|
|
20
|
+
return reply.code(202).send({ accepted: matched });
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=result-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-route.js","sourceRoot":"","sources":["../../src/bridge/result-route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAoB,EAAE,KAAmB;IAC3E,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,KAAK;iBACT,IAAI,CAAC,GAAG,CAAC;iBACT,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,0BAA0B,EAAE,EAAE,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,IAAI,CACd,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAC7B,mDAAmD,CACpD,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raised when server configuration is missing or invalid.
|
|
3
|
+
*
|
|
4
|
+
* A `ConfigError` is fatal: it is thrown during startup, before the server
|
|
5
|
+
* begins listening, and the process exits with a non-zero status.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ConfigError extends Error {
|
|
8
|
+
constructor(message: string, options?: {
|
|
9
|
+
cause?: unknown;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=config-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-error.d.ts","sourceRoot":"","sources":["../../src/config/config-error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raised when server configuration is missing or invalid.
|
|
3
|
+
*
|
|
4
|
+
* A `ConfigError` is fatal: it is thrown during startup, before the server
|
|
5
|
+
* begins listening, and the process exits with a non-zero status.
|
|
6
|
+
*/
|
|
7
|
+
export class ConfigError extends Error {
|
|
8
|
+
constructor(message, options) {
|
|
9
|
+
super(message, options);
|
|
10
|
+
this.name = "ConfigError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=config-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-error.js","sourceRoot":"","sources":["../../src/config/config-error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const EnvironmentSchema: z.ZodObject<{
|
|
3
|
+
/** Bind address. `0.0.0.0` is reachable across the LAN. */
|
|
4
|
+
BRIDGE_HOST: z.ZodDefault<z.ZodString>;
|
|
5
|
+
/** HTTP/HTTPS port. */
|
|
6
|
+
BRIDGE_PORT: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
/** Path to the TLS certificate PEM. Set together with `BRIDGE_TLS_KEY`. */
|
|
8
|
+
BRIDGE_TLS_CERT: z.ZodOptional<z.ZodString>;
|
|
9
|
+
/** Path to the TLS private key PEM. Set together with `BRIDGE_TLS_CERT`. */
|
|
10
|
+
BRIDGE_TLS_KEY: z.ZodOptional<z.ZodString>;
|
|
11
|
+
/** Bearer token for MCP clients on the `/mcp` surface. */
|
|
12
|
+
BRIDGE_CLIENT_TOKEN: z.ZodString;
|
|
13
|
+
/** Bearer token for the behavior pack on the `/bridge` surface. */
|
|
14
|
+
BRIDGE_AGENT_TOKEN: z.ZodString;
|
|
15
|
+
/** Absolute path to the active BDS world folder. */
|
|
16
|
+
BRIDGE_WORLD_PATH: z.ZodString;
|
|
17
|
+
/** Absolute path to the behavior pack folder inside the world. */
|
|
18
|
+
BRIDGE_BEHAVIOR_PACK_PATH: z.ZodString;
|
|
19
|
+
/** pino log level. */
|
|
20
|
+
BRIDGE_LOG_LEVEL: z.ZodDefault<z.ZodEnum<["fatal", "error", "warn", "info", "debug", "trace", "silent"]>>;
|
|
21
|
+
/** Long-poll hold time, in milliseconds, for `GET /bridge/poll`. */
|
|
22
|
+
BRIDGE_POLL_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
/** How long, in milliseconds, a tool call awaits a behavior-pack result. */
|
|
24
|
+
BRIDGE_COMMAND_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
|
|
25
|
+
/** Per-token request rate limit, in requests per minute, on `/mcp`. */
|
|
26
|
+
BRIDGE_RATE_LIMIT_RPM: z.ZodDefault<z.ZodNumber>;
|
|
27
|
+
/** Comma-separated allowed CORS origins; unset disables CORS. */
|
|
28
|
+
BRIDGE_CORS_ORIGINS: z.ZodOptional<z.ZodString>;
|
|
29
|
+
/** Trust `X-Forwarded-*` headers — enable when running behind a reverse proxy. */
|
|
30
|
+
BRIDGE_TRUST_PROXY: z.ZodDefault<z.ZodEffects<z.ZodEnum<["true", "false"]>, boolean, "true" | "false">>;
|
|
31
|
+
/** Maximum accepted request body size, in bytes. */
|
|
32
|
+
BRIDGE_MAX_BODY_BYTES: z.ZodDefault<z.ZodNumber>;
|
|
33
|
+
/** Maximum outstanding commands before enqueue fails with `QUEUE_FULL`. */
|
|
34
|
+
BRIDGE_QUEUE_MAX: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
/** Enables the Prometheus `/metrics` endpoint. */
|
|
36
|
+
BRIDGE_METRICS_ENABLED: z.ZodDefault<z.ZodEffects<z.ZodEnum<["true", "false"]>, boolean, "true" | "false">>;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
BRIDGE_HOST: string;
|
|
39
|
+
BRIDGE_PORT: number;
|
|
40
|
+
BRIDGE_CLIENT_TOKEN: string;
|
|
41
|
+
BRIDGE_AGENT_TOKEN: string;
|
|
42
|
+
BRIDGE_WORLD_PATH: string;
|
|
43
|
+
BRIDGE_BEHAVIOR_PACK_PATH: string;
|
|
44
|
+
BRIDGE_LOG_LEVEL: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent";
|
|
45
|
+
BRIDGE_POLL_TIMEOUT_MS: number;
|
|
46
|
+
BRIDGE_COMMAND_TIMEOUT_MS: number;
|
|
47
|
+
BRIDGE_RATE_LIMIT_RPM: number;
|
|
48
|
+
BRIDGE_TRUST_PROXY: boolean;
|
|
49
|
+
BRIDGE_MAX_BODY_BYTES: number;
|
|
50
|
+
BRIDGE_QUEUE_MAX: number;
|
|
51
|
+
BRIDGE_METRICS_ENABLED: boolean;
|
|
52
|
+
BRIDGE_TLS_CERT?: string | undefined;
|
|
53
|
+
BRIDGE_TLS_KEY?: string | undefined;
|
|
54
|
+
BRIDGE_CORS_ORIGINS?: string | undefined;
|
|
55
|
+
}, {
|
|
56
|
+
BRIDGE_CLIENT_TOKEN: string;
|
|
57
|
+
BRIDGE_AGENT_TOKEN: string;
|
|
58
|
+
BRIDGE_WORLD_PATH: string;
|
|
59
|
+
BRIDGE_BEHAVIOR_PACK_PATH: string;
|
|
60
|
+
BRIDGE_HOST?: string | undefined;
|
|
61
|
+
BRIDGE_PORT?: number | undefined;
|
|
62
|
+
BRIDGE_TLS_CERT?: string | undefined;
|
|
63
|
+
BRIDGE_TLS_KEY?: string | undefined;
|
|
64
|
+
BRIDGE_LOG_LEVEL?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent" | undefined;
|
|
65
|
+
BRIDGE_POLL_TIMEOUT_MS?: number | undefined;
|
|
66
|
+
BRIDGE_COMMAND_TIMEOUT_MS?: number | undefined;
|
|
67
|
+
BRIDGE_RATE_LIMIT_RPM?: number | undefined;
|
|
68
|
+
BRIDGE_CORS_ORIGINS?: string | undefined;
|
|
69
|
+
BRIDGE_TRUST_PROXY?: "true" | "false" | undefined;
|
|
70
|
+
BRIDGE_MAX_BODY_BYTES?: number | undefined;
|
|
71
|
+
BRIDGE_QUEUE_MAX?: number | undefined;
|
|
72
|
+
BRIDGE_METRICS_ENABLED?: "true" | "false" | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
/** Validated server configuration, derived from the process environment. */
|
|
75
|
+
export type Environment = z.infer<typeof EnvironmentSchema>;
|
|
76
|
+
/**
|
|
77
|
+
* Resolves the configured CORS origins.
|
|
78
|
+
*
|
|
79
|
+
* @returns The list of allowed origins, or `null` when CORS is disabled.
|
|
80
|
+
*/
|
|
81
|
+
export declare function corsOrigins(env: Environment): string[] | null;
|
|
82
|
+
/**
|
|
83
|
+
* Validates the process environment and returns typed configuration.
|
|
84
|
+
*
|
|
85
|
+
* @throws {ConfigError} when a required variable is missing or a value is invalid.
|
|
86
|
+
*/
|
|
87
|
+
export declare function loadEnvironment(source?: NodeJS.ProcessEnv): Environment;
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,QAAA,MAAM,iBAAiB;IACrB,2DAA2D;;IAE3D,uBAAuB;;IAEvB,2EAA2E;;IAE3E,4EAA4E;;IAE5E,0DAA0D;;IAE1D,mEAAmE;;IAEnE,oDAAoD;;IAEpD,kEAAkE;;IAElE,sBAAsB;;IAEtB,oEAAoE;;IAEpE,4EAA4E;;IAE5E,uEAAuE;;IAEvE,iEAAiE;;IAEjE,kFAAkF;;IAElF,oDAAoD;;IAMpD,2EAA2E;;IAE3E,kDAAkD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAElD,CAAC;AAEH,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,IAAI,CAM7D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,GAAE,MAAM,CAAC,UAAwB,GAAG,WAAW,CAQpF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ConfigError } from "./config-error.js";
|
|
3
|
+
const LOG_LEVELS = ["fatal", "error", "warn", "info", "debug", "trace", "silent"];
|
|
4
|
+
/** A boolean parsed from an environment-variable string. */
|
|
5
|
+
const EnvBoolean = z.enum(["true", "false"]).transform((value) => value === "true");
|
|
6
|
+
const EnvironmentSchema = z.object({
|
|
7
|
+
/** Bind address. `0.0.0.0` is reachable across the LAN. */
|
|
8
|
+
BRIDGE_HOST: z.string().min(1).default("0.0.0.0"),
|
|
9
|
+
/** HTTP/HTTPS port. */
|
|
10
|
+
BRIDGE_PORT: z.coerce.number().int().min(1).max(65535).default(8765),
|
|
11
|
+
/** Path to the TLS certificate PEM. Set together with `BRIDGE_TLS_KEY`. */
|
|
12
|
+
BRIDGE_TLS_CERT: z.string().min(1).optional(),
|
|
13
|
+
/** Path to the TLS private key PEM. Set together with `BRIDGE_TLS_CERT`. */
|
|
14
|
+
BRIDGE_TLS_KEY: z.string().min(1).optional(),
|
|
15
|
+
/** Bearer token for MCP clients on the `/mcp` surface. */
|
|
16
|
+
BRIDGE_CLIENT_TOKEN: z.string().min(1),
|
|
17
|
+
/** Bearer token for the behavior pack on the `/bridge` surface. */
|
|
18
|
+
BRIDGE_AGENT_TOKEN: z.string().min(1),
|
|
19
|
+
/** Absolute path to the active BDS world folder. */
|
|
20
|
+
BRIDGE_WORLD_PATH: z.string().min(1),
|
|
21
|
+
/** Absolute path to the behavior pack folder inside the world. */
|
|
22
|
+
BRIDGE_BEHAVIOR_PACK_PATH: z.string().min(1),
|
|
23
|
+
/** pino log level. */
|
|
24
|
+
BRIDGE_LOG_LEVEL: z.enum(LOG_LEVELS).default("info"),
|
|
25
|
+
/** Long-poll hold time, in milliseconds, for `GET /bridge/poll`. */
|
|
26
|
+
BRIDGE_POLL_TIMEOUT_MS: z.coerce.number().int().positive().default(30_000),
|
|
27
|
+
/** How long, in milliseconds, a tool call awaits a behavior-pack result. */
|
|
28
|
+
BRIDGE_COMMAND_TIMEOUT_MS: z.coerce.number().int().positive().default(15_000),
|
|
29
|
+
/** Per-token request rate limit, in requests per minute, on `/mcp`. */
|
|
30
|
+
BRIDGE_RATE_LIMIT_RPM: z.coerce.number().int().positive().default(60),
|
|
31
|
+
/** Comma-separated allowed CORS origins; unset disables CORS. */
|
|
32
|
+
BRIDGE_CORS_ORIGINS: z.string().optional(),
|
|
33
|
+
/** Trust `X-Forwarded-*` headers — enable when running behind a reverse proxy. */
|
|
34
|
+
BRIDGE_TRUST_PROXY: EnvBoolean.default("false"),
|
|
35
|
+
/** Maximum accepted request body size, in bytes. */
|
|
36
|
+
BRIDGE_MAX_BODY_BYTES: z.coerce
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.positive()
|
|
40
|
+
.default(16 * 1024 * 1024),
|
|
41
|
+
/** Maximum outstanding commands before enqueue fails with `QUEUE_FULL`. */
|
|
42
|
+
BRIDGE_QUEUE_MAX: z.coerce.number().int().positive().default(256),
|
|
43
|
+
/** Enables the Prometheus `/metrics` endpoint. */
|
|
44
|
+
BRIDGE_METRICS_ENABLED: EnvBoolean.default("false"),
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Resolves the configured CORS origins.
|
|
48
|
+
*
|
|
49
|
+
* @returns The list of allowed origins, or `null` when CORS is disabled.
|
|
50
|
+
*/
|
|
51
|
+
export function corsOrigins(env) {
|
|
52
|
+
if (env.BRIDGE_CORS_ORIGINS === undefined)
|
|
53
|
+
return null;
|
|
54
|
+
const origins = env.BRIDGE_CORS_ORIGINS.split(",")
|
|
55
|
+
.map((origin) => origin.trim())
|
|
56
|
+
.filter((origin) => origin.length > 0);
|
|
57
|
+
return origins.length > 0 ? origins : null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validates the process environment and returns typed configuration.
|
|
61
|
+
*
|
|
62
|
+
* @throws {ConfigError} when a required variable is missing or a value is invalid.
|
|
63
|
+
*/
|
|
64
|
+
export function loadEnvironment(source = process.env) {
|
|
65
|
+
const result = EnvironmentSchema.safeParse(source);
|
|
66
|
+
if (result.success)
|
|
67
|
+
return result.data;
|
|
68
|
+
const detail = result.error.issues
|
|
69
|
+
.map((issue) => ` - ${issue.path.join(".") || "(root)"}: ${issue.message}`)
|
|
70
|
+
.join("\n");
|
|
71
|
+
throw new ConfigError(`invalid configuration:\n${detail}`);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Environment } from "./environment.js";
|
|
2
|
+
/** TLS certificate and private key material, loaded into memory. */
|
|
3
|
+
export interface TlsMaterial {
|
|
4
|
+
readonly cert: Buffer;
|
|
5
|
+
readonly key: Buffer;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Loads TLS material from the configured certificate and key paths.
|
|
9
|
+
*
|
|
10
|
+
* @returns The material when both paths are set; `null` when neither is set,
|
|
11
|
+
* in which case the server listens over plain HTTP.
|
|
12
|
+
* @throws {ConfigError} when exactly one path is set, or a file cannot be read.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadTlsMaterial(env: Environment): TlsMaterial | null;
|
|
15
|
+
//# sourceMappingURL=tls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls.d.ts","sourceRoot":"","sources":["../../src/config/tls.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAkBpE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { ConfigError } from "./config-error.js";
|
|
3
|
+
/**
|
|
4
|
+
* Loads TLS material from the configured certificate and key paths.
|
|
5
|
+
*
|
|
6
|
+
* @returns The material when both paths are set; `null` when neither is set,
|
|
7
|
+
* in which case the server listens over plain HTTP.
|
|
8
|
+
* @throws {ConfigError} when exactly one path is set, or a file cannot be read.
|
|
9
|
+
*/
|
|
10
|
+
export function loadTlsMaterial(env) {
|
|
11
|
+
const certPath = env.BRIDGE_TLS_CERT;
|
|
12
|
+
const keyPath = env.BRIDGE_TLS_KEY;
|
|
13
|
+
if (certPath === undefined && keyPath === undefined)
|
|
14
|
+
return null;
|
|
15
|
+
if (certPath === undefined || keyPath === undefined) {
|
|
16
|
+
throw new ConfigError("BRIDGE_TLS_CERT and BRIDGE_TLS_KEY must be set together, or both left unset");
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
return { cert: readFileSync(certPath), key: readFileSync(keyPath) };
|
|
20
|
+
}
|
|
21
|
+
catch (cause) {
|
|
22
|
+
throw new ConfigError(`unable to read TLS material (cert: ${certPath}, key: ${keyPath})`, {
|
|
23
|
+
cause,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=tls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls.js","sourceRoot":"","sources":["../../src/config/tls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAShD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAgB;IAC9C,MAAM,QAAQ,GAAG,GAAG,CAAC,eAAe,CAAC;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,CAAC;IAEnC,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACpD,MAAM,IAAI,WAAW,CACnB,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,WAAW,CAAC,sCAAsC,QAAQ,UAAU,OAAO,GAAG,EAAE;YACxF,KAAK;SACN,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ErrorCode } from "./error-codes.js";
|
|
2
|
+
/** Construction options for a {@link BridgeError}. */
|
|
3
|
+
export interface BridgeErrorOptions {
|
|
4
|
+
/** Stable, machine-readable error code. */
|
|
5
|
+
readonly code: ErrorCode;
|
|
6
|
+
/** Human-readable description. Safe to log. */
|
|
7
|
+
readonly message: string;
|
|
8
|
+
/** Optional structured diagnostic context. Must be JSON-serializable. */
|
|
9
|
+
readonly details?: unknown;
|
|
10
|
+
/** Hint, in milliseconds, after which a retry may succeed (throttling, rate limits). */
|
|
11
|
+
readonly retryAfterMs?: number;
|
|
12
|
+
/** Underlying cause, preserved for logging. */
|
|
13
|
+
readonly cause?: unknown;
|
|
14
|
+
}
|
|
15
|
+
/** The serializable, wire-safe projection of a {@link BridgeError}. */
|
|
16
|
+
export interface SerializedBridgeError {
|
|
17
|
+
readonly code: ErrorCode;
|
|
18
|
+
readonly message: string;
|
|
19
|
+
readonly details?: unknown;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* An error carrying a stable {@link ErrorCode}.
|
|
23
|
+
*
|
|
24
|
+
* Every failure that crosses a layer boundary — a tool result, an HTTP
|
|
25
|
+
* response, a bridge result — is represented as a `BridgeError` so the code is
|
|
26
|
+
* preserved end to end and can be mapped to a consistent response envelope.
|
|
27
|
+
*/
|
|
28
|
+
export declare class BridgeError extends Error {
|
|
29
|
+
/** Stable, machine-readable error code. */
|
|
30
|
+
readonly code: ErrorCode;
|
|
31
|
+
/** Structured diagnostic context, or `undefined` when none was provided. */
|
|
32
|
+
readonly details: unknown;
|
|
33
|
+
/** Retry hint in milliseconds, or `undefined` when retrying will not help. */
|
|
34
|
+
readonly retryAfterMs: number | undefined;
|
|
35
|
+
constructor(options: BridgeErrorOptions);
|
|
36
|
+
/** Type guard for `BridgeError`, safe across module boundaries. */
|
|
37
|
+
static is(value: unknown): value is BridgeError;
|
|
38
|
+
/** Projects the error to its serializable, wire-safe shape. */
|
|
39
|
+
serialize(): SerializedBridgeError;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=bridge-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-error.d.ts","sourceRoot":"","sources":["../../src/errors/bridge-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE9B,OAAO,EAAE,kBAAkB;IAQvC,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW;IAI/C,+DAA+D;IAC/D,SAAS,IAAI,qBAAqB;CAKnC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error carrying a stable {@link ErrorCode}.
|
|
3
|
+
*
|
|
4
|
+
* Every failure that crosses a layer boundary — a tool result, an HTTP
|
|
5
|
+
* response, a bridge result — is represented as a `BridgeError` so the code is
|
|
6
|
+
* preserved end to end and can be mapped to a consistent response envelope.
|
|
7
|
+
*/
|
|
8
|
+
export class BridgeError extends Error {
|
|
9
|
+
/** Stable, machine-readable error code. */
|
|
10
|
+
code;
|
|
11
|
+
/** Structured diagnostic context, or `undefined` when none was provided. */
|
|
12
|
+
details;
|
|
13
|
+
/** Retry hint in milliseconds, or `undefined` when retrying will not help. */
|
|
14
|
+
retryAfterMs;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
super(options.message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
17
|
+
this.name = "BridgeError";
|
|
18
|
+
this.code = options.code;
|
|
19
|
+
this.details = options.details;
|
|
20
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
21
|
+
}
|
|
22
|
+
/** Type guard for `BridgeError`, safe across module boundaries. */
|
|
23
|
+
static is(value) {
|
|
24
|
+
return value instanceof BridgeError;
|
|
25
|
+
}
|
|
26
|
+
/** Projects the error to its serializable, wire-safe shape. */
|
|
27
|
+
serialize() {
|
|
28
|
+
return this.details === undefined
|
|
29
|
+
? { code: this.code, message: this.message }
|
|
30
|
+
: { code: this.code, message: this.message, details: this.details };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=bridge-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-error.js","sourceRoot":"","sources":["../../src/errors/bridge-error.ts"],"names":[],"mappings":"AAuBA;;;;;;GAMG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,2CAA2C;IAClC,IAAI,CAAY;IACzB,4EAA4E;IACnE,OAAO,CAAU;IAC1B,8EAA8E;IACrE,YAAY,CAAqB;IAE1C,YAAY,OAA2B;QACrC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC3C,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,KAAc;QACtB,OAAO,KAAK,YAAY,WAAW,CAAC;IACtC,CAAC;IAED,+DAA+D;IAC/D,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS;YAC/B,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;YAC5C,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IACxE,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable, machine-readable error codes used across the bridge.
|
|
3
|
+
*
|
|
4
|
+
* These codes are part of the server's public contract: a code is never
|
|
5
|
+
* renamed or repurposed, only added. MCP clients and skills may switch on
|
|
6
|
+
* them, so they must remain stable across minor versions.
|
|
7
|
+
*/
|
|
8
|
+
export declare const ERROR_CODES: readonly ["AUTH_INVALID", "RATE_LIMITED", "COMMAND_THROTTLED", "COMMAND_TIMEOUT", "QUEUE_FULL", "BRIDGE_DISCONNECTED", "INVALID_INPUT", "BEHAVIOR_PACK_ERROR", "STRUCTURE_FILE_ERROR", "PROTOCOL_MISMATCH", "UNSUPPORTED_CAPABILITY", "NOT_FOUND", "INTERNAL"];
|
|
9
|
+
/** A stable error code. See {@link ERROR_CODES}. */
|
|
10
|
+
export type ErrorCode = (typeof ERROR_CODES)[number];
|
|
11
|
+
/** Type guard: whether an arbitrary string is a known {@link ErrorCode}. */
|
|
12
|
+
export declare function isErrorCode(value: string): value is ErrorCode;
|
|
13
|
+
//# sourceMappingURL=error-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/errors/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,gQA2Bd,CAAC;AAEX,oDAAoD;AACpD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAIrD,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE7D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable, machine-readable error codes used across the bridge.
|
|
3
|
+
*
|
|
4
|
+
* These codes are part of the server's public contract: a code is never
|
|
5
|
+
* renamed or repurposed, only added. MCP clients and skills may switch on
|
|
6
|
+
* them, so they must remain stable across minor versions.
|
|
7
|
+
*/
|
|
8
|
+
export const ERROR_CODES = [
|
|
9
|
+
/** Missing or invalid bearer token. */
|
|
10
|
+
"AUTH_INVALID",
|
|
11
|
+
/** Per-token request rate limit exceeded on the MCP surface. */
|
|
12
|
+
"RATE_LIMITED",
|
|
13
|
+
/** Per-kind command throttle rejected the command to protect the script watchdog. */
|
|
14
|
+
"COMMAND_THROTTLED",
|
|
15
|
+
/** A command was not completed by the behavior pack within its deadline. */
|
|
16
|
+
"COMMAND_TIMEOUT",
|
|
17
|
+
/** Too many commands are outstanding; the queue is at capacity. */
|
|
18
|
+
"QUEUE_FULL",
|
|
19
|
+
/** No behavior pack is connected to the bridge. */
|
|
20
|
+
"BRIDGE_DISCONNECTED",
|
|
21
|
+
/** A request or command payload failed schema validation. */
|
|
22
|
+
"INVALID_INPUT",
|
|
23
|
+
/** The behavior pack reported a failure while executing a command. */
|
|
24
|
+
"BEHAVIOR_PACK_ERROR",
|
|
25
|
+
/** A `.mcstructure` filesystem operation failed. */
|
|
26
|
+
"STRUCTURE_FILE_ERROR",
|
|
27
|
+
/** The behavior pack speaks an incompatible bridge protocol version. */
|
|
28
|
+
"PROTOCOL_MISMATCH",
|
|
29
|
+
/** The connected behavior pack lacks a capability the tool requires. */
|
|
30
|
+
"UNSUPPORTED_CAPABILITY",
|
|
31
|
+
/** A referenced entity, structure, or other resource does not exist. */
|
|
32
|
+
"NOT_FOUND",
|
|
33
|
+
/** An unexpected internal error. */
|
|
34
|
+
"INTERNAL",
|
|
35
|
+
];
|
|
36
|
+
const ERROR_CODE_SET = new Set(ERROR_CODES);
|
|
37
|
+
/** Type guard: whether an arbitrary string is a known {@link ErrorCode}. */
|
|
38
|
+
export function isErrorCode(value) {
|
|
39
|
+
return ERROR_CODE_SET.has(value);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=error-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.js","sourceRoot":"","sources":["../../src/errors/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,uCAAuC;IACvC,cAAc;IACd,gEAAgE;IAChE,cAAc;IACd,qFAAqF;IACrF,mBAAmB;IACnB,4EAA4E;IAC5E,iBAAiB;IACjB,mEAAmE;IACnE,YAAY;IACZ,mDAAmD;IACnD,qBAAqB;IACrB,6DAA6D;IAC7D,eAAe;IACf,sEAAsE;IACtE,qBAAqB;IACrB,oDAAoD;IACpD,sBAAsB;IACtB,wEAAwE;IACxE,mBAAmB;IACnB,wEAAwE;IACxE,wBAAwB;IACxB,wEAAwE;IACxE,WAAW;IACX,oCAAoC;IACpC,UAAU;CACF,CAAC;AAKX,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAS,WAAW,CAAC,CAAC;AAEzE,4EAA4E;AAC5E,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { BridgeEvent } from "../protocol/index.js";
|
|
2
|
+
import { type SubscriptionId } from "../queue/command-id.js";
|
|
3
|
+
/** An event held in a subscription's buffer, stamped with an ingest sequence. */
|
|
4
|
+
export interface BufferedEvent {
|
|
5
|
+
readonly sequence: number;
|
|
6
|
+
readonly event_type: string;
|
|
7
|
+
readonly occurred_at: string;
|
|
8
|
+
readonly payload: unknown;
|
|
9
|
+
}
|
|
10
|
+
/** A registered event subscription. */
|
|
11
|
+
export interface Subscription {
|
|
12
|
+
readonly id: SubscriptionId;
|
|
13
|
+
readonly eventType: string;
|
|
14
|
+
readonly filter: unknown;
|
|
15
|
+
readonly createdAt: string;
|
|
16
|
+
}
|
|
17
|
+
/** A subscription with its current buffer statistics. */
|
|
18
|
+
export interface SubscriptionSnapshot extends Subscription {
|
|
19
|
+
readonly buffered: number;
|
|
20
|
+
readonly lastSequence: number;
|
|
21
|
+
}
|
|
22
|
+
/** A page of buffered events plus an opaque cursor to resume after them. */
|
|
23
|
+
export interface EventPage {
|
|
24
|
+
readonly events: readonly BufferedEvent[];
|
|
25
|
+
readonly cursor: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Tracks event subscriptions and buffers the events the behavior pack reports
|
|
29
|
+
* for them. The MCP server owns the ordering cursor — events are stamped with
|
|
30
|
+
* an ingest sequence here, not by the behavior pack.
|
|
31
|
+
*/
|
|
32
|
+
export interface SubscriptionRegistry {
|
|
33
|
+
/** Registers a subscription and returns it. */
|
|
34
|
+
create(eventType: string, filter: unknown): Subscription;
|
|
35
|
+
/** Removes a subscription and its buffer; `false` if it did not exist. */
|
|
36
|
+
remove(id: SubscriptionId): boolean;
|
|
37
|
+
/** Returns a subscription by id. */
|
|
38
|
+
get(id: SubscriptionId): Subscription | undefined;
|
|
39
|
+
/** Lists every subscription with its buffer statistics. */
|
|
40
|
+
list(): SubscriptionSnapshot[];
|
|
41
|
+
/** Buffers an event under its subscription; `false` if the id is unknown. */
|
|
42
|
+
ingest(event: BridgeEvent): boolean;
|
|
43
|
+
/** Drains buffered events newer than `cursor` (omit to read from the start). */
|
|
44
|
+
poll(id: SubscriptionId, cursor: string | undefined): EventPage;
|
|
45
|
+
}
|
|
46
|
+
/** Configuration for {@link createSubscriptionRegistry}. */
|
|
47
|
+
export interface SubscriptionRegistryOptions {
|
|
48
|
+
/** Maximum events retained per subscription; the oldest are dropped when full. */
|
|
49
|
+
readonly bufferSize: number;
|
|
50
|
+
/** Notified after each ingested event — the seam for push notifications. */
|
|
51
|
+
readonly onIngest?: (id: SubscriptionId) => void;
|
|
52
|
+
}
|
|
53
|
+
/** Creates an empty {@link SubscriptionRegistry}. */
|
|
54
|
+
export declare function createSubscriptionRegistry(options: SubscriptionRegistryOptions): SubscriptionRegistry;
|
|
55
|
+
//# sourceMappingURL=subscription-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-registry.d.ts","sourceRoot":"","sources":["../../src/events/subscription-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEhF,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,yDAAyD;AACzD,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,YAAY,CAAC;IACzD,0EAA0E;IAC1E,MAAM,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC;IACpC,oCAAoC;IACpC,GAAG,CAAC,EAAE,EAAE,cAAc,GAAG,YAAY,GAAG,SAAS,CAAC;IAClD,2DAA2D;IAC3D,IAAI,IAAI,oBAAoB,EAAE,CAAC;IAC/B,6EAA6E;IAC7E,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IACpC,gFAAgF;IAChF,IAAI,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACjE;AAED,4DAA4D;AAC5D,MAAM,WAAW,2BAA2B;IAC1C,kFAAkF;IAClF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,cAAc,KAAK,IAAI,CAAC;CAClD;AAQD,qDAAqD;AACrD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,2BAA2B,GACnC,oBAAoB,CAkEtB"}
|