Skip to main content
Glama
shreyas411

Translation Sync MCP Server

by shreyas411

Translation Sync MCP Server

A general-purpose MCP server that keeps per-language JSON locale files in sync with an English source file, using the free MyMemory translation API (no API key required). Works with any project that stores locales as src/assets/i18n/<lang>/<lang>.json (or a custom path you configure).

Features

  • 🌍 Translates to any of MyMemory's ~111 supported languages, not just a fixed list

  • πŸ†“ No API key, no signup β€” free MyMemory API

  • πŸ”„ Two ways to detect changes: a local cache diff, or a JSON-based git diff (immune to the "comma shift" false positives of text-based git diff parsing)

  • 🧩 Validates that {{placeholder}} / %s / %1$s tokens survive translation β€” a mismatch is never written to disk

  • πŸ€– Agent fallback β€” if MyMemory can't produce a usable translation (API error, quota, bad language code, or a token mismatch), the server does not write English text or a broken translation. It reports the failure and asks the calling agent to translate it directly; you feed the result back via manual_translations

  • πŸ—‘οΈ Prunes target-language keys that no longer exist in the source (including add-then-delete-in-the-same-diff via orphan detection)

  • πŸ“ Preserves each target file's existing JSON indentation

  • ⚑ Retries transient MyMemory failures (429/5xx) with backoff; bounded concurrency so it doesn't hammer the API

Related MCP server: i18n-tools-mcp

Requirements

  • Node.js 18+ (uses the native fetch)

  • A git repository (only required for preview_git_changes / diffGitChanges; the cache-based tools work without git)

Installation

cd .mcp/translation-sync
npm install

Add it to your project's .mcp.json (paths are resolved relative to this file, not hardcoded β€” see Configuration below):

{
  "mcpServers": {
    "translation-sync": {
      "command": "node",
      "args": ["./.mcp/translation-sync/index.js"]
    }
  }
}

Restart your MCP client (Claude Code, etc.) to pick it up.

Configuration

The server has no hardcoded project path. It resolves things in this order:

Setting

Resolution order

Project root

TRANSLATION_SYNC_ROOT env var β†’ nearest enclosing git repo root (git rev-parse --show-toplevel) β†’ two directories above this script

Locale folder

TRANSLATION_SYNC_I18N_PATH env var (relative to project root) β†’ src/assets/i18n

Set these as env vars in .mcp.json if your project's locale folder lives somewhere else:

{
  "mcpServers": {
    "translation-sync": {
      "command": "node",
      "args": ["./.mcp/translation-sync/index.js"],
      "env": {
        "TRANSLATION_SYNC_I18N_PATH": "src/locales"
      }
    }
  }
}

Expected folder layout under the locale path β€” one subfolder per language code, containing a file whose name mirrors the source file's with en replaced by that code:

src/assets/i18n/
β”œβ”€β”€ en/
β”‚   β”œβ”€β”€ en.json
β”‚   └── en-b2b.json
β”œβ”€β”€ es/
β”‚   β”œβ”€β”€ es.json
β”‚   └── es-b2b.json
└── fr/
    └── fr.json

A language folder that doesn't exist yet is created automatically the first time you sync to it.

MCP Tools

list_available_languages

list_available_languages({ scope: "project" }) // this project's configured locale folders (default)
list_available_languages({ scope: "all" })     // every language MyMemory supports, project-agnostic

preview_changes

Cache-based diff: compares the source file against the last time sync_translations ran (stored in .translation-cache.json). No git required.

preview_changes({ source_file: "en.json" })

preview_git_changes

Git-based diff against a ref (defaults to HEAD). Use this to see what's changed but not yet synced/committed.

preview_git_changes({ source_file: "en.json", base_ref: "HEAD" })

translate_text

One-off translation utility, independent of any locale file.

translate_text({ text: "Collection Progress", target_language: "es" })

If MyMemory can't translate it, the response asks you (the calling agent) to translate it yourself instead of returning English or a broken string.

sync_translations

The main tool. Syncs added/modified keys into every target language file and removes keys no longer in the source.

// Sync everything that changed, across all of this project's configured languages
sync_translations({ source_file: "en.json" })

