@langapi/mcp-server 1.0.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.
Files changed (67) hide show
  1. package/README.md +551 -0
  2. package/bin/langapi-mcp.js +11 -0
  3. package/dist/api/client.d.ts +24 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +145 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/api/types.d.ts +56 -0
  8. package/dist/api/types.d.ts.map +1 -0
  9. package/dist/api/types.js +6 -0
  10. package/dist/api/types.js.map +1 -0
  11. package/dist/config/env.d.ts +18 -0
  12. package/dist/config/env.d.ts.map +1 -0
  13. package/dist/config/env.js +29 -0
  14. package/dist/config/env.js.map +1 -0
  15. package/dist/index.d.ts +15 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +25 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/locale-detection/index.d.ts +41 -0
  20. package/dist/locale-detection/index.d.ts.map +1 -0
  21. package/dist/locale-detection/index.js +188 -0
  22. package/dist/locale-detection/index.js.map +1 -0
  23. package/dist/locale-detection/patterns.d.ts +21 -0
  24. package/dist/locale-detection/patterns.d.ts.map +1 -0
  25. package/dist/locale-detection/patterns.js +135 -0
  26. package/dist/locale-detection/patterns.js.map +1 -0
  27. package/dist/server.d.ts +9 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +24 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/tools/get-diff.d.ts +23 -0
  32. package/dist/tools/get-diff.d.ts.map +1 -0
  33. package/dist/tools/get-diff.js +88 -0
  34. package/dist/tools/get-diff.js.map +1 -0
  35. package/dist/tools/get-translation-status.d.ts +47 -0
  36. package/dist/tools/get-translation-status.d.ts.map +1 -0
  37. package/dist/tools/get-translation-status.js +176 -0
  38. package/dist/tools/get-translation-status.js.map +1 -0
  39. package/dist/tools/list-local-locales.d.ts +39 -0
  40. package/dist/tools/list-local-locales.d.ts.map +1 -0
  41. package/dist/tools/list-local-locales.js +52 -0
  42. package/dist/tools/list-local-locales.js.map +1 -0
  43. package/dist/tools/sync-translations.d.ts +35 -0
  44. package/dist/tools/sync-translations.d.ts.map +1 -0
  45. package/dist/tools/sync-translations.js +629 -0
  46. package/dist/tools/sync-translations.js.map +1 -0
  47. package/dist/utils/format-preserve.d.ts +25 -0
  48. package/dist/utils/format-preserve.d.ts.map +1 -0
  49. package/dist/utils/format-preserve.js +56 -0
  50. package/dist/utils/format-preserve.js.map +1 -0
  51. package/dist/utils/json-parser.d.ts +33 -0
  52. package/dist/utils/json-parser.d.ts.map +1 -0
  53. package/dist/utils/json-parser.js +92 -0
  54. package/dist/utils/json-parser.js.map +1 -0
  55. package/dist/utils/sync-cache.d.ts +40 -0
  56. package/dist/utils/sync-cache.d.ts.map +1 -0
  57. package/dist/utils/sync-cache.js +153 -0
  58. package/dist/utils/sync-cache.js.map +1 -0
  59. package/dist/utils/sync-cache.test.d.ts +2 -0
  60. package/dist/utils/sync-cache.test.d.ts.map +1 -0
  61. package/dist/utils/sync-cache.test.js +205 -0
  62. package/dist/utils/sync-cache.test.js.map +1 -0
  63. package/dist/utils/validation.d.ts +37 -0
  64. package/dist/utils/validation.d.ts.map +1 -0
  65. package/dist/utils/validation.js +67 -0
  66. package/dist/utils/validation.js.map +1 -0
  67. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,551 @@
