@better-i18n/mcp 0.15.5 → 0.16.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 (92) hide show
  1. package/README.md +41 -3
  2. package/dist/tools/getTranslations.d.ts +11 -4
  3. package/dist/tools/getTranslations.d.ts.map +1 -1
  4. package/dist/tools/getTranslations.js +21 -8
  5. package/dist/tools/getTranslations.js.map +1 -1
  6. package/dist/tools/proposeLanguageEdits.d.ts.map +1 -1
  7. package/dist/tools/proposeLanguageEdits.js +10 -0
  8. package/dist/tools/proposeLanguageEdits.js.map +1 -1
  9. package/dist/tools/proposeLanguages.d.ts.map +1 -1
  10. package/dist/tools/proposeLanguages.js +4 -0
  11. package/dist/tools/proposeLanguages.js.map +1 -1
  12. package/package.json +3 -2
  13. package/dist/__tests__/base-tool.test.d.ts +0 -2
  14. package/dist/__tests__/base-tool.test.d.ts.map +0 -1
  15. package/dist/__tests__/base-tool.test.js +0 -193
  16. package/dist/__tests__/base-tool.test.js.map +0 -1
  17. package/dist/__tests__/contract.test.d.ts +0 -24
  18. package/dist/__tests__/contract.test.d.ts.map +0 -1
  19. package/dist/__tests__/contract.test.js +0 -919
  20. package/dist/__tests__/contract.test.js.map +0 -1
  21. package/dist/__tests__/fixtures/mock-client.d.ts +0 -11
  22. package/dist/__tests__/fixtures/mock-client.d.ts.map +0 -1
  23. package/dist/__tests__/fixtures/mock-client.js +0 -33
  24. package/dist/__tests__/fixtures/mock-client.js.map +0 -1
  25. package/dist/__tests__/helpers.d.ts +0 -10
  26. package/dist/__tests__/helpers.d.ts.map +0 -1
  27. package/dist/__tests__/helpers.js +0 -27
  28. package/dist/__tests__/helpers.js.map +0 -1
  29. package/dist/__tests__/schema-alignment.test.d.ts +0 -15
  30. package/dist/__tests__/schema-alignment.test.d.ts.map +0 -1
  31. package/dist/__tests__/schema-alignment.test.js +0 -1011
  32. package/dist/__tests__/schema-alignment.test.js.map +0 -1
  33. package/dist/__tests__/server-dispatch.test.d.ts +0 -10
  34. package/dist/__tests__/server-dispatch.test.d.ts.map +0 -1
  35. package/dist/__tests__/server-dispatch.test.js +0 -202
  36. package/dist/__tests__/server-dispatch.test.js.map +0 -1
  37. package/dist/__tests__/version-check.test.d.ts +0 -2
  38. package/dist/__tests__/version-check.test.d.ts.map +0 -1
  39. package/dist/__tests__/version-check.test.js +0 -89
  40. package/dist/__tests__/version-check.test.js.map +0 -1
  41. package/dist/tools/__tests__/createKeys.test.d.ts +0 -2
  42. package/dist/tools/__tests__/createKeys.test.d.ts.map +0 -1
  43. package/dist/tools/__tests__/createKeys.test.js +0 -139
  44. package/dist/tools/__tests__/createKeys.test.js.map +0 -1
  45. package/dist/tools/__tests__/deleteKeys.test.d.ts +0 -2
  46. package/dist/tools/__tests__/deleteKeys.test.d.ts.map +0 -1
  47. package/dist/tools/__tests__/deleteKeys.test.js +0 -91
  48. package/dist/tools/__tests__/deleteKeys.test.js.map +0 -1
  49. package/dist/tools/__tests__/getPendingChanges.test.d.ts +0 -2
  50. package/dist/tools/__tests__/getPendingChanges.test.d.ts.map +0 -1
  51. package/dist/tools/__tests__/getPendingChanges.test.js +0 -50
  52. package/dist/tools/__tests__/getPendingChanges.test.js.map +0 -1
  53. package/dist/tools/__tests__/getProject.test.d.ts +0 -2
  54. package/dist/tools/__tests__/getProject.test.d.ts.map +0 -1
  55. package/dist/tools/__tests__/getProject.test.js +0 -55
  56. package/dist/tools/__tests__/getProject.test.js.map +0 -1
  57. package/dist/tools/__tests__/getSync.test.d.ts +0 -2
  58. package/dist/tools/__tests__/getSync.test.d.ts.map +0 -1
  59. package/dist/tools/__tests__/getSync.test.js +0 -42
  60. package/dist/tools/__tests__/getSync.test.js.map +0 -1
  61. package/dist/tools/__tests__/getSyncs.test.d.ts +0 -2
  62. package/dist/tools/__tests__/getSyncs.test.d.ts.map +0 -1
  63. package/dist/tools/__tests__/getSyncs.test.js +0 -66
  64. package/dist/tools/__tests__/getSyncs.test.js.map +0 -1
  65. package/dist/tools/__tests__/getTranslations.test.d.ts +0 -2
  66. package/dist/tools/__tests__/getTranslations.test.d.ts.map +0 -1
  67. package/dist/tools/__tests__/getTranslations.test.js +0 -114
  68. package/dist/tools/__tests__/getTranslations.test.js.map +0 -1
  69. package/dist/tools/__tests__/listKeys.test.d.ts +0 -2
  70. package/dist/tools/__tests__/listKeys.test.d.ts.map +0 -1
  71. package/dist/tools/__tests__/listKeys.test.js +0 -98
  72. package/dist/tools/__tests__/listKeys.test.js.map +0 -1
  73. package/dist/tools/__tests__/listProjects.test.d.ts +0 -2
  74. package/dist/tools/__tests__/listProjects.test.d.ts.map +0 -1
  75. package/dist/tools/__tests__/listProjects.test.js +0 -45
  76. package/dist/tools/__tests__/listProjects.test.js.map +0 -1
  77. package/dist/tools/__tests__/proposeLanguageEdits.test.d.ts +0 -2
  78. package/dist/tools/__tests__/proposeLanguageEdits.test.d.ts.map +0 -1
  79. package/dist/tools/__tests__/proposeLanguageEdits.test.js +0 -87
  80. package/dist/tools/__tests__/proposeLanguageEdits.test.js.map +0 -1
  81. package/dist/tools/__tests__/proposeLanguages.test.d.ts +0 -2
  82. package/dist/tools/__tests__/proposeLanguages.test.d.ts.map +0 -1
  83. package/dist/tools/__tests__/proposeLanguages.test.js +0 -109
  84. package/dist/tools/__tests__/proposeLanguages.test.js.map +0 -1
  85. package/dist/tools/__tests__/publishTranslations.test.d.ts +0 -2
  86. package/dist/tools/__tests__/publishTranslations.test.d.ts.map +0 -1
  87. package/dist/tools/__tests__/publishTranslations.test.js +0 -127
  88. package/dist/tools/__tests__/publishTranslations.test.js.map +0 -1
  89. package/dist/tools/__tests__/updateKeys.test.d.ts +0 -2
  90. package/dist/tools/__tests__/updateKeys.test.d.ts.map +0 -1
  91. package/dist/tools/__tests__/updateKeys.test.js +0 -122
  92. package/dist/tools/__tests__/updateKeys.test.js.map +0 -1