// Only specific languages
sync_translations({ source_file: "en.json", target_languages: ["es", "fr", "de"] })

// Only specific keys
sync_translations({ source_file: "en.json", keys: ["text.collection.progress"] })

// Re-translate keys even if the target already has a value
sync_translations({ source_file: "en.json", force_update: true })

// Supply your own translations for keys MyMemory couldn't handle
// (from a prior response's "needs_agent_translation" list)
sync_translations({
  source_file: "en.json",
  manual_translations: {
    es: { "text.collection.progress": "Progreso de la colecciΓ³n" }
  }
})

When MyMemory fails a key (API error, exhausted retries, or a placeholder/token mismatch), that key/language pair is not written to the target file. It's listed in the response under needs_agent_translation with the reason. Translate those yourself and resync with manual_translations to fill them in β€” manual_translations entries are written as-is, no API call.

  1. Edit src/assets/i18n/en/en.json.

  2. Call preview_git_changes (or preview_changes) to see what changed.

  3. Call sync_translations for the languages you need.

  4. If the response lists needs_agent_translation, translate those yourself and call sync_translations again with manual_translations.

  5. Review the diff in target language files, then commit.

How it works

  • Change detection: preview_changes/sync_translations diff the current source JSON against a cached snapshot from the last sync. preview_git_changes instead diffs parsed JSON against a git ref β€” both compare parsed objects, never raw text, so a key deletion elsewhere in the file never gets misread as an edit to its neighbor.

  • Translation: each changed value is sent to MyMemory individually, 5 requests in flight at a time, with retry/backoff on 429/5xx. MyMemory's own errors (e.g. "invalid target language", quota messages) come back as HTTP 200 with the error text as translatedText β€” the server checks responseStatus in the body to catch these rather than trusting the field's mere presence.

  • Token safety: after translation, {{...}} and %s/%1$s-style tokens in the source and translated text are compared; a mismatch is treated as a failure, not written.

  • Pruning: any key present in a target file but absent from the current source is deleted, including keys that were added and removed again within the same diff (orphan detection).

Known limitations

  • MyMemory free tier: ~5,000 words/day per IP. Heavy use may hit quota; failures surface via needs_agent_translation rather than failing silently.

  • Translation quality: MyMemory is a free machine-translation/translation-memory service, not professional-grade. Always review target-language diffs before committing, especially for domain-specific terminology.

  • Quota: hitting the daily MyMemory word limit surfaces as a clear needs_agent_translation reason ("daily free-tier word quota exhausted") rather than a generic API error.

Troubleshooting

Symptom

Fix

Server not listed as a tool

Check .mcp.json, confirm Node 18+, restart the MCP client

ENOENT ... scandir .../i18n

TRANSLATION_SYNC_I18N_PATH / project root didn't resolve to your actual locale folder β€” set the env vars explicitly

A key keeps appearing in needs_agent_translation

MyMemory can't translate it (bad language code, quota, or the translation keeps dropping a {{token}}/%s) β€” translate it manually and pass it via manual_translations

Translations look wrong/literal

MyMemory is machine translation β€” use force_update after fixing the source text, or supply a manual translation

License

MIT

Available Tools

5 tools
list_available_languagesA

List language codes and names. "project" scope (default) lists the locale folders this project actually has under its i18n path; "all" scope lists every language MyMemory's free API can translate to, regardless of whether this project has a locale file for it.

NameRequiredDescriptionDefault
scopeNoproject = this project's configured locale folders; all = every language MyMemory supportsproject

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full disclosure burden. It helpfully reveals that 'all' scope is backed by MyMemory's free API and may return languages with no local locale folder (a meaningful side effect for downstream planning), but it omits whether 'all' requires a network call, what happens on API failure, or the result ordering/shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the core purpose front-loaded and the scope distinction immediately after. Every clause contributes information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter read tool with no output schema, the description is nearly sufficient: it names the return content, both modes, the default, and the data source. Only the network/error behavior of 'all' scope and result ordering are left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3; the description earns more by clarifying the practical consequence the schema doesn't capture β€” that 'all' includes languages with no locale file in the project, which changes how an agent should interpret results. The default of 'project' is also reinforced in prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List language codes and names') and immediately splits the behavior into two named scopes, so an agent knows exactly what comes back. It doesn't explicitly contrast itself with siblings like translate_text or sync_translations, but the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what each scope value does, which implicitly tells an agent which scope to pick for a given intent (check existing locale files vs. discover all translatable languages). However, it never states when to call this tool versus the siblings (translate_text, sync_translations, preview_changes) that presumably consume its output.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

