# xcstrings-mcp
[](https://github.com/Murzav/xcstrings-mcp/actions/workflows/ci.yml)
[](https://crates.io/crates/xcstrings-mcp)
[](LICENSE-MIT)
MCP server for iOS/macOS `.xcstrings` localization file management.
## The Problem
Xcode String Catalogs (`.xcstrings`) are large JSON files that waste LLM context windows when loaded whole. Manual editing risks corrupting Xcode's specific formatting, there's no validation for format specifiers or plural rules, and plural-aware translation requires understanding CLDR categories across 40+ locales.
## Quick Start
### Install
```sh
brew install Murzav/tap/xcstrings-mcp
# or
cargo install xcstrings-mcp
# or
cargo binstall xcstrings-mcp
```
### Configure
<details>
<summary><strong>Claude Code</strong></summary>
```sh
claude mcp add xcstrings-mcp -- xcstrings-mcp
```
</details>
<details>
<summary><strong>Cursor</strong></summary>
Add to `.cursor/mcp.json`:
```json
{
"mcpServers": {
"xcstrings-mcp": {
"command": "xcstrings-mcp",
"args": []
}
}
}
```
</details>
<details>
<summary><strong>Windsurf</strong></summary>
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"xcstrings-mcp": {
"command": "xcstrings-mcp",
"args": []
}
}
}
```
</details>
<details>
<summary><strong>VS Code + Copilot</strong></summary>
Add to `.vscode/mcp.json`:
```json
{
"servers": {
"xcstrings-mcp": {
"type": "stdio",
"command": "xcstrings-mcp",
"args": []
}
}
}
```
</details>
<details>
<summary><strong>Zed</strong></summary>
Add to Zed settings (`settings.json`):
```json
{
"context_servers": {
"xcstrings-mcp": {
"command": {
"path": "xcstrings-mcp",
"args": []
}
}
}
}
```
</details>
<details>
<summary><strong>OpenAI Codex</strong></summary>
Add to your project's `codex.json` or configure via Codex CLI:
```json
{
"mcpServers": {
"xcstrings-mcp": {
"command": "xcstrings-mcp",
"args": []
}
}
}
```
</details>
<details>
<summary><strong>Any MCP client (generic)</strong></summary>
xcstrings-mcp communicates via stdio using JSON-RPC. Point your MCP client to the binary:
```
command: xcstrings-mcp
transport: stdio
```
</details>
## Usage
Typical workflow:
1. **Parse** the `.xcstrings` file to cache it
2. **Get untranslated** strings in batches that fit the context window
3. **Submit translations** with automatic validation and atomic writes
```
parse_xcstrings → get_untranslated → submit_translations
```
Multi-file projects: parse each file — the server caches all of them and tracks the active one. Use `list_files` to see cached files.
## Tools
| `parse_xcstrings` | Parse and cache `.xcstrings` file |
| `get_untranslated` | Get untranslated strings with batching |
| `submit_translations` | Validate and write translations atomically |
| `get_coverage` | Per-locale coverage statistics |
| `get_stale` | Find stale/removed keys |
| `validate_translations` | File-wide validation report |
| `list_locales` | List locales with stats |
| `add_locale` | Add new locale with empty translations |
| `remove_locale` | Remove a locale from all entries |
| `get_plurals` | Extract keys needing plural translation |
| `get_context` | Find related keys by shared prefix |
| `list_files` | List all cached files with active status |
| `get_diff` | Compare cached vs on-disk file (added/removed/modified keys) |
| `get_glossary` | Get translation glossary entries for a locale pair |
| `update_glossary` | Add or update glossary terms |
| `export_xliff` | Export to XLIFF 1.2 for external translation tools |
| `import_xliff` | Import translations from XLIFF 1.2 file |
| `search_keys` | Search keys by substring (matches key names and source text) |
| `create_xcstrings` | Create a new empty .xcstrings file |
| `add_keys` | Add new localization keys with source text |
| `discover_files` | Recursively find .xcstrings files in a directory |
| `update_comments` | Update developer comments on localization keys |
### Prompts
| `translate_batch` | Step-by-step instructions for batch translation |
| `review_translations` | Instructions for quality review of translations |
| `full_translate` | Complete workflow for translating an entire file |
| `localization_audit` | Full audit: coverage, validation, stale keys, glossary |
| `fix_validation_errors` | Guided workflow to fix all validation issues |
| `add_language` | Add a new locale and translate all strings |
| `extract_strings` | Extract hardcoded strings from Swift code into .xcstrings |
### Getting Started from Scratch
To create a new localization file and begin translating:
```
create_xcstrings → add_keys → add_locale → get_untranslated → submit_translations
```
Or use the `extract_strings` prompt to automatically extract hardcoded strings from your Swift source code.
### CLI Options
```sh
xcstrings-mcp --glossary-path ./my-glossary.json
```
| `--glossary-path` | `glossary.json` | Path to glossary file for consistent terminology |
## Performance
Binary size: **3.6 MB** (stripped + LTO). Zero CPU at idle.
| 968KB (638 keys × 10 loc) | 0.2ms | 0.02ms | 0.04ms | 7.6 MB |
| 4.1MB (2K keys × 10 loc) | 24ms | 5ms | 7ms | 40 MB |
| 10.3MB (5K keys × 10 loc) | 60ms | 11ms | 23ms | 49 MB |
| 56.7MB (10K keys × 30 loc) | 333ms | 62ms | 221ms | 287 MB |
Scaling is linear — no degradation cliffs. Typical iOS projects (2-5K keys) parse in under 60ms.
## Architecture
```
┌─────────────┐ stdio/JSON-RPC ┌──────────────────┐ File I/O ┌───────────────────────┐
│ Claude Code │◄───────────────────►│ xcstrings-mcp │◄──────────────►│ Localizable.xcstrings │
│ (translates)│ │ (Rust MCP server)│ │ (JSON on disk) │
└─────────────┘ └──────────────────┘ └───────────────────────┘
```
Layered architecture: `server` -> `tools` -> `service` -> `model`, with `io` injected via the `FileStore` trait.
- **server** -- MCP tool routing and handler dispatch
- **tools** -- individual tool implementations
- **service** -- pure logic (parser, extractor, merger, validator, formatter); no I/O
- **model** -- serde types for `.xcstrings` format, CLDR plural rules, format specifiers
- **io** -- `FileStore` trait + real filesystem implementation with atomic writes
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.