brainferno-mcp-bridge 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/CHANGELOG.md +19 -0
- package/LICENSE +202 -0
- package/NOTICE +27 -0
- package/README.md +410 -0
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/bridge/handshake.d.ts +34 -0
- package/dist/bridge/handshake.js +36 -0
- package/dist/bridge/handshake.js.map +1 -0
- package/dist/bridge/script-escape.d.ts +16 -0
- package/dist/bridge/script-escape.js +47 -0
- package/dist/bridge/script-escape.js.map +1 -0
- package/dist/bridge/socket.d.ts +79 -0
- package/dist/bridge/socket.js +424 -0
- package/dist/bridge/socket.js.map +1 -0
- package/dist/bridge/types.d.ts +49 -0
- package/dist/bridge/types.js +38 -0
- package/dist/bridge/types.js.map +1 -0
- package/dist/config.d.ts +87 -0
- package/dist/config.js +172 -0
- package/dist/config.js.map +1 -0
- package/dist/drivers/ame-webservice.d.ts +118 -0
- package/dist/drivers/ame-webservice.js +356 -0
- package/dist/drivers/ame-webservice.js.map +1 -0
- package/dist/drivers/illustrator-delegate.d.ts +71 -0
- package/dist/drivers/illustrator-delegate.js +120 -0
- package/dist/drivers/illustrator-delegate.js.map +1 -0
- package/dist/drivers/osscript.d.ts +60 -0
- package/dist/drivers/osscript.js +230 -0
- package/dist/drivers/osscript.js.map +1 -0
- package/dist/http.d.ts +26 -0
- package/dist/http.js +126 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/install/cli.d.ts +2 -0
- package/dist/install/cli.js +310 -0
- package/dist/install/cli.js.map +1 -0
- package/dist/install/lib.d.ts +76 -0
- package/dist/install/lib.js +194 -0
- package/dist/install/lib.js.map +1 -0
- package/dist/jobs.d.ts +117 -0
- package/dist/jobs.js +196 -0
- package/dist/jobs.js.map +1 -0
- package/dist/logging.d.ts +8 -0
- package/dist/logging.js +33 -0
- package/dist/logging.js.map +1 -0
- package/dist/server.d.ts +38 -0
- package/dist/server.js +90 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/after-effects.d.ts +100 -0
- package/dist/tools/after-effects.js +695 -0
- package/dist/tools/after-effects.js.map +1 -0
- package/dist/tools/audio.d.ts +118 -0
- package/dist/tools/audio.js +356 -0
- package/dist/tools/audio.js.map +1 -0
- package/dist/tools/audition.d.ts +15 -0
- package/dist/tools/audition.js +329 -0
- package/dist/tools/audition.js.map +1 -0
- package/dist/tools/diagnostics.d.ts +17 -0
- package/dist/tools/diagnostics.js +61 -0
- package/dist/tools/diagnostics.js.map +1 -0
- package/dist/tools/illustrator-delegate.d.ts +9 -0
- package/dist/tools/illustrator-delegate.js +61 -0
- package/dist/tools/illustrator-delegate.js.map +1 -0
- package/dist/tools/illustrator.d.ts +36 -0
- package/dist/tools/illustrator.js +299 -0
- package/dist/tools/illustrator.js.map +1 -0
- package/dist/tools/jobs.d.ts +39 -0
- package/dist/tools/jobs.js +83 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/media-encoder.d.ts +17 -0
- package/dist/tools/media-encoder.js +180 -0
- package/dist/tools/media-encoder.js.map +1 -0
- package/dist/tools/photoshop.d.ts +17 -0
- package/dist/tools/photoshop.js +202 -0
- package/dist/tools/photoshop.js.map +1 -0
- package/dist/tools/pipelines.d.ts +23 -0
- package/dist/tools/pipelines.js +254 -0
- package/dist/tools/pipelines.js.map +1 -0
- package/dist/tools/premiere.d.ts +26 -0
- package/dist/tools/premiere.js +396 -0
- package/dist/tools/premiere.js.map +1 -0
- package/dist/tools/result.d.ts +17 -0
- package/dist/tools/result.js +51 -0
- package/dist/tools/result.js.map +1 -0
- package/package.json +64 -0
- package/panels/panel-cep/CSXS/manifest.xml +53 -0
- package/panels/panel-cep/bridge-client.js +204 -0
- package/panels/panel-cep/host.jsx +62 -0
- package/panels/panel-cep/icons/logo.svg +61 -0
- package/panels/panel-cep/index.html +48 -0
- package/panels/panel-cep/main.js +173 -0
- package/panels/panel-uxp/README.md +36 -0
- package/panels/panel-uxp/bridge-client.js +204 -0
- package/panels/panel-uxp/commands.js +375 -0
- package/panels/panel-uxp/icons/icon.png +0 -0
- package/panels/panel-uxp/icons/icon@2x.png +0 -0
- package/panels/panel-uxp/icons/logo.svg +61 -0
- package/panels/panel-uxp/index.html +47 -0
- package/panels/panel-uxp/main.js +109 -0
- package/panels/panel-uxp/manifest.json +89 -0
- package/panels/panel-uxp-ppro/README.md +11 -0
- package/panels/panel-uxp-ppro/bridge-client.js +204 -0
- package/panels/panel-uxp-ppro/commands.js +797 -0
- package/panels/panel-uxp-ppro/icons/icon.png +0 -0
- package/panels/panel-uxp-ppro/icons/icon@2x.png +0 -0
- package/panels/panel-uxp-ppro/icons/logo.svg +61 -0
- package/panels/panel-uxp-ppro/index.html +64 -0
- package/panels/panel-uxp-ppro/main.js +113 -0
- package/panels/panel-uxp-ppro/manifest.json +65 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { WebSocketServer } from "ws";
|
|
3
|
+
import { APPS } from "@brainferno/mcp-bridge-protocol";
|
|
4
|
+
import { log } from "../logging.js";
|
|
5
|
+
import { removeHandshake, writeHandshake } from "./handshake.js";
|
|
6
|
+
import { PROTOCOL_VERSION, parsePanelFrame, } from "@brainferno/mcp-bridge-protocol";
|
|
7
|
+
import { AppDisconnectedError, AppNotConnectedError, EvalTimeoutError, ScriptError, } from "./types.js";
|
|
8
|
+
const SERVER_VERSION = "0.1.0";
|
|
9
|
+
const DEFAULT_AUTH_DEADLINE_MS = 3_000;
|
|
10
|
+
const FAST_TIMEOUT_MS = 10_000;
|
|
11
|
+
const MAX_MISSED_PINGS = 2;
|
|
12
|
+
/** Even a "render" gets a ceiling so a silent panel cannot wedge its app queue
|
|
13
|
+
* forever; the job registry (a later phase) will own long renders properly. */
|
|
14
|
+
const RENDER_CEILING_MS = 30 * 60_000;
|
|
15
|
+
/** Cap on concurrent sockets, so a local/web peer cannot exhaust FDs by churn. */
|
|
16
|
+
const DEFAULT_MAX_CONNECTIONS = 64;
|
|
17
|
+
const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "localhost", "::1"]);
|
|
18
|
+
/**
|
|
19
|
+
* Accepts panel connections and routes commands to whichever application each
|
|
20
|
+
* panel authenticated as. One panel per application; a second authenticated
|
|
21
|
+
* connection for the same application replaces the first.
|
|
22
|
+
*
|
|
23
|
+
* Security posture (a localhost WebSocket is reachable by any local process and,
|
|
24
|
+
* because browsers exempt WebSockets from the same-origin policy, by any web
|
|
25
|
+
* page the user visits): the upgrade is Origin/Host-validated; every socket must
|
|
26
|
+
* present a valid token in its hello within a short deadline before any other
|
|
27
|
+
* frame is honored; and results are matched per-socket so one panel can never
|
|
28
|
+
* settle another's in-flight call.
|
|
29
|
+
*/
|
|
30
|
+
export class BridgeServer {
|
|
31
|
+
options;
|
|
32
|
+
wss;
|
|
33
|
+
panels = new Map();
|
|
34
|
+
states = new Map();
|
|
35
|
+
/** Serializes commands per app: one script/modal scope per host at a time. */
|
|
36
|
+
appQueues = new Map();
|
|
37
|
+
token;
|
|
38
|
+
insecure;
|
|
39
|
+
heartbeatIntervalMs;
|
|
40
|
+
authDeadlineMs;
|
|
41
|
+
allowedOrigins;
|
|
42
|
+
maxConnections;
|
|
43
|
+
heartbeat;
|
|
44
|
+
constructor(options) {
|
|
45
|
+
this.options = options;
|
|
46
|
+
this.insecure = options.insecure === true;
|
|
47
|
+
// Resolve the effective token: an explicit one wins; otherwise generate a
|
|
48
|
+
// per-process secret so the bridge is never unauthenticated by default.
|
|
49
|
+
this.token = this.insecure
|
|
50
|
+
? ""
|
|
51
|
+
: options.token !== ""
|
|
52
|
+
? options.token
|
|
53
|
+
: randomBytes(32).toString("hex");
|
|
54
|
+
this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? 15_000;
|
|
55
|
+
this.authDeadlineMs = options.authDeadlineMs ?? DEFAULT_AUTH_DEADLINE_MS;
|
|
56
|
+
this.allowedOrigins = new Set(options.allowedOrigins ?? []);
|
|
57
|
+
this.maxConnections = options.maxConnections ?? DEFAULT_MAX_CONNECTIONS;
|
|
58
|
+
this.wss = this.listen(options.port);
|
|
59
|
+
if (this.heartbeatIntervalMs > 0) {
|
|
60
|
+
this.heartbeat = setInterval(() => this.pingAll(), this.heartbeatIntervalMs);
|
|
61
|
+
this.heartbeat.unref();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
listen(port) {
|
|
65
|
+
const wss = new WebSocketServer({
|
|
66
|
+
port,
|
|
67
|
+
host: this.options.host ?? "127.0.0.1",
|
|
68
|
+
verifyClient: (info, done) => this.verifyUpgrade(info.req, done),
|
|
69
|
+
});
|
|
70
|
+
wss.on("connection", (socket) => this.onConnection(socket));
|
|
71
|
+
wss.on("listening", () => this.onListening());
|
|
72
|
+
return wss;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Resolves once a listening socket is bound. If the preferred port is taken
|
|
76
|
+
* (typically a stale server instance still holding it), falls back to an
|
|
77
|
+
* OS-assigned port: panels discover the real port from the handshake file,
|
|
78
|
+
* so a fixed port is a preference, not a requirement.
|
|
79
|
+
*/
|
|
80
|
+
ready() {
|
|
81
|
+
return this.waitListening(this.wss).catch((error) => {
|
|
82
|
+
if (error.code !== "EADDRINUSE" || this.options.port === 0)
|
|
83
|
+
throw error;
|
|
84
|
+
log.warn(`port ${this.options.port} is in use (a stale server instance?) — falling back to an OS-assigned port`);
|
|
85
|
+
this.wss = this.listen(0);
|
|
86
|
+
return this.waitListening(this.wss);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
waitListening(wss) {
|
|
90
|
+
return new Promise((resolve, reject) => {
|
|
91
|
+
if (wss.address() !== null) {
|
|
92
|
+
resolve();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const onError = (error) => reject(error);
|
|
96
|
+
wss.once("listening", () => {
|
|
97
|
+
wss.off("error", onError);
|
|
98
|
+
wss.on("error", (e) => log.error("bridge server error", e));
|
|
99
|
+
resolve();
|
|
100
|
+
});
|
|
101
|
+
wss.once("error", onError);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/** The bound port, or 0 before the server is listening. */
|
|
105
|
+
port() {
|
|
106
|
+
const address = this.wss.address();
|
|
107
|
+
return address !== null && typeof address === "object" ? address.port : 0;
|
|
108
|
+
}
|
|
109
|
+
bridgeFor(appId) {
|
|
110
|
+
return {
|
|
111
|
+
appId,
|
|
112
|
+
isConnected: () => this.panels.has(appId),
|
|
113
|
+
execute: (name, params, options) => this.execute(appId, name, params, options),
|
|
114
|
+
evaluate: (script, options) => this.execute(appId, "eval", { script }, options),
|
|
115
|
+
close: async () => {
|
|
116
|
+
this.panels.get(appId)?.close();
|
|
117
|
+
this.panels.delete(appId);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
connectedApps() {
|
|
122
|
+
return [...this.panels.keys()];
|
|
123
|
+
}
|
|
124
|
+
onListening() {
|
|
125
|
+
const host = this.options.host ?? "127.0.0.1";
|
|
126
|
+
log.info(`bridge listening on ${host}:${this.port()}`);
|
|
127
|
+
if (this.insecure) {
|
|
128
|
+
log.warn("bridge authentication is DISABLED (insecure mode) — with auth off the Origin/Host checks are the only " +
|
|
129
|
+
"gate, so any local process (and a web page via a null-origin frame) could run script in your apps; " +
|
|
130
|
+
"use only for local debugging");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (this.options.handshakeFilePath !== undefined) {
|
|
134
|
+
try {
|
|
135
|
+
writeHandshake(this.options.handshakeFilePath, {
|
|
136
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
137
|
+
port: this.port(),
|
|
138
|
+
token: this.token,
|
|
139
|
+
pid: process.pid,
|
|
140
|
+
});
|
|
141
|
+
log.info(`handshake written to ${this.options.handshakeFilePath}`);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
log.error("failed to write handshake file", error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
verifyUpgrade(req, done) {
|
|
149
|
+
if (this.states.size >= this.maxConnections) {
|
|
150
|
+
log.warn(`rejecting upgrade: ${this.states.size} connections already open`);
|
|
151
|
+
done(false, 503, "too many connections");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Loopback binding alone does not stop a browser (WebSockets are exempt from
|
|
155
|
+
// the same-origin policy). Allowlist the Origin — an absent one (UXP panels
|
|
156
|
+
// send none) and a loopback one are fine; a web page's Origin is always a
|
|
157
|
+
// real web origin or the literal "null" (sandboxed/file/data documents),
|
|
158
|
+
// neither of which is loopback, so both are rejected.
|
|
159
|
+
if (!this.originAllowed(req.headers.origin)) {
|
|
160
|
+
log.warn(`rejecting upgrade from origin ${JSON.stringify(req.headers.origin)}`);
|
|
161
|
+
done(false, 403, "forbidden origin");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// Host must be loopback too (DNS-rebinding guard: a rebinding page sends the
|
|
165
|
+
// attacker hostname here, not the resolved IP).
|
|
166
|
+
const host = req.headers.host;
|
|
167
|
+
if (typeof host === "string" && !/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/.test(host)) {
|
|
168
|
+
log.warn(`rejecting upgrade with non-loopback host ${host}`);
|
|
169
|
+
done(false, 403, "forbidden host");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
done(true);
|
|
173
|
+
}
|
|
174
|
+
originAllowed(origin) {
|
|
175
|
+
if (origin === undefined)
|
|
176
|
+
return true; // UXP panels send no Origin header.
|
|
177
|
+
// UXP panels (Photoshop 2026 on Windows, verified) send the literal
|
|
178
|
+
// "file://". Browsers never send that for a local document — they send the
|
|
179
|
+
// word "null" — so accepting it does not reopen the drive-by hole; the
|
|
180
|
+
// token remains the real gate.
|
|
181
|
+
if (origin === "file://")
|
|
182
|
+
return true;
|
|
183
|
+
if (this.allowedOrigins.has(origin))
|
|
184
|
+
return true;
|
|
185
|
+
try {
|
|
186
|
+
return LOOPBACK_HOSTNAMES.has(new URL(origin).hostname);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return false; // "null", "file://", or malformed — reject.
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
onConnection(socket) {
|
|
193
|
+
const state = {
|
|
194
|
+
authed: false,
|
|
195
|
+
pending: new Map(),
|
|
196
|
+
missedPings: 0,
|
|
197
|
+
authTimer: setTimeout(() => {
|
|
198
|
+
if (!state.authed) {
|
|
199
|
+
log.warn("closing socket that did not authenticate in time");
|
|
200
|
+
socket.close(4001, "authentication timeout");
|
|
201
|
+
}
|
|
202
|
+
}, this.authDeadlineMs),
|
|
203
|
+
};
|
|
204
|
+
state.authTimer.unref?.();
|
|
205
|
+
this.states.set(socket, state);
|
|
206
|
+
socket.on("message", (data) => this.onMessage(socket, state, data.toString()));
|
|
207
|
+
socket.on("close", () => this.onClose(socket, state));
|
|
208
|
+
socket.on("error", (error) => log.warn("panel socket error", error));
|
|
209
|
+
}
|
|
210
|
+
onMessage(socket, state, raw) {
|
|
211
|
+
let frame;
|
|
212
|
+
try {
|
|
213
|
+
frame = parsePanelFrame(raw);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
log.warn("dropping malformed frame from panel", error);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// Any inbound frame is a sign of life.
|
|
220
|
+
state.missedPings = 0;
|
|
221
|
+
if (!state.authed) {
|
|
222
|
+
if (frame.type !== "hello") {
|
|
223
|
+
log.warn(`dropping ${frame.type} frame from unauthenticated socket`);
|
|
224
|
+
socket.close(4001, "expected hello");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
this.handleHello(socket, state, frame);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
switch (frame.type) {
|
|
231
|
+
case "result":
|
|
232
|
+
this.settle(state, frame.id, frame.ok, frame.value, frame.error);
|
|
233
|
+
return;
|
|
234
|
+
case "progress":
|
|
235
|
+
log.debug(`progress ${frame.id}: ${frame.message ?? ""} ${frame.progress ?? ""}`);
|
|
236
|
+
return;
|
|
237
|
+
case "ping":
|
|
238
|
+
this.send(socket, { type: "ping", ts: Date.now() });
|
|
239
|
+
return;
|
|
240
|
+
case "pong":
|
|
241
|
+
return;
|
|
242
|
+
case "bye":
|
|
243
|
+
log.info(`panel for "${state.appId}" said bye: ${frame.reason ?? ""}`);
|
|
244
|
+
socket.close(1000, "bye");
|
|
245
|
+
return;
|
|
246
|
+
case "hello":
|
|
247
|
+
// Already authenticated; a second hello is ignored.
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
handleHello(socket, state, frame) {
|
|
252
|
+
if (!this.insecure && !this.tokenMatches(frame.token)) {
|
|
253
|
+
log.warn(`rejecting panel for "${frame.appId}": bad or missing token`);
|
|
254
|
+
socket.close(4001, "unauthorized");
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (!(frame.appId in APPS)) {
|
|
258
|
+
socket.close(4002, "unknown appId");
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (frame.protocolVersion !== PROTOCOL_VERSION) {
|
|
262
|
+
log.warn(`panel for "${frame.appId}" speaks protocol v${frame.protocolVersion}, ` +
|
|
263
|
+
`this server speaks v${PROTOCOL_VERSION}`);
|
|
264
|
+
socket.close(4003, "protocol version mismatch");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
clearTimeout(state.authTimer);
|
|
268
|
+
state.authed = true;
|
|
269
|
+
state.appId = frame.appId;
|
|
270
|
+
// Replace any earlier panel for this app (reconnect after a restart).
|
|
271
|
+
const existing = this.panels.get(frame.appId);
|
|
272
|
+
if (existing !== undefined && existing !== socket) {
|
|
273
|
+
existing.close(4004, "replaced by newer connection");
|
|
274
|
+
}
|
|
275
|
+
this.panels.set(frame.appId, socket);
|
|
276
|
+
this.send(socket, {
|
|
277
|
+
type: "welcome",
|
|
278
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
279
|
+
serverVersion: SERVER_VERSION,
|
|
280
|
+
heartbeatIntervalMs: this.heartbeatIntervalMs,
|
|
281
|
+
});
|
|
282
|
+
const version = frame.hostVersion ? ` (${frame.hostVersion})` : "";
|
|
283
|
+
log.info(`panel connected: ${frame.appId}${version}`);
|
|
284
|
+
}
|
|
285
|
+
tokenMatches(provided) {
|
|
286
|
+
if (this.token === "")
|
|
287
|
+
return true; // insecure mode has no token
|
|
288
|
+
if (provided === undefined)
|
|
289
|
+
return false;
|
|
290
|
+
const a = Buffer.from(provided);
|
|
291
|
+
const b = Buffer.from(this.token);
|
|
292
|
+
// Constant-time, and length-guarded (timingSafeEqual throws on a mismatch).
|
|
293
|
+
return a.length === b.length && timingSafeEqual(a, b);
|
|
294
|
+
}
|
|
295
|
+
settle(state, id, ok, value, error) {
|
|
296
|
+
const waiting = state.pending.get(id);
|
|
297
|
+
if (waiting === undefined) {
|
|
298
|
+
log.debug(`result for unknown or already-settled call ${id}`);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
state.pending.delete(id);
|
|
302
|
+
if (waiting.timer !== undefined)
|
|
303
|
+
clearTimeout(waiting.timer);
|
|
304
|
+
if (ok) {
|
|
305
|
+
waiting.resolve((value ?? null));
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
const appId = state.appId ?? "after_effects";
|
|
309
|
+
waiting.reject(new ScriptError(appId, error?.message ?? "script failed without a message", error?.line));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
onClose(socket, state) {
|
|
313
|
+
clearTimeout(state.authTimer);
|
|
314
|
+
if (state.appId !== undefined && this.panels.get(state.appId) === socket) {
|
|
315
|
+
this.panels.delete(state.appId);
|
|
316
|
+
log.info(`panel disconnected: ${state.appId}`);
|
|
317
|
+
}
|
|
318
|
+
// Fail any in-flight calls rather than letting them hang to their timeout.
|
|
319
|
+
for (const [, pending] of state.pending) {
|
|
320
|
+
if (pending.timer !== undefined)
|
|
321
|
+
clearTimeout(pending.timer);
|
|
322
|
+
pending.reject(new AppDisconnectedError(state.appId ?? "after_effects", "socket closed"));
|
|
323
|
+
}
|
|
324
|
+
state.pending.clear();
|
|
325
|
+
this.states.delete(socket);
|
|
326
|
+
}
|
|
327
|
+
pingAll() {
|
|
328
|
+
for (const [socket, state] of this.states) {
|
|
329
|
+
if (!state.authed)
|
|
330
|
+
continue;
|
|
331
|
+
if (state.missedPings >= MAX_MISSED_PINGS) {
|
|
332
|
+
log.warn(`panel for "${state.appId}" missed ${state.missedPings} pings — terminating`);
|
|
333
|
+
socket.terminate();
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
state.missedPings += 1;
|
|
337
|
+
this.send(socket, { type: "ping", ts: Date.now() });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
execute(appId, name, params, options) {
|
|
341
|
+
if (!this.panels.has(appId)) {
|
|
342
|
+
return Promise.reject(new AppNotConnectedError(appId, this.connectHint(appId)));
|
|
343
|
+
}
|
|
344
|
+
// Chain behind any in-flight command for this app; look the socket up when
|
|
345
|
+
// the task actually runs, so a mid-queue reconnect is handled correctly.
|
|
346
|
+
const prior = this.appQueues.get(appId) ?? Promise.resolve();
|
|
347
|
+
const run = prior.catch(() => { }).then(() => this.dispatch(appId, name, params, options));
|
|
348
|
+
this.appQueues.set(appId, run.catch(() => { }));
|
|
349
|
+
return run;
|
|
350
|
+
}
|
|
351
|
+
dispatch(appId, name, params, options) {
|
|
352
|
+
const socket = this.panels.get(appId);
|
|
353
|
+
const state = socket ? this.states.get(socket) : undefined;
|
|
354
|
+
if (socket === undefined || state === undefined) {
|
|
355
|
+
return Promise.reject(new AppNotConnectedError(appId, this.connectHint(appId)));
|
|
356
|
+
}
|
|
357
|
+
const id = randomUUID();
|
|
358
|
+
const timeoutClass = options?.timeoutClass ?? "slow";
|
|
359
|
+
const timeoutMs = this.resolveTimeout(options, timeoutClass);
|
|
360
|
+
return new Promise((resolve, reject) => {
|
|
361
|
+
const timer = setTimeout(() => {
|
|
362
|
+
state.pending.delete(id);
|
|
363
|
+
reject(new EvalTimeoutError(appId, timeoutMs));
|
|
364
|
+
}, timeoutMs);
|
|
365
|
+
state.pending.set(id, { resolve, reject, timer });
|
|
366
|
+
try {
|
|
367
|
+
this.send(socket, { type: "cmd", id, name, params: params ?? null, timeoutClass });
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
clearTimeout(timer);
|
|
371
|
+
state.pending.delete(id);
|
|
372
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
resolveTimeout(options, timeoutClass) {
|
|
377
|
+
if (options?.timeoutMs !== undefined)
|
|
378
|
+
return options.timeoutMs;
|
|
379
|
+
switch (timeoutClass) {
|
|
380
|
+
case "fast":
|
|
381
|
+
return FAST_TIMEOUT_MS;
|
|
382
|
+
case "slow":
|
|
383
|
+
return this.options.defaultTimeoutMs;
|
|
384
|
+
case "render":
|
|
385
|
+
// Renders run for minutes, but keep a generous ceiling so a silent panel
|
|
386
|
+
// cannot wedge the app's command queue forever; the job registry (a
|
|
387
|
+
// later phase) will own long-render lifecycles properly.
|
|
388
|
+
return RENDER_CEILING_MS;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
connectHint(appId) {
|
|
392
|
+
const app = APPS[appId];
|
|
393
|
+
if (app.lane === "os-script") {
|
|
394
|
+
return `Open ${app.displayName}; it is driven directly and needs no panel.`;
|
|
395
|
+
}
|
|
396
|
+
const menu = app.panel === "uxp" ? "Plugins" : "Window > Extensions";
|
|
397
|
+
return `Open ${app.displayName} and launch the brainferno-mcp-bridge panel from its ${menu} menu.`;
|
|
398
|
+
}
|
|
399
|
+
send(socket, frame) {
|
|
400
|
+
socket.send(JSON.stringify(frame));
|
|
401
|
+
}
|
|
402
|
+
async close() {
|
|
403
|
+
if (this.heartbeat !== undefined)
|
|
404
|
+
clearInterval(this.heartbeat);
|
|
405
|
+
for (const state of this.states.values()) {
|
|
406
|
+
clearTimeout(state.authTimer);
|
|
407
|
+
for (const [, pending] of state.pending) {
|
|
408
|
+
if (pending.timer !== undefined)
|
|
409
|
+
clearTimeout(pending.timer);
|
|
410
|
+
pending.reject(new AppDisconnectedError(state.appId ?? "after_effects", "bridge shutting down"));
|
|
411
|
+
}
|
|
412
|
+
state.pending.clear();
|
|
413
|
+
}
|
|
414
|
+
for (const socket of this.panels.values())
|
|
415
|
+
socket.close();
|
|
416
|
+
this.panels.clear();
|
|
417
|
+
this.states.clear();
|
|
418
|
+
if (!this.insecure && this.options.handshakeFilePath !== undefined) {
|
|
419
|
+
removeHandshake(this.options.handshakeFilePath);
|
|
420
|
+
}
|
|
421
|
+
await new Promise((resolve) => this.wss.close(() => resolve()));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=socket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/bridge/socket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { AppId } from "@brainferno/mcp-bridge-protocol";
|
|
2
|
+
import type { TimeoutClass } from "@brainferno/mcp-bridge-protocol";
|
|
3
|
+
/** A JSON value, as returned across the bridge from a host application. */
|
|
4
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
5
|
+
[key: string]: JsonValue;
|
|
6
|
+
};
|
|
7
|
+
export interface EvalOptions {
|
|
8
|
+
/** Override the configured timeout for this one call. */
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/** Command weight class, selecting a default deadline. Defaults to "slow". */
|
|
11
|
+
timeoutClass?: TimeoutClass;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A live connection to one running Creative Cloud application.
|
|
15
|
+
*
|
|
16
|
+
* The primitive is {@link execute}: it delivers a *named* command and its
|
|
17
|
+
* params to the host and resolves with whatever the host returned, parsed as
|
|
18
|
+
* JSON. {@link evaluate} is a convenience for the generic `eval` command.
|
|
19
|
+
*/
|
|
20
|
+
export interface AppBridge {
|
|
21
|
+
readonly appId: AppId;
|
|
22
|
+
/** Whether a host is currently reachable through this bridge. */
|
|
23
|
+
isConnected(): boolean;
|
|
24
|
+
/** Send a named command to the host and resolve with its result. */
|
|
25
|
+
execute(name: string, params?: JsonValue, options?: EvalOptions): Promise<JsonValue>;
|
|
26
|
+
/** Convenience wrapper for the generic `eval` command (params `{script}`). */
|
|
27
|
+
evaluate(script: string, options?: EvalOptions): Promise<JsonValue>;
|
|
28
|
+
close(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/** Raised when no host is reachable for the requested application. */
|
|
31
|
+
export declare class AppNotConnectedError extends Error {
|
|
32
|
+
readonly appId: AppId;
|
|
33
|
+
constructor(appId: AppId, hint: string);
|
|
34
|
+
}
|
|
35
|
+
/** Raised when a panel disconnected while a command was in flight. */
|
|
36
|
+
export declare class AppDisconnectedError extends Error {
|
|
37
|
+
readonly appId: AppId;
|
|
38
|
+
constructor(appId: AppId, reason: string);
|
|
39
|
+
}
|
|
40
|
+
/** Raised when the host received the command but the script itself threw. */
|
|
41
|
+
export declare class ScriptError extends Error {
|
|
42
|
+
readonly appId: AppId;
|
|
43
|
+
readonly scriptLine?: number | undefined;
|
|
44
|
+
constructor(appId: AppId, message: string, scriptLine?: number | undefined);
|
|
45
|
+
}
|
|
46
|
+
/** Raised when the host never answered within the timeout. */
|
|
47
|
+
export declare class EvalTimeoutError extends Error {
|
|
48
|
+
constructor(appId: AppId, timeoutMs: number);
|
|
49
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Raised when no host is reachable for the requested application. */
|
|
2
|
+
export class AppNotConnectedError extends Error {
|
|
3
|
+
appId;
|
|
4
|
+
constructor(appId, hint) {
|
|
5
|
+
super(`No running host connected for "${appId}". ${hint}`);
|
|
6
|
+
this.appId = appId;
|
|
7
|
+
this.name = "AppNotConnectedError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Raised when a panel disconnected while a command was in flight. */
|
|
11
|
+
export class AppDisconnectedError extends Error {
|
|
12
|
+
appId;
|
|
13
|
+
constructor(appId, reason) {
|
|
14
|
+
super(`The "${appId}" panel disconnected before the command completed (${reason}).`);
|
|
15
|
+
this.appId = appId;
|
|
16
|
+
this.name = "AppDisconnectedError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Raised when the host received the command but the script itself threw. */
|
|
20
|
+
export class ScriptError extends Error {
|
|
21
|
+
appId;
|
|
22
|
+
scriptLine;
|
|
23
|
+
constructor(appId, message, scriptLine) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.appId = appId;
|
|
26
|
+
this.scriptLine = scriptLine;
|
|
27
|
+
this.name = "ScriptError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Raised when the host never answered within the timeout. */
|
|
31
|
+
export class EvalTimeoutError extends Error {
|
|
32
|
+
constructor(appId, timeoutMs) {
|
|
33
|
+
super(`"${appId}" did not return a result within ${timeoutMs}ms. ` +
|
|
34
|
+
`A modal dialog open in the application will block scripting until dismissed.`);
|
|
35
|
+
this.name = "EvalTimeoutError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/bridge/types.ts"],"names":[],"mappings":"AA+BA,sEAAsE;AACtE,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACjB;IAA5B,YAA4B,KAAY,EAAE,IAAY;QACpD,KAAK,CAAC,kCAAkC,KAAK,MAAM,IAAI,EAAE,CAAC,CAAC;QADjC,UAAK,GAAL,KAAK,CAAO;QAEtC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,sEAAsE;AACtE,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAE3B;IADlB,YACkB,KAAY,EAC5B,MAAc;QAEd,KAAK,CAAC,QAAQ,KAAK,sDAAsD,MAAM,IAAI,CAAC,CAAC;QAHrE,UAAK,GAAL,KAAK,CAAO;QAI5B,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,6EAA6E;AAC7E,MAAM,OAAO,WAAY,SAAQ,KAAK;IAElB;IAEA;IAHlB,YACkB,KAAY,EAC5B,OAAe,EACC,UAAmB;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,UAAK,GAAL,KAAK,CAAO;QAEZ,eAAU,GAAV,UAAU,CAAS;QAGnC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,8DAA8D;AAC9D,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,KAAY,EAAE,SAAiB;QACzC,KAAK,CACH,IAAI,KAAK,oCAAoC,SAAS,MAAM;YAC1D,8EAA8E,CACjF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** Runtime configuration, read once at startup from the environment. */
|
|
2
|
+
export declare const DEFAULT_ILLUSTRATOR_MCP_URL = "http://localhost:18412/v1/mcp";
|
|
3
|
+
export type LogLevel = "error" | "warn" | "info" | "debug";
|
|
4
|
+
/** Read BRAINFERNO_MCP_X, falling back to the pre-rename ADOBE_CC_MCP_X with a one-time warning. */
|
|
5
|
+
export declare function envValue(name: string): string | undefined;
|
|
6
|
+
/** Settings live in ~/.brainferno-mcp-bridge; copy config.json from the pre-rename ~/.adobe-cc-mcp once. */
|
|
7
|
+
export declare function migrateLegacyUserDir(home?: string): string | null;
|
|
8
|
+
export interface Config {
|
|
9
|
+
/** TCP port the in-app panels dial back to (0 lets the OS pick one). */
|
|
10
|
+
bridgePort: number;
|
|
11
|
+
/**
|
|
12
|
+
* Explicit shared secret panels must present. Empty means "generate a random
|
|
13
|
+
* one at startup" unless {@link bridgeInsecure} is set.
|
|
14
|
+
*/
|
|
15
|
+
bridgeToken: string;
|
|
16
|
+
/**
|
|
17
|
+
* Disable panel authentication entirely (no token, no handshake file). For
|
|
18
|
+
* local debugging and tests only — never run this on a shared machine, since
|
|
19
|
+
* the bridge evaluates arbitrary script inside your Adobe applications.
|
|
20
|
+
*/
|
|
21
|
+
bridgeInsecure: boolean;
|
|
22
|
+
/** Default deadline for a "slow" script result before rejecting. */
|
|
23
|
+
evalTimeoutMs: number;
|
|
24
|
+
/** How often the bridge pings each panel to detect a dead connection. */
|
|
25
|
+
heartbeatIntervalMs: number;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to register the raw-script escape-hatch tool (`cc_eval_script`).
|
|
28
|
+
* Off by default: it is arbitrary code execution at user privilege.
|
|
29
|
+
*/
|
|
30
|
+
allowRawScripts: boolean;
|
|
31
|
+
/** Where to write the port+token handshake file panels read. */
|
|
32
|
+
handshakeFilePath: string;
|
|
33
|
+
/**
|
|
34
|
+
* Extra WebSocket Origins to accept on the upgrade, beyond loopback origins
|
|
35
|
+
* and the no-Origin case (UXP panels send none). Fill in a panel's actual
|
|
36
|
+
* Origin here once a spike establishes what it sends.
|
|
37
|
+
*/
|
|
38
|
+
allowedOrigins: string[];
|
|
39
|
+
/** Adobe's official Illustrator (Beta) MCP endpoint the delegate lane dials. */
|
|
40
|
+
illustratorMcpUrl: string;
|
|
41
|
+
/**
|
|
42
|
+
* Bearer key for Adobe's Illustrator (Beta) MCP server. Empty disables the
|
|
43
|
+
* delegate lane. A capability key to the user's local Illustrator — never log
|
|
44
|
+
* it or put it in an error message.
|
|
45
|
+
*/
|
|
46
|
+
illustratorMcpKey: string;
|
|
47
|
+
/** ffmpeg / ffprobe executables for the audio process lane (name on PATH or absolute path). */
|
|
48
|
+
ffmpegPath: string;
|
|
49
|
+
ffprobePath: string;
|
|
50
|
+
/** ame_webservice_console(.exe) path; "" = auto-detect the newest Media Encoder. */
|
|
51
|
+
ameWebServicePath: string;
|
|
52
|
+
/** Port of the AME web service; 0 = read it from the ini beside the console. */
|
|
53
|
+
amePort: number;
|
|
54
|
+
/** Stop the AME web service after this idle time; 0 = keep it running. */
|
|
55
|
+
ameIdleMs: number;
|
|
56
|
+
/**
|
|
57
|
+
* Remote mode: also serve MCP over Streamable HTTP on this port (0 = off).
|
|
58
|
+
* Requires {@link httpToken}. Set by the installer's "shared on my network" choice.
|
|
59
|
+
*/
|
|
60
|
+
httpPort: number;
|
|
61
|
+
/** Address to bind in remote mode: 127.0.0.1 (this computer) or 0.0.0.0 (network). */
|
|
62
|
+
httpHost: string;
|
|
63
|
+
/** Bearer token every remote request must present. */
|
|
64
|
+
httpToken: string;
|
|
65
|
+
/** Which applications get their tools registered (installer choice; env BRAINFERNO_MCP_APPS overrides). */
|
|
66
|
+
enabledApps: InstallableApp[];
|
|
67
|
+
logLevel: LogLevel;
|
|
68
|
+
}
|
|
69
|
+
/** Keys the installer may write to `~/.brainferno-mcp-bridge/config.json` (mode 600). */
|
|
70
|
+
/** Everything the installer can switch on or off. */
|
|
71
|
+
export declare const INSTALLABLE_APPS: readonly ["photoshop", "after_effects", "premiere", "illustrator", "audition", "media_encoder"];
|
|
72
|
+
export type InstallableApp = (typeof INSTALLABLE_APPS)[number];
|
|
73
|
+
export declare function parseApps(raw: string | undefined, fallback?: readonly InstallableApp[]): InstallableApp[];
|
|
74
|
+
export interface UserConfigFile {
|
|
75
|
+
/** Apps whose tools are registered; missing = all. */
|
|
76
|
+
enabledApps?: InstallableApp[];
|
|
77
|
+
illustratorKey?: string;
|
|
78
|
+
/** Adobe's Illustrator MCP endpoint; override when the shipping release moves it. */
|
|
79
|
+
illustratorUrl?: string;
|
|
80
|
+
httpPort?: number;
|
|
81
|
+
httpHost?: string;
|
|
82
|
+
httpToken?: string;
|
|
83
|
+
}
|
|
84
|
+
export declare function userConfigPath(): string;
|
|
85
|
+
/** The user config file, or {} when missing/malformed. */
|
|
86
|
+
export declare function readUserConfig(): UserConfigFile;
|
|
87
|
+
export declare function loadConfig(): Config;
|