preview_changesA

Preview what translation keys have been added, modified, or deleted in the source file relative to the last sync (cache-based)

NameRequiredDescriptionDefault
source_fileNoSource file to check for changesen.json

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full behavioral burden. 'Preview' conveys non-destructiveness and 'cache-based' usefully signals that results depend on cache freshness, but it says nothing about what happens on a stale/missing cache, whether auth is required, or whether the output is a flat key list or grouped by change type.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with the operation, change taxonomy, and comparison baseline front-loaded, plus a tight parenthetical for the cache qualifier. Nothing is redundant or padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter, no-annotation, no-output-schema preview tool, the description covers the essential operation and the three change categories an agent needs. The main remaining gap is that the shape of the preview result (counts vs. key lists) is unspecified, which matters for a tool whose whole output is the payload.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single enum parameter is fully documented, so the baseline is 3. The description refers only generically to 'the source file' and adds no detail beyond the schema β€” it does not mention that only en.json and en-b2b.json are valid or what the default is.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (preview), resource (translation key changes), and the three change categories (added/modified/deleted) plus the comparison baseline (last sync). The '(cache-based)' qualifier implicitly distinguishes it from the sibling preview_git_changes, but it never names that sibling explicitly, so the differentiation requires inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the 'relative to the last sync (cache-based)' phrasing β€” an agent can infer this is for cache-state checks versus git-state checks. There is no explicit statement of when to prefer this over preview_git_changes or sync_translations, and no prerequisites or exclusions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

preview_git_changesA

Preview translation keys added, modified, or deleted between a git ref and the current working tree (JSON-diff based, not text-diff based β€” immune to comma-shift false positives)

NameRequiredDescriptionDefault
base_refNoGit ref to diff against (branch, commit, tag). Defaults to HEAD.HEAD
source_fileNoSource file to check for git changesen.json

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It does disclose a genuinely useful trait beyond structured fields β€” the diff is JSON-based, so comma-shift reordering won't produce false positives β€” but it says nothing about what happens with an invalid/missing ref, whether uncommitted staged vs unstaged changes are included, or whether the operation is purely read-only (only implied by 'Preview').

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the resource named first and the disambiguating mechanism in a tight parenthetical. No filler, nothing truncated or buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-optional-parameter, enum-constrained, defaulted tool this is nearly sufficient β€” the diff semantics are clear and the schema covers the inputs. The main gap is that no output schema exists, so the description could have sketched the shape of the result (e.g., key paths grouped by added/modified/deleted) rather than leaving it to inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters carry their own descriptions plus a default and an enum, so the schema already does the work. The description adds no parameter-level detail (e.g., accepted ref formats) beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Preview') and resource ('translation keys added, modified, or deleted between a git ref and the working tree'), which is far more precise than the sibling preview_changes. The git-ref scope implicitly separates it from the non-git preview sibling, but no sibling is named explicitly, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The git-diff framing implies when to reach for it (checking uncommitted translation changes before syncing), but there is no explicit when-to-use, when-not-to-use, or comparison against preview_changes/sync_translations. Usage is inferred rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sync_translationsB

Synchronize translation keys from English source file to all target language files using MyMemory API (free, no API key required). Also removes keys that no longer exist in the source.

