@pired/lightroom-mcp 3.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 +70 -0
- package/dist/LightroomMCP.lrplugin/HandlerAI.lua +466 -0
- package/dist/LightroomMCP.lrplugin/HandlerAIMasks.lua +549 -0
- package/dist/LightroomMCP.lrplugin/HandlerCatalog.lua +256 -0
- package/dist/LightroomMCP.lrplugin/HandlerCollections.lua +337 -0
- package/dist/LightroomMCP.lrplugin/HandlerDevelop.lua +1668 -0
- package/dist/LightroomMCP.lrplugin/HandlerExport.lua +149 -0
- package/dist/LightroomMCP.lrplugin/HandlerImport.lua +108 -0
- package/dist/LightroomMCP.lrplugin/HandlerLocalAdjustments.lua +330 -0
- package/dist/LightroomMCP.lrplugin/HandlerMetadata.lua +169 -0
- package/dist/LightroomMCP.lrplugin/HandlerOrganization.lua +783 -0
- package/dist/LightroomMCP.lrplugin/HandlerPreview.lua +189 -0
- package/dist/LightroomMCP.lrplugin/HandlerSearch.lua +185 -0
- package/dist/LightroomMCP.lrplugin/HandlerSelection.lua +302 -0
- package/dist/LightroomMCP.lrplugin/HandlerSpots.lua +313 -0
- package/dist/LightroomMCP.lrplugin/HandlerWatermark.lua +59 -0
- package/dist/LightroomMCP.lrplugin/Info.lua +25 -0
- package/dist/LightroomMCP.lrplugin/JSON.lua +270 -0
- package/dist/LightroomMCP.lrplugin/Log.lua +92 -0
- package/dist/LightroomMCP.lrplugin/MenuShowStatus.lua +22 -0
- package/dist/LightroomMCP.lrplugin/PhotoLookup.lua +39 -0
- package/dist/LightroomMCP.lrplugin/PluginInfoProvider.lua +865 -0
- package/dist/LightroomMCP.lrplugin/PluginInit.lua +48 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +31 -0
- package/dist/cli.js.map +1 -0
- package/dist/configs/claude-code.mcp.json +9 -0
- package/dist/configs/claude-desktop.json +12 -0
- package/dist/configs/generic-stdio-client.json +10 -0
- package/dist/configs/mcp-proxy-http.json +9 -0
- package/dist/create-server.d.ts +12 -0
- package/dist/create-server.d.ts.map +1 -0
- package/dist/create-server.js +17 -0
- package/dist/create-server.js.map +1 -0
- package/dist/deepseek-harness/README.md +112 -0
- package/dist/deepseek-harness/deepseek-mcp-harness.mjs +292 -0
- package/dist/dispatcher.d.ts +34 -0
- package/dist/dispatcher.d.ts.map +1 -0
- package/dist/dispatcher.js +72 -0
- package/dist/dispatcher.js.map +1 -0
- package/dist/heartbeat.d.ts +17 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +36 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +255 -0
- package/dist/index.js.map +1 -0
- package/dist/install-plugin.d.ts +16 -0
- package/dist/install-plugin.d.ts.map +1 -0
- package/dist/install-plugin.js +125 -0
- package/dist/install-plugin.js.map +1 -0
- package/dist/instance-lock.d.ts +5 -0
- package/dist/instance-lock.d.ts.map +1 -0
- package/dist/instance-lock.js +77 -0
- package/dist/instance-lock.js.map +1 -0
- package/dist/list-tools-handler.d.ts +16 -0
- package/dist/list-tools-handler.d.ts.map +1 -0
- package/dist/list-tools-handler.js +50 -0
- package/dist/list-tools-handler.js.map +1 -0
- package/dist/plugin-liveness.d.ts +48 -0
- package/dist/plugin-liveness.d.ts.map +1 -0
- package/dist/plugin-liveness.js +75 -0
- package/dist/plugin-liveness.js.map +1 -0
- package/dist/plugin-socket.d.ts +32 -0
- package/dist/plugin-socket.d.ts.map +1 -0
- package/dist/plugin-socket.js +97 -0
- package/dist/plugin-socket.js.map +1 -0
- package/dist/ports.d.ts +3 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +22 -0
- package/dist/ports.js.map +1 -0
- package/dist/token.d.ts +3 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +23 -0
- package/dist/token.js.map +1 -0
- package/dist/tool-contracts.d.ts +13 -0
- package/dist/tool-contracts.d.ts.map +1 -0
- package/dist/tool-contracts.js +1422 -0
- package/dist/tool-contracts.js.map +1 -0
- package/dist/tool-handler.d.ts +23 -0
- package/dist/tool-handler.d.ts.map +1 -0
- package/dist/tool-handler.js +96 -0
- package/dist/tool-handler.js.map +1 -0
- package/dist/validate-args.d.ts +7 -0
- package/dist/validate-args.d.ts.map +1 -0
- package/dist/validate-args.js +37 -0
- package/dist/validate-args.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/dist/wait-until.d.ts +7 -0
- package/dist/wait-until.d.ts.map +1 -0
- package/dist/wait-until.js +15 -0
- package/dist/wait-until.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export class Dispatcher {
|
|
2
|
+
pending = new Map();
|
|
3
|
+
idCounter = 0;
|
|
4
|
+
timeoutMs;
|
|
5
|
+
actionTimeoutsMs;
|
|
6
|
+
send;
|
|
7
|
+
getToken;
|
|
8
|
+
log;
|
|
9
|
+
constructor(opts) {
|
|
10
|
+
this.send = opts.send;
|
|
11
|
+
this.getToken = opts.getToken;
|
|
12
|
+
this.timeoutMs = opts.timeoutMs ?? 30_000;
|
|
13
|
+
this.actionTimeoutsMs = opts.actionTimeoutsMs ?? {};
|
|
14
|
+
this.log = opts.log ?? ((msg) => console.error(msg));
|
|
15
|
+
}
|
|
16
|
+
handleResponseLine(line) {
|
|
17
|
+
let resp;
|
|
18
|
+
try {
|
|
19
|
+
resp = JSON.parse(line);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
23
|
+
this.log(`Bad JSON from plugin (${msg}): ${line}`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const p = this.pending.get(resp.id);
|
|
27
|
+
if (!p) {
|
|
28
|
+
this.log(`Response for unknown id: ${resp.id}`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
clearTimeout(p.timer);
|
|
32
|
+
this.pending.delete(resp.id);
|
|
33
|
+
p.resolve(resp);
|
|
34
|
+
}
|
|
35
|
+
async call(action, params, timeoutOverrideMs) {
|
|
36
|
+
const id = `req_${Date.now()}_${this.idCounter++}`;
|
|
37
|
+
// A non-positive override means "no override": `0` would otherwise arm a
|
|
38
|
+
// 0 ms timer that rejects on the next tick.
|
|
39
|
+
const override = timeoutOverrideMs ?? this.actionTimeoutsMs[action];
|
|
40
|
+
const timeoutMs = override !== undefined && override > 0 ? override : this.timeoutMs;
|
|
41
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
this.pending.delete(id);
|
|
44
|
+
reject(new Error(`Plugin response timeout (${timeoutMs / 1000}s)`));
|
|
45
|
+
}, timeoutMs);
|
|
46
|
+
this.pending.set(id, { resolve, reject, timer });
|
|
47
|
+
});
|
|
48
|
+
const cleanup = () => {
|
|
49
|
+
const p = this.pending.get(id);
|
|
50
|
+
if (p)
|
|
51
|
+
clearTimeout(p.timer);
|
|
52
|
+
this.pending.delete(id);
|
|
53
|
+
};
|
|
54
|
+
let payload;
|
|
55
|
+
try {
|
|
56
|
+
payload = JSON.stringify({ hello: this.getToken(), id, action, params: params ?? {} });
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
cleanup();
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
if (!this.send(payload)) {
|
|
63
|
+
cleanup();
|
|
64
|
+
throw new Error("Failed to send request to plugin (socket dropped)");
|
|
65
|
+
}
|
|
66
|
+
return responsePromise;
|
|
67
|
+
}
|
|
68
|
+
pendingCount() {
|
|
69
|
+
return this.pending.size;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface HeartbeatDispatcher {
|
|
2
|
+
call(action: string, params: unknown, timeoutMs?: number): Promise<unknown>;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Starts a fire-and-forget ping loop against the dispatcher and returns the
|
|
6
|
+
* timer handle so the caller can clearInterval() it (e.g. on shutdown).
|
|
7
|
+
* dispatcher.call() rejects on its own if the request socket is currently
|
|
8
|
+
* disconnected, so this is safe to run unconditionally regardless of
|
|
9
|
+
* connection state -- a failed ping is just logged via onError, never thrown.
|
|
10
|
+
*/
|
|
11
|
+
export declare function startHeartbeat(dispatcher: HeartbeatDispatcher, intervalMs: number, onError?: (err: Error) => void, onSuccess?: () => void): NodeJS.Timeout;
|
|
12
|
+
/**
|
|
13
|
+
* One ping outside the interval loop, for probing a freshly opened connection.
|
|
14
|
+
* Resolves true when the plugin answered.
|
|
15
|
+
*/
|
|
16
|
+
export declare function probePlugin(dispatcher: HeartbeatDispatcher, timeoutMs?: number): Promise<boolean>;
|
|
17
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,mBAAmB,EAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAwE,EACjG,SAAS,GAAE,MAAM,IAAe,GAC/B,MAAM,CAAC,OAAO,CAOhB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,mBAAmB,EAC/B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAOlB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Extracted from index.ts so the ping-interval wiring can be unit tested in
|
|
2
|
+
// isolation, without booting the real MCP server / sockets that main() sets
|
|
3
|
+
// up. See tests/heartbeat.test.ts.
|
|
4
|
+
//
|
|
5
|
+
// Heartbeat: ping the plugin on this interval so it can tell a healthy-but-
|
|
6
|
+
// idle session apart from a genuinely dead connection (issue #134 follow-up,
|
|
7
|
+
// PR #151 review) instead of relying on a long fixed idle timer. The plugin
|
|
8
|
+
// derives liveness from any inbound message -- ping included -- via its
|
|
9
|
+
// existing lastRequestTime tracking, so this side doesn't need to react to a
|
|
10
|
+
// missed pong itself; a failed/timed-out ping is only logged for visibility.
|
|
11
|
+
/**
|
|
12
|
+
* Starts a fire-and-forget ping loop against the dispatcher and returns the
|
|
13
|
+
* timer handle so the caller can clearInterval() it (e.g. on shutdown).
|
|
14
|
+
* dispatcher.call() rejects on its own if the request socket is currently
|
|
15
|
+
* disconnected, so this is safe to run unconditionally regardless of
|
|
16
|
+
* connection state -- a failed ping is just logged via onError, never thrown.
|
|
17
|
+
*/
|
|
18
|
+
export function startHeartbeat(dispatcher, intervalMs, onError = (err) => console.error(`[heartbeat] ping failed: ${err.message}`), onSuccess = () => { }) {
|
|
19
|
+
return setInterval(() => {
|
|
20
|
+
dispatcher.call("ping", {}).then(() => onSuccess(), (err) => onError(err));
|
|
21
|
+
}, intervalMs);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One ping outside the interval loop, for probing a freshly opened connection.
|
|
25
|
+
* Resolves true when the plugin answered.
|
|
26
|
+
*/
|
|
27
|
+
export async function probePlugin(dispatcher, timeoutMs) {
|
|
28
|
+
try {
|
|
29
|
+
await dispatcher.call("ping", {}, timeoutMs);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,mCAAmC;AACnC,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,wEAAwE;AACxE,6EAA6E;AAC7E,6EAA6E;AAM7E;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,UAA+B,EAC/B,UAAkB,EAClB,OAAO,GAAyB,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,4BAA4B,GAAG,CAAC,OAAO,EAAE,CAAC,EACjG,SAAS,GAAe,GAAG,EAAE,GAAE,CAAC;IAEhC,OAAO,WAAW,CAAC,GAAG,EAAE;QACtB,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAC9B,GAAG,EAAE,CAAC,SAAS,EAAE,EACjB,CAAC,GAAU,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAC7B,CAAC;IACJ,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAA+B,EAC/B,SAAkB;IAElB,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { PluginSocket } from "./plugin-socket.js";
|
|
6
|
+
import { Dispatcher } from "./dispatcher.js";
|
|
7
|
+
import { readToken, tokenFilePath } from "./token.js";
|
|
8
|
+
import { requestPort, responsePort } from "./ports.js";
|
|
9
|
+
import { createMcpServer } from "./create-server.js";
|
|
10
|
+
import { NOT_CONNECTED_MESSAGE } from "./tool-handler.js";
|
|
11
|
+
import { parseCli, helpText } from "./cli.js";
|
|
12
|
+
import { VERSION } from "./version.js";
|
|
13
|
+
import { startHeartbeat, probePlugin } from "./heartbeat.js";
|
|
14
|
+
import { PluginLiveness, SHADOW_BRIDGE_MESSAGE } from "./plugin-liveness.js";
|
|
15
|
+
import { waitUntil } from "./wait-until.js";
|
|
16
|
+
import { acquireInstanceLock } from "./instance-lock.js";
|
|
17
|
+
import { ensurePluginInstalled, findBundledPlugin, installPlugin, lightroomModulesDir, } from "./install-plugin.js";
|
|
18
|
+
const REQUEST_TIMEOUT_MS = 30_000;
|
|
19
|
+
// Batch export/import render files and can run for minutes; the default
|
|
20
|
+
// timeout would report a spurious failure mid-export. See issue #128.
|
|
21
|
+
const LONG_RUNNING_TIMEOUT_MS = 300_000;
|
|
22
|
+
// Keep this interval in sync with HEARTBEAT_INTERVAL_SECONDS in
|
|
23
|
+
// PluginInfoProvider.lua. See heartbeat.ts for what this drives.
|
|
24
|
+
const HEARTBEAT_INTERVAL_MS = 30_000;
|
|
25
|
+
const PING_TIMEOUT_MS = 10_000;
|
|
26
|
+
const RESPONSE_CONNECT_SETTLE_MS = 200;
|
|
27
|
+
// Short enough that a tool call waiting on the verdict is not left hanging,
|
|
28
|
+
// generous enough for a busy-but-healthy plugin: a ping is a no-op dispatch
|
|
29
|
+
// that answered in single-digit milliseconds even mid-export.
|
|
30
|
+
const PROBE_TIMEOUT_MS = 5_000;
|
|
31
|
+
const PROBE_RECOVERY_INTERVAL_MS = 5_000;
|
|
32
|
+
// A client that calls a tool immediately after initialize would otherwise be
|
|
33
|
+
// told "plugin not connected" while the sockets are still coming up, which is
|
|
34
|
+
// a lie about a perfectly healthy Lightroom. Wait out the connect instead.
|
|
35
|
+
const STARTUP_GRACE_MS = 3_000;
|
|
36
|
+
const CONNECT_POLL_MS = 50;
|
|
37
|
+
const ACTION_TIMEOUTS_MS = {
|
|
38
|
+
export_photos: LONG_RUNNING_TIMEOUT_MS,
|
|
39
|
+
import_photos: LONG_RUNNING_TIMEOUT_MS,
|
|
40
|
+
ping: PING_TIMEOUT_MS,
|
|
41
|
+
// AI Denoise must wait out SendKeys + the actual DNG render (which can run
|
|
42
|
+
// minutes on high-resolution RAW files) before its verification window
|
|
43
|
+
// closes and the manual fallback kicks in.
|
|
44
|
+
ai_denoise: LONG_RUNNING_TIMEOUT_MS,
|
|
45
|
+
// Flagging large batches selects photos through the UI and retries one by
|
|
46
|
+
// one; the default 30s is too tight near the 1000-photo cap.
|
|
47
|
+
set_flags: 120_000,
|
|
48
|
+
// AI masking drives Lightroom's on-device AI per photo (subject/sky/
|
|
49
|
+
// background detection takes seconds per image on most machines), plus
|
|
50
|
+
// module switches and per-photo selection.
|
|
51
|
+
add_ai_mask: 120_000,
|
|
52
|
+
// apply_auto drives the Develop module UI per photo with settle pauses
|
|
53
|
+
// and before/after read-backs.
|
|
54
|
+
apply_auto: 120_000,
|
|
55
|
+
// The preview render inside the plugin polls for up to 60s (photos still
|
|
56
|
+
// building standard previews can take that long), plus file I/O.
|
|
57
|
+
get_photo_preview: 90_000,
|
|
58
|
+
// reset_develop/set_process_version/add_range_mask drive the Develop
|
|
59
|
+
// module UI with module switches, settle pauses and read-backs.
|
|
60
|
+
reset_develop: 120_000,
|
|
61
|
+
set_process_version: 120_000,
|
|
62
|
+
add_range_mask: 120_000,
|
|
63
|
+
toggle_mask_overlay: 60_000,
|
|
64
|
+
// Batch metadata writes up to 1000 photos through one write gate plus a
|
|
65
|
+
// full read-back verification pass.
|
|
66
|
+
batch_metadata: 120_000,
|
|
67
|
+
// Selection changes yield to the Lightroom UI thread; large batches with
|
|
68
|
+
// verification need headroom.
|
|
69
|
+
select_photos: 60_000,
|
|
70
|
+
rotate_photo: 60_000,
|
|
71
|
+
remove_from_catalog: 60_000,
|
|
72
|
+
};
|
|
73
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
74
|
+
async function main() {
|
|
75
|
+
let cli;
|
|
76
|
+
try {
|
|
77
|
+
cli = parseCli(process.argv);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.error(err.message);
|
|
81
|
+
process.exit(2);
|
|
82
|
+
}
|
|
83
|
+
if (cli.command === "help") {
|
|
84
|
+
process.stdout.write(helpText());
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (cli.command === "version") {
|
|
88
|
+
process.stdout.write(VERSION + "\n");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (cli.command === "install-plugin") {
|
|
92
|
+
runInstallPlugin();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
let REQUEST_PORT;
|
|
96
|
+
let RESPONSE_PORT;
|
|
97
|
+
try {
|
|
98
|
+
REQUEST_PORT = requestPort();
|
|
99
|
+
RESPONSE_PORT = responsePort();
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
console.error(err.message);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
acquireInstanceLock(REQUEST_PORT, RESPONSE_PORT);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
console.error(err.message);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
ensurePluginInstalled(here, (m) => console.error(m));
|
|
113
|
+
let requestSocket;
|
|
114
|
+
let responseSocket = null;
|
|
115
|
+
let responseConnectTimer = null;
|
|
116
|
+
const dispatcher = new Dispatcher({
|
|
117
|
+
send: (line) => requestSocket.send(line),
|
|
118
|
+
getToken: () => readToken(),
|
|
119
|
+
timeoutMs: REQUEST_TIMEOUT_MS,
|
|
120
|
+
actionTimeoutsMs: ACTION_TIMEOUTS_MS,
|
|
121
|
+
});
|
|
122
|
+
const liveness = new PluginLiveness();
|
|
123
|
+
let recoveryTimer = null;
|
|
124
|
+
const probeOnConnect = () => {
|
|
125
|
+
const token = liveness.beginProbe();
|
|
126
|
+
if (token === null)
|
|
127
|
+
return;
|
|
128
|
+
void probePlugin(dispatcher, PROBE_TIMEOUT_MS).then((answered) => {
|
|
129
|
+
if (!liveness.settleProbe(token, answered))
|
|
130
|
+
return;
|
|
131
|
+
if (answered) {
|
|
132
|
+
if (recoveryTimer) {
|
|
133
|
+
clearInterval(recoveryTimer);
|
|
134
|
+
recoveryTimer = null;
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
console.error(`[plugin] ${SHADOW_BRIDGE_MESSAGE}`);
|
|
139
|
+
// Re-probe faster than the 30s heartbeat so the bridge recovers promptly
|
|
140
|
+
// once the process holding the plugin goes away.
|
|
141
|
+
if (!recoveryTimer) {
|
|
142
|
+
recoveryTimer = setInterval(() => probeOnConnect(), PROBE_RECOVERY_INTERVAL_MS);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
const startResponseSocket = () => {
|
|
147
|
+
if (responseSocket || !requestSocket.isConnected())
|
|
148
|
+
return;
|
|
149
|
+
responseSocket = new PluginSocket({
|
|
150
|
+
port: RESPONSE_PORT,
|
|
151
|
+
label: "response",
|
|
152
|
+
onLine: (line) => dispatcher.handleResponseLine(line),
|
|
153
|
+
onConnect: () => probeOnConnect(),
|
|
154
|
+
});
|
|
155
|
+
responseSocket.connect();
|
|
156
|
+
};
|
|
157
|
+
const stopResponseSocket = () => {
|
|
158
|
+
liveness.reset();
|
|
159
|
+
if (responseConnectTimer) {
|
|
160
|
+
clearTimeout(responseConnectTimer);
|
|
161
|
+
responseConnectTimer = null;
|
|
162
|
+
}
|
|
163
|
+
responseSocket?.stop();
|
|
164
|
+
responseSocket = null;
|
|
165
|
+
};
|
|
166
|
+
requestSocket = new PluginSocket({
|
|
167
|
+
port: REQUEST_PORT,
|
|
168
|
+
label: "request",
|
|
169
|
+
onConnect: () => {
|
|
170
|
+
if (responseConnectTimer)
|
|
171
|
+
clearTimeout(responseConnectTimer);
|
|
172
|
+
responseConnectTimer = setTimeout(() => {
|
|
173
|
+
responseConnectTimer = null;
|
|
174
|
+
startResponseSocket();
|
|
175
|
+
}, RESPONSE_CONNECT_SETTLE_MS);
|
|
176
|
+
},
|
|
177
|
+
onDisconnect: () => {
|
|
178
|
+
stopResponseSocket();
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
requestSocket.connect();
|
|
182
|
+
const socketsConnected = () => requestSocket.isConnected() && (responseSocket?.isConnected() ?? false);
|
|
183
|
+
startHeartbeat(dispatcher, HEARTBEAT_INTERVAL_MS, (err) => {
|
|
184
|
+
console.error(`[heartbeat] ping failed: ${err.message}`);
|
|
185
|
+
// A ping that fails because the socket is down is an ordinary disconnect,
|
|
186
|
+
// not a second bridge holding the plugin. Only diagnose the latter while
|
|
187
|
+
// the connection is actually up, or a stopped plugin gets blamed on a
|
|
188
|
+
// process that does not exist.
|
|
189
|
+
if (!socketsConnected()) {
|
|
190
|
+
liveness.reset();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
liveness.markUnresponsive();
|
|
194
|
+
console.error(`[plugin] ${SHADOW_BRIDGE_MESSAGE}`);
|
|
195
|
+
}, () => liveness.markResponsive());
|
|
196
|
+
const server = createMcpServer({
|
|
197
|
+
dispatcher,
|
|
198
|
+
isReady: () => socketsConnected() && liveness.isUsable(),
|
|
199
|
+
notReadyMessage: () => (socketsConnected() ? SHADOW_BRIDGE_MESSAGE : NOT_CONNECTED_MESSAGE),
|
|
200
|
+
settleReadiness: async () => {
|
|
201
|
+
await waitUntil(socketsConnected, STARTUP_GRACE_MS, CONNECT_POLL_MS);
|
|
202
|
+
await liveness.settled();
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
const transport = new StdioServerTransport();
|
|
206
|
+
await server.connect(transport);
|
|
207
|
+
// Exit when the MCP client goes away. Signal handlers never fire when the
|
|
208
|
+
// parent dies without signaling (typical on Windows), and the live plugin
|
|
209
|
+
// sockets plus the heartbeat interval keep the event loop alive — the
|
|
210
|
+
// orphaned bridge then holds both the single-client plugin connection and
|
|
211
|
+
// the instance lock, so every future bridge instance fails with "Another
|
|
212
|
+
// Lightroom MCP bridge is already running". Stdin EOF is the one reliable
|
|
213
|
+
// cross-platform signal that the client is gone.
|
|
214
|
+
const exitOnClientGone = (reason) => () => {
|
|
215
|
+
console.error(`Shutting down: ${reason}`);
|
|
216
|
+
process.exit(0);
|
|
217
|
+
};
|
|
218
|
+
process.stdin.once("end", exitOnClientGone("stdin ended (client exited)"));
|
|
219
|
+
process.stdin.once("close", exitOnClientGone("stdin closed (client exited)"));
|
|
220
|
+
console.error(`Lightroom MCP server v${VERSION} running on stdio`);
|
|
221
|
+
console.error(`Connecting to plugin: request :${REQUEST_PORT}, response :${RESPONSE_PORT}`);
|
|
222
|
+
console.error(`Token file: ${tokenFilePath()}`);
|
|
223
|
+
}
|
|
224
|
+
function runInstallPlugin() {
|
|
225
|
+
const source = findBundledPlugin(here);
|
|
226
|
+
if (!source) {
|
|
227
|
+
console.error("Could not locate bundled LightroomMCP.lrplugin folder near this binary.");
|
|
228
|
+
console.error("If you cloned the repo, run from the repo root or pass a path explicitly.");
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
const dest = lightroomModulesDir();
|
|
232
|
+
try {
|
|
233
|
+
const result = installPlugin({ source, destDir: dest });
|
|
234
|
+
if (result.status === "installed") {
|
|
235
|
+
console.error(`Installed plugin: ${result.destination}`);
|
|
236
|
+
console.error(`Restart Lightroom Classic to load it.`);
|
|
237
|
+
}
|
|
238
|
+
else if (result.status === "already-present") {
|
|
239
|
+
console.error(`Plugin already present at ${result.destination}`);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
console.error(`Skipped: ${result.reason ?? "unknown reason"}`);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
console.error(`Install failed: ${err.message}`);
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
main().catch((error) => {
|
|
252
|
+
console.error("Fatal error:", error);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
});
|
|
255
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface InstallResult {
|
|
2
|
+
status: "installed" | "already-present" | "skipped";
|
|
3
|
+
destination: string;
|
|
4
|
+
reason?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function lightroomModulesDir(): string;
|
|
7
|
+
export declare function lightroomPluginsDir(): string;
|
|
8
|
+
export declare function isPluginInstalledAnywhere(): boolean;
|
|
9
|
+
export declare function findBundledPlugin(startDir: string): string | null;
|
|
10
|
+
export declare function installPlugin(opts: {
|
|
11
|
+
source: string;
|
|
12
|
+
destDir?: string;
|
|
13
|
+
force?: boolean;
|
|
14
|
+
}): InstallResult;
|
|
15
|
+
export declare function ensurePluginInstalled(startDir: string, log: (msg: string) => void): void;
|
|
16
|
+
//# sourceMappingURL=install-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-plugin.d.ts","sourceRoot":"","sources":["../src/install-plugin.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,SAAS,CAAC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAgB5C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAgB5C;AAED,wBAAgB,yBAAyB,IAAI,OAAO,CAYnD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBjE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,aAAa,CA6BhB;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAaxF"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export function lightroomModulesDir() {
|
|
5
|
+
if (process.platform === "darwin") {
|
|
6
|
+
return path.join(os.homedir(), "Library", "Application Support", "Adobe", "Lightroom", "Modules");
|
|
7
|
+
}
|
|
8
|
+
if (process.platform === "win32") {
|
|
9
|
+
const appData = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
|
|
10
|
+
return path.join(appData, "Adobe", "Lightroom", "Modules");
|
|
11
|
+
}
|
|
12
|
+
return path.join(os.homedir(), ".local", "share", "Adobe", "Lightroom", "Modules");
|
|
13
|
+
}
|
|
14
|
+
export function lightroomPluginsDir() {
|
|
15
|
+
if (process.platform === "darwin") {
|
|
16
|
+
return path.join(os.homedir(), "Library", "Application Support", "Adobe", "Lightroom", "Plugins");
|
|
17
|
+
}
|
|
18
|
+
if (process.platform === "win32") {
|
|
19
|
+
const appData = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
|
|
20
|
+
return path.join(appData, "Adobe", "Lightroom", "Plugins");
|
|
21
|
+
}
|
|
22
|
+
return path.join(os.homedir(), ".local", "share", "Adobe", "Lightroom", "Plugins");
|
|
23
|
+
}
|
|
24
|
+
export function isPluginInstalledAnywhere() {
|
|
25
|
+
const targets = [
|
|
26
|
+
path.join(lightroomModulesDir(), "LightroomMCP.lrplugin", "Info.lua"),
|
|
27
|
+
path.join(lightroomPluginsDir(), "LightroomMCP.lrplugin", "Info.lua"),
|
|
28
|
+
];
|
|
29
|
+
return targets.some((p) => {
|
|
30
|
+
try {
|
|
31
|
+
return fs.statSync(p).isFile();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export function findBundledPlugin(startDir) {
|
|
39
|
+
const candidates = [
|
|
40
|
+
path.join(startDir, "LightroomMCP.lrplugin"),
|
|
41
|
+
path.join(startDir, "..", "LightroomMCP.lrplugin"),
|
|
42
|
+
path.join(startDir, "..", "..", "LightroomMCP.lrplugin"),
|
|
43
|
+
path.join(startDir, "..", "..", "..", "LightroomMCP.lrplugin"),
|
|
44
|
+
path.join(startDir, "..", "plugin", "LightroomMCP.lrplugin"),
|
|
45
|
+
path.join(startDir, "..", "..", "plugin", "LightroomMCP.lrplugin"),
|
|
46
|
+
path.join(startDir, "..", "..", "..", "plugin", "LightroomMCP.lrplugin"),
|
|
47
|
+
];
|
|
48
|
+
for (const c of candidates) {
|
|
49
|
+
try {
|
|
50
|
+
const st = fs.statSync(c);
|
|
51
|
+
if (st.isDirectory() && fs.existsSync(path.join(c, "Info.lua"))) {
|
|
52
|
+
return path.resolve(c);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// not present, keep looking
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
export function installPlugin(opts) {
|
|
62
|
+
const destDir = opts.destDir ?? lightroomModulesDir();
|
|
63
|
+
const destination = path.join(destDir, "LightroomMCP.lrplugin");
|
|
64
|
+
if (!fs.existsSync(opts.source)) {
|
|
65
|
+
return {
|
|
66
|
+
status: "skipped",
|
|
67
|
+
destination,
|
|
68
|
+
reason: `Source plugin not found at ${opts.source}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (!fs.existsSync(path.join(opts.source, "Info.lua"))) {
|
|
72
|
+
return {
|
|
73
|
+
status: "skipped",
|
|
74
|
+
destination,
|
|
75
|
+
reason: `Source ${opts.source} is not a valid .lrplugin (missing Info.lua)`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (!opts.force && fs.existsSync(destination)) {
|
|
79
|
+
return { status: "already-present", destination };
|
|
80
|
+
}
|
|
81
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
82
|
+
if (opts.force && fs.existsSync(destination)) {
|
|
83
|
+
fs.rmSync(destination, { recursive: true, force: true });
|
|
84
|
+
}
|
|
85
|
+
copyDirRecursive(opts.source, destination);
|
|
86
|
+
return { status: "installed", destination };
|
|
87
|
+
}
|
|
88
|
+
export function ensurePluginInstalled(startDir, log) {
|
|
89
|
+
if (isPluginInstalledAnywhere())
|
|
90
|
+
return;
|
|
91
|
+
const source = findBundledPlugin(startDir);
|
|
92
|
+
if (!source)
|
|
93
|
+
return;
|
|
94
|
+
try {
|
|
95
|
+
const result = installPlugin({ source });
|
|
96
|
+
if (result.status === "installed") {
|
|
97
|
+
log(`[install-plugin] copied ${source} → ${result.destination}`);
|
|
98
|
+
log(`[install-plugin] restart Lightroom to load the plugin`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
log(`[install-plugin] failed: ${err.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function copyDirRecursive(src, dest) {
|
|
106
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
107
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
108
|
+
const s = path.join(src, entry.name);
|
|
109
|
+
const d = path.join(dest, entry.name);
|
|
110
|
+
if (entry.isDirectory())
|
|
111
|
+
copyDirRecursive(s, d);
|
|
112
|
+
else if (entry.isSymbolicLink()) {
|
|
113
|
+
const link = fs.readlinkSync(s);
|
|
114
|
+
try {
|
|
115
|
+
fs.symlinkSync(link, d);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
fs.copyFileSync(s, d);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
fs.copyFileSync(s, d);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=install-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-plugin.js","sourceRoot":"","sources":["../src/install-plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-lock.d.ts","sourceRoot":"","sources":["../src/instance-lock.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAqBD,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,SAAsD,GAC5D,YAAY,CAuDd"}
|