@i18n-agent/mcp-client 1.7.8 → 1.8.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.
- package/README.md +45 -29
- package/install.js +41 -25
- package/mcp-client.js +137 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Professional translation service client for Claude, Cursor, VS Code, and other A
|
|
|
13
13
|
- **🔄 Timeout Improvements**: Extended timeouts (5-10 min) for large translations
|
|
14
14
|
- **📊 Progress Tracking**: Real-time job status and completion monitoring
|
|
15
15
|
- **💰 Credit Tracking**: Real-time credit balance and word count estimates
|
|
16
|
-
- **🌐
|
|
16
|
+
- **🌐 48 Languages**: Comprehensive language support with regional variants
|
|
17
17
|
- **🔧 Easy Setup**: One-command installation for major AI IDEs
|
|
18
18
|
|
|
19
19
|
## 🚀 Quick Installation
|
|
@@ -71,7 +71,7 @@ List supported languages with quality ratings
|
|
|
71
71
|
|
|
72
72
|
### Content Analysis
|
|
73
73
|
```
|
|
74
|
-
Analyze
|
|
74
|
+
Analyze "Hello world! This is a test." for translation to Spanish
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
## 🛠 Supported AI IDEs
|
|
@@ -83,41 +83,54 @@ Analyze content for translation readiness and get improvement suggestions
|
|
|
83
83
|
| **VS Code** | ✅ Auto-configured | `~/.vscode/mcp_settings.json` |
|
|
84
84
|
| **Other MCP IDEs** | 🔧 Manual setup | Varies |
|
|
85
85
|
|
|
86
|
-
## 🌐 Language Support
|
|
87
|
-
- **
|
|
88
|
-
- **
|
|
86
|
+
## 🌐 Language Support (48 Languages)
|
|
87
|
+
- **bg**: Bulgarian
|
|
88
|
+
- **ca**: Catalan
|
|
89
|
+
- **cs**: Czech
|
|
90
|
+
- **da**: Danish
|
|
89
91
|
- **de**: German
|
|
92
|
+
- **el**: Greek
|
|
93
|
+
- **en**: English
|
|
94
|
+
- **en-AU**: English (Australia)
|
|
95
|
+
- **en-CA**: English (Canada)
|
|
96
|
+
- **en-GB**: English (United Kingdom)
|
|
97
|
+
- **en-US**: English (United States)
|
|
90
98
|
- **es**: Spanish
|
|
99
|
+
- **es-MX**: Spanish (Mexico)
|
|
100
|
+
- **et**: Estonian
|
|
101
|
+
- **fi**: Finnish
|
|
102
|
+
- **fr**: French
|
|
103
|
+
- **fr-CA**: French (Canada)
|
|
104
|
+
- **hi**: Hindi
|
|
105
|
+
- **hr**: Croatian
|
|
106
|
+
- **hu**: Hungarian
|
|
107
|
+
- **id**: Indonesian
|
|
108
|
+
- **is**: Icelandic
|
|
91
109
|
- **it**: Italian
|
|
92
|
-
- **pt**: Portuguese
|
|
93
|
-
- **ru**: Russian
|
|
94
110
|
- **ja**: Japanese
|
|
95
111
|
- **ko**: Korean
|
|
96
|
-
- **
|
|
112
|
+
- **lt**: Lithuanian
|
|
113
|
+
- **lv**: Latvian
|
|
114
|
+
- **ms**: Malay
|
|
97
115
|
- **nl**: Dutch
|
|
98
|
-
- **pl**: Polish
|
|
99
|
-
- **cs**: Czech
|
|
100
|
-
- **ar**: Arabic
|
|
101
|
-
- **he**: Hebrew
|
|
102
|
-
- **hi**: Hindi
|
|
103
|
-
- **zh-TW**: Chinese (Traditional)
|
|
104
|
-
- **sv**: Swedish
|
|
105
|
-
- **da**: Danish
|
|
106
116
|
- **no**: Norwegian
|
|
107
|
-
- **
|
|
108
|
-
- **
|
|
109
|
-
- **
|
|
110
|
-
- **th**: Thai
|
|
111
|
-
- **vi**: Vietnamese
|
|
112
|
-
- **uk**: Ukrainian
|
|
113
|
-
- **bg**: Bulgarian
|
|
117
|
+
- **pl**: Polish
|
|
118
|
+
- **pt**: Portuguese
|
|
119
|
+
- **pt-BR**: Portuguese (Brazil)
|
|
114
120
|
- **ro**: Romanian
|
|
115
|
-
- **
|
|
121
|
+
- **ru**: Russian
|
|
116
122
|
- **sk**: Slovak
|
|
117
123
|
- **sl**: Slovenian
|
|
118
|
-
- **
|
|
119
|
-
- **
|
|
120
|
-
- **
|
|
124
|
+
- **sr**: Serbian
|
|
125
|
+
- **sv**: Swedish
|
|
126
|
+
- **th**: Thai
|
|
127
|
+
- **tl**: Filipino
|
|
128
|
+
- **tr**: Turkish
|
|
129
|
+
- **uk**: Ukrainian
|
|
130
|
+
- **vi**: Vietnamese
|
|
131
|
+
- **zh-Hans**: Chinese (Simplified)
|
|
132
|
+
- **zh-Hant-HK**: Chinese (Traditional, Hong Kong)
|
|
133
|
+
- **zh-Hant-TW**: Chinese (Traditional, Taiwan)
|
|
121
134
|
|
|
122
135
|
## 📁 Supported File Formats
|
|
123
136
|
|
|
@@ -128,8 +141,11 @@ Analyze content for translation readiness and get improvement suggestions
|
|
|
128
141
|
| CSV | `.csv` | Handles quoted fields, commas |
|
|
129
142
|
| XML/HTML | `.xml`, `.html` | Extracts text content |
|
|
130
143
|
| Markdown | `.md` | Preserves formatting, skips code |
|
|
131
|
-
| Properties | `.properties` |
|
|
144
|
+
| Properties | `.properties` | Java properties key-value pairs |
|
|
132
145
|
| Plain Text | `.txt` | Direct translation |
|
|
146
|
+
| PDF | `.pdf` | Text extraction and translation |
|
|
147
|
+
| Word | `.docx`, `.doc` | Document translation |
|
|
148
|
+
| Gettext | `.po`, `.pot`, `.mo` | Localization file formats |
|
|
133
149
|
|
|
134
150
|
## 🔧 Manual Setup
|
|
135
151
|
|
|
@@ -347,7 +363,7 @@ Translate files while preserving structure and format.
|
|
|
347
363
|
- `outputFormat` (string): Output format (same, json, yaml, txt)
|
|
348
364
|
|
|
349
365
|
### analyze_content
|
|
350
|
-
Analyze content for translation readiness and get improvement suggestions before translation.
|
|
366
|
+
Analyze content for translation readiness and get improvement suggestions before translation. This helps identify potential issues and optimize content before spending credits on translation.
|
|
351
367
|
|
|
352
368
|
**Parameters:**
|
|
353
369
|
- `content` (string/array/object): Content to analyze
|
package/install.js
CHANGED
|
@@ -41,9 +41,15 @@ Features:
|
|
|
41
41
|
✨ Text translation with cultural context
|
|
42
42
|
📁 File translation (JSON, YAML, CSV, MD, etc.)
|
|
43
43
|
💰 Credit balance checking
|
|
44
|
-
🌐
|
|
44
|
+
🌐 48 languages supported with regional variants
|
|
45
45
|
`);
|
|
46
46
|
|
|
47
|
+
const getMcpClientPaths = () => {
|
|
48
|
+
const mcpClientPath = path.resolve(__dirname, 'mcp-client.js');
|
|
49
|
+
const packageDir = path.dirname(mcpClientPath);
|
|
50
|
+
return { mcpClientPath, packageDir };
|
|
51
|
+
};
|
|
52
|
+
|
|
47
53
|
async function detectAvailableIDEs() {
|
|
48
54
|
const available = [];
|
|
49
55
|
|
|
@@ -58,13 +64,14 @@ async function detectAvailableIDEs() {
|
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
function createMCPConfig() {
|
|
61
|
-
const mcpClientPath =
|
|
62
|
-
|
|
67
|
+
const { mcpClientPath, packageDir } = getMcpClientPaths();
|
|
68
|
+
|
|
63
69
|
return {
|
|
64
70
|
mcpServers: {
|
|
65
71
|
"i18n-agent": {
|
|
66
72
|
command: "node",
|
|
67
73
|
args: [mcpClientPath],
|
|
74
|
+
cwd: packageDir,
|
|
68
75
|
env: {
|
|
69
76
|
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
70
77
|
API_KEY: ""
|
|
@@ -90,25 +97,27 @@ function detectNodeEnvironment() {
|
|
|
90
97
|
function createWrapperScript(targetDir) {
|
|
91
98
|
const nodeEnv = detectNodeEnvironment();
|
|
92
99
|
const wrapperPath = path.join(targetDir, 'run-mcp.sh');
|
|
93
|
-
const mcpClientPath
|
|
94
|
-
|
|
100
|
+
const { mcpClientPath, packageDir } = getMcpClientPaths();
|
|
101
|
+
|
|
102
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
103
|
+
|
|
95
104
|
let wrapperContent;
|
|
96
|
-
|
|
105
|
+
|
|
97
106
|
if (nodeEnv.isNvm) {
|
|
98
107
|
// For nvm users, we need to set up the PATH properly
|
|
99
108
|
wrapperContent = `#!/bin/bash
|
|
100
109
|
# Wrapper script for i18n-agent MCP client (handles nvm environments)
|
|
101
110
|
export PATH="${path.dirname(nodeEnv.nodePath)}:$PATH"
|
|
102
|
-
cd "${
|
|
111
|
+
cd "${packageDir}"
|
|
103
112
|
exec node "${mcpClientPath}"`;
|
|
104
113
|
} else {
|
|
105
114
|
// For system node installations
|
|
106
115
|
wrapperContent = `#!/bin/bash
|
|
107
116
|
# Wrapper script for i18n-agent MCP client
|
|
108
|
-
cd "${
|
|
117
|
+
cd "${packageDir}"
|
|
109
118
|
exec node "${mcpClientPath}"`;
|
|
110
119
|
}
|
|
111
|
-
|
|
120
|
+
|
|
112
121
|
fs.writeFileSync(wrapperPath, wrapperContent, { mode: 0o755 });
|
|
113
122
|
return wrapperPath;
|
|
114
123
|
}
|
|
@@ -139,7 +148,7 @@ function updateClaudeConfig(configPath) {
|
|
|
139
148
|
// Create wrapper script for nvm users
|
|
140
149
|
console.log(' 🔧 Detected nvm environment, creating wrapper script...');
|
|
141
150
|
const wrapperPath = createWrapperScript(claudeDir);
|
|
142
|
-
|
|
151
|
+
|
|
143
152
|
config.mcpServers["i18n-agent"] = {
|
|
144
153
|
command: wrapperPath,
|
|
145
154
|
env: {
|
|
@@ -149,17 +158,8 @@ function updateClaudeConfig(configPath) {
|
|
|
149
158
|
};
|
|
150
159
|
} else {
|
|
151
160
|
// Standard configuration for system node
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
config.mcpServers["i18n-agent"] = {
|
|
155
|
-
command: "node",
|
|
156
|
-
args: [mcpClientPath],
|
|
157
|
-
cwd: claudeDir,
|
|
158
|
-
env: {
|
|
159
|
-
MCP_SERVER_URL: "https://mcp.i18nagent.ai",
|
|
160
|
-
API_KEY: ""
|
|
161
|
-
}
|
|
162
|
-
};
|
|
161
|
+
const baseConfig = createMCPConfig();
|
|
162
|
+
config.mcpServers["i18n-agent"] = baseConfig.mcpServers["i18n-agent"];
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
// Write updated config
|
|
@@ -170,12 +170,28 @@ function updateClaudeConfig(configPath) {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
function updateGenericMCPConfig(configPath) {
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
let config = {};
|
|
174
|
+
|
|
175
|
+
if (fs.existsSync(configPath)) {
|
|
176
|
+
try {
|
|
177
|
+
const existing = fs.readFileSync(configPath, 'utf8');
|
|
178
|
+
config = JSON.parse(existing);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.warn(`Warning: Could not parse existing config at ${configPath}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!config.mcpServers) {
|
|
185
|
+
config.mcpServers = {};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const baseConfig = createMCPConfig();
|
|
189
|
+
config.mcpServers["i18n-agent"] = baseConfig.mcpServers["i18n-agent"];
|
|
190
|
+
|
|
175
191
|
// Write config
|
|
176
192
|
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
177
193
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
178
|
-
|
|
194
|
+
|
|
179
195
|
return config;
|
|
180
196
|
}
|
|
181
197
|
|
|
@@ -274,4 +290,4 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
274
290
|
main();
|
|
275
291
|
}
|
|
276
292
|
|
|
277
|
-
export { main, IDE_CONFIGS, createMCPConfig };
|
|
293
|
+
export { main, IDE_CONFIGS, createMCPConfig };
|
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
|
+
const MCP_CLIENT_VERSION = '1.8.0';
|
|
9
9
|
|
|
10
10
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
11
11
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -117,8 +117,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
117
117
|
},
|
|
118
118
|
fileType: {
|
|
119
119
|
type: 'string',
|
|
120
|
-
description: 'File type: json, yaml, yml, xml, csv, txt, md, html, properties',
|
|
121
|
-
enum: ['json', 'yaml', 'yml', 'xml', 'csv', 'txt', 'md', 'html', 'properties', 'auto'],
|
|
120
|
+
description: 'File type: json, yaml, yml, xml, csv, txt, md, html, properties (Java), pdf, docx, doc, po (gettext), pot (gettext), mo (gettext), auto',
|
|
121
|
+
enum: ['json', 'yaml', 'yml', 'xml', 'csv', 'txt', 'md', 'html', 'properties', 'pdf', 'docx', 'doc', 'po', 'pot', 'mo', 'auto'],
|
|
122
122
|
default: 'auto',
|
|
123
123
|
},
|
|
124
124
|
targetLanguages: {
|
|
@@ -164,6 +164,46 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
164
164
|
required: ['targetLanguages'],
|
|
165
165
|
},
|
|
166
166
|
},
|
|
167
|
+
{
|
|
168
|
+
name: 'analyze_content',
|
|
169
|
+
description: 'Analyze content for translation readiness and get improvement suggestions. Returns detailed analysis including content type, quality score, and specific recommendations. Costs the same credits as translation.',
|
|
170
|
+
inputSchema: {
|
|
171
|
+
type: 'object',
|
|
172
|
+
properties: {
|
|
173
|
+
content: {
|
|
174
|
+
type: ['string', 'array', 'object'],
|
|
175
|
+
description: 'Content to analyze (text string, array of texts, or structured object)',
|
|
176
|
+
},
|
|
177
|
+
fileType: {
|
|
178
|
+
type: 'string',
|
|
179
|
+
description: 'Optional file type if content is from a file (json, yaml, xml, etc.)',
|
|
180
|
+
},
|
|
181
|
+
sourceLanguage: {
|
|
182
|
+
type: 'string',
|
|
183
|
+
description: 'Source language code (auto-detected if not provided)',
|
|
184
|
+
},
|
|
185
|
+
targetLanguage: {
|
|
186
|
+
type: 'string',
|
|
187
|
+
description: 'Target language code for translation',
|
|
188
|
+
},
|
|
189
|
+
industry: {
|
|
190
|
+
type: 'string',
|
|
191
|
+
description: 'Industry context (e.g., "technology", "healthcare", "finance")',
|
|
192
|
+
default: 'general',
|
|
193
|
+
},
|
|
194
|
+
targetAudience: {
|
|
195
|
+
type: 'string',
|
|
196
|
+
description: 'Target audience (e.g., "general", "technical", "professional")',
|
|
197
|
+
default: 'general',
|
|
198
|
+
},
|
|
199
|
+
region: {
|
|
200
|
+
type: 'string',
|
|
201
|
+
description: 'Specific region for localization (e.g., "Spain", "Mexico", "Brazil")',
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
required: ['content', 'targetLanguage'],
|
|
205
|
+
},
|
|
206
|
+
},
|
|
167
207
|
{
|
|
168
208
|
name: 'get_credits',
|
|
169
209
|
description: 'Get remaining credits for the user and approximate word count available at 0.001 credits per word',
|
|
@@ -265,15 +305,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
265
305
|
case 'translate_file':
|
|
266
306
|
return await handleTranslateFile(args);
|
|
267
307
|
|
|
308
|
+
case 'analyze_content':
|
|
309
|
+
return await handleAnalyzeContent(args);
|
|
310
|
+
|
|
268
311
|
case 'get_credits':
|
|
269
312
|
return await handleGetCredits(args);
|
|
270
|
-
|
|
313
|
+
|
|
271
314
|
/*
|
|
272
315
|
* TOKEN USAGE TOOLS - BLOCKED FOR SECURITY
|
|
273
316
|
* These cases are intentionally removed to prevent access to sensitive analytics data
|
|
274
317
|
* through MCP interfaces. See tool definition comments above for details.
|
|
275
318
|
*/
|
|
276
|
-
|
|
319
|
+
|
|
277
320
|
case 'check_translation_status':
|
|
278
321
|
return await handleCheckTranslationStatus(args);
|
|
279
322
|
|
|
@@ -911,10 +954,86 @@ async function pollTranslationJob(jobId, estimatedTime) {
|
|
|
911
954
|
throw new Error(`Translation job ${jobId} timed out after ${maxPolls * pollInterval / 1000} seconds. Please retry with a smaller chunk or split the content into multiple requests.`);
|
|
912
955
|
}
|
|
913
956
|
|
|
957
|
+
async function handleAnalyzeContent(args) {
|
|
958
|
+
const {
|
|
959
|
+
content,
|
|
960
|
+
fileType,
|
|
961
|
+
sourceLanguage,
|
|
962
|
+
targetLanguage,
|
|
963
|
+
industry = 'general',
|
|
964
|
+
targetAudience = 'general',
|
|
965
|
+
region
|
|
966
|
+
} = args;
|
|
967
|
+
|
|
968
|
+
if (!content) {
|
|
969
|
+
throw new Error('content is required');
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
if (!targetLanguage) {
|
|
973
|
+
throw new Error('targetLanguage is required');
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// Use MCP JSON-RPC protocol for analyze_content
|
|
977
|
+
const mcpRequest = {
|
|
978
|
+
jsonrpc: '2.0',
|
|
979
|
+
id: Date.now(),
|
|
980
|
+
method: 'tools/call',
|
|
981
|
+
params: {
|
|
982
|
+
name: 'analyze_content',
|
|
983
|
+
arguments: {
|
|
984
|
+
apiKey: API_KEY,
|
|
985
|
+
content,
|
|
986
|
+
fileType,
|
|
987
|
+
sourceLanguage,
|
|
988
|
+
targetLanguage,
|
|
989
|
+
industry,
|
|
990
|
+
targetAudience,
|
|
991
|
+
region
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
try {
|
|
997
|
+
const response = await axios.post(MCP_SERVER_URL, mcpRequest, {
|
|
998
|
+
headers: {
|
|
999
|
+
'Content-Type': 'application/json',
|
|
1000
|
+
},
|
|
1001
|
+
timeout: 60000, // 1 minute timeout for analysis
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
if (response.data.error) {
|
|
1005
|
+
const errorMsg = response.data.error.message || response.data.error;
|
|
1006
|
+
throw new Error(`Content analysis error: ${errorMsg}`);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
return response.data.result;
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
// Handle 401 unauthorized
|
|
1012
|
+
if (error.response?.status === 401) {
|
|
1013
|
+
const authErrorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
|
|
1014
|
+
throw new Error(`❌ Invalid API key (401)\nDetails: ${authErrorDetails}\nPlease check your API key at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/analyze_content]`);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// Handle 402 payment required
|
|
1018
|
+
if (error.response?.status === 402) {
|
|
1019
|
+
const creditErrorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
|
|
1020
|
+
throw new Error(`⚠️ Insufficient credits (402)\nDetails: ${creditErrorDetails}\nPlease top up at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/analyze_content]`);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// Handle 503 service unavailable
|
|
1024
|
+
if (error.response?.status === 503) {
|
|
1025
|
+
throw new Error(`i18n-agent encountered unexpected problem, and we are working on it, try again later.`);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
console.error('Content analysis error:', error);
|
|
1029
|
+
throw new Error(`Unable to analyze content: ${error.message}`);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
914
1033
|
async function handleGetCredits(args) {
|
|
915
1034
|
const { apiKey } = args;
|
|
916
1035
|
const creditsApiKey = apiKey || API_KEY;
|
|
917
|
-
|
|
1036
|
+
|
|
918
1037
|
// Use MCP JSON-RPC protocol for get_credits
|
|
919
1038
|
const mcpRequest = {
|
|
920
1039
|
jsonrpc: '2.0',
|
|
@@ -927,7 +1046,7 @@ async function handleGetCredits(args) {
|
|
|
927
1046
|
}
|
|
928
1047
|
}
|
|
929
1048
|
};
|
|
930
|
-
|
|
1049
|
+
|
|
931
1050
|
try {
|
|
932
1051
|
const response = await axios.post(MCP_SERVER_URL, mcpRequest, {
|
|
933
1052
|
headers: {
|
|
@@ -938,13 +1057,13 @@ async function handleGetCredits(args) {
|
|
|
938
1057
|
|
|
939
1058
|
if (response.data.error) {
|
|
940
1059
|
const errorMsg = response.data.error.message || response.data.error;
|
|
941
|
-
const isAuthError = errorMsg.toString().toLowerCase().includes('api key') ||
|
|
1060
|
+
const isAuthError = errorMsg.toString().toLowerCase().includes('api key') ||
|
|
942
1061
|
errorMsg.toString().toLowerCase().includes('api_key') ||
|
|
943
1062
|
errorMsg.toString().toLowerCase().includes('unauthorized');
|
|
944
|
-
const isCreditError = errorMsg.toString().toLowerCase().includes('credit') ||
|
|
1063
|
+
const isCreditError = errorMsg.toString().toLowerCase().includes('credit') ||
|
|
945
1064
|
errorMsg.toString().toLowerCase().includes('quota') ||
|
|
946
1065
|
errorMsg.toString().toLowerCase().includes('limit exceeded');
|
|
947
|
-
|
|
1066
|
+
|
|
948
1067
|
let finalErrorMsg = `Credits service error: ${errorMsg}`;
|
|
949
1068
|
if (!isAuthError && !isCreditError) {
|
|
950
1069
|
finalErrorMsg += `. Please check the service status or contact support.`;
|
|
@@ -955,12 +1074,12 @@ async function handleGetCredits(args) {
|
|
|
955
1074
|
const result = response.data.result;
|
|
956
1075
|
if (result && result.content && result.content[0]) {
|
|
957
1076
|
const textContent = result.content[0].text;
|
|
958
|
-
|
|
1077
|
+
|
|
959
1078
|
// Try to parse as JSON for structured data
|
|
960
1079
|
try {
|
|
961
1080
|
const parsed = JSON.parse(textContent);
|
|
962
1081
|
const approximateWordsAvailable = parsed.credits ? Math.floor(parsed.credits * 1000) : 0;
|
|
963
|
-
|
|
1082
|
+
|
|
964
1083
|
return {
|
|
965
1084
|
content: [
|
|
966
1085
|
{
|
|
@@ -979,7 +1098,7 @@ async function handleGetCredits(args) {
|
|
|
979
1098
|
return result;
|
|
980
1099
|
}
|
|
981
1100
|
}
|
|
982
|
-
|
|
1101
|
+
|
|
983
1102
|
return result;
|
|
984
1103
|
} catch (error) {
|
|
985
1104
|
// Handle 401 unauthorized
|
|
@@ -987,7 +1106,7 @@ async function handleGetCredits(args) {
|
|
|
987
1106
|
const creditsAuthErrorDetails = error.response.data?.message || error.response.data?.result?.content?.[0]?.text || error.message;
|
|
988
1107
|
throw new Error(`❌ Invalid API key (401)\nDetails: ${creditsAuthErrorDetails}\nPlease check your API key at https://app.i18nagent.ai\n[MCP v${MCP_CLIENT_VERSION}/STDIO/get_credits]`);
|
|
989
1108
|
}
|
|
990
|
-
|
|
1109
|
+
|
|
991
1110
|
console.error('Credits check error:', error);
|
|
992
1111
|
throw new Error(`Unable to check credits: ${error.message}`);
|
|
993
1112
|
}
|
|
@@ -1469,7 +1588,10 @@ async function handleDownloadTranslations(args) {
|
|
|
1469
1588
|
method: 'tools/call',
|
|
1470
1589
|
params: {
|
|
1471
1590
|
name: 'download_translations',
|
|
1472
|
-
arguments: {
|
|
1591
|
+
arguments: {
|
|
1592
|
+
apiKey: API_KEY,
|
|
1593
|
+
jobId
|
|
1594
|
+
}
|
|
1473
1595
|
}
|
|
1474
1596
|
};
|
|
1475
1597
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-agent/mcp-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "MCP client for i18n-agent translation service with async job support and enhanced progress tracking - supports Claude, Cursor, VS Code, and other AI IDEs",
|
|
5
5
|
"main": "mcp-client.js",
|
|
6
6
|
"bin": {
|