package/README.md CHANGED
@@ -15,7 +15,7 @@ MCP (Model Context Protocol) server for [Better i18n](https://better-i18n.com).
15
15
 
16
16
  ```bash
17
17
  # With npx (no install needed)
18
- npx @better-i18n/mcp
18
+ npx -y @better-i18n/mcp@latest
19
19
 
20
20
  # Or install globally
21
21
  npm install -g @better-i18n/mcp
@@ -43,7 +43,9 @@ export const i18n = createI18n({
43
43
 
44
44
  The AI assistant will read this file to get the `project` value and include it in all tool calls.
45
45
 
46
- ### 3. Configure Cursor
46
+ ### 3. Configure Your AI Client
47
+
48
+ #### Cursor
47
49
 
48
50
  Add to `~/.cursor/mcp.json`:
49
51
 
@@ -52,7 +54,43 @@ Add to `~/.cursor/mcp.json`:
52
54
  "mcpServers": {
53
55
  "better-i18n": {
54
56
  "command": "npx",
55
- "args": ["@better-i18n/mcp"],
57
+ "args": ["-y", "@better-i18n/mcp@latest"],
58
+ "env": {
59
+ "BETTER_I18N_API_KEY": "your-api-key-here"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ #### Claude Desktop
67
+
68
+ Add to `claude_desktop_config.json`:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "better-i18n": {
74
+ "command": "npx",
75
+ "args": ["-y", "@better-i18n/mcp@latest"],
76
+ "env": {
77
+ "BETTER_I18N_API_KEY": "your-api-key-here"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ #### Claude Code
85
+
86
+ Add to `.claude/settings.json` or `~/.claude/settings.json`:
87
+
88
+ ```json
89
+ {
90
+ "mcpServers": {
91
+ "better-i18n": {
92
+ "command": "npx",
93
+ "args": ["-y", "@better-i18n/mcp@latest"],
56
94
  "env": {
57
95
  "BETTER_I18N_API_KEY": "your-api-key-here"
58
96
  }
@@ -7,9 +7,15 @@
7
7
  * USE THIS when you need actual translation text (to translate, review, or update).
8
8
  * Use listKeys instead for browsing/exploring keys — it's faster and uses fewer tokens.
9
9
  *
10
- * SEARCH + FILTER:
11
- * - search: Text to search for (in source text or specified languages)
12
- * - languages: Which languages to search in AND return translations for
10
+ * SEARCH BEHAVIOR:
11
+ * - search WITHOUT languages: searches key names, source text, AND all translation texts across every language.
12
+ * Use this when you don't know which language the text is in (e.g., user mentions text they saw on screen).
13
+ * - search WITH languages: searches key names, source text (if source language included), AND translations
14
+ * only in the specified languages. Faster and more targeted.
15
+ * - Without search: returns all keys (filtered by other params).
16
+ *
17
+ * FILTER PARAMETERS:
18
+ * - languages: Languages to search in AND return translations for
13
19
  * - status: Filter by translation status ("missing", "draft", "published", "all")
14
20
  * - namespaces: Filter by namespace(s)
15
21
  * - keys: Fetch specific keys by exact name
@@ -21,9 +27,10 @@
21
27
  * - hasMore: true when total > limit — use narrower filters to get specific keys
22
28
  *
23
29
  * EXAMPLES:
30
+ * - Find text in ANY language: { project: "org/project", search: "Mehmet" }
24
31
  * - Find "login" in source: { project: "org/project", search: "login" }
25
32
  * - Multi-term search: { project: "org/project", search: ["login", "signup", "forgot_password"] }
26
- * - Find "Giriş" in Turkish: { project: "org/project", search: "Giriş", languages: ["tr"] }
33
+ * - Find "Giriş" in Turkish (faster): { project: "org/project", search: "Giriş", languages: ["tr"] }
27
34
  * - Get all Turkish translations: { project: "org/project", languages: ["tr"] }
28
35
  * - Get missing Turkish: { project: "org/project", languages: ["tr"], status: "missing" }
29
36
  * - Get specific keys: { project: "org/project", keys: ["auth.login.title", "auth.login.button"] }
@@ -1 +1 @@
1
- {"version":3,"file":"getTranslations.d.ts","sourceRoot":"","sources":["../../src/tools/getTranslations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAW9C,eAAO,MAAM,eAAe,EAAE,IA6F7B,CAAC"}
1
+ {"version":3,"file":"getTranslations.d.ts","sourceRoot":"","sources":["../../src/tools/getTranslations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAW9C,eAAO,MAAM,eAAe,EAAE,IAmG7B,CAAC"}
@@ -7,9 +7,15 @@
7
7
  * USE THIS when you need actual translation text (to translate, review, or update).
8
8
  * Use listKeys instead for browsing/exploring keys — it's faster and uses fewer tokens.
9
9
  *
10
- * SEARCH + FILTER:
11
- * - search: Text to search for (in source text or specified languages)
12
- * - languages: Which languages to search in AND return translations for
10
+ * SEARCH BEHAVIOR:
11
+ * - search WITHOUT languages: searches key names, source text, AND all translation texts across every language.
12
+ * Use this when you don't know which language the text is in (e.g., user mentions text they saw on screen).
13
+ * - search WITH languages: searches key names, source text (if source language included), AND translations
14
+ * only in the specified languages. Faster and more targeted.
15
+ * - Without search: returns all keys (filtered by other params).
16
+ *
17
+ * FILTER PARAMETERS:
18
+ * - languages: Languages to search in AND return translations for
13
19
  * - status: Filter by translation status ("missing", "draft", "published", "all")
14
20
  * - namespaces: Filter by namespace(s)
15
21
  * - keys: Fetch specific keys by exact name
@@ -21,9 +27,10 @@
21
27
  * - hasMore: true when total > limit — use narrower filters to get specific keys
22
28
  *
23
29
  * EXAMPLES:
30
+ * - Find text in ANY language: { project: "org/project", search: "Mehmet" }
24
31
  * - Find "login" in source: { project: "org/project", search: "login" }
25
32
  * - Multi-term search: { project: "org/project", search: ["login", "signup", "forgot_password"] }
26
- * - Find "Giriş" in Turkish: { project: "org/project", search: "Giriş", languages: ["tr"] }
33
+ * - Find "Giriş" in Turkish (faster): { project: "org/project", search: "Giriş", languages: ["tr"] }
27
34
  * - Get all Turkish translations: { project: "org/project", languages: ["tr"] }
28
35
  * - Get missing Turkish: { project: "org/project", languages: ["tr"], status: "missing" }
29
36
  * - Get specific keys: { project: "org/project", keys: ["auth.login.title", "auth.login.button"] }
@@ -50,8 +57,13 @@ IMPORTANT: status filter REQUIRES languages parameter.
50
57
  { status: "missing" } alone returns ALL keys (filter silently ignored).
51
58
  Always pair: { languages: ["hr"], status: "missing" }
52
59
 
53
- SEARCH + FILTER:
54
- - search: Text to search for (in source text or specified languages)
60
+ SEARCH BEHAVIOR:
61
+ - search WITHOUT languages: searches key names, source text, AND all translations across every language.
62
+ Use this when you don't know which language the text is in.
63
+ - search WITH languages: searches only in specified languages (faster, more targeted).
64
+ Use this when you know the language of the text you're looking for.
65
+
66
+ FILTER PARAMETERS:
55
67
  - languages: Languages to search in AND return translations for
56
68
  - status: Filter by translation status ("missing", "draft", "published", "all")
57
69
  - namespaces: Filter by namespace(s)
@@ -64,9 +76,10 @@ RESPONSE METADATA:
64
76
  - hasMore: true when total > limit — narrow your filters to get specific results
65
77
 
66
78
  EXAMPLES:
79
+ - Find text in ANY language: { search: "Mehmet" }
67
80
  - Find "login" in source: { search: "login" }
68
81
  - Multi-term search: { search: ["login", "signup", "forgot_password"] }
69
- - Find "Giriş" in Turkish: { search: "Giriş", languages: ["tr"] }
82
+ - Find "Giriş" in Turkish (faster): { search: "Giriş", languages: ["tr"] }
70
83
  - Get all Turkish translations: { languages: ["tr"] }
71
84
  - Get missing Turkish translations: { languages: ["tr"], status: "missing" }
72
85
  - Get specific keys: { keys: ["auth.login.title", "auth.login.button"] }
@@ -78,7 +91,7 @@ Response includes namespaceDetails: a map of namespace metadata (name, keyCount,
78
91
  ...projectInputProperty,
79
92
  search: {
80
93
  type: "string",
81
- description: "Text to search for in source text or translations (case-insensitive). Single string or array of strings for multi-term search (OR matching). If languages is specified, searches in those languages; otherwise searches source text.",
94
+ description: "Text to search for (case-insensitive). Single string or array of strings for multi-term OR search. Searches key names + source text always. Without languages: also searches ALL translation texts across every language. With languages: searches only in those languages (faster).",
82
95
  },
83
96
  languages: {
84
97
  type: "array",
@@ -1 +1 @@
1
- {"version":3,"file":"getTranslations.js","sourceRoot":"","sources":["../../src/tools/getTranslations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"getTranslations.js","sourceRoot":"","sources":["../../src/tools/getTranslations.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"proposeLanguageEdits.d.ts","sourceRoot":"","sources":["../../src/tools/proposeLanguageEdits.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAc9C,eAAO,MAAM,oBAAoB,EAAE,IAoDlC,CAAC"}
1
+ {"version":3,"file":"proposeLanguageEdits.d.ts","sourceRoot":"","sources":["../../src/tools/proposeLanguageEdits.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAc9C,eAAO,MAAM,oBAAoB,EAAE,IA8DlC,CAAC"}
@@ -54,11 +54,21 @@ export const proposeLanguageEdits = {
54
54
  projectSlug,
55
55
  updates,
56
56
  });
57
+ // Build contextual hints
58
+ let hint;
59
+ if (result.notFound.length > 0) {
60
+ hint = `${result.notFound.length} language(s) not found: [${result.notFound.join(", ")}]. Language codes are case-normalized. Call getProject to see exact codes.`;
61
+ }
62
+ else if (result.results.every((r) => !r.changed)) {
63
+ hint = "All language status updates were no-ops — the requested status was already set.";
64
+ }
57
65
  return success({
58
66
  success: result.success,
59
67
  results: result.results,
60
68
  notFound: result.notFound,
61
69
  project: input.project,
70
+ ...(result.pendingPublish ? { pendingPublish: result.pendingPublish } : {}),
71
+ ...(hint ? { hint } : {}),
62
72
  });
63
73
  }),
64
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"proposeLanguageEdits.js","sourceRoot":"","sources":["../../src/tools/proposeLanguageEdits.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC;SACL,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;KACnD,CAAC,CACH;SACA,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAS;IACxC,UAAU,EAAE;QACV,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EACT,0MAA0M;QAC5M,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,KAAK,EAAE;oBACL,IAAI,EAAE,OAAO;oBACb,WAAW,EACT,kGAAkG;oBACpG,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uGAAuG,EAAE;4BACtJ,SAAS,EAAE;gCACT,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC;gCACrC,WAAW,EAAE,sFAAsF;6BACpG;yBACF;wBACD,QAAQ,EAAE,CAAC,cAAc,EAAE,WAAW,CAAC;qBACxC;iBACF;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC;SAC/B;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,2EAA2E;QAC3E,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACzC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;YAC7C,MAAM,EAAE,IAAI,CAAC,SAAS;SACvB,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC;YACrD,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,OAAO;SACR,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
1
+ {"version":3,"file":"proposeLanguageEdits.js","sourceRoot":"","sources":["../../src/tools/proposeLanguageEdits.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"proposeLanguages.d.ts","sourceRoot":"","sources":["../../src/tools/proposeLanguages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAc9C,eAAO,MAAM,gBAAgB,EAAE,IAqD9B,CAAC"}
1
+ {"version":3,"file":"proposeLanguages.d.ts","sourceRoot":"","sources":["../../src/tools/proposeLanguages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAc9C,eAAO,MAAM,gBAAgB,EAAE,IAyD9B,CAAC"}
@@ -60,6 +60,10 @@ export const proposeLanguages = {
60
60
  skipped: result.skipped,
61
61
  results: result.results,
62
62
  project: input.project,
63
+ ...(result.pendingPublish ? { pendingPublish: result.pendingPublish } : {}),
64
+ ...(result.added === 0 && result.skipped > 0
65
+ ? { hint: `All ${result.skipped} submitted language(s) already exist — nothing was added. To change their status, use proposeLanguageEdits.` }
66
+ : {}),
63
67
  });
64
68
  }),
65
69
  };
@@ -1 +1 @@
1
- {"version":3,"file":"proposeLanguages.js","sourceRoot":"","sources":["../../src/tools/proposeLanguages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,SAAS,EAAE,CAAC;SACT,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;KACjE,CAAC,CACH;SACA,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,iMAAiM;QACnM,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,SAAS,EAAE;oBACT,IAAI,EAAE,OAAO;oBACb,WAAW,EACT,iHAAiH;oBACnH,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mFAAmF,EAAE;4BAClI,MAAM,EAAE;gCACN,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;gCACzB,WAAW,EAAE,4FAA4F;6BAC1G;yBACF;wBACD,QAAQ,EAAE,CAAC,cAAc,CAAC;qBAC3B;iBACF;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC;SACnC;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,wCAAwC;QACxC,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7C,GAAG,IAAI;YACP,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;SAC9C,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC;YAClD,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,SAAS;SACV,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
1
+ {"version":3,"file":"proposeLanguages.js","sourceRoot":"","sources":["../../src/tools/proposeLanguages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,SAAS,EAAE,CAAC;SACT,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;KACjE,CAAC,CACH;SACA,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;CACX,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,iMAAiM;QACnM,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,SAAS,EAAE;oBACT,IAAI,EAAE,OAAO;oBACb,WAAW,EACT,iHAAiH;oBACnH,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mFAAmF,EAAE;4BAClI,MAAM,EAAE;gCACN,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;gCACzB,WAAW,EAAE,4FAA4F;6BAC1G;yBACF;wBACD,QAAQ,EAAE,CAAC,cAAc,CAAC;qBAC3B;iBACF;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC;SACnC;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,wCAAwC;QACxC,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7C,GAAG,IAAI;YACP,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;SAC9C,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC;YAClD,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,SAAS;SACV,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC;gBAC1C,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,MAAM,CAAC,OAAO,6GAA6G,EAAE;gBAC9I,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-i18n/mcp",
3
- "version": "0.15.5",
3
+ "version": "0.16.0",
4
4
  "description": "MCP server for Better i18n translation management - AI-powered translation workflow for Cursor, Claude, and other AI assistants",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "files": [
13
13
  "dist",
14
+ "!dist/**/__tests__",
14
15
  "package.json",
15
16
  "README.md"
16
17
  ],
@@ -50,12 +51,12 @@
50
51
  "prepublishOnly": "npm run clean && npm run build && chmod +x ./dist/index.js ./dist/http.js"
51
52
  },
52
53
  "dependencies": {
53
- "@better-i18n/mcp-types": "0.0.0",
54
54
  "@modelcontextprotocol/sdk": "^1.25.3",
55
55
  "@trpc/client": "^11.0.0",
56
56
  "zod": "^3.25.1"
57
57
  },
58
58
  "devDependencies": {
59
+ "@better-i18n/mcp-types": "0.0.0",
59
60
  "@types/node": "^20.0.0",
60
61
  "typescript": "~5.9.2"
61
62
  },
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=base-tool.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-tool.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/base-tool.test.ts"],"names":[],"mappings":""}
@@ -1,193 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { z } from "zod";
3
- import { parseProject } from "../helpers.js";
4
- import { success, error, executeTool, executeSimpleTool, projectSchema, } from "../base-tool.js";
5
- import { isErrorResult, expectSuccess, expectError } from "./helpers.js";
6
- // ---------------------------------------------------------------------------
7
- // parseProject
8
- // ---------------------------------------------------------------------------
9
- describe("parseProject", () => {
10
- it('parses "org/project" into workspaceId and projectSlug', () => {
11
- expect(parseProject("org/project")).toEqual({
12
- workspaceId: "org",
13
- projectSlug: "project",
14
- });
15
- });
16
- it("throws a descriptive error for a single-segment string", () => {
17
- expect(() => parseProject("invalid")).toThrow(/Invalid project format "invalid"/);
18
- });
19
- it("throws for an empty string", () => {
20
- expect(() => parseProject("")).toThrow(/Invalid project format/);
21
- });
22
- it("throws when there are 3 segments (a/b/c)", () => {
23
- expect(() => parseProject("a/b/c")).toThrow(/Invalid project format "a\/b\/c"/);
24
- });
25
- it("throws when the slug part is empty (org/)", () => {
26
- expect(() => parseProject("org/")).toThrow(/Invalid project format "org\/"/);
27
- });
28
- it("throws when the org part is empty (/project)", () => {
29
- expect(() => parseProject("/project")).toThrow(/Invalid project format "\/project"/);
30
- });
31
- it("handles hyphens in both org and slug", () => {
32
- expect(parseProject("org-with-hyphens/proj-123")).toEqual({
33
- workspaceId: "org-with-hyphens",
34
- projectSlug: "proj-123",
35
- });
36
- });
37
- });
38
- // ---------------------------------------------------------------------------
39
- // projectSchema
40
- // ---------------------------------------------------------------------------
41
- describe("projectSchema", () => {
42
- it("accepts a non-empty project string", () => {
43
- expect(() => projectSchema.parse({ project: "org/slug" })).not.toThrow();
44
- });
45
- it("rejects an empty project string", () => {
46
- expect(() => projectSchema.parse({ project: "" })).toThrow();
47
- });
48
- it("rejects a missing project field", () => {
49
- expect(() => projectSchema.parse({})).toThrow();
50
- });
51
- });
52
- // ---------------------------------------------------------------------------
53
- // success
54
- // ---------------------------------------------------------------------------
55
- describe("success", () => {
56
- it("produces a result with type=text content", () => {
57
- const result = success({ data: 1 });
58
- expect(result.content).toHaveLength(1);
59
- expect(result.content[0]?.type).toBe("text");
60
- });
61
- it("serialises the payload as valid JSON", () => {
62
- const result = success({ hello: "world", count: 42 });
63
- const text = result.content[0]?.text;
64
- expect(text).toBeDefined();
65
- expect(() => JSON.parse(text)).not.toThrow();
66
- expect(JSON.parse(text)).toEqual({ hello: "world", count: 42 });
67
- });
68
- it("does not set isError", () => {
69
- const result = success({ ok: true });
70
- expect(result.isError).toBeUndefined();
71
- });
72
- });
73
- // ---------------------------------------------------------------------------
74
- // error
75
- // ---------------------------------------------------------------------------
76
- describe("error", () => {
77
- it("sets isError: true", () => {
78
- const result = error("something went wrong");
79
- expect(result.isError).toBe(true);
80
- });
81
- it("includes the message in the text content", () => {
82
- const msg = "something went wrong";
83
- const result = error(msg);
84
- expect(result.content[0]?.text).toBe(msg);
85
- });
86
- it("produces exactly one content entry", () => {
87
- const result = error("oops");
88
- expect(result.content).toHaveLength(1);
89
- expect(result.content[0]?.type).toBe("text");
90
- });
91
- });
92
- // ---------------------------------------------------------------------------
93
- // executeTool
94
- // ---------------------------------------------------------------------------
95
- describe("executeTool", () => {
96
- const schema = z.object({ project: z.string().min(1), value: z.string() });
97
- it("calls the handler with parsed input and ParsedProject on success", async () => {
98
- const result = await executeTool({ project: "acme/website", value: "hello" }, schema, async (input, parsed) => {
99
- return success({
100
- value: input.value,
101
- workspaceId: parsed.workspaceId,
102
- projectSlug: parsed.projectSlug,
103
- });
104
- });
105
- const data = expectSuccess(result);
106
- expect(data.value).toBe("hello");
107
- expect(data.workspaceId).toBe("acme");
108
- expect(data.projectSlug).toBe("website");
109
- });
110
- it("returns isError: true with 'Validation error' on Zod failure", async () => {
111
- const result = await executeTool({ project: "valid/project" /* missing required `value` */ }, schema, async () => success({}));
112
- expect(isErrorResult(result)).toBe(true);
113
- const msg = expectError(result);
114
- expect(msg).toMatch(/Validation error/i);
115
- });
116
- it("returns isError: true when the handler throws", async () => {
117
- const result = await executeTool({ project: "acme/website", value: "x" }, schema, async () => {
118
- throw new Error("handler blew up");
119
- });
120
- expect(isErrorResult(result)).toBe(true);
121
- expect(expectError(result)).toContain("handler blew up");
122
- });
123
- it("returns isError: true for invalid project format", async () => {
124
- const result = await executeTool({ project: "not-a-valid-format", value: "x" }, schema, async () => success({}));
125
- expect(isErrorResult(result)).toBe(true);
126
- expect(expectError(result)).toMatch(/Invalid project format/i);
127
- });
128
- it("returns isError: true when args fail schema type coercion", async () => {
129
- const result = await executeTool(null, // completely invalid args
130
- schema, async () => success({}));
131
- expect(isErrorResult(result)).toBe(true);
132
- });
133
- it("passes the full parsed project to the handler", async () => {
134
- let capturedParsed = null;
135
- await executeTool({ project: "my-org/my-slug", value: "test" }, schema, async (_input, parsed) => {
136
- capturedParsed = parsed;
137
- return success({});
138
- });
139
- expect(capturedParsed).toEqual({
140
- workspaceId: "my-org",
141
- projectSlug: "my-slug",
142
- });
143
- });
144
- it("surfaces non-Error throws as string messages", async () => {
145
- const result = await executeTool({ project: "acme/website", value: "x" }, schema, async () => {
146
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
147
- throw "string error";
148
- });
149
- expect(isErrorResult(result)).toBe(true);
150
- expect(expectError(result)).toBe("string error");
151
- });
152
- });
153
- // ---------------------------------------------------------------------------
154
- // executeSimpleTool
155
- // ---------------------------------------------------------------------------
156
- describe("executeSimpleTool", () => {
157
- const schema = z.object({ name: z.string().min(1), count: z.number() });
158
- it("calls the handler with parsed input and returns its result", async () => {
159
- const result = await executeSimpleTool({ name: "test", count: 5 }, schema, async (input) => success({ echo: input.name, times: input.count }));
160
- const data = expectSuccess(result);
161
- expect(data.echo).toBe("test");
162
- expect(data.times).toBe(5);
163
- });
164
- it("returns isError: true with 'Validation error' on Zod failure", async () => {
165
- const result = await executeSimpleTool({ name: "" /* fails min(1) */, count: 3 }, schema, async () => success({}));
166
- expect(isErrorResult(result)).toBe(true);
167
- expect(expectError(result)).toMatch(/Validation error/i);
168
- });
169
- it("returns isError: true when the handler throws an Error", async () => {
170
- const result = await executeSimpleTool({ name: "good", count: 1 }, schema, async () => {
171
- throw new Error("simple handler failed");
172
- });
173
- expect(isErrorResult(result)).toBe(true);
174
- expect(expectError(result)).toContain("simple handler failed");
175
- });
176
- it("returns isError: true when the handler throws a non-Error value", async () => {
177
- const result = await executeSimpleTool({ name: "good", count: 1 }, schema, async () => {
178
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
179
- throw 42;
180
- });
181
- expect(isErrorResult(result)).toBe(true);
182
- expect(expectError(result)).toBe("42");
183
- });
184
- it("returns isError: true when args are completely invalid", async () => {
185
- const result = await executeSimpleTool(undefined, schema, async () => success({}));
186
- expect(isErrorResult(result)).toBe(true);
187
- });
188
- it("does not include isError on a successful result", async () => {
189
- const result = await executeSimpleTool({ name: "ok", count: 0 }, schema, async () => success({ ok: true }));
190
- expect(result.isError).toBeUndefined();
191
- });
192
- });
193
- //# sourceMappingURL=base-tool.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-tool.test.js","sourceRoot":"","sources":["../../src/__tests__/base-tool.test.ts"],"names":[],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- /**
2
- * contract.test.ts
3
- *
4
- * End-to-end contract tests that bridge the gap between tool logic and the real API.
5
- *
6
- * THREE test sections:
7
- *
8
- * 1. FORWARD CONTRACT — tool output → API schema validation
9
- * Execute each tool with a mock client, capture what it ACTUALLY sends to the
10
- * API (orgSlug, projectSlug, payload), and validate those args against the
11
- * mcp-types Zod schemas (the real API contract). If the API schema rejects it,
12
- * the tool has a normalization or mapping bug.
13
- *
14
- * 2. REVERSE CONTRACT — LLM-plausible args → tool acceptance
15
- * Simulate inputs an LLM would plausibly generate from reading inputSchema,
16
- * and assert the tool accepts them without isError. Catches regressions where
17
- * a schema tightening breaks something an LLM was expected to send.
18
- *
19
- * 3. NEGATIVE CONTRACT — invalid args MUST be rejected
20
- * Guard rails: assert that clearly invalid inputs are rejected (isError=true)
21
- * so we never silently swallow bad data from an LLM.
22
- */
23
- export {};
24
- //# sourceMappingURL=contract.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/contract.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}