NameRequiredDescriptionDefault
keysNoOptional: Specific keys to sync. If not provided, syncs all changed keys.
verboseNoShow detailed progress for each language. Set to false for minimal output (saves tokens).
source_fileNoSource file to sync fromen.json
force_updateNoForce re-translation even if the target already has a value for a key
target_languagesNoOptional: Specific languages to sync (e.g., ["es", "fr"]). If not provided, syncs all languages.
manual_translationsNoTranslations supplied by the calling agent for keys MyMemory could not translate (from a prior sync_translations response's "needs_agent_translation" list). Shape: { "<language_code>": { "<key>": "<translated text>" } }. These are written as-is, no API call, no retry.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden. It usefully discloses the MyMemory API dependency, no API key requirement, and destructive removal of keys no longer in the source, but it does not explain overwrite behavior, error handling, file access requirements, or response structure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two tightly written sentences, front-loaded with the core action and followed by the important destructive side effect. The parenthetical about MyMemory being free and requiring no API key is useful context without bloating the text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Parameters are fully covered by the schema, and the description covers the main purpose and deletion behavior. However, for a tool with six parameters, a nested object, no annotations, and no output schema, it omits return values, the needs_agent_translation workflow implied by manual_translations, and guidance on previewing changes before destructive synchronization.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters in detail, including the nested manual_translations shape. The description adds no parameter-specific meaning beyond what the schema provides, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: synchronize translation keys from an English source file to target language files, including removal of obsolete keys. It is clear what the tool does, but it does not explicitly distinguish itself from siblings such as translate_text or preview_changes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies a batch synchronization use case, but gives no explicit when-to-use or when-not-to-use guidance and does not mention alternatives such as preview_changes or translate_text. An agent must infer the appropriate context from the tool name and description alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

translate_textB

Translate a specific text to a target language using MyMemory API (free, no API key required)

NameRequiredDescriptionDefault
textYesText to translate
contextNoOptional: Context for better translation (e.g., "Button label", "Error message")
target_languageYesTarget language code (e.g., "es", "fr")

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden, and it does add real context: the provider is MyMemory and no API key or auth setup is needed. However, it omits the quota/rate-limit behavior typical of a free translation API, error behavior for unsupported language codes, and what the call returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence that names the action, the input scope, the provider, and the auth situation with zero filler. Nothing could be removed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Parameters are fully covered by the schema and there is no output schema to explain, but with no annotations the description should still say roughly what comes back (a translated string) and whether language codes must be validated via list_available_languages. Those gaps matter for an agent calling this unattended.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with only 3 params, so the schema already documents text, target_language, and the optional context hint. The description adds no meaning beyond that, which is the expected baseline when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Translate a specific text') plus the backing provider (MyMemory API). It does not explicitly contrast with the sibling sync_translations, so an agent must infer that this is the single-string path versus a bulk sync.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance is given, and no sibling is named. The phrase 'a specific text' faintly implies single-item translation as opposed to sync_translations, and 'no API key required' hints at zero setup, but neither is stated as a selection rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.0.0
    • First observedlist_available_languages
    • First observedpreview_changes
    • First observedpreview_git_changes
    • First observedsync_translations
    • First observedtranslate_text

TDQS

A3.8/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct role: sync performs writes, two previews use different comparison baselines (cache vs git ref), list reports locales, and translate_text handles ad hoc translation. The most similar pair, preview_changes and preview_git_changes, is explicitly differentiated by baseline and description.

Naming Consistency5/5

All tool names use snake_case with a verb-first pattern: sync_translations, preview_changes, preview_git_changes, list_available_languages, translate_text. The convention is predictable and readable throughout.

Tool Count5/5

Five tools is well-scoped for a translation synchronization server. Each tool supports a distinct part of the workflow without obvious bloat or missing core operations.

Completeness4/5

The tool set covers the core lifecycle: syncing translations, previewing changes from cache and git, listing languages, and translating individual text. Minor gaps exist around cache/config management or per-key editing, but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Translation QA for i18n locale files. Deterministic validators β€” missing keys, placeholder drift, collapsed plurals, glossary breaches β€” that need no API key, plus a review tool that hands translation pairs and judging criteria back to the calling agent, so meaning-level review runs on the model your client already has. Translation with your own LLM key is optional. JSON, Flutter .arb, Apple .
    8
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to inspect, audit and safely edit locale JSON files across flat, nested, and namespaced layouts without loading whole files into the model context, with compact token-efficient reads and write paths that cannot drop keys or overwrite silently. Ships ten tools plus slash-command prompts for project info, key search, reference lookup, translation upserts, and missing-translation audits.
    10
    44 npm
    MIT