@createlex/figma-swiftui-mcp 1.3.1 → 1.4.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.
@@ -6,10 +6,13 @@
6
6
  *
7
7
  * Supported targets:
8
8
  * - Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json)
9
- * - Claude Code (~/.claude.json → mcpServers)
9
+ * - Claude Code (~/.claude.json → mcpServers) (covers CLI + desktop + web)
10
10
  * - Cursor (~/.cursor/mcp.json)
11
11
  * - Windsurf (~/.codeium/windsurf/mcp_config.json)
12
12
  * - VS Code (~/.vscode/mcp.json — user-level)
13
+ * - OpenCode (~/.config/opencode/opencode.json → mcp)
14
+ * - Codex CLI (~/.codex/config.toml → [mcp_servers.figma-swiftui])
15
+ * - Gemini CLI (~/.gemini/settings.json)
13
16
  * - Antigravity (~/.gemini/antigravity/mcp_config.json)
14
17
  */
15
18
 
@@ -118,6 +121,26 @@ function getTargets({ nodePath, scriptPath }) {
118
121
  entry: stdioEntry,
119
122
  wrapKey: null, // VS Code uses { servers: { ... } } at top level
120
123
  },
124
+ {
125
+ name: 'OpenCode',
126
+ path: path.join(home, '.config', 'opencode', 'opencode.json'),
127
+ key: 'mcp',
128
+ entry: scriptPath
129
+ ? { type: 'local', command: [nodePath, scriptPath, 'start'], enabled: true }
130
+ : { type: 'local', command: [resolveNpxPath(), '-y', '@createlex/figma-swiftui-mcp', 'start'], enabled: true },
131
+ },
132
+ {
133
+ name: 'Codex CLI',
134
+ path: path.join(home, '.codex', 'config.toml'),
135
+ format: 'toml',
136
+ entry: { command: stdioEntry.command, args: stdioEntry.args },
137
+ },
138
+ {
139
+ name: 'Gemini CLI',
140
+ path: path.join(home, '.gemini', 'settings.json'),
141
+ key: 'mcpServers',
142
+ entry: stdioEntry,
143
+ },
121
144
  {
122
145
  name: 'Antigravity (Gemini)',
123
146
  path: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'),
@@ -145,6 +168,48 @@ function writeJsonSafe(filePath, data) {
145
168
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
146
169
  }
147
170
 
171
+ // ── TOML helpers (minimal, for Codex config.toml) ────────────────────
172
+ // We only need to append/check a [mcp_servers.<name>] section — no full
173
+ // TOML parser required.
174
+
175
+ function tomlHasServer(raw, serverName) {
176
+ const pattern = new RegExp(`^\\[mcp_servers\\.${serverName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\]`, 'm');
177
+ return pattern.test(raw);
178
+ }
179
+
180
+ function tomlFormatValue(v) {
181
+ if (typeof v === 'string') return `"${v.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
182
+ if (typeof v === 'boolean') return v ? 'true' : 'false';
183
+ if (typeof v === 'number') return String(v);
184
+ if (Array.isArray(v)) return `[${v.map(tomlFormatValue).join(', ')}]`;
185
+ return `"${v}"`;
186
+ }
187
+
188
+ function buildTomlSection(serverName, entry) {
189
+ const lines = [`[mcp_servers.${serverName}]`];
190
+ for (const [k, v] of Object.entries(entry)) {
191
+ if (k === 'env' && typeof v === 'object') continue; // handle env as sub-table
192
+ lines.push(`${k} = ${tomlFormatValue(v)}`);
193
+ }
194
+ if (entry.env && Object.keys(entry.env).length > 0) {
195
+ lines.push(`[mcp_servers.${serverName}.env]`);
196
+ for (const [ek, ev] of Object.entries(entry.env)) {
197
+ lines.push(`${ek} = ${tomlFormatValue(ev)}`);
198
+ }
199
+ }
200
+ return lines.join('\n') + '\n';
201
+ }
202
+
203
+ function appendTomlServer(filePath, serverName, entry, dryRun) {
204
+ const raw = fs.readFileSync(filePath, 'utf-8');
205
+ if (tomlHasServer(raw, serverName)) return false; // already present
206
+ const section = '\n' + buildTomlSection(serverName, entry);
207
+ if (!dryRun) {
208
+ fs.appendFileSync(filePath, section, 'utf-8');
209
+ }
210
+ return true;
211
+ }
212
+
148
213
  // ── Main ──────────────────────────────────────────────────────────────
149
214
  function runSetup(flags = {}) {
150
215
  const force = flags.force || false;
@@ -177,6 +242,25 @@ function runSetup(flags = {}) {
177
242
  continue;
178
243
  }
179
244
 
245
+ // ── TOML targets (Codex) ──────────────────────────────────────
246
+ if (target.format === 'toml') {
247
+ const raw = fs.readFileSync(target.path, 'utf-8');
248
+ if (tomlHasServer(raw, MCP_KEY) && !force) {
249
+ console.log(` ✅ ${target.name} — already configured`);
250
+ skipped++;
251
+ continue;
252
+ }
253
+ if (dryRun) {
254
+ console.log(` 🟡 ${target.name} — would configure (dry run)`);
255
+ } else {
256
+ appendTomlServer(target.path, MCP_KEY, target.entry, false);
257
+ console.log(` ✅ ${target.name} — configured!`);
258
+ }
259
+ configured++;
260
+ continue;
261
+ }
262
+
263
+ // ── JSON targets ────────────────────────────────────────────
180
264
  const config = readJsonSafe(target.path);
181
265
  if (!config) {
182
266
  console.log(` ⚠️ ${target.name} — could not parse config`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@createlex/figma-swiftui-mcp",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "CreateLex MCP runtime for Figma-to-SwiftUI generation and Xcode export",
5
5
  "bin": {
6
6
  "figma-swiftui-mcp": "bin/figma-swiftui-mcp.js"