@i18n-agent/mcp-client 1.9.0 → 1.9.2

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.
Files changed (3) hide show
  1. package/install.js +101 -30
  2. package/mcp-client.js +2 -2
  3. package/package.json +1 -1
package/install.js CHANGED
@@ -153,21 +153,40 @@ function checkExistingApiKey(configPath) {
153
153
  }
154
154
  }
155
155
 
156
- async function checkExistingApiKeys(availableIDEs) {
156
+ async function checkExistingApiKeys(availableIDEs, claudeCodeCLIAvailable = false, codexCLIAvailable = false) {
157
157
  const withKeys = [];
158
158
  const withoutKeys = [];
159
159
 
160
160
  for (const ide of availableIDEs) {
161
- // Also check ~/.claude.json for Claude Code CLI
162
- if (ide.key === 'claude-code') {
163
- const claudeJsonPath = path.join(os.homedir(), '.claude.json');
164
- if (checkExistingApiKey(claudeJsonPath)) {
165
- withKeys.push(ide);
166
- continue;
161
+ let hasKey = false;
162
+
163
+ // Check CLI registrations first for native CLI tools
164
+ if (ide.key === 'claude-code' && claudeCodeCLIAvailable) {
165
+ const cliKey = getClaudeCodeExistingApiKey('i18n-agent');
166
+ if (cliKey) {
167
+ hasKey = true;
168
+ }
169
+ } else if (ide.key === 'codex' && codexCLIAvailable) {
170
+ const cliKey = getCodexExistingApiKey('i18n-agent');
171
+ if (cliKey) {
172
+ hasKey = true;
167
173
  }
168
174
  }
169
175
 
170
- if (checkExistingApiKey(ide.configPath)) {
176
+ // Fall back to config file check
177
+ if (!hasKey) {
178
+ // Also check ~/.claude.json for Claude Code CLI
179
+ if (ide.key === 'claude-code') {
180
+ const claudeJsonPath = path.join(os.homedir(), '.claude.json');
181
+ if (checkExistingApiKey(claudeJsonPath)) {
182
+ hasKey = true;
183
+ }
184
+ } else if (checkExistingApiKey(ide.configPath)) {
185
+ hasKey = true;
186
+ }
187
+ }
188
+
189
+ if (hasKey) {
171
190
  withKeys.push(ide);
172
191
  } else {
173
192
  withoutKeys.push(ide);
@@ -234,20 +253,17 @@ function installViaCodexCLI(existingApiKey = '') {
234
253
  const { mcpClientPath, packageDir } = getMcpClientPaths();
235
254
  const nodeEnv = detectNodeEnvironment();
236
255
 
237
- // Build the command with env vars
238
- const envArgs = [
239
- '--env', `MCP_SERVER_URL=https://mcp.i18nagent.ai`
240
- ];
241
-
242
- if (existingApiKey) {
243
- envArgs.push('--env', `API_KEY=${existingApiKey}`);
244
- } else {
245
- envArgs.push('--env', 'API_KEY=');
246
- }
247
-
248
256
  // Determine node command - use absolute path for nvm
249
257
  const nodeCmd = nodeEnv.isNvm ? nodeEnv.nodePath : 'node';
250
258
 
259
+ // Get existing API key from CLI registration BEFORE removing
260
+ if (!existingApiKey) {
261
+ existingApiKey = getCodexExistingApiKey('i18n-agent');
262
+ if (existingApiKey) {
263
+ console.log(' 🔑 Preserving existing API key from CLI registration');
264
+ }
265
+ }
266
+
251
267
  // Remove existing registration if present
252
268
  if (isCodexMCPRegistered('i18n-agent')) {
253
269
  try {
@@ -258,6 +274,17 @@ function installViaCodexCLI(existingApiKey = '') {
258
274
  }
259
275
  }
260
276
 
277
+ // Build the command with env vars
278
+ const envArgs = [
279
+ '--env', `MCP_SERVER_URL=https://mcp.i18nagent.ai`
280
+ ];
281
+
282
+ if (existingApiKey) {
283
+ envArgs.push('--env', `API_KEY=${existingApiKey}`);
284
+ } else {
285
+ envArgs.push('--env', 'API_KEY=');
286
+ }
287
+
261
288
  // Build the full command
262
289
  // codex mcp add [--env KEY=VALUE]... <name> <command> [args...]
263
290
  const cmdParts = [
@@ -297,6 +324,41 @@ function isClaudeCodeMCPRegistered(serverName) {
297
324
  }
298
325
  }
299
326
 
327
+ // Get existing API key from Claude Code CLI registration
328
+ function getClaudeCodeExistingApiKey(serverName) {
329
+ try {
330
+ const output = execSync(`claude mcp get ${serverName}`, { stdio: 'pipe', encoding: 'utf8' });
331
+ // Parse output like: API_KEY=i18n_xxx
332
+ const match = output.match(/API_KEY=([^\s,\n]+)/);
333
+ if (match && match[1] && match[1] !== '') {
334
+ return match[1];
335
+ }
336
+ } catch {
337
+ // Server not registered
338
+ }
339
+ return '';
340
+ }
341
+
342
+ // Get existing API key from Codex CLI registration
343
+ function getCodexExistingApiKey(serverName) {
344
+ try {
345
+ const output = execSync(`codex mcp list`, { stdio: 'pipe', encoding: 'utf8' });
346
+ // Parse output - Codex shows: API_KEY=i18n_xxx, MCP_SERVER_URL=...
347
+ const lines = output.split('\n');
348
+ for (const line of lines) {
349
+ if (line.includes(serverName)) {
350
+ const match = line.match(/API_KEY=([^\s,]+)/);
351
+ if (match && match[1] && match[1] !== '') {
352
+ return match[1];
353
+ }
354
+ }
355
+ }
356
+ } catch {
357
+ // Server not registered
358
+ }
359
+ return '';
360
+ }
361
+
300
362
  // Install MCP server via Claude Code CLI native command
301
363
  function installViaClaudeCodeCLI(existingApiKey = '', scope = 'user') {
302
364
  const { mcpClientPath } = getMcpClientPaths();
@@ -305,6 +367,14 @@ function installViaClaudeCodeCLI(existingApiKey = '', scope = 'user') {
305
367
  // Determine node command - use absolute path for nvm
306
368
  const nodeCmd = nodeEnv.isNvm ? nodeEnv.nodePath : 'node';
307
369
 
370
+ // Get existing API key from CLI registration BEFORE removing
371
+ if (!existingApiKey) {
372
+ existingApiKey = getClaudeCodeExistingApiKey('i18n-agent');
373
+ if (existingApiKey) {
374
+ console.log(' 🔑 Preserving existing API key from CLI registration');
375
+ }
376
+ }
377
+
308
378
  // Remove existing registration if present
309
379
  if (isClaudeCodeMCPRegistered('i18n-agent')) {
310
380
  try {
@@ -545,8 +615,12 @@ For manual setup instructions, visit: https://docs.i18nagent.ai/setup
545
615
  });
546
616
  console.log('');
547
617
 
618
+ // Check if native CLIs are available (needed for API key detection)
619
+ const codexCLIAvailable = isCodexCLIAvailable();
620
+ const claudeCodeCLIAvailable = isClaudeCodeCLIAvailable();
621
+
548
622
  // Check for existing API keys BEFORE installation
549
- const { withKeys, withoutKeys } = await checkExistingApiKeys(availableIDEs);
623
+ const { withKeys, withoutKeys } = await checkExistingApiKeys(availableIDEs, claudeCodeCLIAvailable, codexCLIAvailable);
550
624
 
551
625
  if (withKeys.length > 0 && withoutKeys.length === 0) {
552
626
  console.log(`✅ API Keys Already Configured:`);
@@ -586,10 +660,7 @@ For manual setup instructions, visit: https://docs.i18nagent.ai/setup
586
660
  const idesWithApiKey = [];
587
661
  const idesNeedingApiKey = [];
588
662
 
589
- // Check if native CLIs are available
590
- const codexCLIAvailable = isCodexCLIAvailable();
591
- const claudeCodeCLIAvailable = isClaudeCodeCLIAvailable();
592
-
663
+ // Show native CLI detection message (CLIs already detected above)
593
664
  if (codexCLIAvailable || claudeCodeCLIAvailable) {
594
665
  console.log('🔧 Native CLI support detected:');
595
666
  if (claudeCodeCLIAvailable) {
@@ -609,9 +680,9 @@ For manual setup instructions, visit: https://docs.i18nagent.ai/setup
609
680
 
610
681
  // Special handling for Claude Code CLI - use native CLI if available
611
682
  if (ide.key === 'claude-code' && claudeCodeCLIAvailable) {
612
- // Get existing API key from config file if present
613
- let existingApiKey = '';
614
- if (fs.existsSync(ide.configPath)) {
683
+ // Get existing API key - check CLI registration first, then config file
684
+ let existingApiKey = getClaudeCodeExistingApiKey('i18n-agent');
685
+ if (!existingApiKey && fs.existsSync(ide.configPath)) {
615
686
  try {
616
687
  const content = fs.readFileSync(ide.configPath, 'utf8');
617
688
  const config = JSON.parse(content);
@@ -643,9 +714,9 @@ For manual setup instructions, visit: https://docs.i18nagent.ai/setup
643
714
 
644
715
  // Special handling for Codex - use native CLI if available
645
716
  if (ide.key === 'codex' && codexCLIAvailable) {
646
- // Get existing API key from config file if present
647
- let existingApiKey = '';
648
- if (fs.existsSync(ide.configPath)) {
717
+ // Get existing API key - check CLI registration first, then config file
718
+ let existingApiKey = getCodexExistingApiKey('i18n-agent');
719
+ if (!existingApiKey && fs.existsSync(ide.configPath)) {
649
720
  try {
650
721
  const content = fs.readFileSync(ide.configPath, 'utf8');
651
722
  const config = JSON.parse(content);
package/mcp-client.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Integrates with Claude Code CLI to provide translation capabilities
6
6
  */
7
7
 
8
- const MCP_CLIENT_VERSION = '1.9.0';
8
+ const MCP_CLIENT_VERSION = '1.9.2';
9
9
 
10
10
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
11
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
@@ -144,7 +144,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
144
144
  },
145
145
  {
146
146
  name: 'translate_file',
147
- description: 'Translate file content while preserving structure and format. Supports single or multi-language translation via targetLanguages parameter (string for single, array for multiple). Supports JSON, YAML, XML, CSV, TXT, MD, and other text files. Always returns a jobId for async processing - use check_translation_status to monitor progress and download_translations to get results. Set pseudoTranslation=true for testing i18n implementations without AI cost.',
147
+ description: 'Translate file content while preserving structure and format. Supports single or multi-language translation via targetLanguages parameter (string for single, array for multiple). Supports JSON, YAML, XML, CSV, TXT, MD, and other text files. Always returns a jobId for async processing - use check_translation_status to monitor progress and download_translations to get results. Set pseudoTranslation=true for testing i18n implementations without AI cost. TOKEN-SAVING TIP: After receiving the jobId, run check_translation_status in background (using run_in_background parameter) to avoid blocking the conversation and reduce token usage from repeated status polling.',
148
148
  inputSchema: {
149
149
  type: 'object',
150
150
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-agent/mcp-client",
3
- "version": "1.9.0",
3
+ "version": "1.9.2",
4
4
  "description": "🌍 i18n-agent MCP Client - 48 languages, AI-powered translation for Claude, Claude Code, Cursor, VS Code, Codex. Get API key at https://app.i18nagent.ai",
5
5
  "main": "mcp-client.js",
6
6
  "bin": {