@synthetic-ai/ae-mcp 2.10.0-dev.1 → 2.10.3

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/i18n/node.cjs ADDED
@@ -0,0 +1,124 @@
1
+ /* synthetic-idiomas · core/node.cjs
2
+ *
3
+ * Lado Node (servers MCP): decide el idioma al arrancar y carga los diccionarios del producto.
4
+ *
5
+ * Orden para elegir el idioma (el primero que dé un idioma soportado gana):
6
+ * 1. Variable de entorno del producto (ej. PS_MCP_LANG), si el producto define una.
7
+ * 2. SYNTHETIC_LANG (vale para todos los productos).
8
+ * 3. settings.json del panel del producto: <USER_DATA>/<carpeta del panel>/settings.json
9
+ * 4. settings.json compartido de Synthetic: <USER_DATA>/com.synthetic/settings.json
10
+ * 5. Inglés.
11
+ *
12
+ * <USER_DATA> es la misma carpeta que devuelve CEP con SystemPath.USER_DATA:
13
+ * Windows: %APPDATA% · macOS: ~/Library/Application Support · Linux (dev): ~/.config
14
+ *
15
+ * El idioma se lee UNA vez al arrancar: las descripciones de las tools se registran al inicio
16
+ * de la sesión MCP y los clientes no las vuelven a pedir. Cambiar el idioma en el panel se
17
+ * aplica al reiniciar el server (o la app cliente).
18
+ */
19
+ 'use strict';
20
+ var fs = require('fs');
21
+ var path = require('path');
22
+ var os = require('os');
23
+ var core = require('./i18n-core.cjs');
24
+
25
+ var SHARED_FOLDER = 'com.synthetic';
26
+
27
+ function userDataDir(env, platform) {
28
+ env = env || process.env;
29
+ platform = platform || process.platform;
30
+ if (platform === 'win32') return env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
31
+ if (platform === 'darwin') return path.join(os.homedir(), 'Library', 'Application Support');
32
+ return env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
33
+ }
34
+
35
+ function settingsPath(folder, env, platform) {
36
+ return path.join(userDataDir(env, platform), folder, 'settings.json');
37
+ }
38
+
39
+ function readJson(file) {
40
+ try { return JSON.parse(fs.readFileSync(file, 'utf8').replace(/^/, '')); } catch (e) { return null; }
41
+ }
42
+
43
+ /**
44
+ * @param {object} o
45
+ * envVar: variable propia del producto (ej. 'PS_MCP_LANG')
46
+ * settingsFolder: carpeta del panel dentro de USER_DATA (ej. 'com.synthetic.photoshop-mcp.bridge')
47
+ * @returns {{ language: string, source: string }}
48
+ */
49
+ function resolveLanguage(o) {
50
+ o = o || {};
51
+ var env = o.env || process.env;
52
+ var tries = [];
53
+ if (o.envVar) tries.push([env[o.envVar], 'env:' + o.envVar]);
54
+ tries.push([env.SYNTHETIC_LANG, 'env:SYNTHETIC_LANG']);
55
+ if (o.settingsFolder) {
56
+ var p = settingsPath(o.settingsFolder, env, o.platform);
57
+ var s = readJson(p);
58
+ tries.push([s && s.language, p]);
59
+ }
60
+ var shared = settingsPath(SHARED_FOLDER, env, o.platform);
61
+ var sh = readJson(shared);
62
+ tries.push([sh && sh.language, shared]);
63
+ for (var i = 0; i < tries.length; i++) {
64
+ var lang = core.normalizeLanguage(tries[i][0]);
65
+ if (lang) return { language: lang, source: tries[i][1] };
66
+ }
67
+ return { language: core.SOURCE, source: 'default' };
68
+ }
69
+
70
+ // Lee <dir>/<idioma>.json y <dir>/hashes/<idioma>.json para todos los idiomas soportados.
71
+ function loadLocales(dir) {
72
+ var locales = {}, hashes = {};
73
+ core.CODES.forEach(function (code) {
74
+ var d = readJson(path.join(dir, code + '.json'));
75
+ if (d) locales[code] = d;
76
+ var h = readJson(path.join(dir, 'hashes', code + '.json'));
77
+ if (h) hashes[code] = h;
78
+ });
79
+ return { locales: locales, hashes: hashes };
80
+ }
81
+
82
+ /**
83
+ * Atajo para un server MCP:
84
+ * const i18n = createServerI18n({ localesDir, envVar: 'PS_MCP_LANG', settingsFolder: '...' });
85
+ * i18n.t('msg.license.missing') // mensajes
86
+ * i18n.localizeTools(tools) // respuesta de tools/list
87
+ */
88
+ function createServerI18n(o) {
89
+ var picked = resolveLanguage(o);
90
+ var data = loadLocales(o.localesDir);
91
+ var i18n = core.createI18n({ locales: data.locales, hashes: data.hashes, language: picked.language });
92
+ i18n.languageSource = picked.source;
93
+ // Idioma pedido (puede diferir de `language` si ese idioma todavía no tiene diccionario).
94
+ i18n.requestedLanguage = picked.language;
95
+ return i18n;
96
+ }
97
+
98
+ // Para servers hechos con McpServer del SDK oficial: envuelve la respuesta de tools/list.
99
+ // Llamar DESPUÉS de registrar todas las tools y ANTES de server.connect().
100
+ function patchMcpServerToolsList(mcpServer, i18n) {
101
+ if (!i18n || i18n.language === core.SOURCE) return false;
102
+ var inner = mcpServer && (mcpServer.server || mcpServer);
103
+ var handlers = inner && inner._requestHandlers;
104
+ if (!handlers || typeof handlers.get !== 'function') return false;
105
+ var original = handlers.get('tools/list');
106
+ if (typeof original !== 'function') return false;
107
+ handlers.set('tools/list', async function (request, extra) {
108
+ var result = await original(request, extra);
109
+ if (result && Array.isArray(result.tools)) return Object.assign({}, result, { tools: i18n.localizeTools(result.tools) });
110
+ return result;
111
+ });
112
+ return true;
113
+ }
114
+
115
+ module.exports = {
116
+ SHARED_FOLDER: SHARED_FOLDER,
117
+ userDataDir: userDataDir,
118
+ settingsPath: settingsPath,
119
+ resolveLanguage: resolveLanguage,
120
+ loadLocales: loadLocales,
121
+ createServerI18n: createServerI18n,
122
+ patchMcpServerToolsList: patchMcpServerToolsList,
123
+ core: core
124
+ };
package/package.json CHANGED
@@ -1,56 +1,59 @@
1
- {
2
- "name": "@synthetic-ai/ae-mcp",
3
- "version": "2.10.0-dev.1",
4
- "type": "module",
5
- "description": "Control Adobe After Effects with 220+ AI tools via MCP. Two modes: Standalone (npx, no AE open) or Panel (CEP bridge, instant). By Synthetic (synthetic.com.ar).",
6
- "homepage": "https://synthetic.com.ar/ae-mcp",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/matiasEltrece/after-effects-mcp"
10
- },
11
- "author": "Synthetic <hola@synthetic.com.ar> (https://synthetic.com.ar)",
12
- "license": "UNLICENSED",
13
- "keywords": [
14
- "mcp",
15
- "after-effects",
16
- "adobe",
17
- "jsx",
18
- "extendscript",
19
- "model-context-protocol",
20
- "claude",
21
- "ai",
22
- "synthetic"
23
- ],
24
- "main": "./dist/server.mjs",
25
- "bin": {
26
- "ae-mcp": "./dist/server.mjs"
27
- },
28
- "files": [
29
- "dist/server.mjs",
30
- "dist/bridge.mjs",
31
- "dist/store.mjs",
32
- "dist/psdBounds.mjs",
33
- "scripts/ae-dialogs.ps1",
34
- "DISCLOSURE.md"
35
- ],
36
- "scripts": {
37
- "build": "node scripts/build.mjs",
38
- "prepublishOnly": "npm run build",
39
- "check": "node --check src/server.mjs",
40
- "inspect:tools": "node scripts/inspect-tools.mjs",
41
- "smoke": "node scripts/smoke-suite.mjs",
42
- "package-cep": "node scripts/package-cep.mjs"
43
- },
44
- "engines": {
45
- "node": ">=18"
46
- },
47
- "publishConfig": {
48
- "access": "public"
49
- },
50
- "devDependencies": {
51
- "javascript-obfuscator": "^5.4.3"
52
- },
53
- "dependencies": {
54
- "ag-psd": "^31.0.2"
55
- }
56
- }
1
+ {
2
+ "name": "@synthetic-ai/ae-mcp",
3
+ "version": "2.10.3",
4
+ "type": "module",
5
+ "description": "Control Adobe After Effects with 220+ AI tools via MCP. Two modes: Standalone (npx, no AE open) or Panel (CEP bridge, instant). By Synthetic (synthetic.com.ar).",
6
+ "homepage": "https://synthetic.com.ar/ae-mcp",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/matiasEltrece/after-effects-mcp"
10
+ },
11
+ "author": "Synthetic <hola@synthetic.com.ar> (https://synthetic.com.ar)",
12
+ "license": "UNLICENSED",
13
+ "keywords": [
14
+ "mcp",
15
+ "after-effects",
16
+ "adobe",
17
+ "jsx",
18
+ "extendscript",
19
+ "model-context-protocol",
20
+ "claude",
21
+ "ai",
22
+ "synthetic"
23
+ ],
24
+ "main": "./dist/server.mjs",
25
+ "bin": {
26
+ "ae-mcp": "./dist/server.mjs"
27
+ },
28
+ "files": [
29
+ "dist/server.mjs",
30
+ "dist/bridge.mjs",
31
+ "dist/store.mjs",
32
+ "dist/psdBounds.mjs",
33
+ "dist/i18n.mjs",
34
+ "i18n/",
35
+ "scripts/ae-dialogs.ps1",
36
+ "DISCLOSURE.md"
37
+ ],
38
+ "scripts": {
39
+ "build": "node scripts/build.mjs",
40
+ "prepublishOnly": "npm run build",
41
+ "check": "node --check src/server.mjs",
42
+ "sync-i18n": "node scripts/sync-i18n.mjs",
43
+ "inspect:tools": "node scripts/inspect-tools.mjs",
44
+ "smoke": "node scripts/smoke-suite.mjs",
45
+ "package-cep": "node scripts/package-cep.mjs"
46
+ },
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "devDependencies": {
54
+ "javascript-obfuscator": "^5.4.3"
55
+ },
56
+ "dependencies": {
57
+ "ag-psd": "^31.0.2"
58
+ }
59
+ }