Xcstrings
STDIO管理Xcode本地化文件的MCP服务器
管理Xcode本地化文件的MCP服务器
A Rust implementation of a Model Context Protocol (MCP) server designed for working with Xcode .xcstrings files. It exposes the translation catalog as MCP tools and optionally serves a lightweight web editor (when enabled via environment variables) so teams can browse, search, and edit strings from a browser.
Note: This project was created with AI assistance using tools like Codex and Claude Code. While we strive for quality, there may be issues or areas for improvement. We welcome bug reports, feature requests, and contributions via GitHub Issues.

This MCP server provides the following functions for managing Xcode Localizable.xcstrings files:
list_translations(path, query?, limit?) - List translation entries with optional filtering
path: Path to the .xcstrings filequery: Optional case-insensitive search query to filter resultslimit: Maximum number of items to return (defaults to 100, set to 0 for no limit)list_keys(path, query?, limit?) - List translation keys without loading full records
path: Path to the .xcstrings filequery: Optional case-insensitive search query to filter resultslimit: Maximum number of items to return (defaults to 100, set to 0 for no limit)keys, total, returned, and truncated flagsget_translation(path, key, language) - Fetch a single translation by key and language
path: Path to the .xcstrings filekey: Translation key identifierlanguage: Language code (e.g., "en", "fr", "es")upsert_translation(path, key, language, value?, state?, variations?, substitutions?) - Create or update a translation
path: Path to the .xcstrings filekey: Translation key identifierlanguage: Language codevalue: Translation text (optional)state: Translation state (optional)variations: Map of variation selectors to their cases (e.g., plural forms)substitutions: Map of substitution identifiers with metadatadelete_translation(path, key, language) - Delete a translation for a specific language
path: Path to the .xcstrings filekey: Translation key identifierlanguage: Language code to removedelete_key(path, key) - Delete an entire translation key across all languages
path: Path to the .xcstrings filekey: Translation key identifier to remove completelyset_comment(path, key, comment?) - Set or clear the developer comment for a translation key
path: Path to the .xcstrings filekey: Translation key identifiercomment: Developer comment text (optional, omit to clear)set_extraction_state(path, key, extractionState?) - Set or clear the extraction state for a string key
path: Path to the .xcstrings filekey: Translation key identifierextractionState: Extraction state value (optional, omit to clear)list_languages(path) - List all languages present in the xcstrings file
path: Path to the .xcstrings fileadd_language(path, language) - Add a new language to the xcstrings file
path: Path to the .xcstrings filelanguage: Language code to add (e.g., "fr", "es", "de")needs-translation state so the language is immediately discoverableremove_language(path, language) - Remove a language from the xcstrings file
path: Path to the .xcstrings filelanguage: Language code to removeupdate_language(path, oldLanguage, newLanguage) - Rename/update a language code in the xcstrings file
path: Path to the .xcstrings fileoldLanguage: Current language code to renamenewLanguage: New language codelist_untranslated(path) - List untranslated keys per language
path: Path to the .xcstrings fileLocalizable.xcstrings JSON on every change.xcstrings files when no default path is provided, with a selector in the web UI for runtime catalog switching (when web UI is enabled)argNum, formatSpecifier, and nested plural cases)xcstrings.schema.json to keep generated catalogs consistent with Apple's formatRust 1.75 or newer: Install using Homebrew (recommended on macOS):
brew install rust
Alternatively, install using the official installer:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
After installation, restart your terminal or run source ~/.cargo/env to update your PATH.
cargo run -- [path-to/Localizable.xcstrings] # This will build and run the MCP server
cargo install --path . # This will install `xcstrings-mcp` into `~/.cargo/bin/`
path-to/Localizable.xcstrings: Optional. When omitted, the server scans the workspace for .xcstrings files and MCP tool calls must supply a path argument.You can also configure the server via environment variables:
| Variable | Description | Default | 
|---|---|---|
STRINGS_PATH | Path to the .xcstrings file | unset (dynamic mode) | 
WEB_HOST | Host/interface for the web UI (enables web server) | unset (disabled) | 
WEB_PORT | Port for the web UI (enables web server) | 8787 | 
Note: The web server is disabled by default. To enable it, you must set either WEB_HOST or WEB_PORT environment variables. When enabled, the web interface becomes available at http://<host>:<port>/ (defaults to http://127.0.0.1:8787/).
Run the binary with stdio transport (default) and wire it into an MCP-enabled client. The following tools are exposed (each expects a path argument pointing to the target .xcstrings file):
list_translations(path, query?, limit?)list_keys(path, query?, limit?)get_translation(path, key, language)upsert_translation(path, key, language, value?, state?, variations?)delete_translation(path, key, language)delete_key(path, key)set_comment(path, key, comment?)set_extraction_state(path, key, extractionState?)list_languages(path)add_language(path, language)remove_language(path, language)update_language(path, oldLanguage, newLanguage)list_untranslated(path)Each tool returns JSON payloads encoded into text content for easier consumption.
list_translations now returns compact summaries (key, comment, extractionState, languages, and hasVariations) so responses stay lightweight even for large catalogs. Use limit (defaults to 100, set to 0 for no limit) to page through results and pair it with get_translation for per-language details without flooding the client context.
When calling upsert_translation, you can send:
variations — map selectors (e.g. "plural") to their cases; each case is another translation update.substitutions — map substitution identifiers ("arg1", "device", etc.) to updates containing value, state, argNum, formatSpecifier, and nested variations.
Missing selectors or substitutions are left untouched so you can patch individual pieces without resending the entire localization payload.If the server starts without a default path (no CLI argument and no STRINGS_PATH), it scans the working tree for .xcstrings files and surfaces them through the web UI selector. When none are found, the UI shows a placeholder until a file appears. MCP tools still require an explicit path in this mode. Providing a default path pins the selector to that file and lets tool calls omit path.
Modern MCP-aware AI clients let you register external servers through a JSON manifest.
{ "mcpServers": { "xcstrings": { "command": "/Users/you/.cargo/bin/xcstrings-mcp", "transport": "stdio" } } }
Restart the client after saving so it loads the new MCP server definition. The path parameter is required in all tool calls when running in dynamic-path mode.
To enable the web UI, set the WEB_HOST or WEB_PORT environment variables:
{ "mcpServers": { "xcstrings": { "command": "/Users/you/.cargo/bin/xcstrings-mcp", "transport": "stdio", "env": { "WEB_PORT": "8787" } } } }
You can customize both host and port:
{ "mcpServers": { "xcstrings": { "command": "/Users/you/.cargo/bin/xcstrings-mcp", "transport": "stdio", "env": { "WEB_HOST": "127.0.0.1", "WEB_PORT": "8787" } } } }
To run with a default localization file (letting tools omit path), specify the path via arguments or environment variables:
{ "mcpServers": { "xcstrings": { "command": "/Users/you/.cargo/bin/xcstrings-mcp", "args": ["--", "/Users/you/Projects/Localizable.xcstrings"], "transport": "stdio", "env": { "WEB_PORT": "8787" } } } }
You can supply the path via STRINGS_PATH instead of CLI arguments if you prefer. When a default path is configured, MCP tool calls may omit the path parameter.
Basic setup (web UI disabled):
claude mcp add-json xcstrings '{"command":"/Users/you/.cargo/bin/xcstrings-mcp","transport":"stdio"}'
With web UI enabled:
claude mcp add-json xcstrings '{"command":"/Users/you/.cargo/bin/xcstrings-mcp","transport":"stdio","env":{"WEB_PORT":"8787"}}'
You can also add the JSON manually to ~/.claude.json.
Basic setup (web UI disabled):
[mcp_servers.xcstrings_mcp] command = "/Users/you/.cargo/bin/xcstrings-mcp" args = ["--"]
With web UI enabled:
[mcp_servers.xcstrings_mcp] command = "/Users/you/.cargo/bin/xcstrings-mcp" args = ["--"] env = { WEB_PORT = "8787" }
Install dependencies and run the full test suite:
cargo test
cargo fmt --all is recommended before submitting changes.
The repository vendors the official schema as a git submodule under schema/. Use git submodule update --init --remote to pull the latest definition when updating validation logic.
src/store.rs – async storage layer for .xcstrings files.src/mcp_server.rs – MCP tool definitions exposing translation functionality.src/web/mod.rs – Axum HTTP routes and HTML/JS single page view.src/main.rs – entrypoint that launches both web and MCP services.If you find this project useful, consider supporting me by buying me a coffee.
Distributed under the MIT License.