@i18n-agent/mcp-client 1.8.17 → 1.8.19
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/install.js +12 -6
- package/mcp-client.js +129 -39
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -184,7 +184,8 @@ function createMCPConfig() {
|
|
|
184
184
|
env: {
|
|
185
185
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
186
186
|
API_KEY: ""
|
|
187
|
-
}
|
|
187
|
+
},
|
|
188
|
+
disabled: false
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
191
|
};
|
|
@@ -272,7 +273,8 @@ function updateClaudeConfig(configPath, ideKey = 'claude') {
|
|
|
272
273
|
env: {
|
|
273
274
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
274
275
|
API_KEY: existingApiKey || ""
|
|
275
|
-
}
|
|
276
|
+
},
|
|
277
|
+
disabled: false
|
|
276
278
|
};
|
|
277
279
|
} else {
|
|
278
280
|
// For system node, use 'node' with args
|
|
@@ -294,7 +296,8 @@ function updateClaudeConfig(configPath, ideKey = 'claude') {
|
|
|
294
296
|
env: {
|
|
295
297
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
296
298
|
API_KEY: existingApiKey || ""
|
|
297
|
-
}
|
|
299
|
+
},
|
|
300
|
+
disabled: false
|
|
298
301
|
};
|
|
299
302
|
} else {
|
|
300
303
|
const baseConfig = createMCPConfig();
|
|
@@ -350,7 +353,8 @@ function updateGenericMCPConfig(configPath) {
|
|
|
350
353
|
env: {
|
|
351
354
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
352
355
|
API_KEY: existingApiKey || ""
|
|
353
|
-
}
|
|
356
|
+
},
|
|
357
|
+
disabled: false
|
|
354
358
|
};
|
|
355
359
|
} else {
|
|
356
360
|
const baseConfig = createMCPConfig();
|
|
@@ -402,7 +406,8 @@ function updateClaudeJsonConfig(configPath) {
|
|
|
402
406
|
env: {
|
|
403
407
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
404
408
|
API_KEY: existingApiKey || ""
|
|
405
|
-
}
|
|
409
|
+
},
|
|
410
|
+
disabled: false
|
|
406
411
|
};
|
|
407
412
|
} else {
|
|
408
413
|
config.mcpServers["i18n-agent"] = {
|
|
@@ -411,7 +416,8 @@ function updateClaudeJsonConfig(configPath) {
|
|
|
411
416
|
env: {
|
|
412
417
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
413
418
|
API_KEY: existingApiKey || ""
|
|
414
|
-
}
|
|
419
|
+
},
|
|
420
|
+
disabled: false
|
|
415
421
|
};
|
|
416
422
|
}
|
|
417
423
|
|
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.8.
|
|
8
|
+
const MCP_CLIENT_VERSION = '1.8.19';
|
|
9
9
|
|
|
10
10
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
11
11
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -47,7 +47,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
47
47
|
tools: [
|
|
48
48
|
{
|
|
49
49
|
name: 'translate_text',
|
|
50
|
-
description: '⚠️ CRITICAL: For multi-language translation, use targetLanguages parameter (not targetLanguage). Translate text content with cultural adaptation using AI subagents. Supports both single and multi-language translation. For large requests (>100 texts or >50,000 characters), returns a jobId for async processing. Use check_translation_status to monitor progress and download results.',
|
|
50
|
+
description: '⚠️ CRITICAL: For multi-language translation, use targetLanguages parameter (not targetLanguage). Translate text content with cultural adaptation using AI subagents. Supports both single and multi-language translation. For large requests (>100 texts or >50,000 characters), returns a jobId for async processing. Use check_translation_status to monitor progress and download results. Set pseudoTranslation=true for testing i18n implementations without AI cost.',
|
|
51
51
|
inputSchema: {
|
|
52
52
|
type: 'object',
|
|
53
53
|
properties: {
|
|
@@ -83,6 +83,36 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
83
83
|
type: 'string',
|
|
84
84
|
description: 'Optional additional context or instructions for the translation (e.g., "Keep technical terms in English", "Use formal tone")',
|
|
85
85
|
},
|
|
86
|
+
pseudoTranslation: {
|
|
87
|
+
type: 'boolean',
|
|
88
|
+
description: 'Enable pseudo-translation mode for testing i18n implementations (bypasses AI translation, no credit cost)',
|
|
89
|
+
},
|
|
90
|
+
pseudoOptions: {
|
|
91
|
+
type: 'object',
|
|
92
|
+
properties: {
|
|
93
|
+
addCJK: {
|
|
94
|
+
type: 'boolean',
|
|
95
|
+
description: 'Add CJK characters to test wide character support',
|
|
96
|
+
},
|
|
97
|
+
expansionRatio: {
|
|
98
|
+
type: 'number',
|
|
99
|
+
description: 'Length expansion ratio (1.0 = no expansion, 1.3 = 30% longer, 2.0 = double length)',
|
|
100
|
+
},
|
|
101
|
+
addSpecialChars: {
|
|
102
|
+
type: 'boolean',
|
|
103
|
+
description: 'Add special characters to test encoding/escaping',
|
|
104
|
+
},
|
|
105
|
+
addBrackets: {
|
|
106
|
+
type: 'boolean',
|
|
107
|
+
description: 'Wrap strings with brackets to identify untranslated content',
|
|
108
|
+
},
|
|
109
|
+
addAccents: {
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
description: 'Replace Latin characters with accented equivalents',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
description: 'Configuration options for pseudo-translation',
|
|
115
|
+
},
|
|
86
116
|
},
|
|
87
117
|
required: ['texts', 'targetLanguages'],
|
|
88
118
|
},
|
|
@@ -103,7 +133,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
103
133
|
},
|
|
104
134
|
{
|
|
105
135
|
name: 'translate_file',
|
|
106
|
-
description: '⚠️ CRITICAL: For multi-language translation, use targetLanguages parameter (not targetLanguage). Translate file content while preserving structure and format. Supports both single and multi-language translation. Supports JSON, YAML, XML, CSV, TXT, MD, and other text files. For large files (>100KB), returns a jobId for async processing. Use check_translation_status to monitor progress and download results.',
|
|
136
|
+
description: '⚠️ CRITICAL: For multi-language translation, use targetLanguages parameter (not targetLanguage). Translate file content while preserving structure and format. Supports both single and multi-language translation. Supports JSON, YAML, XML, CSV, TXT, MD, and other text files. For large files (>100KB), returns a jobId for async processing. Use check_translation_status to monitor progress and download results. Set pseudoTranslation=true for testing i18n implementations without AI cost.',
|
|
107
137
|
inputSchema: {
|
|
108
138
|
type: 'object',
|
|
109
139
|
properties: {
|
|
@@ -160,6 +190,36 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
160
190
|
type: 'string',
|
|
161
191
|
description: 'Optional additional context or instructions for the translation (e.g., "Keep technical terms in English", "Use formal tone")',
|
|
162
192
|
},
|
|
193
|
+
pseudoTranslation: {
|
|
194
|
+
type: 'boolean',
|
|
195
|
+
description: 'Enable pseudo-translation mode for testing i18n implementations (bypasses AI translation, no credit cost)',
|
|
196
|
+
},
|
|
197
|
+
pseudoOptions: {
|
|
198
|
+
type: 'object',
|
|
199
|
+
properties: {
|
|
200
|
+
addCJK: {
|
|
201
|
+
type: 'boolean',
|
|
202
|
+
description: 'Add CJK characters to test wide character support',
|
|
203
|
+
},
|
|
204
|
+
expansionRatio: {
|
|
205
|
+
type: 'number',
|
|
206
|
+
description: 'Length expansion ratio (1.0 = no expansion, 1.3 = 30% longer, 2.0 = double length)',
|
|
207
|
+
},
|
|
208
|
+
addSpecialChars: {
|
|
209
|
+
type: 'boolean',
|
|
210
|
+
description: 'Add special characters to test encoding/escaping',
|
|
211
|
+
},
|
|
212
|
+
addBrackets: {
|
|
213
|
+
type: 'boolean',
|
|
214
|
+
description: 'Wrap strings with brackets to identify untranslated content',
|
|
215
|
+
},
|
|
216
|
+
addAccents: {
|
|
217
|
+
type: 'boolean',
|
|
218
|
+
description: 'Replace Latin characters with accented equivalents',
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
description: 'Configuration options for pseudo-translation',
|
|
222
|
+
},
|
|
163
223
|
},
|
|
164
224
|
required: ['targetLanguages'],
|
|
165
225
|
},
|
|
@@ -376,7 +436,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
376
436
|
});
|
|
377
437
|
|
|
378
438
|
async function handleTranslateText(args) {
|
|
379
|
-
const { texts, targetLanguages: rawTargetLanguages, sourceLanguage, targetAudience = 'general', industry = 'technology', region, context } = args;
|
|
439
|
+
const { texts, targetLanguages: rawTargetLanguages, sourceLanguage, targetAudience = 'general', industry = 'technology', region, context, pseudoTranslation, pseudoOptions } = args;
|
|
380
440
|
|
|
381
441
|
if (!texts || !Array.isArray(texts) || texts.length === 0) {
|
|
382
442
|
throw new Error('texts must be a non-empty array');
|
|
@@ -420,6 +480,8 @@ async function handleTranslateText(args) {
|
|
|
420
480
|
industry: industry,
|
|
421
481
|
region: region,
|
|
422
482
|
context: context,
|
|
483
|
+
pseudoTranslation: pseudoTranslation,
|
|
484
|
+
pseudoOptions: pseudoOptions,
|
|
423
485
|
}
|
|
424
486
|
}
|
|
425
487
|
};
|
|
@@ -684,7 +746,9 @@ async function handleTranslateFile(args) {
|
|
|
684
746
|
outputFormat = 'same',
|
|
685
747
|
sourceLanguage,
|
|
686
748
|
region,
|
|
687
|
-
context
|
|
749
|
+
context,
|
|
750
|
+
pseudoTranslation,
|
|
751
|
+
pseudoOptions
|
|
688
752
|
} = args;
|
|
689
753
|
|
|
690
754
|
if (!filePath && !fileContent) {
|
|
@@ -740,6 +804,8 @@ async function handleTranslateFile(args) {
|
|
|
740
804
|
if (targetLanguages !== undefined) requestArgs.targetLanguages = targetLanguages;
|
|
741
805
|
if (region !== undefined) requestArgs.region = region;
|
|
742
806
|
if (context !== undefined) requestArgs.context = context;
|
|
807
|
+
if (pseudoTranslation !== undefined) requestArgs.pseudoTranslation = pseudoTranslation;
|
|
808
|
+
if (pseudoOptions !== undefined) requestArgs.pseudoOptions = pseudoOptions;
|
|
743
809
|
|
|
744
810
|
// Use MCP JSON-RPC protocol for translate_file
|
|
745
811
|
const mcpRequest = {
|
|
@@ -1630,11 +1696,8 @@ async function handleDownloadTranslations(args) {
|
|
|
1630
1696
|
parsedResult = result;
|
|
1631
1697
|
}
|
|
1632
1698
|
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
// Step 2: Download files from URLs and write to local /tmp
|
|
1699
|
+
// Detect storage type and handle accordingly
|
|
1700
|
+
const storageType = parsedResult.storageType || 'local';
|
|
1638
1701
|
const outputDir = `/tmp/i18n-translations-${jobId}`;
|
|
1639
1702
|
|
|
1640
1703
|
// Create output directory
|
|
@@ -1642,40 +1705,65 @@ async function handleDownloadTranslations(args) {
|
|
|
1642
1705
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
1643
1706
|
}
|
|
1644
1707
|
|
|
1645
|
-
const downloadUrls = parsedResult.downloadUrls;
|
|
1646
|
-
if (!downloadUrls || downloadUrls.length === 0) {
|
|
1647
|
-
throw new Error('No download URLs provided by server');
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
1708
|
const filesWritten = [];
|
|
1651
1709
|
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
console.error(`📥 Downloading ${language}...`);
|
|
1710
|
+
if (storageType === 's3' && parsedResult.downloadUrls) {
|
|
1711
|
+
// Case 1: S3 Storage - download files from presigned URLs
|
|
1712
|
+
console.error(`📥 Downloading ${Object.keys(parsedResult.downloadUrls).length} translation files from S3...`);
|
|
1656
1713
|
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1714
|
+
for (const [language, urlInfo] of Object.entries(parsedResult.downloadUrls)) {
|
|
1715
|
+
try {
|
|
1716
|
+
console.error(`📥 Downloading ${language}...`);
|
|
1717
|
+
|
|
1718
|
+
const fileResponse = await axios.get(urlInfo.url, {
|
|
1719
|
+
responseType: 'text',
|
|
1720
|
+
timeout: 60000, // 1 minute per file
|
|
1721
|
+
headers: {
|
|
1722
|
+
'Authorization': `Bearer ${API_KEY}`
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1664
1725
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1726
|
+
// Determine file extension from file name or metadata
|
|
1727
|
+
const fileType = parsedResult.fileName?.split('.').pop() || 'json';
|
|
1728
|
+
const fileName = `${language}.${fileType}`;
|
|
1729
|
+
const filePath = path.join(outputDir, fileName);
|
|
1669
1730
|
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1731
|
+
// Write file to disk
|
|
1732
|
+
fs.writeFileSync(filePath, fileResponse.data, 'utf8');
|
|
1733
|
+
filesWritten.push(filePath);
|
|
1673
1734
|
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1735
|
+
console.error(`✅ Downloaded ${fileName}`);
|
|
1736
|
+
} catch (downloadError) {
|
|
1737
|
+
console.error(`❌ Failed to download ${language}:`, downloadError.message);
|
|
1738
|
+
throw new Error(`Failed to download ${language}: ${downloadError.message}`);
|
|
1739
|
+
}
|
|
1678
1740
|
}
|
|
1741
|
+
} else if (parsedResult.translations) {
|
|
1742
|
+
// Case 2: Raw Translations - write directly from response
|
|
1743
|
+
console.error(`💾 Writing ${Object.keys(parsedResult.translations).length} translation files from raw content...`);
|
|
1744
|
+
|
|
1745
|
+
for (const [language, content] of Object.entries(parsedResult.translations)) {
|
|
1746
|
+
try {
|
|
1747
|
+
console.error(`💾 Writing ${language}...`);
|
|
1748
|
+
|
|
1749
|
+
// Determine file extension from file name or default to json
|
|
1750
|
+
const fileType = parsedResult.fileName?.split('.').pop() || 'json';
|
|
1751
|
+
const fileName = `${language}.${fileType}`;
|
|
1752
|
+
const filePath = path.join(outputDir, fileName);
|
|
1753
|
+
|
|
1754
|
+
// Write file to disk
|
|
1755
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
1756
|
+
filesWritten.push(filePath);
|
|
1757
|
+
|
|
1758
|
+
console.error(`✅ Wrote ${fileName}`);
|
|
1759
|
+
} catch (writeError) {
|
|
1760
|
+
console.error(`❌ Failed to write ${language}:`, writeError.message);
|
|
1761
|
+
throw new Error(`Failed to write ${language}: ${writeError.message}`);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
} else {
|
|
1765
|
+
// No valid download method found
|
|
1766
|
+
throw new Error(`No translations available. Storage type: ${storageType}. Expected either downloadUrls (S3) or translations (raw content).`);
|
|
1679
1767
|
}
|
|
1680
1768
|
|
|
1681
1769
|
// Return success with file paths
|
|
@@ -1687,8 +1775,10 @@ async function handleDownloadTranslations(args) {
|
|
|
1687
1775
|
jobId,
|
|
1688
1776
|
outputDirectory: outputDir,
|
|
1689
1777
|
filesWritten,
|
|
1690
|
-
|
|
1691
|
-
|
|
1778
|
+
storageType,
|
|
1779
|
+
fileName: parsedResult.fileName,
|
|
1780
|
+
targetLanguages: parsedResult.targetLanguages,
|
|
1781
|
+
message: `✅ ${storageType === 's3' ? 'Downloaded' : 'Wrote'} ${filesWritten.length} translation files to ${outputDir}`
|
|
1692
1782
|
}, null, 2)
|
|
1693
1783
|
}]
|
|
1694
1784
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-agent/mcp-client",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.19",
|
|
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": {
|