1
+ # @langapi/mcp-server
2
+
3
+ MCP (Model Context Protocol) server for [LangAPI](https://langapi.io) - AI-powered translation management for i18n projects.
4
+
5
+ This package enables AI assistants like Claude, Cursor, and VS Code extensions to manage translations in your project programmatically.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ # 1. Get your API key at https://langapi.io (2,000 free credits)
11
+
12
+ # 2. Add to your AI tool (example for Claude Desktop on macOS):
13
+ # Edit ~/Library/Application Support/Claude/claude_desktop_config.json
14
+
15
+ # 3. Start chatting:
16
+ # "Scan my project for translations"
17
+ # "What keys are missing in German?"
18
+ # "Sync all translations"
19
+ ```
20
+
21
+ ## Features
22
+
23
+ - **Locale Detection**: Automatically detect i18n framework (next-intl, i18next, react-intl) and locale files
24
+ - **Translation Status**: Compare source and target locales to find missing translations
25
+ - **Sync Translations**: Translate missing keys via LangAPI with credit-based billing
26
+ - **Dry Run Mode**: Preview changes and costs before syncing (enabled by default)
27
+ - **Format Preservation**: Maintains JSON formatting when writing translated files
28
+ - **Delta Detection**: Only translate new/changed keys, saving up to 90% on costs
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ npm install @langapi/mcp-server
34
+ ```
35
+
36
+ Or use directly with npx (recommended):
37
+
38
+ ```bash
39
+ npx @langapi/mcp-server
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Setup by Tool
45
+
46
+ ### Claude Desktop
47
+
48
+ **Config file locations:**
49
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
50
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
51
+ - **Linux**: `~/.config/Claude/claude_desktop_config.json`
52
+
53
+ **Configuration:**
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "langapi": {
59
+ "command": "npx",
60
+ "args": ["@langapi/mcp-server"],
61
+ "env": {
62
+ "LANGAPI_API_KEY": "your-api-key-here"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ After editing, **restart Claude Desktop** for changes to take effect.
70
+
71
+ ---
72
+
73
+ ### Claude Code (CLI)
74
+
75
+ **Option 1: Project-level config** (recommended for teams)
76
+
77
+ Create `.mcp.json` in your project root:
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "langapi": {
83
+ "command": "npx",
84
+ "args": ["@langapi/mcp-server"],
85
+ "env": {
86
+ "LANGAPI_API_KEY": "your-api-key-here"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ **Option 2: Global config**
94
+
95
+ Add to `~/.claude/settings.json`:
96
+
97
+ ```json
98
+ {
99
+ "mcpServers": {
100
+ "langapi": {
101
+ "command": "npx",
102
+ "args": ["@langapi/mcp-server"],
103
+ "env": {
104
+ "LANGAPI_API_KEY": "your-api-key-here"
105
+ }
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ **Option 3: Environment variable**
112
+
113
+ ```bash
114
+ export LANGAPI_API_KEY="your-api-key-here"
115
+ ```
116
+
117
+ Then the MCP server will pick it up automatically.
118
+
119
+ ---
120
+
121
+ ### Cursor
122
+
123
+ **Config file locations:**
124
+ - **Project-level**: `.cursor/mcp.json` in your project root
125
+ - **Global**: `~/.cursor/mcp.json`
126
+
127
+ **Configuration:**
128
+
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "langapi": {
133
+ "command": "npx",
134
+ "args": ["@langapi/mcp-server"],
135
+ "env": {
136
+ "LANGAPI_API_KEY": "your-api-key-here"
137
+ }
138
+ }
139
+ }
140
+ }
141
+ ```
142
+
143
+ **Alternative: Via UI**
144
+ 1. Open Cursor Settings (Cmd/Ctrl + ,)
145
+ 2. Search for "MCP"
146
+ 3. Click "Edit in settings.json"
147
+ 4. Add the configuration above
148
+
149
+ ---
150
+
151
+ ### VS Code with Cline
152
+
153
+ 1. Install the [Cline extension](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev)
154
+ 2. Create `.vscode/cline_mcp_settings.json` in your project:
155
+
156
+ ```json
157
+ {
158
+ "mcpServers": {
159
+ "langapi": {
160
+ "command": "npx",
161
+ "args": ["@langapi/mcp-server"],
162
+ "env": {
163
+ "LANGAPI_API_KEY": "your-api-key-here"
164
+ }
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ 3. Reload VS Code window (Cmd/Ctrl + Shift + P > "Reload Window")
171
+
172
+ ---
173
+
174
+ ### VS Code with Roo Code
175
+
176
+ 1. Install the [Roo Code extension](https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline)
177
+ 2. Create `.vscode/mcp.json` in your project:
178
+
179
+ ```json
180
+ {
181
+ "mcpServers": {
182
+ "langapi": {
183
+ "command": "npx",
184
+ "args": ["@langapi/mcp-server"],
185
+ "env": {
186
+ "LANGAPI_API_KEY": "your-api-key-here"
187
+ }
188
+ }
189
+ }
190
+ }
191
+ ```
192
+
193
+ 3. Reload VS Code window
194
+
195
+ ---
196
+
197
+ ### Windsurf
198
+
199
+ **Config file**: `~/.codeium/windsurf/mcp_config.json`
200
+
201
+ ```json
202
+ {
203
+ "mcpServers": {
204
+ "langapi": {
205
+ "command": "npx",
206
+ "args": ["@langapi/mcp-server"],
207
+ "env": {
208
+ "LANGAPI_API_KEY": "your-api-key-here"
209
+ }
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ Restart Windsurf after editing.
216
+
217
+ ---
218
+
219
+ ## Environment Variables
220
+
221
+ | Variable | Required | Description |
222
+ |----------|----------|-------------|
223
+ | `LANGAPI_API_KEY` | Yes | Your LangAPI API key (get one at [langapi.io](https://langapi.io)) |
224
+ | `LANGAPI_API_URL` | No | Custom API URL (default: `https://api.langapi.io`) |
225
+
226
+ ---
227
+
228
+ ## MCP Tools
229
+
230
+ ### `list_local_locales`
231
+
232
+ Scan your project for locale JSON files and detect the i18n framework.
233
+
234
+ **Input:**
235
+ ```json
236
+ {
237
+ "project_path": "/path/to/project", // optional, defaults to cwd
238
+ "include_key_count": true // optional, default: true
239
+ }
240
+ ```
241
+
242
+ **Output:**
243
+ ```json
244
+ {
245
+ "framework": "next-intl",
246
+ "confidence": "high",
247
+ "source_lang": "en",
248
+ "locales_path": "messages",
249
+ "locales": [
250
+ {
251
+ "lang": "en",
252
+ "files": [{ "path": "messages/en.json", "namespace": null, "key_count": 150 }],
253
+ "total_keys": 150
254
+ },
255
+ {
256
+ "lang": "de",
257
+ "files": [{ "path": "messages/de.json", "namespace": null, "key_count": 120 }],
258
+ "total_keys": 120
259
+ }
260
+ ],
261
+ "config_file": "i18n.ts"
262
+ }
263
+ ```
264
+
265
+ ### `get_translation_status`
266
+
267
+ Compare source locale against targets to identify missing keys and estimate costs.
268
+
269
+ **Input:**
270
+ ```json
271
+ {
272
+ "source_lang": "en",
273
+ "target_langs": ["de", "fr"], // optional, all non-source by default
274
+ "project_path": "/path/to/project", // optional
275
+ "app_id": "your-app-id" // optional, for accurate cost estimate
276
+ }
277
+ ```
278
+
279
+ **Output:**
280
+ ```json
281
+ {
282
+ "source_lang": "en",
283
+ "source_keys": 150,
284
+ "targets": [
285
+ {
286
+ "lang": "de",
287
+ "status": "outdated",
288
+ "keys": { "total": 120, "missing": ["new.key1", "new.key2"], "extra": [] }
289
+ }
290
+ ],
291
+ "cost_estimate": {
292
+ "words_to_translate": 45,
293
+ "credits_required": 90,
294
+ "current_balance": 2000,
295
+ "balance_after_sync": 1910
296
+ }
297
+ }
298
+ ```
299
+
300
+ ### `sync_translations`
301
+
302
+ Sync translations via the LangAPI API. **Default is dry_run=true for safety.**
303
+
304
+ **Input:**
305
+ ```json
306
+ {
307
+ "source_lang": "en",
308
+ "target_langs": ["de", "fr"],
309
+ "dry_run": true, // default: true (preview mode)
310
+ "project_path": "/path/to/project", // optional
311
+ "write_to_files": true, // optional, default: true
312
+ "skip_keys": ["key.to.skip"] // optional, keys to exclude
313
+ }
314
+ ```
315
+
316
+ **Output (dry_run=true):**
317
+ ```json
318
+ {
319
+ "success": true,
320
+ "dry_run": true,
321
+ "delta": {
322
+ "new_keys": ["new.key1", "new.key2"],
323
+ "changed_keys": [],
324
+ "total_keys_to_sync": 2
325
+ },
326
+ "cost": {
327
+ "words_to_translate": 45,
328
+ "credits_required": 90,
329
+ "current_balance": 2000,
330
+ "balance_after_sync": 1910
331
+ },
332
+ "message": "Preview: 2 keys to sync, 90 credits required. Run with dry_run=false to execute."
333
+ }
334
+ ```
335
+
336
+ **Output (dry_run=false):**
337
+ ```json
338
+ {
339
+ "success": true,
340
+ "dry_run": false,
341
+ "results": [
342
+ { "language": "de", "translated_count": 2, "file_written": "messages/de.json" },
343
+ { "language": "fr", "translated_count": 2, "file_written": "messages/fr.json" }
344
+ ],
345
+ "cost": {
346
+ "credits_used": 90,
347
+ "balance_after_sync": 1910
348
+ },
349
+ "message": "Sync complete. 4 keys translated across 2 languages. 90 credits used."
350
+ }
351
+ ```
352
+
353
+ ### `get_diff`
354
+
355
+ Compare current source locale against the last synced version.
356
+
357
+ **Input:**
358
+ ```json
359
+ {
360
+ "source_lang": "en",
361
+ "project_path": "/path/to/project" // optional
362
+ }
363
+ ```
364
+
365
+ **Output:**
366
+ ```json
367
+ {
368
+ "has_changes": true,
369
+ "summary": {
370
+ "new_keys": 3,
371
+ "changed_keys": 1,
372
+ "removed_keys": 0,
373
+ "unchanged_keys": 146
374
+ },
375
+ "diff": {
376
+ "new": ["feature.title", "feature.description", "feature.cta"],
377
+ "changed": ["home.welcome"],
378
+ "removed": [],
379
+ "unchanged": ["..."]
380
+ }
381
+ }
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Prompt Examples
387
+
388
+ ### Scanning Your Project
389
+
390
+ ```
391
+ "Scan my project for translations"
392
+ "What i18n framework am I using?"
393
+ "List all my locale files"
394
+ "How many translation keys do I have?"
395
+ "What languages are configured in my project?"
396
+ ```
397
+
398
+ ### Checking Translation Status
399
+
400
+ ```
401
+ "What translations are missing?"
402
+ "Compare English to all other languages"
403
+ "How many keys need to be translated for French?"
404
+ "Which languages are out of sync?"
405
+ "Show me the missing keys for German"
406
+ "How much will it cost to sync all languages?"
407
+ ```
408
+
409
+ ### Preview Changes (Dry Run)
410
+
411
+ ```
412
+ "Preview what would happen if I sync all languages"
413
+ "Do a dry run for French translations"
414
+ "Show me what keys will be translated"
415
+ "What's the cost estimate for syncing German?"
416
+ "Preview the sync without making changes"
417
+ ```
418
+
419
+ ### Syncing Translations
420
+
421
+ ```
422
+ "Sync all missing translations"
423
+ "Translate to German and French"
424
+ "Update all locale files with missing keys"
425
+ "Sync translations and write to files"
426
+ "Execute the translation sync"
427
+ ```
428
+
429
+ ### Advanced Operations
430
+
431
+ ```
432
+ "What changed since my last sync?"
433
+ "Show diff between current and last synced version"
434
+ "Are there any extra keys in German that aren't in English?"
435
+ "Skip the settings.* keys when syncing"
436
+ "Only sync the home.* and nav.* keys"
437
+ "Sync to Japanese but skip experimental features"
438
+ ```
439
+
440
+ ### Complete Workflow Example
441
+
442
+ ```
443
+ You: List the translations in my project
444
+
445
+ Claude: [Calls list_local_locales]
446
+ I found a next-intl project with English (150 keys) and German (120 keys) translations.
447
+
448
+ You: What translations are missing for German?
449
+
450
+ Claude: [Calls get_translation_status]
451
+ German is missing 30 keys. The sync would cost 85 credits (you have 2000 credits).
452
+
453
+ You: Sync the German translations
454
+
455
+ Claude: [Calls sync_translations with dry_run=true]
456
+ Preview: 30 keys will be translated, costing 85 credits. Should I proceed?
457
+
458
+ You: Yes, go ahead
459
+
460
+ Claude: [Calls sync_translations with dry_run=false]
461
+ Done! 30 keys translated. German file updated at messages/de.json.
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Supported Frameworks
467
+
468
+ The server automatically detects these i18n frameworks:
469
+
470
+ | Framework | Locale Patterns | Config Files |
471
+ |-----------|-----------------|--------------|
472
+ | **next-intl** | `messages/*.json`, `locales/*.json` | `i18n.ts`, `next.config.js` |
473
+ | **i18next** | `public/locales/*/*.json`, `locales/*/*.json` | `i18next.config.js`, `i18n.js` |
474
+ | **react-intl** | `src/lang/*.json`, `lang/*.json` | `src/i18n.ts` |
475
+ | **generic** | Various common patterns | - |
476
+
477
+ ---
478
+
479
+ ## Troubleshooting
480
+
481
+ ### "MCP server not found"
482
+ - Ensure `npx` is in your PATH
483
+ - Try running `npx @langapi/mcp-server` manually to test
484
+ - On Windows, you may need to use the full path to npx
485
+
486
+ ### "API key invalid" or "Unauthorized"
487
+ - Verify your API key at [langapi.io/dashboard](https://langapi.io/dashboard)
488
+ - Check for extra spaces or quotes in your config
489
+ - Ensure the key is set in the `env` section, not `args`
490
+
491
+ ### "No locale files found"
492
+ - Check that your locale files match supported patterns (see Frameworks above)
493
+ - Verify files are valid JSON
494
+ - Try specifying `project_path` explicitly
495
+
496
+ ### "Permission denied" when writing files
497
+ - Check file/directory write permissions
498
+ - On macOS, ensure your terminal has disk access
499
+
500
+ ### Server not connecting
501
+ 1. Restart your IDE/tool completely (not just reload)
502
+ 2. Check the config file syntax (valid JSON?)
503
+ 3. Look for error messages in your tool's developer console
504
+
505
+ ### Dry run works but execute fails
506
+ - Check your credit balance at langapi.io
507
+ - Verify network connectivity to api.langapi.io
508
+
509
+ ---
510
+
511
+ ## Advanced Configuration
512
+
513
+ ### Multiple Projects
514
+
515
+ Use project-level config files (`.mcp.json`, `.cursor/mcp.json`) with different API keys per project.
516
+
517
+ ### Custom API URL
518
+
519
+ For self-hosted or enterprise deployments:
520
+
521
+ ```json
522
+ {
523
+ "mcpServers": {
524
+ "langapi": {
525
+ "command": "npx",
526
+ "args": ["@langapi/mcp-server"],
527
+ "env": {
528
+ "LANGAPI_API_KEY": "your-api-key",
529
+ "LANGAPI_API_URL": "https://your-api-server.com"
530
+ }
531
+ }
532
+ }
533
+ }
534
+ ```
535
+
536
+ ---
537
+
538
+ ## Credits & Billing
539
+
540
+ LangAPI uses a credit-based billing system:
541
+ - **1 credit = 1 word** to translate
542
+ - New users get **2,000 free credits**
543
+ - Top up with **100,000 credits for $15** (no subscription, no expiry)
544
+
545
+ Get your API key at [langapi.io](https://langapi.io).
546
+
547
+ ---
548
+
549
+ ## License
550
+
551
+ MIT
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { fileURLToPath } from "url";
4
+ import { dirname, join } from "path";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+
9
+ // Import and run the MCP server
10
+ const serverPath = join(__dirname, "..", "dist", "index.js");
11
+ await import(serverPath);
@@ -0,0 +1,24 @@
1
+ /**
2
+ * LangAPI client for making API requests
3
+ */
4
+ import type { SyncRequest, SyncResponse } from "./types.js";
5
+ export declare class LangAPIClient {
6
+ private apiKey;
7
+ private baseUrl;
8
+ private timeoutMs;
9
+ constructor(apiKey: string, baseUrl?: string, timeoutMs?: number);
10
+ /**
11
+ * Create a client instance using the configured API key
12
+ * @throws Error if no API key is configured
13
+ */
14
+ static create(): LangAPIClient;
15
+ /**
16
+ * Check if client can be created (API key is configured)
17
+ */
18
+ static canCreate(): boolean;
19
+ /**
20
+ * Sync translations with the LangAPI service
21
+ */
22
+ sync(request: SyncRequest): Promise<SyncResponse>;
23
+ }
24
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EAGb,MAAM,YAAY,CAAC;AAoCpB,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;gBAGxB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,MAAqB,EAC9B,SAAS,GAAE,MAA2B;IAOxC;;;OAGG;IACH,MAAM,CAAC,MAAM,IAAI,aAAa;IAU9B;;OAEG;IACH,MAAM,CAAC,SAAS,IAAI,OAAO;IAI3B;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CA2FxD"}