@synthetic-ai/photoshop-mcp 1.0.6 → 1.0.7-dev.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/package.json +1 -1
- package/server.mjs +41 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synthetic-ai/photoshop-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7-dev.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Control Adobe Photoshop with 409 AI tools via MCP — layers, text, masks, filters, adjustments, smart objects, export. By Synthetic (synthetic.com.ar).",
|
|
6
6
|
"homepage": "https://synthetic.com.ar/photoshop-mcp",
|
package/server.mjs
CHANGED
|
@@ -17,10 +17,45 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
17
17
|
import WebSocket from "ws";
|
|
18
18
|
import { z } from "zod";
|
|
19
19
|
import https from "https";
|
|
20
|
+
import os from "os";
|
|
21
|
+
import fs from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
import crypto from "crypto";
|
|
20
24
|
|
|
21
25
|
const PORT = Number(process.env.PS_MCP_PORT || 41219);
|
|
22
26
|
const WS_URL = "ws://127.0.0.1:" + PORT;
|
|
23
27
|
|
|
28
|
+
// ── Device identity (for the 2-device license cap) ─────────────────────
|
|
29
|
+
// Shared across all Synthetic MCP packages (ae-mcp, premiere-mcp,
|
|
30
|
+
// photoshop-mcp) on purpose: one physical machine should count as ONE
|
|
31
|
+
// device against the cap, not one per product installed on it. Generated
|
|
32
|
+
// once and persisted locally — not real hardware fingerprinting, just a
|
|
33
|
+
// stable per-installation id that survives restarts and `npx` re-runs.
|
|
34
|
+
function getMachineId() {
|
|
35
|
+
try {
|
|
36
|
+
const dir = path.join(os.homedir(), ".synthetic");
|
|
37
|
+
const file = path.join(dir, "device-id");
|
|
38
|
+
if (fs.existsSync(file)) {
|
|
39
|
+
const id = fs.readFileSync(file, "utf8").trim();
|
|
40
|
+
if (id) return id;
|
|
41
|
+
}
|
|
42
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
43
|
+
const id = crypto.randomUUID();
|
|
44
|
+
fs.writeFileSync(file, id, "utf8");
|
|
45
|
+
return id;
|
|
46
|
+
} catch {
|
|
47
|
+
// Filesystem unavailable/read-only — fall back to a per-process id.
|
|
48
|
+
// Worst case this machine's slot doesn't stick across restarts; it
|
|
49
|
+
// never blocks the tool from working.
|
|
50
|
+
return "volatile-" + crypto.randomUUID();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function getDeviceLabel() {
|
|
54
|
+
try { return `${os.hostname()} (${process.platform})`; } catch { return null; }
|
|
55
|
+
}
|
|
56
|
+
const MACHINE_ID = getMachineId();
|
|
57
|
+
const DEVICE_LABEL = getDeviceLabel();
|
|
58
|
+
|
|
24
59
|
// ── License validation ──────────────────────────────────────────────────
|
|
25
60
|
// Same pattern as ae-mcp/premiere-mcp: validate once, cache for an hour,
|
|
26
61
|
// gate everything except the free diagnostic tools. PS_MCP_LICENSE is set
|
|
@@ -60,7 +95,12 @@ async function checkLicense() {
|
|
|
60
95
|
return _licenseCache;
|
|
61
96
|
}
|
|
62
97
|
try {
|
|
63
|
-
const result = await _httpsPost(LICENSE_VALIDATION_URL, {
|
|
98
|
+
const result = await _httpsPost(LICENSE_VALIDATION_URL, {
|
|
99
|
+
key: LICENSE_KEY,
|
|
100
|
+
product: "photoshop-mcp",
|
|
101
|
+
machineId: MACHINE_ID,
|
|
102
|
+
deviceLabel: DEVICE_LABEL,
|
|
103
|
+
});
|
|
64
104
|
_licenseCache = { ...(result || {}), checkedAt: Date.now() };
|
|
65
105
|
if (!result) _licenseCache = { valid: false, message: "License server unreachable. Will retry next call.", checkedAt: Date.now() };
|
|
66
106
|
} catch {
|