@i18n-agent/mcp-client 1.1.1 → 1.1.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.
Files changed (2) hide show
  1. package/mcp-client.js +79 -12
  2. package/package.json +1 -1
package/mcp-client.js CHANGED
@@ -5,6 +5,8 @@
5
5
  * Integrates with Claude Code CLI to provide translation capabilities
6
6
  */
7
7
 
8
+ const MCP_CLIENT_VERSION = '1.1.2';
9
+
8
10
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
9
11
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
12
  import {
@@ -20,7 +22,7 @@ import path from 'path';
20
22
  const server = new Server(
21
23
  {
22
24
  name: 'i18n-agent',
23
- version: '1.0.0',
25
+ version: MCP_CLIENT_VERSION,
24
26
  },
25
27
  {
26
28
  capabilities: {
@@ -305,17 +307,47 @@ async function handleTranslateText(args) {
305
307
  };
306
308
  }
307
309
 
308
- // Check if it's actually a service unavailable error (503, timeout, connection issues)
310
+ // Handle 401 unauthorized - invalid API key
311
+ if (error.response?.status === 401) {
312
+ const errorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
313
+ throw new Error(`❌ Invalid API key (401)\nDetails: ${errorDetails}\nPlease check your API key at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_text]`);
314
+ }
315
+
316
+ // Handle 402 payment required with user-friendly message
317
+ if (error.response?.status === 402) {
318
+ const errorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
319
+ throw new Error(`⚠️ Insufficient credits (402)\nDetails: ${errorDetails}\nPlease top up at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_text]`);
320
+ }
321
+
322
+ // Check if it's a large content issue
323
+ const totalChars = texts.reduce((sum, text) => sum + text.length, 0);
324
+ if (error.response?.status === 413 ||
325
+ (error.response?.status === 503 && totalChars > 50000)) {
326
+ const errorDetails = error.response?.data?.message || error.response?.data?.result?.content?.[0]?.text || error.message;
327
+ const errorMsg = `Content too large (${totalChars} characters, ${texts.length} texts)\nStatus: ${error.response?.status}\nDetails: ${errorDetails}\n\nPlease break into smaller batches:\n• Split into batches of 50-100 texts\n• Keep total size under 50KB per request\n• Process sequentially to avoid overload\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_text]`;
328
+ throw new Error(errorMsg);
329
+ }
330
+
331
+ // Check if it's actually a service unavailable error (only for real infrastructure issues)
309
332
  if (error.code === 'ECONNREFUSED' ||
310
333
  error.code === 'ETIMEDOUT' ||
311
- error.response?.status === 503 ||
334
+ error.code === 'ENOTFOUND' ||
335
+ (error.response?.status === 503 && totalChars <= 50000) ||
312
336
  error.response?.status === 502 ||
313
337
  error.response?.status === 504) {
314
- throw new Error(`Translation service unavailable: ${error.message}`);
338
+ const errorDetails = error.response?.data?.result?.content?.[0]?.text ||
339
+ error.response?.data?.error?.message ||
340
+ error.message;
341
+ const debugInfo = `Code: ${error.code || 'N/A'}\nStatus: ${error.response?.status || 'N/A'}\nStatusText: ${error.response?.statusText || 'N/A'}\nDetails: ${errorDetails}\nURL: ${error.config?.url || 'N/A'}\nTimestamp: ${new Date().toISOString()}`;
342
+ throw new Error(`Translation service error\n${debugInfo}\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_text]`);
315
343
  }
316
344
 
317
- // For other errors (401, 402, 404, etc), throw them as-is without "unavailable" keyword
318
- throw error;
345
+ // For other errors, include all debug info in the error message
346
+ const errorDetails = error.response?.data?.result?.content?.[0]?.text ||
347
+ error.response?.data?.error?.message ||
348
+ error.message;
349
+ const debugInfo = `Status: ${error.response?.status || 'N/A'}\nStatusText: ${error.response?.statusText || 'N/A'}\nDetails: ${errorDetails}\nTimestamp: ${new Date().toISOString()}`;
350
+ throw new Error(`Error\n${debugInfo}\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_text]`);
319
351
  }
320
352
  }
321
353
 
@@ -485,6 +517,8 @@ async function handleTranslateFile(args) {
485
517
  return result;
486
518
 
487
519
  } catch (error) {
520
+ // Debug info will be included in error messages for visibility
521
+
488
522
  if (error.code === 'ECONNABORTED') {
489
523
  return {
490
524
  content: [
@@ -507,17 +541,50 @@ async function handleTranslateFile(args) {
507
541
  };
508
542
  }
509
543
 
510
- // Check if it's actually a service unavailable error
544
+ // Handle 401 unauthorized - invalid API key
545
+ if (error.response?.status === 401) {
546
+ const errorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
547
+ throw new Error(`❌ Invalid API key (401)\nDetails: ${errorDetails}\nPlease check your API key at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_file]`);
548
+ }
549
+
550
+ // Handle 402 payment required with user-friendly message
551
+ if (error.response?.status === 402) {
552
+ const errorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
553
+ throw new Error(`⚠️ Insufficient credits (402)\nDetails: ${errorDetails}\nPlease top up at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_file]`);
554
+ }
555
+
556
+ // Check if it's a timeout issue (45-second server timeout) or large file issue
557
+ const errorDetails = error.response?.data?.result?.content?.[0]?.text ||
558
+ error.response?.data?.error?.message ||
559
+ error.message;
560
+
561
+ if (error.response?.status === 413 ||
562
+ (error.response?.status === 503 && content.length > 50000) ||
563
+ (error.response?.status === 503 && errorDetails.includes('timeout after 45 seconds'))) {
564
+ const errorMsg = `File too large or complex (${content.length} characters)\n\nThe server has a 45-second timeout. Your file requires more processing time.\n\nPlease break into smaller chunks:\n• Split files over 50KB into multiple parts\n• Translate sections separately (e.g., split by top-level keys for JSON)\n• Use translate_text for batches of 50-100 strings\n• Each chunk should process in under 45 seconds\n\nAlternatively, wait for async job support (coming soon).\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_file]`;
565
+ throw new Error(errorMsg);
566
+ }
567
+
568
+ // Check if it's actually a service unavailable error (only for real infrastructure issues)
511
569
  if (error.code === 'ECONNREFUSED' ||
512
570
  error.code === 'ETIMEDOUT' ||
513
- error.response?.status === 503 ||
571
+ error.code === 'ENOTFOUND' ||
572
+ (error.response?.status === 503 && content.length <= 50000) ||
514
573
  error.response?.status === 502 ||
515
574
  error.response?.status === 504) {
516
- throw new Error(`Translation service unavailable: ${error.message}`);
575
+ const errorDetails = error.response?.data?.result?.content?.[0]?.text ||
576
+ error.response?.data?.error?.message ||
577
+ error.message;
578
+ const debugInfo = `Code: ${error.code || 'N/A'}\nStatus: ${error.response?.status || 'N/A'}\nStatusText: ${error.response?.statusText || 'N/A'}\nDetails: ${errorDetails}\nURL: ${error.config?.url || 'N/A'}\nTimestamp: ${new Date().toISOString()}`;
579
+ throw new Error(`Translation service error\n${debugInfo}\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_file]`);
517
580
  }
518
581
 
519
- // For other errors, throw them as-is without "unavailable" keyword
520
- throw error;
582
+ // For other errors, include all debug info in the error message
583
+ const errorDetails = error.response?.data?.result?.content?.[0]?.text ||
584
+ error.response?.data?.error?.message ||
585
+ error.message;
586
+ const debugInfo = `Status: ${error.response?.status || 'N/A'}\nStatusText: ${error.response?.statusText || 'N/A'}\nDetails: ${errorDetails}\nTimestamp: ${new Date().toISOString()}`;
587
+ throw new Error(`Error\n${debugInfo}\n[MCP v${MCP_CLIENT_VERSION}/STDIO/translate_file]`);
521
588
  }
522
589
  }
523
590
 
@@ -597,7 +664,7 @@ async function pollTranslationJob(jobId, estimatedTime) {
597
664
  async function handleGetCredits(args) {
598
665
  try {
599
666
  // Get team info first using the API key
600
- const teamResponse = await axios.get(`https://platform.i18nagent.ai/api/teams/by-api-key/${API_KEY}`, {
667
+ const teamResponse = await axios.get(`https://app.i18nagent.ai/api/teams/by-api-key/${API_KEY}`, {
601
668
  headers: {
602
669
  'Content-Type': 'application/json'
603
670
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-agent/mcp-client",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "MCP client for i18n-agent translation service - supports Claude, Cursor, VS Code, and other AI IDEs",
5
5
  "main": "mcp-client.js",
6
6
  "bin": {