Install
$ agentstack add mcp-lexrus-xcstrings-mcp Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Pipes remote content directly into a shell (remote code execution).
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
xcstrings-mcp
[](https://www.rust-lang.org) [](https://opensource.org/licenses/MIT) [](https://github.com/lexrus/xcstrings_mcp/stargazers)
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.
Functions
This MCP server provides the following functions for managing Xcode Localizable.xcstrings files:
Core Translation Functions
list_translations(path, query?, limit?)- List translation entries with optional filteringpath: Path to the.xcstringsfilequery: Optional case-insensitive search query to filter resultslimit: Maximum number of items to return (defaults to 100, set to 0 for no limit)- Returns: JSON array of translation summaries including key metadata
list_keys(path, query?, limit?)- List translation keys without loading full recordspath: Path to the.xcstringsfilequery: Optional case-insensitive search query to filter resultslimit: Maximum number of items to return (defaults to 100, set to 0 for no limit)- Returns: JSON payload containing
keys,total,returned, andtruncatedflags
get_translation(path, key, language)- Fetch a single translation by key and languagepath: Path to the.xcstringsfilekey: Translation key identifierlanguage: Language code (e.g., "en", "fr", "es")- Returns: Complete translation value with variations and substitutions
upsert_translation(path, key, language, value?, state?, variations?, substitutions?)- Create or update a translationpath: Path to the.xcstringsfilekey: 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 metadata- Returns: Updated translation value
delete_translation(path, key, language)- Delete a translation for a specific languagepath: Path to the.xcstringsfilekey: Translation key identifierlanguage: Language code to remove- Returns: Success confirmation
Key Management Functions
delete_key(path, key)- Delete an entire translation key across all languagespath: Path to the.xcstringsfilekey: Translation key identifier to remove completely- Returns: Success confirmation
set_comment(path, key, comment?)- Set or clear the developer comment for a translation keypath: Path to the.xcstringsfilekey: Translation key identifiercomment: Developer comment text (optional, omit to clear)- Returns: Success confirmation
set_translation_state(path, key, language, state?)- Set or clear the translation state for a specific language entrypath: Path to the.xcstringsfilekey: Translation key identifierlanguage: Language code for the localization to updatestate: Translation state value (optional, omit to clear; defaults back to"translated"when a non-empty value exists)- Returns: Updated translation value
set_extraction_state(path, key, extractionState?)- Set or clear the extraction state for a string keypath: Path to the.xcstringsfilekey: Translation key identifierextractionState: Extraction state value (optional, omit to clear)- Returns: Success confirmation
Language Management Functions
list_languages(path)- List all languages present in the xcstrings filepath: Path to the.xcstringsfile- Returns: JSON array of language codes found in the catalog
add_language(path, language)- Add a new language to the xcstrings filepath: Path to the.xcstringsfilelanguage: Language code to add (e.g., "fr", "es", "de")- Returns: Success confirmation
- Note: Creates placeholder entries in existing keys with
needs-translationstate so the language is immediately discoverable
remove_language(path, language)- Remove a language from the xcstrings filepath: Path to the.xcstringsfilelanguage: Language code to remove- Returns: Success confirmation
- Note: Cannot remove the source language (typically "en")
update_language(path, oldLanguage, newLanguage)- Rename/update a language code in the xcstrings filepath: Path to the.xcstringsfileoldLanguage: Current language code to renamenewLanguage: New language code- Returns: Success confirmation
- Note: Cannot rename the source language; preserves all existing translations
list_untranslated(path)- List untranslated keys per languagepath: Path to the.xcstringsfile- Returns: JSON map of language codes to arrays of untranslated keys
- Note: A translation is considered untranslated if the value is empty/None or no localization exists
Additional Features
- Async-safe store that loads and persists
Localizable.xcstringsJSON on every change - Optional embedded Axum web UI (enabled via environment variables) for browsing translations, filtering by query, editing values, plural/device variations, and managing comments
- Translation progress tracking with percentage display in the language dropdown (excludes keys marked as should_translate=false)
- Automatic discovery of
.xcstringsfiles when no default path is provided, with a selector in the web UI for runtime catalog switching (when web UI is enabled) - Device-specific variations support (iPhone, iPad, Mac, Apple Watch, etc.) with mutual exclusivity logic between plural and device variations
- Inline editing for extraction state, translation state, and substitution placeholders (including
argNum,formatSpecifier, and nested plural cases) - JSON-first responses from all tools to make automation and debugging easier
- Schema-backed validation using the vendored [
xcstrings.schema.json](schema/xcstrings.schema.json) to keep generated catalogs consistent with Apple's format
Prerequisites
- Rust 1.75 or newer: Install using Homebrew (recommended on macOS):
``bash brew install rust ``
Alternatively, install using the official installer:
``bash 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.
Running the server
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.xcstringsfiles and MCP tool calls must supply apathargument.
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://:/ (defaults to http://127.0.0.1:8787/).
MCP usage
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 containingvalue,state,argNum,formatSpecifier, and nestedvariations.
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.
Integrating with AI tools
Modern MCP-aware AI clients let you register external servers through a JSON manifest.
Basic MCP server (web UI disabled)
{
"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.
With web UI enabled
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"
}
}
}
}
With default xcstrings path
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.
Claude Code
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.
Codex
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" }
Development
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.
Project layout
src/store.rs– async storage layer for.xcstringsfiles.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.
Support
If you find this project useful, consider supporting me by buying me a coffee.
License
Distributed under the [MIT License](LICENSE).
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: lexrus
- Source: lexrus/xcstrings_mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.