string-catalog-mcp 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 (62) hide show
  1. package/.prettierrc +8 -0
  2. package/README.md +127 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +23 -0
  5. package/dist/mcp/prompts/batch-translate.d.ts +2 -0
  6. package/dist/mcp/prompts/batch-translate.js +88 -0
  7. package/dist/mcp/prompts/index.d.ts +2 -0
  8. package/dist/mcp/prompts/index.js +12 -0
  9. package/dist/mcp/prompts/review-translations.d.ts +2 -0
  10. package/dist/mcp/prompts/review-translations.js +75 -0
  11. package/dist/mcp/prompts/translate-strings.d.ts +2 -0
  12. package/dist/mcp/prompts/translate-strings.js +81 -0
  13. package/dist/mcp/tools/get-catalog-statistics.d.ts +2 -0
  14. package/dist/mcp/tools/get-catalog-statistics.js +25 -0
  15. package/dist/mcp/tools/get-translations-for-key.d.ts +2 -0
  16. package/dist/mcp/tools/get-translations-for-key.js +36 -0
  17. package/dist/mcp/tools/index.d.ts +2 -0
  18. package/dist/mcp/tools/index.js +18 -0
  19. package/dist/mcp/tools/list-all-keys.d.ts +2 -0
  20. package/dist/mcp/tools/list-all-keys.js +44 -0
  21. package/dist/mcp/tools/list-supported-languages.d.ts +2 -0
  22. package/dist/mcp/tools/list-supported-languages.js +30 -0
  23. package/dist/mcp/tools/search-keys.d.ts +2 -0
  24. package/dist/mcp/tools/search-keys.js +32 -0
  25. package/dist/mcp/tools/update-translations.d.ts +2 -0
  26. package/dist/mcp/tools/update-translations.js +78 -0
  27. package/dist/string-catalog.d.ts +53 -0
  28. package/dist/string-catalog.js +220 -0
  29. package/dist/tools/get-catalog-statistics.d.ts +2 -0
  30. package/dist/tools/get-catalog-statistics.js +25 -0
  31. package/dist/tools/get-translations-for-key.d.ts +2 -0
  32. package/dist/tools/get-translations-for-key.js +36 -0
  33. package/dist/tools/index.d.ts +2 -0
  34. package/dist/tools/index.js +18 -0
  35. package/dist/tools/list-all-keys.d.ts +2 -0
  36. package/dist/tools/list-all-keys.js +44 -0
  37. package/dist/tools/list-supported-languages.d.ts +2 -0
  38. package/dist/tools/list-supported-languages.js +30 -0
  39. package/dist/tools/search-keys.d.ts +2 -0
  40. package/dist/tools/search-keys.js +32 -0
  41. package/dist/tools/update-translations.d.ts +2 -0
  42. package/dist/tools/update-translations.js +78 -0
  43. package/dist/types.d.ts +86 -0
  44. package/dist/types.js +6 -0
  45. package/eslint.config.js +23 -0
  46. package/images/mcp.jpeg +0 -0
  47. package/package.json +49 -0
  48. package/src/index.ts +25 -0
  49. package/src/mcp/prompts/batch-translate.ts +91 -0
  50. package/src/mcp/prompts/index.ts +10 -0
  51. package/src/mcp/prompts/review-translations.ts +79 -0
  52. package/src/mcp/prompts/translate-strings.ts +85 -0
  53. package/src/mcp/tools/get-catalog-statistics.ts +29 -0
  54. package/src/mcp/tools/get-translations-for-key.ts +45 -0
  55. package/src/mcp/tools/index.ts +16 -0
  56. package/src/mcp/tools/list-all-keys.ts +52 -0
  57. package/src/mcp/tools/list-supported-languages.ts +38 -0
  58. package/src/mcp/tools/search-keys.ts +40 -0
  59. package/src/mcp/tools/update-translations.ts +89 -0
  60. package/src/string-catalog.ts +232 -0
  61. package/src/types.ts +82 -0
  62. package/tsconfig.json +28 -0
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "tabWidth": 4,
3
+ "useTabs": false,
4
+ "semi": true,
5
+ "singleQuote": true,
6
+ "trailingComma": "es5",
7
+ "printWidth": 100
8
+ }
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # string-catalog-mcp
2
+
3
+ An MCP server for working with Xcode String Catalog (.xcstrings) files. It lets AI assistants read, search, and update your iOS/macOS localization strings.
4
+
5
+ ![MCP in action](images/mcp.jpeg)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm install
11
+ pnpm build
12
+ ```
13
+
14
+ ## Usage with Claude Code
15
+
16
+ ```bash
17
+ pnpm run mcp:add
18
+ ```
19
+
20
+ Or manually add to your MCP config:
21
+
22
+ ```json
23
+ {
24
+ "mcpServers": {
25
+ "string-catalog-mcp": {
26
+ "command": "node",
27
+ "args": ["/path/to/string-catalog-mcp/dist/index.js"]
28
+ }
29
+ }
30
+ }
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Available Tools
36
+
37
+ ### list_supported_languages
38
+
39
+ List all languages in a string catalog with the source language identified.
40
+
41
+ > "What languages are supported in my Localizable.xcstrings file?"
42
+
43
+ ---
44
+
45
+ ### get_catalog_statistics
46
+
47
+ Get translation coverage breakdown per language, including total keys and completion percentages.
48
+
49
+ > "Show me the translation statistics for my string catalog"
50
+
51
+ ---
52
+
53
+ ### get_translations_for_key
54
+
55
+ Get all translations for a specific key across all supported languages.
56
+
57
+ > "Show me all translations for the 'welcome_message' key"
58
+
59
+ ---
60
+
61
+ ### search_keys
62
+
63
+ Search for localization keys containing a specific substring (case-insensitive).
64
+
65
+ > "Find all keys that contain 'error' in my string catalog"
66
+
67
+ ---
68
+
69
+ ### list_all_keys
70
+
71
+ List all localization keys in the catalog (supports pagination for large catalogs).
72
+
73
+ > "List all the localization keys in my project"
74
+
75
+ ---
76
+
77
+ ### update_translations
78
+
79
+ Add or update translations in the string catalog. Accepts a structured JSON payload with support for iOS format placeholders (`%@`, `%d`, `%lld`, `%f`, `%1$@`).
80
+
81
+ > "Add German and French translations for the 'hello_world' key"
82
+
83
+ ---
84
+
85
+ ## Available Prompts
86
+
87
+ ### translate-strings
88
+
89
+ Generate translations for specific keys with guidance on format placeholders.
90
+
91
+ > "Use the translate-strings prompt to translate 'welcome_message' and 'goodbye' into German, French, and Japanese"
92
+
93
+ ### batch-translate
94
+
95
+ Translate all untranslated or stale strings in a catalog for specified languages.
96
+
97
+ > "Use batch-translate to add German translations for all missing strings in my catalog"
98
+
99
+ ### review-translations
100
+
101
+ Review existing translations for quality, consistency, and proper placeholder usage.
102
+
103
+ > "Review my German translations for quality issues"
104
+
105
+ ## Common Workflows
106
+
107
+ ### Add a new language to your app
108
+
109
+ 1. "What languages are supported in my Localizable.xcstrings?"
110
+ 2. "Use batch-translate to add Spanish translations to /path/to/Localizable.xcstrings"
111
+
112
+ ### Translate specific strings
113
+
114
+ 1. "Search for keys containing 'settings' in my string catalog"
115
+ 2. "Show me translations for the 'settings_title' key"
116
+ 3. "Translate 'settings_title' and 'settings_description' into German and French"
117
+
118
+ ### Review translation quality
119
+
120
+ 1. "Show me translation statistics for my catalog"
121
+ 2. "Review German translations for placeholder issues and consistency"
122
+
123
+ ---
124
+
125
+ ## License
126
+
127
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const index_1 = require("./mcp/tools/index");
7
+ const index_2 = require("./mcp/prompts/index");
8
+ const server = new mcp_js_1.McpServer({
9
+ name: 'string-catalog-mcp',
10
+ version: '1.0.0',
11
+ });
12
+ (0, index_1.registerAllTools)(server);
13
+ (0, index_2.registerAllPrompts)(server);
14
+ async function main() {
15
+ const transport = new stdio_js_1.StdioServerTransport();
16
+ await server.connect(transport);
17
+ console.error('String Catalog MCP Server running on stdio');
18
+ }
19
+ main().catch((error) => {
20
+ console.error('Fatal error:', error);
21
+ process.exit(1);
22
+ });
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsb0VBQW9FO0FBQ3BFLHdFQUFpRjtBQUNqRiw2Q0FBcUQ7QUFDckQsK0NBQXlEO0FBRXpELE1BQU0sTUFBTSxHQUFHLElBQUksa0JBQVMsQ0FBQztJQUN6QixJQUFJLEVBQUUsb0JBQW9CO0lBQzFCLE9BQU8sRUFBRSxPQUFPO0NBQ25CLENBQUMsQ0FBQztBQUVILElBQUEsd0JBQWdCLEVBQUMsTUFBTSxDQUFDLENBQUM7QUFDekIsSUFBQSwwQkFBa0IsRUFBQyxNQUFNLENBQUMsQ0FBQztBQUUzQixLQUFLLFVBQVUsSUFBSTtJQUNmLE1BQU0sU0FBUyxHQUFHLElBQUksK0JBQW9CLEVBQUUsQ0FBQztJQUM3QyxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDaEMsT0FBTyxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRCxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtJQUNuQixPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiIyEvdXNyL2Jpbi9lbnYgbm9kZVxuXG5pbXBvcnQgeyBNY3BTZXJ2ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgU3RkaW9TZXJ2ZXJUcmFuc3BvcnQgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9zdGRpby5qcyc7XG5pbXBvcnQgeyByZWdpc3RlckFsbFRvb2xzIH0gZnJvbSAnLi9tY3AvdG9vbHMvaW5kZXgnO1xuaW1wb3J0IHsgcmVnaXN0ZXJBbGxQcm9tcHRzIH0gZnJvbSAnLi9tY3AvcHJvbXB0cy9pbmRleCc7XG5cbmNvbnN0IHNlcnZlciA9IG5ldyBNY3BTZXJ2ZXIoe1xuICAgIG5hbWU6ICdzdHJpbmctY2F0YWxvZy1tY3AnLFxuICAgIHZlcnNpb246ICcxLjAuMCcsXG59KTtcblxucmVnaXN0ZXJBbGxUb29scyhzZXJ2ZXIpO1xucmVnaXN0ZXJBbGxQcm9tcHRzKHNlcnZlcik7XG5cbmFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7XG4gICAgY29uc3QgdHJhbnNwb3J0ID0gbmV3IFN0ZGlvU2VydmVyVHJhbnNwb3J0KCk7XG4gICAgYXdhaXQgc2VydmVyLmNvbm5lY3QodHJhbnNwb3J0KTtcbiAgICBjb25zb2xlLmVycm9yKCdTdHJpbmcgQ2F0YWxvZyBNQ1AgU2VydmVyIHJ1bm5pbmcgb24gc3RkaW8nKTtcbn1cblxubWFpbigpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgIGNvbnNvbGUuZXJyb3IoJ0ZhdGFsIGVycm9yOicsIGVycm9yKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG59KTtcbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerBatchTranslatePrompt(server: McpServer): void;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerBatchTranslatePrompt = registerBatchTranslatePrompt;
4
+ const zod_1 = require("zod");
5
+ function registerBatchTranslatePrompt(server) {
6
+ server.registerPrompt('batch-translate', {
7
+ description: 'Translate all untranslated or stale strings in a catalog for specified languages.',
8
+ argsSchema: {
9
+ filePath: zod_1.z.string().describe('Absolute path to the .xcstrings file'),
10
+ targetLanguages: zod_1.z.string().describe('Comma-separated list of target language codes (e.g., "de,fr,ja")'),
11
+ includeStale: zod_1.z.boolean().default(false).describe('Whether to re-translate stale entries'),
12
+ batchSize: zod_1.z.number().default(20).describe('Number of keys to translate per batch (default: 20)'),
13
+ },
14
+ }, async ({ filePath, targetLanguages, includeStale, batchSize }) => {
15
+ const targetLangList = targetLanguages.split(',').map(l => l.trim()).filter(Boolean);
16
+ return {
17
+ messages: [
18
+ {
19
+ role: 'user',
20
+ content: {
21
+ type: 'text',
22
+ text: `# Batch Translation Request
23
+
24
+ ## String Catalog File
25
+ ${filePath}
26
+
27
+ ## Target Languages
28
+ ${targetLangList.map(l => `- ${l}`).join('\n')}
29
+
30
+ ## Options
31
+ - Include stale translations: ${includeStale ? 'Yes' : 'No'}
32
+ - Batch size: ${batchSize} keys per batch
33
+
34
+ ## Workflow
35
+
36
+ ### Step 1: Analyze the Catalog
37
+ Use \`get_catalog_statistics\` to understand the current translation coverage.
38
+
39
+ ### Step 2: Identify Keys Needing Translation
40
+ Use \`search_keys\` or \`list_all_keys\` to find:
41
+ - Keys with missing translations for target languages
42
+ ${includeStale ? '- Keys with stale translations that need updating' : ''}
43
+
44
+ ### Step 3: Translate in Batches
45
+ For each batch of up to ${batchSize} keys:
46
+ 1. Get the source text using \`get_translations_for_key\`
47
+ 2. Translate to all target languages
48
+ 3. Prepare the JSON payload for \`update_translations\`
49
+
50
+ ## iOS Format Placeholders Reference
51
+ Preserve these placeholders in translations:
52
+ - \`%@\` - String (object)
53
+ - \`%d\` / \`%lld\` - Integer
54
+ - \`%f\` - Float
55
+ - \`%1$@\`, \`%2$@\` - Positional (can reorder for grammar)
56
+
57
+ ## Output Format
58
+ For each batch, provide:
59
+
60
+ \`\`\`json
61
+ {
62
+ "data": [
63
+ {
64
+ "key": "key_name",
65
+ "translations": [
66
+ { "language": "de", "value": "German translation" },
67
+ { "language": "fr", "value": "French translation" }
68
+ ]
69
+ }
70
+ ]
71
+ }
72
+ \`\`\`
73
+
74
+ ## Instructions
75
+ 1. Start by analyzing the catalog
76
+ 2. Identify which keys need translation
77
+ 3. Process keys in batches
78
+ 4. After each batch, use \`update_translations\` to save
79
+ 5. Report progress after each batch
80
+
81
+ Begin the batch translation process now.`,
82
+ },
83
+ },
84
+ ],
85
+ };
86
+ });
87
+ }
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2gtdHJhbnNsYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21jcC9wcm9tcHRzL2JhdGNoLXRyYW5zbGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUdBLG9FQXVGQztBQXpGRCw2QkFBd0I7QUFFeEIsU0FBZ0IsNEJBQTRCLENBQUMsTUFBaUI7SUFDMUQsTUFBTSxDQUFDLGNBQWMsQ0FDakIsaUJBQWlCLEVBQ2pCO1FBQ0ksV0FBVyxFQUFFLG1GQUFtRjtRQUNoRyxVQUFVLEVBQUU7WUFDUixRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxzQ0FBc0MsQ0FBQztZQUNyRSxlQUFlLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxrRUFBa0UsQ0FBQztZQUN4RyxZQUFZLEVBQUUsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsdUNBQXVDLENBQUM7WUFDMUYsU0FBUyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLHFEQUFxRCxDQUFDO1NBQ3BHO0tBQ0osRUFDRCxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO1FBQzdELE1BQU0sY0FBYyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXJGLE9BQU87WUFDSCxRQUFRLEVBQUU7Z0JBQ047b0JBQ0ksSUFBSSxFQUFFLE1BQU07b0JBQ1osT0FBTyxFQUFFO3dCQUNMLElBQUksRUFBRSxNQUFNO3dCQUNaLElBQUksRUFBRTs7O0VBR2hDLFFBQVE7OztFQUdSLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzs7O2dDQUdkLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUMzQyxTQUFTOzs7Ozs7Ozs7O0VBVXZCLFlBQVksQ0FBQyxDQUFDLENBQUMsbURBQW1ELENBQUMsQ0FBQyxDQUFDLEVBQUU7OzswQkFHL0MsU0FBUzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O3lDQW9DTTtxQkFDaEI7aUJBQ0o7YUFDSjtTQUNKLENBQUM7SUFDTixDQUFDLENBQ0osQ0FBQztBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNY3BTZXJ2ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckJhdGNoVHJhbnNsYXRlUHJvbXB0KHNlcnZlcjogTWNwU2VydmVyKSB7XG4gICAgc2VydmVyLnJlZ2lzdGVyUHJvbXB0KFxuICAgICAgICAnYmF0Y2gtdHJhbnNsYXRlJyxcbiAgICAgICAge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246ICdUcmFuc2xhdGUgYWxsIHVudHJhbnNsYXRlZCBvciBzdGFsZSBzdHJpbmdzIGluIGEgY2F0YWxvZyBmb3Igc3BlY2lmaWVkIGxhbmd1YWdlcy4nLFxuICAgICAgICAgICAgYXJnc1NjaGVtYToge1xuICAgICAgICAgICAgICAgIGZpbGVQYXRoOiB6LnN0cmluZygpLmRlc2NyaWJlKCdBYnNvbHV0ZSBwYXRoIHRvIHRoZSAueGNzdHJpbmdzIGZpbGUnKSxcbiAgICAgICAgICAgICAgICB0YXJnZXRMYW5ndWFnZXM6IHouc3RyaW5nKCkuZGVzY3JpYmUoJ0NvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIHRhcmdldCBsYW5ndWFnZSBjb2RlcyAoZS5nLiwgXCJkZSxmcixqYVwiKScpLFxuICAgICAgICAgICAgICAgIGluY2x1ZGVTdGFsZTogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSkuZGVzY3JpYmUoJ1doZXRoZXIgdG8gcmUtdHJhbnNsYXRlIHN0YWxlIGVudHJpZXMnKSxcbiAgICAgICAgICAgICAgICBiYXRjaFNpemU6IHoubnVtYmVyKCkuZGVmYXVsdCgyMCkuZGVzY3JpYmUoJ051bWJlciBvZiBrZXlzIHRvIHRyYW5zbGF0ZSBwZXIgYmF0Y2ggKGRlZmF1bHQ6IDIwKScpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgYXN5bmMgKHsgZmlsZVBhdGgsIHRhcmdldExhbmd1YWdlcywgaW5jbHVkZVN0YWxlLCBiYXRjaFNpemUgfSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0TGFuZ0xpc3QgPSB0YXJnZXRMYW5ndWFnZXMuc3BsaXQoJywnKS5tYXAobCA9PiBsLnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pO1xuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvbGU6ICd1c2VyJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogYCMgQmF0Y2ggVHJhbnNsYXRpb24gUmVxdWVzdFxuXG4jIyBTdHJpbmcgQ2F0YWxvZyBGaWxlXG4ke2ZpbGVQYXRofVxuXG4jIyBUYXJnZXQgTGFuZ3VhZ2VzXG4ke3RhcmdldExhbmdMaXN0Lm1hcChsID0+IGAtICR7bH1gKS5qb2luKCdcXG4nKX1cblxuIyMgT3B0aW9uc1xuLSBJbmNsdWRlIHN0YWxlIHRyYW5zbGF0aW9uczogJHtpbmNsdWRlU3RhbGUgPyAnWWVzJyA6ICdObyd9XG4tIEJhdGNoIHNpemU6ICR7YmF0Y2hTaXplfSBrZXlzIHBlciBiYXRjaFxuXG4jIyBXb3JrZmxvd1xuXG4jIyMgU3RlcCAxOiBBbmFseXplIHRoZSBDYXRhbG9nXG5Vc2UgXFxgZ2V0X2NhdGFsb2dfc3RhdGlzdGljc1xcYCB0byB1bmRlcnN0YW5kIHRoZSBjdXJyZW50IHRyYW5zbGF0aW9uIGNvdmVyYWdlLlxuXG4jIyMgU3RlcCAyOiBJZGVudGlmeSBLZXlzIE5lZWRpbmcgVHJhbnNsYXRpb25cblVzZSBcXGBzZWFyY2hfa2V5c1xcYCBvciBcXGBsaXN0X2FsbF9rZXlzXFxgIHRvIGZpbmQ6XG4tIEtleXMgd2l0aCBtaXNzaW5nIHRyYW5zbGF0aW9ucyBmb3IgdGFyZ2V0IGxhbmd1YWdlc1xuJHtpbmNsdWRlU3RhbGUgPyAnLSBLZXlzIHdpdGggc3RhbGUgdHJhbnNsYXRpb25zIHRoYXQgbmVlZCB1cGRhdGluZycgOiAnJ31cblxuIyMjIFN0ZXAgMzogVHJhbnNsYXRlIGluIEJhdGNoZXNcbkZvciBlYWNoIGJhdGNoIG9mIHVwIHRvICR7YmF0Y2hTaXplfSBrZXlzOlxuMS4gR2V0IHRoZSBzb3VyY2UgdGV4dCB1c2luZyBcXGBnZXRfdHJhbnNsYXRpb25zX2Zvcl9rZXlcXGBcbjIuIFRyYW5zbGF0ZSB0byBhbGwgdGFyZ2V0IGxhbmd1YWdlc1xuMy4gUHJlcGFyZSB0aGUgSlNPTiBwYXlsb2FkIGZvciBcXGB1cGRhdGVfdHJhbnNsYXRpb25zXFxgXG5cbiMjIGlPUyBGb3JtYXQgUGxhY2Vob2xkZXJzIFJlZmVyZW5jZVxuUHJlc2VydmUgdGhlc2UgcGxhY2Vob2xkZXJzIGluIHRyYW5zbGF0aW9uczpcbi0gXFxgJUBcXGAgLSBTdHJpbmcgKG9iamVjdClcbi0gXFxgJWRcXGAgLyBcXGAlbGxkXFxgIC0gSW50ZWdlclxuLSBcXGAlZlxcYCAtIEZsb2F0XG4tIFxcYCUxJEBcXGAsIFxcYCUyJEBcXGAgLSBQb3NpdGlvbmFsIChjYW4gcmVvcmRlciBmb3IgZ3JhbW1hcilcblxuIyMgT3V0cHV0IEZvcm1hdFxuRm9yIGVhY2ggYmF0Y2gsIHByb3ZpZGU6XG5cblxcYFxcYFxcYGpzb25cbntcbiAgICBcImRhdGFcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgICBcImtleVwiOiBcImtleV9uYW1lXCIsXG4gICAgICAgICAgICBcInRyYW5zbGF0aW9uc1wiOiBbXG4gICAgICAgICAgICAgICAgeyBcImxhbmd1YWdlXCI6IFwiZGVcIiwgXCJ2YWx1ZVwiOiBcIkdlcm1hbiB0cmFuc2xhdGlvblwiIH0sXG4gICAgICAgICAgICAgICAgeyBcImxhbmd1YWdlXCI6IFwiZnJcIiwgXCJ2YWx1ZVwiOiBcIkZyZW5jaCB0cmFuc2xhdGlvblwiIH1cbiAgICAgICAgICAgIF1cbiAgICAgICAgfVxuICAgIF1cbn1cblxcYFxcYFxcYFxuXG4jIyBJbnN0cnVjdGlvbnNcbjEuIFN0YXJ0IGJ5IGFuYWx5emluZyB0aGUgY2F0YWxvZ1xuMi4gSWRlbnRpZnkgd2hpY2gga2V5cyBuZWVkIHRyYW5zbGF0aW9uXG4zLiBQcm9jZXNzIGtleXMgaW4gYmF0Y2hlc1xuNC4gQWZ0ZXIgZWFjaCBiYXRjaCwgdXNlIFxcYHVwZGF0ZV90cmFuc2xhdGlvbnNcXGAgdG8gc2F2ZVxuNS4gUmVwb3J0IHByb2dyZXNzIGFmdGVyIGVhY2ggYmF0Y2hcblxuQmVnaW4gdGhlIGJhdGNoIHRyYW5zbGF0aW9uIHByb2Nlc3Mgbm93LmAsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgKTtcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerAllPrompts(server: McpServer): void;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerAllPrompts = registerAllPrompts;
4
+ const translate_strings_1 = require("./translate-strings");
5
+ const review_translations_1 = require("./review-translations");
6
+ const batch_translate_1 = require("./batch-translate");
7
+ function registerAllPrompts(server) {
8
+ (0, translate_strings_1.registerTranslateStringsPrompt)(server);
9
+ (0, review_translations_1.registerReviewTranslationsPrompt)(server);
10
+ (0, batch_translate_1.registerBatchTranslatePrompt)(server);
11
+ }
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbWNwL3Byb21wdHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSxnREFJQztBQVJELDJEQUFxRTtBQUNyRSwrREFBeUU7QUFDekUsdURBQWlFO0FBRWpFLFNBQWdCLGtCQUFrQixDQUFDLE1BQWlCO0lBQ2hELElBQUEsa0RBQThCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFDdkMsSUFBQSxzREFBZ0MsRUFBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxJQUFBLDhDQUE0QixFQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3pDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNY3BTZXJ2ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgcmVnaXN0ZXJUcmFuc2xhdGVTdHJpbmdzUHJvbXB0IH0gZnJvbSAnLi90cmFuc2xhdGUtc3RyaW5ncyc7XG5pbXBvcnQgeyByZWdpc3RlclJldmlld1RyYW5zbGF0aW9uc1Byb21wdCB9IGZyb20gJy4vcmV2aWV3LXRyYW5zbGF0aW9ucyc7XG5pbXBvcnQgeyByZWdpc3RlckJhdGNoVHJhbnNsYXRlUHJvbXB0IH0gZnJvbSAnLi9iYXRjaC10cmFuc2xhdGUnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJBbGxQcm9tcHRzKHNlcnZlcjogTWNwU2VydmVyKSB7XG4gICAgcmVnaXN0ZXJUcmFuc2xhdGVTdHJpbmdzUHJvbXB0KHNlcnZlcik7XG4gICAgcmVnaXN0ZXJSZXZpZXdUcmFuc2xhdGlvbnNQcm9tcHQoc2VydmVyKTtcbiAgICByZWdpc3RlckJhdGNoVHJhbnNsYXRlUHJvbXB0KHNlcnZlcik7XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerReviewTranslationsPrompt(server: McpServer): void;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerReviewTranslationsPrompt = registerReviewTranslationsPrompt;
4
+ const zod_1 = require("zod");
5
+ function registerReviewTranslationsPrompt(server) {
6
+ server.registerPrompt('review-translations', {
7
+ description: 'Review existing translations for quality, consistency, and proper placeholder usage.',
8
+ argsSchema: {
9
+ filePath: zod_1.z.string().describe('Absolute path to the .xcstrings file'),
10
+ languages: zod_1.z.string().optional().describe('Comma-separated list of language codes to review (default: all)'),
11
+ focusAreas: zod_1.z.string().optional().describe('Comma-separated areas to focus on (e.g., "placeholders,consistency,tone")'),
12
+ },
13
+ }, async ({ filePath, languages, focusAreas }) => {
14
+ const langSection = languages
15
+ ? `\n## Languages to Review\n${languages.split(',').map(l => `- ${l.trim()}`).join('\n')}\n`
16
+ : '\n## Languages to Review\nAll available languages in the catalog.\n';
17
+ const focusSection = focusAreas
18
+ ? `\n## Focus Areas\n${focusAreas.split(',').map(f => `- ${f.trim()}`).join('\n')}\n`
19
+ : '';
20
+ return {
21
+ messages: [
22
+ {
23
+ role: 'user',
24
+ content: {
25
+ type: 'text',
26
+ text: `# Translation Review Request
27
+
28
+ ## String Catalog File
29
+ ${filePath}
30
+ ${langSection}${focusSection}
31
+ ## Review Checklist
32
+
33
+ ### 1. Format Placeholder Verification
34
+ - Ensure all \`%@\`, \`%d\`, \`%lld\`, \`%f\` placeholders are preserved
35
+ - Verify positional arguments (\`%1$@\`, \`%2$@\`) are used correctly
36
+ - Check that placeholder count matches the source string
37
+
38
+ ### 2. Translation Quality
39
+ - Verify translations are accurate and natural-sounding
40
+ - Check for grammatical errors
41
+ - Ensure translations fit the context of a mobile app UI
42
+
43
+ ### 3. Consistency
44
+ - Similar strings should have consistent translations
45
+ - Terminology should be uniform across the app
46
+ - UI element names should match platform conventions
47
+
48
+ ### 4. Cultural Appropriateness
49
+ - Verify idioms are properly localized
50
+ - Check for culturally sensitive content
51
+ - Ensure date/number formats are appropriate
52
+
53
+ ### 5. Length Considerations
54
+ - Flag translations that are significantly longer than source
55
+ - Consider UI space constraints for mobile apps
56
+
57
+ ## Instructions
58
+ 1. Use the \`get_catalog_statistics\` tool to see overall translation coverage
59
+ 2. Use the \`list_all_keys\` tool to see available keys
60
+ 3. Use the \`get_translations_for_key\` tool to examine specific translations
61
+ 4. Report any issues found with specific keys and languages
62
+ 5. Suggest corrections using the \`update_translations\` tool format
63
+
64
+ ## Output Format
65
+ Provide a structured review report:
66
+ - Summary of findings
67
+ - List of issues by severity (critical, warning, suggestion)
68
+ - Recommended fixes in JSON format for the update_translations tool`,
69
+ },
70
+ },
71
+ ],
72
+ };
73
+ });
74
+ }
75
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV2aWV3LXRyYW5zbGF0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tY3AvcHJvbXB0cy9yZXZpZXctdHJhbnNsYXRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBR0EsNEVBMkVDO0FBN0VELDZCQUF3QjtBQUV4QixTQUFnQixnQ0FBZ0MsQ0FBQyxNQUFpQjtJQUM5RCxNQUFNLENBQUMsY0FBYyxDQUNqQixxQkFBcUIsRUFDckI7UUFDSSxXQUFXLEVBQUUsc0ZBQXNGO1FBQ25HLFVBQVUsRUFBRTtZQUNSLFFBQVEsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLHNDQUFzQyxDQUFDO1lBQ3JFLFNBQVMsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGlFQUFpRSxDQUFDO1lBQzVHLFVBQVUsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLDJFQUEyRSxDQUFDO1NBQzFIO0tBQ0osRUFDRCxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUU7UUFDMUMsTUFBTSxXQUFXLEdBQUcsU0FBUztZQUN6QixDQUFDLENBQUMsNkJBQTZCLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSTtZQUM1RixDQUFDLENBQUMscUVBQXFFLENBQUM7UUFFNUUsTUFBTSxZQUFZLEdBQUcsVUFBVTtZQUMzQixDQUFDLENBQUMscUJBQXFCLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSTtZQUNyRixDQUFDLENBQUMsRUFBRSxDQUFDO1FBRVQsT0FBTztZQUNILFFBQVEsRUFBRTtnQkFDTjtvQkFDSSxJQUFJLEVBQUUsTUFBTTtvQkFDWixPQUFPLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLE1BQU07d0JBQ1osSUFBSSxFQUFFOzs7RUFHaEMsUUFBUTtFQUNSLFdBQVcsR0FBRyxZQUFZOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztvRUFzQ3dDO3FCQUMzQztpQkFDSjthQUNKO1NBQ0osQ0FBQztJQUNOLENBQUMsQ0FDSixDQUFDO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1jcFNlcnZlciB9IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvc2VydmVyL21jcC5qcyc7XG5pbXBvcnQgeyB6IH0gZnJvbSAnem9kJztcblxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyUmV2aWV3VHJhbnNsYXRpb25zUHJvbXB0KHNlcnZlcjogTWNwU2VydmVyKSB7XG4gICAgc2VydmVyLnJlZ2lzdGVyUHJvbXB0KFxuICAgICAgICAncmV2aWV3LXRyYW5zbGF0aW9ucycsXG4gICAgICAgIHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnUmV2aWV3IGV4aXN0aW5nIHRyYW5zbGF0aW9ucyBmb3IgcXVhbGl0eSwgY29uc2lzdGVuY3ksIGFuZCBwcm9wZXIgcGxhY2Vob2xkZXIgdXNhZ2UuJyxcbiAgICAgICAgICAgIGFyZ3NTY2hlbWE6IHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aDogei5zdHJpbmcoKS5kZXNjcmliZSgnQWJzb2x1dGUgcGF0aCB0byB0aGUgLnhjc3RyaW5ncyBmaWxlJyksXG4gICAgICAgICAgICAgICAgbGFuZ3VhZ2VzOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoJ0NvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIGxhbmd1YWdlIGNvZGVzIHRvIHJldmlldyAoZGVmYXVsdDogYWxsKScpLFxuICAgICAgICAgICAgICAgIGZvY3VzQXJlYXM6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZSgnQ29tbWEtc2VwYXJhdGVkIGFyZWFzIHRvIGZvY3VzIG9uIChlLmcuLCBcInBsYWNlaG9sZGVycyxjb25zaXN0ZW5jeSx0b25lXCIpJyksXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBhc3luYyAoeyBmaWxlUGF0aCwgbGFuZ3VhZ2VzLCBmb2N1c0FyZWFzIH0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxhbmdTZWN0aW9uID0gbGFuZ3VhZ2VzXG4gICAgICAgICAgICAgICAgPyBgXFxuIyMgTGFuZ3VhZ2VzIHRvIFJldmlld1xcbiR7bGFuZ3VhZ2VzLnNwbGl0KCcsJykubWFwKGwgPT4gYC0gJHtsLnRyaW0oKX1gKS5qb2luKCdcXG4nKX1cXG5gXG4gICAgICAgICAgICAgICAgOiAnXFxuIyMgTGFuZ3VhZ2VzIHRvIFJldmlld1xcbkFsbCBhdmFpbGFibGUgbGFuZ3VhZ2VzIGluIHRoZSBjYXRhbG9nLlxcbic7XG5cbiAgICAgICAgICAgIGNvbnN0IGZvY3VzU2VjdGlvbiA9IGZvY3VzQXJlYXNcbiAgICAgICAgICAgICAgICA/IGBcXG4jIyBGb2N1cyBBcmVhc1xcbiR7Zm9jdXNBcmVhcy5zcGxpdCgnLCcpLm1hcChmID0+IGAtICR7Zi50cmltKCl9YCkuam9pbignXFxuJyl9XFxuYFxuICAgICAgICAgICAgICAgIDogJyc7XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9sZTogJ3VzZXInLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBgIyBUcmFuc2xhdGlvbiBSZXZpZXcgUmVxdWVzdFxuXG4jIyBTdHJpbmcgQ2F0YWxvZyBGaWxlXG4ke2ZpbGVQYXRofVxuJHtsYW5nU2VjdGlvbn0ke2ZvY3VzU2VjdGlvbn1cbiMjIFJldmlldyBDaGVja2xpc3RcblxuIyMjIDEuIEZvcm1hdCBQbGFjZWhvbGRlciBWZXJpZmljYXRpb25cbi0gRW5zdXJlIGFsbCBcXGAlQFxcYCwgXFxgJWRcXGAsIFxcYCVsbGRcXGAsIFxcYCVmXFxgIHBsYWNlaG9sZGVycyBhcmUgcHJlc2VydmVkXG4tIFZlcmlmeSBwb3NpdGlvbmFsIGFyZ3VtZW50cyAoXFxgJTEkQFxcYCwgXFxgJTIkQFxcYCkgYXJlIHVzZWQgY29ycmVjdGx5XG4tIENoZWNrIHRoYXQgcGxhY2Vob2xkZXIgY291bnQgbWF0Y2hlcyB0aGUgc291cmNlIHN0cmluZ1xuXG4jIyMgMi4gVHJhbnNsYXRpb24gUXVhbGl0eVxuLSBWZXJpZnkgdHJhbnNsYXRpb25zIGFyZSBhY2N1cmF0ZSBhbmQgbmF0dXJhbC1zb3VuZGluZ1xuLSBDaGVjayBmb3IgZ3JhbW1hdGljYWwgZXJyb3JzXG4tIEVuc3VyZSB0cmFuc2xhdGlvbnMgZml0IHRoZSBjb250ZXh0IG9mIGEgbW9iaWxlIGFwcCBVSVxuXG4jIyMgMy4gQ29uc2lzdGVuY3lcbi0gU2ltaWxhciBzdHJpbmdzIHNob3VsZCBoYXZlIGNvbnNpc3RlbnQgdHJhbnNsYXRpb25zXG4tIFRlcm1pbm9sb2d5IHNob3VsZCBiZSB1bmlmb3JtIGFjcm9zcyB0aGUgYXBwXG4tIFVJIGVsZW1lbnQgbmFtZXMgc2hvdWxkIG1hdGNoIHBsYXRmb3JtIGNvbnZlbnRpb25zXG5cbiMjIyA0LiBDdWx0dXJhbCBBcHByb3ByaWF0ZW5lc3Ncbi0gVmVyaWZ5IGlkaW9tcyBhcmUgcHJvcGVybHkgbG9jYWxpemVkXG4tIENoZWNrIGZvciBjdWx0dXJhbGx5IHNlbnNpdGl2ZSBjb250ZW50XG4tIEVuc3VyZSBkYXRlL251bWJlciBmb3JtYXRzIGFyZSBhcHByb3ByaWF0ZVxuXG4jIyMgNS4gTGVuZ3RoIENvbnNpZGVyYXRpb25zXG4tIEZsYWcgdHJhbnNsYXRpb25zIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgbG9uZ2VyIHRoYW4gc291cmNlXG4tIENvbnNpZGVyIFVJIHNwYWNlIGNvbnN0cmFpbnRzIGZvciBtb2JpbGUgYXBwc1xuXG4jIyBJbnN0cnVjdGlvbnNcbjEuIFVzZSB0aGUgXFxgZ2V0X2NhdGFsb2dfc3RhdGlzdGljc1xcYCB0b29sIHRvIHNlZSBvdmVyYWxsIHRyYW5zbGF0aW9uIGNvdmVyYWdlXG4yLiBVc2UgdGhlIFxcYGxpc3RfYWxsX2tleXNcXGAgdG9vbCB0byBzZWUgYXZhaWxhYmxlIGtleXNcbjMuIFVzZSB0aGUgXFxgZ2V0X3RyYW5zbGF0aW9uc19mb3Jfa2V5XFxgIHRvb2wgdG8gZXhhbWluZSBzcGVjaWZpYyB0cmFuc2xhdGlvbnNcbjQuIFJlcG9ydCBhbnkgaXNzdWVzIGZvdW5kIHdpdGggc3BlY2lmaWMga2V5cyBhbmQgbGFuZ3VhZ2VzXG41LiBTdWdnZXN0IGNvcnJlY3Rpb25zIHVzaW5nIHRoZSBcXGB1cGRhdGVfdHJhbnNsYXRpb25zXFxgIHRvb2wgZm9ybWF0XG5cbiMjIE91dHB1dCBGb3JtYXRcblByb3ZpZGUgYSBzdHJ1Y3R1cmVkIHJldmlldyByZXBvcnQ6XG4tIFN1bW1hcnkgb2YgZmluZGluZ3Ncbi0gTGlzdCBvZiBpc3N1ZXMgYnkgc2V2ZXJpdHkgKGNyaXRpY2FsLCB3YXJuaW5nLCBzdWdnZXN0aW9uKVxuLSBSZWNvbW1lbmRlZCBmaXhlcyBpbiBKU09OIGZvcm1hdCBmb3IgdGhlIHVwZGF0ZV90cmFuc2xhdGlvbnMgdG9vbGAsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgKTtcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerTranslateStringsPrompt(server: McpServer): void;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerTranslateStringsPrompt = registerTranslateStringsPrompt;
4
+ const zod_1 = require("zod");
5
+ function registerTranslateStringsPrompt(server) {
6
+ server.registerPrompt('translate-strings', {
7
+ description: 'Generate translations for iOS string catalog keys. Provides guidance on format placeholders and returns structured JSON for the update_translations tool.',
8
+ argsSchema: {
9
+ keys: zod_1.z.string().describe('Comma-separated list of keys to translate (e.g., "hello_world,goodbye,welcome_message")'),
10
+ sourceLanguage: zod_1.z.string().default('en').describe('Source language code (default: en)'),
11
+ targetLanguages: zod_1.z.string().describe('Comma-separated list of target language codes (e.g., "de,fr,ja,zh-Hans")'),
12
+ context: zod_1.z.string().optional().describe('Optional context about where these strings are used in the app'),
13
+ },
14
+ }, async ({ keys, sourceLanguage, targetLanguages, context }) => {
15
+ const keyList = keys.split(',').map(k => k.trim()).filter(Boolean);
16
+ const targetLangList = targetLanguages.split(',').map(l => l.trim()).filter(Boolean);
17
+ const contextSection = context
18
+ ? `\n## Context\nThese strings are used in: ${context}\n`
19
+ : '';
20
+ return {
21
+ messages: [
22
+ {
23
+ role: 'user',
24
+ content: {
25
+ type: 'text',
26
+ text: `# Translation Request for iOS String Catalog
27
+
28
+ ## Keys to Translate
29
+ ${keyList.map(k => `- "${k}"`).join('\n')}
30
+
31
+ ## Source Language
32
+ ${sourceLanguage}
33
+
34
+ ## Target Languages
35
+ ${targetLangList.map(l => `- ${l}`).join('\n')}
36
+ ${contextSection}
37
+ ## iOS Format Placeholders
38
+ When translating, preserve these iOS format placeholders exactly as they appear:
39
+ - \`%@\` - String placeholder (objects)
40
+ - \`%d\` or \`%lld\` - Integer placeholder
41
+ - \`%f\` - Floating point number placeholder
42
+ - \`%1$@\`, \`%2$@\` - Positional arguments (order CAN be changed to fit natural language grammar)
43
+
44
+ ## Example
45
+ If source is: "Hello %@, you have %lld items"
46
+ German could be: "Hallo %@, Sie haben %lld Artikel"
47
+ Japanese could be: "%@さん、%lld個のアイテムがあります"
48
+
49
+ ## Instructions
50
+ 1. Translate each key into all target languages
51
+ 2. Preserve all format placeholders
52
+ 3. Ensure translations sound natural in each language
53
+ 4. Consider cultural context and localization best practices
54
+
55
+ ## Required Output Format
56
+ Return the translations as JSON that can be used with the \`update_translations\` tool:
57
+
58
+ \`\`\`json
59
+ {
60
+ "data": [
61
+ {
62
+ "key": "key_name",
63
+ "translations": [
64
+ { "language": "en", "value": "English text" },
65
+ { "language": "de", "value": "German text" },
66
+ { "language": "fr", "value": "French text" }
67
+ ],
68
+ "comment": "Optional: describe where this string is used"
69
+ }
70
+ ]
71
+ }
72
+ \`\`\`
73
+
74
+ Please translate the keys now.`,
75
+ },
76
+ },
77
+ ],
78
+ };
79
+ });
80
+ }
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRlLXN0cmluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbWNwL3Byb21wdHMvdHJhbnNsYXRlLXN0cmluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSx3RUFpRkM7QUFuRkQsNkJBQXdCO0FBRXhCLFNBQWdCLDhCQUE4QixDQUFDLE1BQWlCO0lBQzVELE1BQU0sQ0FBQyxjQUFjLENBQ2pCLG1CQUFtQixFQUNuQjtRQUNJLFdBQVcsRUFBRSwySkFBMko7UUFDeEssVUFBVSxFQUFFO1lBQ1IsSUFBSSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMseUZBQXlGLENBQUM7WUFDcEgsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLG9DQUFvQyxDQUFDO1lBQ3ZGLGVBQWUsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLDBFQUEwRSxDQUFDO1lBQ2hILE9BQU8sRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGdFQUFnRSxDQUFDO1NBQzVHO0tBQ0osRUFDRCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLGVBQWUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3pELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25FLE1BQU0sY0FBYyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXJGLE1BQU0sY0FBYyxHQUFHLE9BQU87WUFDMUIsQ0FBQyxDQUFDLDRDQUE0QyxPQUFPLElBQUk7WUFDekQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUVULE9BQU87WUFDSCxRQUFRLEVBQUU7Z0JBQ047b0JBQ0ksSUFBSSxFQUFFLE1BQU07b0JBQ1osT0FBTyxFQUFFO3dCQUNMLElBQUksRUFBRSxNQUFNO3dCQUNaLElBQUksRUFBRTs7O0VBR2hDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzs7O0VBR3ZDLGNBQWM7OztFQUdkLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztFQUM1QyxjQUFjOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrQkFzQ2U7cUJBQ047aUJBQ0o7YUFDSjtTQUNKLENBQUM7SUFDTixDQUFDLENBQ0osQ0FBQztBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNY3BTZXJ2ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlclRyYW5zbGF0ZVN0cmluZ3NQcm9tcHQoc2VydmVyOiBNY3BTZXJ2ZXIpIHtcbiAgICBzZXJ2ZXIucmVnaXN0ZXJQcm9tcHQoXG4gICAgICAgICd0cmFuc2xhdGUtc3RyaW5ncycsXG4gICAgICAgIHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnR2VuZXJhdGUgdHJhbnNsYXRpb25zIGZvciBpT1Mgc3RyaW5nIGNhdGFsb2cga2V5cy4gUHJvdmlkZXMgZ3VpZGFuY2Ugb24gZm9ybWF0IHBsYWNlaG9sZGVycyBhbmQgcmV0dXJucyBzdHJ1Y3R1cmVkIEpTT04gZm9yIHRoZSB1cGRhdGVfdHJhbnNsYXRpb25zIHRvb2wuJyxcbiAgICAgICAgICAgIGFyZ3NTY2hlbWE6IHtcbiAgICAgICAgICAgICAgICBrZXlzOiB6LnN0cmluZygpLmRlc2NyaWJlKCdDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBrZXlzIHRvIHRyYW5zbGF0ZSAoZS5nLiwgXCJoZWxsb193b3JsZCxnb29kYnllLHdlbGNvbWVfbWVzc2FnZVwiKScpLFxuICAgICAgICAgICAgICAgIHNvdXJjZUxhbmd1YWdlOiB6LnN0cmluZygpLmRlZmF1bHQoJ2VuJykuZGVzY3JpYmUoJ1NvdXJjZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0OiBlbiknKSxcbiAgICAgICAgICAgICAgICB0YXJnZXRMYW5ndWFnZXM6IHouc3RyaW5nKCkuZGVzY3JpYmUoJ0NvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIHRhcmdldCBsYW5ndWFnZSBjb2RlcyAoZS5nLiwgXCJkZSxmcixqYSx6aC1IYW5zXCIpJyksXG4gICAgICAgICAgICAgICAgY29udGV4dDogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKCdPcHRpb25hbCBjb250ZXh0IGFib3V0IHdoZXJlIHRoZXNlIHN0cmluZ3MgYXJlIHVzZWQgaW4gdGhlIGFwcCcpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgYXN5bmMgKHsga2V5cywgc291cmNlTGFuZ3VhZ2UsIHRhcmdldExhbmd1YWdlcywgY29udGV4dCB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBrZXlMaXN0ID0ga2V5cy5zcGxpdCgnLCcpLm1hcChrID0+IGsudHJpbSgpKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXRMYW5nTGlzdCA9IHRhcmdldExhbmd1YWdlcy5zcGxpdCgnLCcpLm1hcChsID0+IGwudHJpbSgpKS5maWx0ZXIoQm9vbGVhbik7XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbnRleHRTZWN0aW9uID0gY29udGV4dFxuICAgICAgICAgICAgICAgID8gYFxcbiMjIENvbnRleHRcXG5UaGVzZSBzdHJpbmdzIGFyZSB1c2VkIGluOiAke2NvbnRleHR9XFxuYFxuICAgICAgICAgICAgICAgIDogJyc7XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9sZTogJ3VzZXInLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBgIyBUcmFuc2xhdGlvbiBSZXF1ZXN0IGZvciBpT1MgU3RyaW5nIENhdGFsb2dcblxuIyMgS2V5cyB0byBUcmFuc2xhdGVcbiR7a2V5TGlzdC5tYXAoayA9PiBgLSBcIiR7a31cImApLmpvaW4oJ1xcbicpfVxuXG4jIyBTb3VyY2UgTGFuZ3VhZ2VcbiR7c291cmNlTGFuZ3VhZ2V9XG5cbiMjIFRhcmdldCBMYW5ndWFnZXNcbiR7dGFyZ2V0TGFuZ0xpc3QubWFwKGwgPT4gYC0gJHtsfWApLmpvaW4oJ1xcbicpfVxuJHtjb250ZXh0U2VjdGlvbn1cbiMjIGlPUyBGb3JtYXQgUGxhY2Vob2xkZXJzXG5XaGVuIHRyYW5zbGF0aW5nLCBwcmVzZXJ2ZSB0aGVzZSBpT1MgZm9ybWF0IHBsYWNlaG9sZGVycyBleGFjdGx5IGFzIHRoZXkgYXBwZWFyOlxuLSBcXGAlQFxcYCAtIFN0cmluZyBwbGFjZWhvbGRlciAob2JqZWN0cylcbi0gXFxgJWRcXGAgb3IgXFxgJWxsZFxcYCAtIEludGVnZXIgcGxhY2Vob2xkZXJcbi0gXFxgJWZcXGAgLSBGbG9hdGluZyBwb2ludCBudW1iZXIgcGxhY2Vob2xkZXJcbi0gXFxgJTEkQFxcYCwgXFxgJTIkQFxcYCAtIFBvc2l0aW9uYWwgYXJndW1lbnRzIChvcmRlciBDQU4gYmUgY2hhbmdlZCB0byBmaXQgbmF0dXJhbCBsYW5ndWFnZSBncmFtbWFyKVxuXG4jIyBFeGFtcGxlXG5JZiBzb3VyY2UgaXM6IFwiSGVsbG8gJUAsIHlvdSBoYXZlICVsbGQgaXRlbXNcIlxuR2VybWFuIGNvdWxkIGJlOiBcIkhhbGxvICVALCBTaWUgaGFiZW4gJWxsZCBBcnRpa2VsXCJcbkphcGFuZXNlIGNvdWxkIGJlOiBcIiVA44GV44KT44CBJWxsZOWAi+OBruOCouOCpOODhuODoOOBjOOBguOCiuOBvuOBmVwiXG5cbiMjIEluc3RydWN0aW9uc1xuMS4gVHJhbnNsYXRlIGVhY2gga2V5IGludG8gYWxsIHRhcmdldCBsYW5ndWFnZXNcbjIuIFByZXNlcnZlIGFsbCBmb3JtYXQgcGxhY2Vob2xkZXJzXG4zLiBFbnN1cmUgdHJhbnNsYXRpb25zIHNvdW5kIG5hdHVyYWwgaW4gZWFjaCBsYW5ndWFnZVxuNC4gQ29uc2lkZXIgY3VsdHVyYWwgY29udGV4dCBhbmQgbG9jYWxpemF0aW9uIGJlc3QgcHJhY3RpY2VzXG5cbiMjIFJlcXVpcmVkIE91dHB1dCBGb3JtYXRcblJldHVybiB0aGUgdHJhbnNsYXRpb25zIGFzIEpTT04gdGhhdCBjYW4gYmUgdXNlZCB3aXRoIHRoZSBcXGB1cGRhdGVfdHJhbnNsYXRpb25zXFxgIHRvb2w6XG5cblxcYFxcYFxcYGpzb25cbntcbiAgICBcImRhdGFcIjogW1xuICAgICAgICB7XG4gICAgICAgICAgICBcImtleVwiOiBcImtleV9uYW1lXCIsXG4gICAgICAgICAgICBcInRyYW5zbGF0aW9uc1wiOiBbXG4gICAgICAgICAgICAgICAgeyBcImxhbmd1YWdlXCI6IFwiZW5cIiwgXCJ2YWx1ZVwiOiBcIkVuZ2xpc2ggdGV4dFwiIH0sXG4gICAgICAgICAgICAgICAgeyBcImxhbmd1YWdlXCI6IFwiZGVcIiwgXCJ2YWx1ZVwiOiBcIkdlcm1hbiB0ZXh0XCIgfSxcbiAgICAgICAgICAgICAgICB7IFwibGFuZ3VhZ2VcIjogXCJmclwiLCBcInZhbHVlXCI6IFwiRnJlbmNoIHRleHRcIiB9XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgXCJjb21tZW50XCI6IFwiT3B0aW9uYWw6IGRlc2NyaWJlIHdoZXJlIHRoaXMgc3RyaW5nIGlzIHVzZWRcIlxuICAgICAgICB9XG4gICAgXVxufVxuXFxgXFxgXFxgXG5cblBsZWFzZSB0cmFuc2xhdGUgdGhlIGtleXMgbm93LmAsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgKTtcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerGetCatalogStatistics(server: McpServer): void;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerGetCatalogStatistics = registerGetCatalogStatistics;
4
+ const zod_1 = require("zod");
5
+ const string_catalog_1 = require("../../string-catalog");
6
+ function registerGetCatalogStatistics(server) {
7
+ server.registerTool('get_catalog_statistics', {
8
+ description: 'Get statistics about a String Catalog including total keys, supported languages, and translation coverage percentage for each language.',
9
+ inputSchema: {
10
+ filePath: zod_1.z.string().describe('Absolute path to the .xcstrings file'),
11
+ },
12
+ }, async ({ filePath }) => {
13
+ const catalog = new string_catalog_1.StringCatalog(filePath);
14
+ const stats = catalog.getStatistics();
15
+ return {
16
+ content: [
17
+ {
18
+ type: 'text',
19
+ text: JSON.stringify(stats, null, 2),
20
+ },
21
+ ],
22
+ };
23
+ });
24
+ }
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LWNhdGFsb2ctc3RhdGlzdGljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tY3AvdG9vbHMvZ2V0LWNhdGFsb2ctc3RhdGlzdGljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUlBLG9FQXdCQztBQTNCRCw2QkFBd0I7QUFDeEIseURBQXFEO0FBRXJELFNBQWdCLDRCQUE0QixDQUFDLE1BQWlCO0lBQzFELE1BQU0sQ0FBQyxZQUFZLENBQ2Ysd0JBQXdCLEVBQ3hCO1FBQ0ksV0FBVyxFQUNQLHlJQUF5STtRQUM3SSxXQUFXLEVBQUU7WUFDVCxRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxzQ0FBc0MsQ0FBQztTQUN4RTtLQUNKLEVBQ0QsS0FBSyxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRTtRQUNuQixNQUFNLE9BQU8sR0FBRyxJQUFJLDhCQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDNUMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBRXRDLE9BQU87WUFDSCxPQUFPLEVBQUU7Z0JBQ0w7b0JBQ0ksSUFBSSxFQUFFLE1BQWU7b0JBQ3JCLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2lCQUN2QzthQUNKO1NBQ0osQ0FBQztJQUNOLENBQUMsQ0FDSixDQUFDO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1jcFNlcnZlciB9IGZyb20gJ0Btb2RlbGNvbnRleHRwcm90b2NvbC9zZGsvc2VydmVyL21jcC5qcyc7XG5pbXBvcnQgeyB6IH0gZnJvbSAnem9kJztcbmltcG9ydCB7IFN0cmluZ0NhdGFsb2cgfSBmcm9tICcuLi8uLi9zdHJpbmctY2F0YWxvZyc7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckdldENhdGFsb2dTdGF0aXN0aWNzKHNlcnZlcjogTWNwU2VydmVyKSB7XG4gICAgc2VydmVyLnJlZ2lzdGVyVG9vbChcbiAgICAgICAgJ2dldF9jYXRhbG9nX3N0YXRpc3RpY3MnLFxuICAgICAgICB7XG4gICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAnR2V0IHN0YXRpc3RpY3MgYWJvdXQgYSBTdHJpbmcgQ2F0YWxvZyBpbmNsdWRpbmcgdG90YWwga2V5cywgc3VwcG9ydGVkIGxhbmd1YWdlcywgYW5kIHRyYW5zbGF0aW9uIGNvdmVyYWdlIHBlcmNlbnRhZ2UgZm9yIGVhY2ggbGFuZ3VhZ2UuJyxcbiAgICAgICAgICAgIGlucHV0U2NoZW1hOiB7XG4gICAgICAgICAgICAgICAgZmlsZVBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoJ0Fic29sdXRlIHBhdGggdG8gdGhlIC54Y3N0cmluZ3MgZmlsZScpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgYXN5bmMgKHsgZmlsZVBhdGggfSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2F0YWxvZyA9IG5ldyBTdHJpbmdDYXRhbG9nKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRzID0gY2F0YWxvZy5nZXRTdGF0aXN0aWNzKCk7XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBKU09OLnN0cmluZ2lmeShzdGF0cywgbnVsbCwgMiksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICApO1xufVxuIl19
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerGetTranslationsForKey(server: McpServer): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerGetTranslationsForKey = registerGetTranslationsForKey;
4
+ const zod_1 = require("zod");
5
+ const string_catalog_1 = require("../../string-catalog");
6
+ function registerGetTranslationsForKey(server) {
7
+ server.registerTool('get_translations_for_key', {
8
+ description: 'Get all translations for a specific key in a String Catalog. Shows the translated text in each supported language along with the translation state.',
9
+ inputSchema: {
10
+ filePath: zod_1.z.string().describe('Absolute path to the .xcstrings file'),
11
+ key: zod_1.z.string().describe('The localization key to look up'),
12
+ },
13
+ }, async ({ filePath, key }) => {
14
+ const catalog = new string_catalog_1.StringCatalog(filePath);
15
+ const result = catalog.getTranslationsForKey(key);
16
+ if (!result) {
17
+ return {
18
+ content: [
19
+ {
20
+ type: 'text',
21
+ text: JSON.stringify({ error: `Key "${key}" not found in catalog` }, null, 2),
22
+ },
23
+ ],
24
+ };
25
+ }
26
+ return {
27
+ content: [
28
+ {
29
+ type: 'text',
30
+ text: JSON.stringify(result, null, 2),
31
+ },
32
+ ],
33
+ };
34
+ });
35
+ }
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXRyYW5zbGF0aW9ucy1mb3Ita2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21jcC90b29scy9nZXQtdHJhbnNsYXRpb25zLWZvci1rZXkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFJQSxzRUF3Q0M7QUEzQ0QsNkJBQXdCO0FBQ3hCLHlEQUFxRDtBQUVyRCxTQUFnQiw2QkFBNkIsQ0FBQyxNQUFpQjtJQUMzRCxNQUFNLENBQUMsWUFBWSxDQUNmLDBCQUEwQixFQUMxQjtRQUNJLFdBQVcsRUFDUCxxSkFBcUo7UUFDekosV0FBVyxFQUFFO1lBQ1QsUUFBUSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsc0NBQXNDLENBQUM7WUFDckUsR0FBRyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsaUNBQWlDLENBQUM7U0FDOUQ7S0FDSixFQUNELEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFO1FBQ3hCLE1BQU0sT0FBTyxHQUFHLElBQUksOEJBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFbEQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1YsT0FBTztnQkFDSCxPQUFPLEVBQUU7b0JBQ0w7d0JBQ0ksSUFBSSxFQUFFLE1BQWU7d0JBQ3JCLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUNoQixFQUFFLEtBQUssRUFBRSxRQUFRLEdBQUcsd0JBQXdCLEVBQUUsRUFDOUMsSUFBSSxFQUNKLENBQUMsQ0FDSjtxQkFDSjtpQkFDSjthQUNKLENBQUM7UUFDTixDQUFDO1FBRUQsT0FBTztZQUNILE9BQU8sRUFBRTtnQkFDTDtvQkFDSSxJQUFJLEVBQUUsTUFBZTtvQkFDckIsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7aUJBQ3hDO2FBQ0o7U0FDSixDQUFDO0lBQ04sQ0FBQyxDQUNKLENBQUM7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTWNwU2VydmVyIH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvbWNwLmpzJztcbmltcG9ydCB7IHogfSBmcm9tICd6b2QnO1xuaW1wb3J0IHsgU3RyaW5nQ2F0YWxvZyB9IGZyb20gJy4uLy4uL3N0cmluZy1jYXRhbG9nJztcblxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyR2V0VHJhbnNsYXRpb25zRm9yS2V5KHNlcnZlcjogTWNwU2VydmVyKSB7XG4gICAgc2VydmVyLnJlZ2lzdGVyVG9vbChcbiAgICAgICAgJ2dldF90cmFuc2xhdGlvbnNfZm9yX2tleScsXG4gICAgICAgIHtcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICdHZXQgYWxsIHRyYW5zbGF0aW9ucyBmb3IgYSBzcGVjaWZpYyBrZXkgaW4gYSBTdHJpbmcgQ2F0YWxvZy4gU2hvd3MgdGhlIHRyYW5zbGF0ZWQgdGV4dCBpbiBlYWNoIHN1cHBvcnRlZCBsYW5ndWFnZSBhbG9uZyB3aXRoIHRoZSB0cmFuc2xhdGlvbiBzdGF0ZS4nLFxuICAgICAgICAgICAgaW5wdXRTY2hlbWE6IHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aDogei5zdHJpbmcoKS5kZXNjcmliZSgnQWJzb2x1dGUgcGF0aCB0byB0aGUgLnhjc3RyaW5ncyBmaWxlJyksXG4gICAgICAgICAgICAgICAga2V5OiB6LnN0cmluZygpLmRlc2NyaWJlKCdUaGUgbG9jYWxpemF0aW9uIGtleSB0byBsb29rIHVwJyksXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBhc3luYyAoeyBmaWxlUGF0aCwga2V5IH0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNhdGFsb2cgPSBuZXcgU3RyaW5nQ2F0YWxvZyhmaWxlUGF0aCk7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBjYXRhbG9nLmdldFRyYW5zbGF0aW9uc0ZvcktleShrZXkpO1xuXG4gICAgICAgICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgZXJyb3I6IGBLZXkgXCIke2tleX1cIiBub3QgZm91bmQgaW4gY2F0YWxvZ2AgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAndGV4dCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBKU09OLnN0cmluZ2lmeShyZXN1bHQsIG51bGwsIDIpLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgKTtcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerAllTools(server: McpServer): void;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerAllTools = registerAllTools;
4
+ const list_supported_languages_1 = require("./list-supported-languages");
5
+ const get_translations_for_key_1 = require("./get-translations-for-key");
6
+ const search_keys_1 = require("./search-keys");
7
+ const update_translations_1 = require("./update-translations");
8
+ const get_catalog_statistics_1 = require("./get-catalog-statistics");
9
+ const list_all_keys_1 = require("./list-all-keys");
10
+ function registerAllTools(server) {
11
+ (0, list_supported_languages_1.registerListSupportedLanguages)(server);
12
+ (0, get_translations_for_key_1.registerGetTranslationsForKey)(server);
13
+ (0, search_keys_1.registerSearchKeys)(server);
14
+ (0, update_translations_1.registerUpdateTranslations)(server);
15
+ (0, get_catalog_statistics_1.registerGetCatalogStatistics)(server);
16
+ (0, list_all_keys_1.registerListAllKeys)(server);
17
+ }
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbWNwL3Rvb2xzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBUUEsNENBT0M7QUFkRCx5RUFBNEU7QUFDNUUseUVBQTJFO0FBQzNFLCtDQUFtRDtBQUNuRCwrREFBbUU7QUFDbkUscUVBQXdFO0FBQ3hFLG1EQUFzRDtBQUV0RCxTQUFnQixnQkFBZ0IsQ0FBQyxNQUFpQjtJQUM5QyxJQUFBLHlEQUE4QixFQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZDLElBQUEsd0RBQTZCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsSUFBQSxnQ0FBa0IsRUFBQyxNQUFNLENBQUMsQ0FBQztJQUMzQixJQUFBLGdEQUEwQixFQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ25DLElBQUEscURBQTRCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFDckMsSUFBQSxtQ0FBbUIsRUFBQyxNQUFNLENBQUMsQ0FBQztBQUNoQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTWNwU2VydmVyIH0gZnJvbSAnQG1vZGVsY29udGV4dHByb3RvY29sL3Nkay9zZXJ2ZXIvbWNwLmpzJztcbmltcG9ydCB7IHJlZ2lzdGVyTGlzdFN1cHBvcnRlZExhbmd1YWdlcyB9IGZyb20gJy4vbGlzdC1zdXBwb3J0ZWQtbGFuZ3VhZ2VzJztcbmltcG9ydCB7IHJlZ2lzdGVyR2V0VHJhbnNsYXRpb25zRm9yS2V5IH0gZnJvbSAnLi9nZXQtdHJhbnNsYXRpb25zLWZvci1rZXknO1xuaW1wb3J0IHsgcmVnaXN0ZXJTZWFyY2hLZXlzIH0gZnJvbSAnLi9zZWFyY2gta2V5cyc7XG5pbXBvcnQgeyByZWdpc3RlclVwZGF0ZVRyYW5zbGF0aW9ucyB9IGZyb20gJy4vdXBkYXRlLXRyYW5zbGF0aW9ucyc7XG5pbXBvcnQgeyByZWdpc3RlckdldENhdGFsb2dTdGF0aXN0aWNzIH0gZnJvbSAnLi9nZXQtY2F0YWxvZy1zdGF0aXN0aWNzJztcbmltcG9ydCB7IHJlZ2lzdGVyTGlzdEFsbEtleXMgfSBmcm9tICcuL2xpc3QtYWxsLWtleXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJBbGxUb29scyhzZXJ2ZXI6IE1jcFNlcnZlcikge1xuICAgIHJlZ2lzdGVyTGlzdFN1cHBvcnRlZExhbmd1YWdlcyhzZXJ2ZXIpO1xuICAgIHJlZ2lzdGVyR2V0VHJhbnNsYXRpb25zRm9yS2V5KHNlcnZlcik7XG4gICAgcmVnaXN0ZXJTZWFyY2hLZXlzKHNlcnZlcik7XG4gICAgcmVnaXN0ZXJVcGRhdGVUcmFuc2xhdGlvbnMoc2VydmVyKTtcbiAgICByZWdpc3RlckdldENhdGFsb2dTdGF0aXN0aWNzKHNlcnZlcik7XG4gICAgcmVnaXN0ZXJMaXN0QWxsS2V5cyhzZXJ2ZXIpO1xufVxuIl19
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerListAllKeys(server: McpServer): void;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerListAllKeys = registerListAllKeys;
4
+ const zod_1 = require("zod");
5
+ const string_catalog_1 = require("../../string-catalog");
6
+ function registerListAllKeys(server) {
7
+ server.registerTool('list_all_keys', {
8
+ description: 'List all localization keys in a String Catalog. Returns keys sorted alphabetically.',
9
+ inputSchema: {
10
+ filePath: zod_1.z.string().describe('Absolute path to the .xcstrings file'),
11
+ limit: zod_1.z
12
+ .number()
13
+ .optional()
14
+ .default(100)
15
+ .describe('Maximum number of keys to return (default: 100)'),
16
+ offset: zod_1.z
17
+ .number()
18
+ .optional()
19
+ .default(0)
20
+ .describe('Number of keys to skip (for pagination, default: 0)'),
21
+ },
22
+ }, async ({ filePath, limit: limitArg, offset: offsetArg }) => {
23
+ const limit = limitArg ?? 100;
24
+ const offset = offsetArg ?? 0;
25
+ const catalog = new string_catalog_1.StringCatalog(filePath);
26
+ const allKeys = catalog.getAllKeys();
27
+ const paginatedKeys = allKeys.slice(offset, offset + limit);
28
+ return {
29
+ content: [
30
+ {
31
+ type: 'text',
32
+ text: JSON.stringify({
33
+ keys: paginatedKeys,
34
+ total: allKeys.length,
35
+ offset,
36
+ limit,
37
+ hasMore: offset + limit < allKeys.length,
38
+ }, null, 2),
39
+ },
40
+ ],
41
+ };
42
+ });
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC1hbGwta2V5cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tY3AvdG9vbHMvbGlzdC1hbGwta2V5cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUlBLGtEQStDQztBQWxERCw2QkFBd0I7QUFDeEIseURBQXFEO0FBRXJELFNBQWdCLG1CQUFtQixDQUFDLE1BQWlCO0lBQ2pELE1BQU0sQ0FBQyxZQUFZLENBQ2YsZUFBZSxFQUNmO1FBQ0ksV0FBVyxFQUNQLHFGQUFxRjtRQUN6RixXQUFXLEVBQUU7WUFDVCxRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxzQ0FBc0MsQ0FBQztZQUNyRSxLQUFLLEVBQUUsT0FBQztpQkFDSCxNQUFNLEVBQUU7aUJBQ1IsUUFBUSxFQUFFO2lCQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUM7aUJBQ1osUUFBUSxDQUFDLGlEQUFpRCxDQUFDO1lBQ2hFLE1BQU0sRUFBRSxPQUFDO2lCQUNKLE1BQU0sRUFBRTtpQkFDUixRQUFRLEVBQUU7aUJBQ1YsT0FBTyxDQUFDLENBQUMsQ0FBQztpQkFDVixRQUFRLENBQUMscURBQXFELENBQUM7U0FDdkU7S0FDSixFQUNELEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO1FBQ3ZELE1BQU0sS0FBSyxHQUFHLFFBQVEsSUFBSSxHQUFHLENBQUM7UUFDOUIsTUFBTSxNQUFNLEdBQUcsU0FBUyxJQUFJLENBQUMsQ0FBQztRQUM5QixNQUFNLE9BQU8sR0FBRyxJQUFJLDhCQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDNUMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQztRQUU1RCxPQUFPO1lBQ0gsT0FBTyxFQUFFO2dCQUNMO29CQUNJLElBQUksRUFBRSxNQUFlO29CQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FDaEI7d0JBQ0ksSUFBSSxFQUFFLGFBQWE7d0JBQ25CLEtBQUssRUFBRSxPQUFPLENBQUMsTUFBTTt3QkFDckIsTUFBTTt3QkFDTixLQUFLO3dCQUNMLE9BQU8sRUFBRSxNQUFNLEdBQUcsS0FBSyxHQUFHLE9BQU8sQ0FBQyxNQUFNO3FCQUMzQyxFQUNELElBQUksRUFDSixDQUFDLENBQ0o7aUJBQ0o7YUFDSjtTQUNKLENBQUM7SUFDTixDQUFDLENBQ0osQ0FBQztBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNY3BTZXJ2ZXIgfSBmcm9tICdAbW9kZWxjb250ZXh0cHJvdG9jb2wvc2RrL3NlcnZlci9tY3AuanMnO1xuaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5pbXBvcnQgeyBTdHJpbmdDYXRhbG9nIH0gZnJvbSAnLi4vLi4vc3RyaW5nLWNhdGFsb2cnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJMaXN0QWxsS2V5cyhzZXJ2ZXI6IE1jcFNlcnZlcikge1xuICAgIHNlcnZlci5yZWdpc3RlclRvb2woXG4gICAgICAgICdsaXN0X2FsbF9rZXlzJyxcbiAgICAgICAge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgJ0xpc3QgYWxsIGxvY2FsaXphdGlvbiBrZXlzIGluIGEgU3RyaW5nIENhdGFsb2cuIFJldHVybnMga2V5cyBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkuJyxcbiAgICAgICAgICAgIGlucHV0U2NoZW1hOiB7XG4gICAgICAgICAgICAgICAgZmlsZVBhdGg6IHouc3RyaW5nKCkuZGVzY3JpYmUoJ0Fic29sdXRlIHBhdGggdG8gdGhlIC54Y3N0cmluZ3MgZmlsZScpLFxuICAgICAgICAgICAgICAgIGxpbWl0OiB6XG4gICAgICAgICAgICAgICAgICAgIC5udW1iZXIoKVxuICAgICAgICAgICAgICAgICAgICAub3B0aW9uYWwoKVxuICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCgxMDApXG4gICAgICAgICAgICAgICAgICAgIC5kZXNjcmliZSgnTWF4aW11bSBudW1iZXIgb2Yga2V5cyB0byByZXR1cm4gKGRlZmF1bHQ6IDEwMCknKSxcbiAgICAgICAgICAgICAgICBvZmZzZXQ6IHpcbiAgICAgICAgICAgICAgICAgICAgLm51bWJlcigpXG4gICAgICAgICAgICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0KDApXG4gICAgICAgICAgICAgICAgICAgIC5kZXNjcmliZSgnTnVtYmVyIG9mIGtleXMgdG8gc2tpcCAoZm9yIHBhZ2luYXRpb24sIGRlZmF1bHQ6IDApJyksXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBhc3luYyAoeyBmaWxlUGF0aCwgbGltaXQ6IGxpbWl0QXJnLCBvZmZzZXQ6IG9mZnNldEFyZyB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBsaW1pdCA9IGxpbWl0QXJnID8/IDEwMDtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IG9mZnNldEFyZyA/PyAwO1xuICAgICAgICAgICAgY29uc3QgY2F0YWxvZyA9IG5ldyBTdHJpbmdDYXRhbG9nKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIGNvbnN0IGFsbEtleXMgPSBjYXRhbG9nLmdldEFsbEtleXMoKTtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2luYXRlZEtleXMgPSBhbGxLZXlzLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgbGltaXQpO1xuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzOiBwYWdpbmF0ZWRLZXlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbDogYWxsS2V5cy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc01vcmU6IG9mZnNldCArIGxpbWl0IDwgYWxsS2V5cy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDJcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICApO1xufVxuIl19
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerListSupportedLanguages(server: McpServer): void;